diff --git a/AUTHORS b/AUTHORS index 4b63c63..36ae208 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -51,6 +51,7 @@ Andrei Parvu <andrei.prv@gmail.com> Andrei Parvu <parvu@adobe.com> Andrew Brampton <me@bramp.net> +Andrew Hung <andrhung@amazon.com> Andrew Tulloch <andrew@tullo.ch> Anish Patankar <anish.p@samsung.com> Ankit Kumar <ankit2.kumar@samsung.com> @@ -130,6 +131,7 @@ Daegyu Lee <na7jun8gi@gmail.com> Dai Chunyang <chunyang.dai@intel.com> Daiwei Li <daiweili@suitabletech.com> +Damien Marié <damien@dam.io> Dan McCombs <overridex@gmail.com> Daniel Bomar <dbdaniel42@gmail.com> Daniel Carvalho Liedke <dliedke@gmail.com> @@ -465,6 +467,7 @@ Nitish Mehrotra <nitish.m@samsung.com> Noj Vek <nojvek@gmail.com> Nolan Cao <nolan.robin.cao@gmail.com> +Omar Sandoval <osandov@osandov.com> Pan Deng <pan.deng@intel.com> Parag Radke <nrqv63@motorola.com> Paritosh Kumar <paritosh.in@samsung.com>
diff --git a/BUILD.gn b/BUILD.gn index ed2dcdd..76b06bbd 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -344,6 +344,10 @@ deps += [ "//components/policy:policy_templates" ] } + if (v8_use_external_startup_data) { + deps += [ "//gin:gin_v8_snapshot_fingerprint" ] + } + if (is_win) { deps += [ "//chrome/installer/gcapi", @@ -661,10 +665,6 @@ deps += [ "//chromecast:cast_shell" ] } - if (is_mac) { # TODO(GYP) || is_ios - deps += [ "//media/cast:cast_h264_vt_encoder_unittests" ] - } - if (is_mac || is_win) { deps += [ "//third_party/crashpad/crashpad/handler:crashpad_handler", @@ -985,8 +985,7 @@ if (is_win && symbol_level == 2 && target_cpu == "x86" && is_syzyasan) { deps += [ "//chrome/tools/build/win/syzygy:chrome_dll_syzygy", - # TODO(GYP): Add this once it exists, https://crbug.com/619086 - # "//content/shell:content_shell_syzyasan + "//content/shell:content_shell_syzyasan", ] } }
diff --git a/DEPS b/DEPS index 1f7e9024..ffac181 100644 --- a/DEPS +++ b/DEPS
@@ -36,27 +36,27 @@ # 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': 'f119796f95f336d5b29f06f369b15b48a6a0df45', + 'skia_revision': '614d8f9a3c44e22d77fa909e82119e8a6746e1b1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '909f0b27d3baff1005248545e3f47246a59c0159', + 'v8_revision': 'bfdebc9e64162c24a869703c64e558fe91077540', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. - 'swarming_revision': 'df6e95e7669883c8fe9ef956c69a544154701a49', + 'swarming_revision': '7f63a272f7d9785ce41b6d10bb3106c49a968e57', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '9585a784bff9752bed369d8247a918495bcdf3ab', + 'angle_revision': '84954988ad266c11cacdfd716bf09e3d7910ec7b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. - 'buildtools_revision': 'aa47d9773d8f4d6254a587a1240b3dc023d54f06', + 'buildtools_revision': '031420bbafaaa8c33e2bc0623c22fb6181a57f47', # 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': '3c27a84d15c06f85cc7f455f96dc124673f9f9d2', + 'pdfium_revision': 'dbc7716e1b8d67a5ca422ef0bbfe87ff8c5cf4ea', # 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. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. - 'boringssl_revision': '95c69563dc5422c3b3cd3a0bf435944a7530a12d', + 'boringssl_revision': '10f97f3bfcecc3fbe8e9f02e7c426f7e340f7f54', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling google-toolbox-for-mac # and whatever else without interference from each other. @@ -88,7 +88,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': '4160831d2082e3e07cc9b2a957dca49391ba7edf', + 'catapult_revision': '13aca87891c16ce452da5e26b52063f934e0a31b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -148,7 +148,7 @@ Var('chromium_git') + '/external/snappy.git' + '@' + '762bb32f0c9d2f31ba4958c7c0933d22e80c20bf', 'src/tools/gyp': - Var('chromium_git') + '/external/gyp.git' + '@' + 'bac4680ec9a5c55ab692490b6732999648ecf1e9', + Var('chromium_git') + '/external/gyp.git' + '@' + 'e7079f0e0e14108ab0dba58728ff219637458563', 'src/tools/swarming_client': Var('chromium_git') + '/external/swarming.client.git' + '@' + Var('swarming_revision'), @@ -178,7 +178,7 @@ Var('chromium_git') + '/external/bidichecker/lib.git' + '@' + '97f2aa645b74c28c57eca56992235c79850fa9e0', 'src/third_party/webgl/src': - Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '443264a6dadf61e92a6569b5ec90777009160b94', + Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '50c670170b1a7c9566e389962ec0e2bfb70a7eec', 'src/third_party/webdriver/pylib': Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd', @@ -214,7 +214,7 @@ Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067', 'src/third_party/webrtc': - Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '05929e21d437bc5f80309455f168a9e4bb2bc94b', # commit position 13407 + Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '87fd07bce3c04d0555a3fbbb486024dce8302b40', # commit position 13457 'src/third_party/openmax_dl': Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' + Var('openmax_dl_revision'),
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index d60a19c..d90eeda 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -513,7 +513,9 @@ for f in input_api.AffectedFiles(): if (not f.LocalPath().endswith(('.cc', '.h')) or f.LocalPath().endswith(('test.cc', '_win.cc', '_win.h')) or - '/win/' in f.LocalPath()): + '/win/' in f.LocalPath() or + 'chrome_elf' in f.LocalPath() or + 'install_static' in f.LocalPath()): continue allowWString = False @@ -2182,19 +2184,19 @@ """ # Potentially ambiguous bot names are listed explicitly. master_map = { - 'chromium_presubmit': 'tryserver.chromium.linux', - 'tools_build_presubmit': 'tryserver.chromium.linux', + 'chromium_presubmit': 'master.tryserver.chromium.linux', + 'tools_build_presubmit': 'master.tryserver.chromium.linux', } master = master_map.get(bot) if not master: if 'android' in bot: - master = 'tryserver.chromium.android' + master = 'master.tryserver.chromium.android' elif 'linux' in bot or 'presubmit' in bot: - master = 'tryserver.chromium.linux' + master = 'master.tryserver.chromium.linux' elif 'win' in bot: - master = 'tryserver.chromium.win' + master = 'master.tryserver.chromium.win' elif 'mac' in bot or 'ios' in bot: - master = 'tryserver.chromium.mac' + master = 'master.tryserver.chromium.mac' return master
diff --git a/PRESUBMIT_test.py b/PRESUBMIT_test.py index 9269964..c45378b 100755 --- a/PRESUBMIT_test.py +++ b/PRESUBMIT_test.py
@@ -706,7 +706,7 @@ class TryServerMasterTest(unittest.TestCase): def testTryServerMasters(self): bots = { - 'tryserver.chromium.android': [ + 'master.tryserver.chromium.android': [ 'android_archive_rel_ng', 'android_arm64_dbg_recipe', 'android_blink_rel', @@ -730,7 +730,7 @@ 'linux_android_dbg_ng', 'linux_android_rel_ng', ], - 'tryserver.chromium.mac': [ + 'master.tryserver.chromium.mac': [ 'ios_dbg_simulator', 'ios_rel_device', 'ios_rel_device_ninja', @@ -746,7 +746,7 @@ 'mac_x64_rel', 'mac_xcodebuild', ], - 'tryserver.chromium.linux': [ + 'master.tryserver.chromium.linux': [ 'chromium_presubmit', 'linux_arm_cross_compile', 'linux_arm_tester', @@ -781,7 +781,7 @@ 'linux_valgrind', 'tools_build_presubmit', ], - 'tryserver.chromium.win': [ + 'master.tryserver.chromium.win': [ 'win8_aura', 'win8_chromium_dbg', 'win8_chromium_rel',
diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc index ef2418d0..7ba66c5e 100644 --- a/android_webview/browser/browser_view_renderer.cc +++ b/android_webview/browser/browser_view_renderer.cc
@@ -343,7 +343,10 @@ { // Reset scroll back to the origin, will go back to the old // value when scroll_reset is out of scope. - compositor_->DidChangeRootLayerScrollOffset(gfx::ScrollOffset()); + base::AutoReset<gfx::Vector2dF> scroll_reset(&scroll_offset_dip_, + gfx::Vector2dF()); + compositor_->DidChangeRootLayerScrollOffset( + gfx::ScrollOffset(scroll_offset_dip_)); CompositeSW(rec_canvas); } compositor_->DidChangeRootLayerScrollOffset(
diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc index 33b1eaec..b1405bef 100644 --- a/android_webview/browser/hardware_renderer.cc +++ b/android_webview/browser/hardware_renderer.cc
@@ -32,7 +32,7 @@ last_submitted_output_surface_id_(0u) { DCHECK(last_egl_context_); surfaces_->GetSurfaceManager()->RegisterSurfaceFactoryClient( - surface_id_allocator_->id_namespace(), this); + surface_id_allocator_->client_id(), this); } HardwareRenderer::~HardwareRenderer() { @@ -42,7 +42,7 @@ DestroySurface(); surface_factory_.reset(); surfaces_->GetSurfaceManager()->UnregisterSurfaceFactoryClient( - surface_id_allocator_->id_namespace()); + surface_id_allocator_->client_id()); // Reset draw constraints. render_thread_manager_->PostExternalDrawConstraintsToChildCompositorOnRT(
diff --git a/android_webview/browser/parent_output_surface.cc b/android_webview/browser/parent_output_surface.cc index 7373d39..79b855d 100644 --- a/android_webview/browser/parent_output_surface.cc +++ b/android_webview/browser/parent_output_surface.cc
@@ -35,7 +35,6 @@ void ParentOutputSurface::SwapBuffers(cc::CompositorFrame frame) { context_provider_->ContextGL()->ShallowFlushCHROMIUM(); - client_->DidSwapBuffers(); } void ParentOutputSurface::ApplyExternalStencil() {
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 71df045..7f4cf31 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
@@ -327,8 +327,7 @@ void AwResourceDispatcherHostDelegate::OnResponseStarted( net::URLRequest* request, content::ResourceContext* resource_context, - content::ResourceResponse* response, - IPC::Sender* sender) { + content::ResourceResponse* response) { const content::ResourceRequestInfo* request_info = content::ResourceRequestInfo::ForRequest(request); if (!request_info) {
diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h index d5af23f9..0528e56b 100644 --- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h +++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h
@@ -18,10 +18,6 @@ struct ResourceResponse; } // namespace content -namespace IPC { -class Sender; -} // namespace IPC - namespace android_webview { class IoThreadClientThrottle; @@ -60,8 +56,7 @@ content::ResourceContext* resource_context) override; void OnResponseStarted(net::URLRequest* request, content::ResourceContext* resource_context, - content::ResourceResponse* response, - IPC::Sender* sender) override; + content::ResourceResponse* response) override; void OnRequestRedirected(const GURL& redirect_url, net::URLRequest* request,
diff --git a/android_webview/browser/surfaces_instance.cc b/android_webview/browser/surfaces_instance.cc index b418075..b796730 100644 --- a/android_webview/browser/surfaces_instance.cc +++ b/android_webview/browser/surfaces_instance.cc
@@ -39,8 +39,7 @@ } SurfacesInstance::SurfacesInstance() - : next_surface_id_namespace_(1u), - gl_surface_(new AwGLSurface) { + : next_surface_client_id_(1u), gl_surface_(new AwGLSurface) { cc::RendererSettings settings; // Should be kept in sync with compositor_impl_android.cc. @@ -52,8 +51,8 @@ surface_manager_.reset(new cc::SurfaceManager); surface_id_allocator_.reset( - new cc::SurfaceIdAllocator(next_surface_id_namespace_++)); - surface_id_allocator_->RegisterSurfaceIdNamespace(surface_manager_.get()); + new cc::SurfaceIdAllocator(next_surface_client_id_++)); + surface_id_allocator_->RegisterSurfaceClientId(surface_manager_.get()); std::unique_ptr<cc::BeginFrameSource> begin_frame_source( new cc::StubBeginFrameSource); @@ -69,7 +68,7 @@ display_.reset(new cc::Display( surface_manager_.get(), nullptr /* shared_bitmap_manager */, nullptr /* gpu_memory_buffer_manager */, settings, - surface_id_allocator_->id_namespace(), std::move(begin_frame_source), + surface_id_allocator_->client_id(), std::move(begin_frame_source), std::move(output_surface_holder), std::move(scheduler), std::move(texture_mailbox_deleter))); display_->Initialize(this); @@ -92,9 +91,9 @@ std::unique_ptr<cc::SurfaceIdAllocator> SurfacesInstance::CreateSurfaceIdAllocator() { - std::unique_ptr<cc::SurfaceIdAllocator> allocator = base::WrapUnique( - new cc::SurfaceIdAllocator(next_surface_id_namespace_++)); - allocator->RegisterSurfaceIdNamespace(surface_manager_.get()); + std::unique_ptr<cc::SurfaceIdAllocator> allocator = + base::WrapUnique(new cc::SurfaceIdAllocator(next_surface_client_id_++)); + allocator->RegisterSurfaceClientId(surface_manager_.get()); return allocator; }
diff --git a/android_webview/browser/surfaces_instance.h b/android_webview/browser/surfaces_instance.h index 709b389b..e92f15b 100644 --- a/android_webview/browser/surfaces_instance.h +++ b/android_webview/browser/surfaces_instance.h
@@ -68,7 +68,7 @@ void SetEmptyRootFrame(); - uint32_t next_surface_id_namespace_; + uint32_t next_surface_client_id_; scoped_refptr<AwGLSurface> gl_surface_; std::unique_ptr<cc::SurfaceManager> surface_manager_;
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java index 0aef4c9c..3089aaf 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java
@@ -838,4 +838,44 @@ Math.abs(atomicContentHeight.get() - atomicNewContentHeightApproximation.get()) <= 1); } + + @SmallTest + @Feature("AndroidWebView") + public void testScrollOffsetAfterCapturePicture() throws Throwable { + final TestAwContentsClient contentsClient = new TestAwContentsClient(); + final ScrollTestContainerView testContainerView = + (ScrollTestContainerView) createAwTestContainerViewOnMainSync(contentsClient); + enableJavaScriptOnUiThread(testContainerView.getAwContents()); + + final int targetScrollYPix = 322; + + loadTestPageAndWaitForFirstFrame(testContainerView, contentsClient, null, ""); + + assertScrollOnMainSync(testContainerView, 0, 0); + + scrollToOnMainSync(testContainerView, 0, targetScrollYPix); + + final int scrolledYPix = runTestOnUiThreadAndGetResult(new Callable<Integer>() { + @Override + public Integer call() { + return testContainerView.getScrollY(); + } + }); + + assertTrue(scrolledYPix > 0); + + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + testContainerView.getAwContents().capturePicture(); + } + }); + + getInstrumentation().runOnMainSync(new Runnable() { + @Override + public void run() { + assertEquals(testContainerView.getScrollY(), scrolledYPix); + } + }); + } }
diff --git a/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt b/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt index 01fad36..318bb0e 100644 --- a/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt +++ b/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt
@@ -4377,13 +4377,6 @@ getter zoomAndPan method constructor setter zoomAndPan -interface SVGZoomEvent : UIEvent - getter newScale - getter newTranslate - getter previousScale - getter previousTranslate - getter zoomRectScreen - method constructor interface Screen getter availHeight getter availLeft
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 3a885ac..1649467a 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -181,7 +181,7 @@ } # TODO(msw): Move support code with content deps to test_support_with_content. -source_set("test_support") { +static_library("test_support") { testonly = true sources = gypi_values.ash_test_support_sources configs += [ "//build/config:precompiled_headers" ] @@ -237,7 +237,7 @@ } } -source_set("test_support_with_content") { +static_library("test_support_with_content") { testonly = true sources = gypi_values.ash_test_support_with_content_sources configs += [ "//build/config:precompiled_headers" ] @@ -249,7 +249,7 @@ ] } -source_set("interactive_ui_test_support") { +static_library("interactive_ui_test_support") { testonly = true configs += [ "//build/config:precompiled_headers" ] public_deps = [
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc index dbc9d21..13b422265 100644 --- a/ash/accelerators/accelerator_controller.cc +++ b/ash/accelerators/accelerator_controller.cc
@@ -23,7 +23,9 @@ #include "ash/common/shell_window_ids.h" #include "ash/common/system/brightness_control_delegate.h" #include "ash/common/system/keyboard_brightness_control_delegate.h" +#include "ash/common/system/status_area_widget.h" #include "ash/common/system/system_notifier.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/system_tray_notifier.h" #include "ash/common/system/volume_control_delegate.h" @@ -50,8 +52,6 @@ #include "ash/shelf/shelf_delegate.h" #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" -#include "ash/system/status_area_widget.h" -#include "ash/system/tray/system_tray.h" #include "ash/touch/touch_hud_debug.h" #include "ash/utility/screenshot_controller.h" #include "ash/wm/power_button_controller.h"
diff --git a/ash/accelerators/debug_commands.cc b/ash/accelerators/debug_commands.cc index cd3d46d1..63898f9 100644 --- a/ash/accelerators/debug_commands.cc +++ b/ash/accelerators/debug_commands.cc
@@ -7,6 +7,8 @@ #include "ash/accelerators/accelerator_commands.h" #include "ash/common/ash_switches.h" #include "ash/common/shell_delegate.h" +#include "ash/common/system/toast/toast_data.h" +#include "ash/common/system/toast/toast_manager.h" #include "ash/common/wm/maximize_mode/maximize_mode_controller.h" #include "ash/common/wm_shell.h" #include "ash/debug.h" @@ -16,8 +18,6 @@ #include "ash/host/ash_window_tree_host.h" #include "ash/root_window_controller.h" #include "ash/shell.h" -#include "ash/system/toast/toast_data.h" -#include "ash/system/toast/toast_manager.h" #include "ash/wm/window_util.h" #include "base/command_line.h" #include "base/metrics/user_metrics.h"
diff --git a/ash/ash.gyp b/ash/ash.gyp index 83fc888e..a6cfa315 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp
@@ -34,8 +34,6 @@ 'ash_export.h', 'ash_touch_exploration_manager_chromeos.cc', 'ash_touch_exploration_manager_chromeos.h', - 'audio/sounds.cc', - 'audio/sounds.h', 'aura/aura_layout_manager_adapter.cc', 'aura/aura_layout_manager_adapter.h', 'aura/wm_lookup_aura.cc', @@ -140,6 +138,8 @@ 'common/system/chromeos/keyboard_brightness_controller.cc', 'common/system/chromeos/keyboard_brightness_controller.h', 'common/system/chromeos/media_security/media_capture_observer.h', + 'common/system/chromeos/media_security/multi_profile_media_tray_item.cc', + 'common/system/chromeos/media_security/multi_profile_media_tray_item.h', 'common/system/chromeos/network/network_detailed_view.h', 'common/system/chromeos/network/network_observer.h', 'common/system/chromeos/network/network_portal_detector_observer.h', @@ -219,10 +219,18 @@ 'common/system/networking_config_delegate.h', 'common/system/overview/overview_button_tray.cc', 'common/system/overview/overview_button_tray.h', + 'common/system/status_area_widget.cc', + 'common/system/status_area_widget.h', 'common/system/status_area_widget_delegate.cc', 'common/system/status_area_widget_delegate.h', 'common/system/system_notifier.cc', 'common/system/system_notifier.h', + 'common/system/toast/toast_data.cc', + 'common/system/toast/toast_data.h', + 'common/system/toast/toast_manager.cc', + 'common/system/toast/toast_manager.h', + 'common/system/toast/toast_overlay.cc', + 'common/system/toast/toast_overlay.h', 'common/system/tray/actionable_view.cc', 'common/system/tray/actionable_view.h', 'common/system/tray/default_system_tray_delegate.cc', @@ -237,6 +245,8 @@ 'common/system/tray/label_tray_view.h', 'common/system/tray/special_popup_row.cc', 'common/system/tray/special_popup_row.h', + 'common/system/tray/system_tray.cc', + 'common/system/tray/system_tray.h', 'common/system/tray/system_tray_bubble.cc', 'common/system/tray/system_tray_bubble.h', 'common/system/tray/system_tray_delegate.cc', @@ -620,10 +630,6 @@ 'sticky_keys/sticky_keys_overlay.cc', 'sticky_keys/sticky_keys_overlay.h', 'sticky_keys/sticky_keys_state.h', - 'system/chromeos/media_security/multi_profile_media_tray_item.cc', - 'system/chromeos/media_security/multi_profile_media_tray_item.h', - 'system/chromeos/multi_user/user_switch_util.cc', - 'system/chromeos/multi_user/user_switch_util.h', 'system/chromeos/power/power_event_observer.cc', 'system/chromeos/power/power_event_observer.h', 'system/chromeos/power/video_activity_notifier.cc', @@ -632,16 +638,6 @@ 'system/chromeos/rotation/tray_rotation_lock.h', 'system/chromeos/tray_display.cc', 'system/chromeos/tray_display.h', - 'system/status_area_widget.cc', - 'system/status_area_widget.h', - 'system/toast/toast_data.cc', - 'system/toast/toast_data.h', - 'system/toast/toast_manager.cc', - 'system/toast/toast_manager.h', - 'system/toast/toast_overlay.cc', - 'system/toast/toast_overlay.h', - 'system/tray/system_tray.cc', - 'system/tray/system_tray.h', 'touch/touch_hud_debug.cc', 'touch/touch_hud_debug.h', 'touch/touch_hud_projection.cc', @@ -844,8 +840,6 @@ 'test/ui_controls_factory_ash.h', 'test/user_metrics_recorder_test_api.cc', 'test/user_metrics_recorder_test_api.h', - 'test/virtual_keyboard_test_helper.cc', - 'test/virtual_keyboard_test_helper.h', ], 'ash_test_support_with_content_sources': [ 'test/content/test_shell_content_state.cc', @@ -909,6 +903,7 @@ 'common/system/chromeos/supervised/tray_supervised_user_unittest.cc', 'common/system/date/date_view_unittest.cc', 'common/system/ime/tray_ime_chromeos_unittest.cc', + 'common/system/tray/system_tray_unittest.cc', 'common/system/tray/tray_details_view_unittest.cc', 'common/system/update/tray_update_unittest.cc', 'common/system/user/tray_user_unittest.cc', @@ -965,14 +960,12 @@ 'sticky_keys/sticky_keys_overlay_unittest.cc', 'sticky_keys/sticky_keys_unittest.cc', 'system/chromeos/media_security/multi_profile_media_tray_item_unittest.cc', - 'system/chromeos/multi_user/user_switch_util_unittest.cc', 'system/chromeos/power/power_event_observer_unittest.cc', 'system/chromeos/power/video_activity_notifier_unittest.cc', 'system/chromeos/rotation/tray_rotation_lock_unittest.cc', 'system/chromeos/tray_display_unittest.cc', 'system/overview/overview_button_tray_unittest.cc', 'system/toast/toast_manager_unittest.cc', - 'system/tray/system_tray_unittest.cc', 'system/web_notification/ash_popup_alignment_delegate_unittest.cc', 'system/web_notification/web_notification_tray_unittest.cc', 'test/ash_test_helper_unittest.cc', @@ -1045,7 +1038,6 @@ '../components/components.gyp:signin_core_account_id', '../components/components.gyp:user_manager', '../components/components.gyp:wallpaper', - '../media/media.gyp:media', '../net/net.gyp:net', '../skia/skia.gyp:skia', '../third_party/icu/icu.gyp:icui18n',
diff --git a/ash/ash_chromeos_strings.grdp b/ash/ash_chromeos_strings.grdp index 1b3a4e5..1d563d14 100644 --- a/ash/ash_chromeos_strings.grdp +++ b/ash/ash_chromeos_strings.grdp
@@ -499,6 +499,14 @@ Take our survey </message> + <!-- Quick Unlock Strings --> + <message name="IDS_ASH_QUICK_UNLOCK_NOTIFICATION_TITLE" desc="The title of the notification for Quick Unlock feature notification."> + QU Feature notification title here + </message> + <message name="IDS_ASH_QUICK_UNLOCK_NOTIFICATION_BODY" desc="The body of the notification for Quick Unlock feature notification."> + QU Feature notification body goes here. QU Feature notification body goes here. QU Feature notification body goes here. QU Feature notification body goes here. QU Feature notification body goes here. + </message> + <!-- Deprecated Accelerators Messages --> <!-- Shortcut keys MUST be connected with pluses (e.g. Ctrl+Shift+L). --> <message name="IDS_SHORTCUT_LOCK_SCREEN_OLD" desc="the old deprecated shortcut to lock the screen.">
diff --git a/ash/ash_touch_exploration_manager_chromeos.cc b/ash/ash_touch_exploration_manager_chromeos.cc index 7e60f17..505d7378 100644 --- a/ash/ash_touch_exploration_manager_chromeos.cc +++ b/ash/ash_touch_exploration_manager_chromeos.cc
@@ -4,7 +4,6 @@ #include "ash/ash_touch_exploration_manager_chromeos.h" -#include "ash/audio/sounds.h" #include "ash/common/accessibility_delegate.h" #include "ash/common/system/tray/system_tray_notifier.h" #include "ash/common/wm_shell.h"
diff --git a/ash/audio/sounds.cc b/ash/audio/sounds.cc deleted file mode 100644 index 8eb4b38..0000000 --- a/ash/audio/sounds.cc +++ /dev/null
@@ -1,37 +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. - -#include "ash/audio/sounds.h" - -#include "ash/common/accessibility_delegate.h" -#include "ash/common/ash_switches.h" -#include "ash/common/wm_shell.h" -#include "base/command_line.h" - -using media::SoundsManager; - -namespace ash { - -bool PlaySystemSoundAlways(SoundsManager::SoundKey key) { - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshDisableSystemSounds)) - return false; - return SoundsManager::Get()->Play(key); -} - -bool PlaySystemSoundIfSpokenFeedback(SoundsManager::SoundKey key) { - base::CommandLine* cl = base::CommandLine::ForCurrentProcess(); - if (cl->HasSwitch(switches::kAshDisableSystemSounds)) - return false; - - if (cl->HasSwitch(switches::kAshEnableSystemSounds)) - return SoundsManager::Get()->Play(key); - - if (!WmShell::Get()->GetAccessibilityDelegate()->IsSpokenFeedbackEnabled()) - return false; - - return SoundsManager::Get()->Play(key); -} - -} // namespace ash
diff --git a/ash/audio/sounds.h b/ash/audio/sounds.h deleted file mode 100644 index 2d0f8fa9..0000000 --- a/ash/audio/sounds.h +++ /dev/null
@@ -1,28 +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 ASH_AUDIO_SOUNDS_H_ -#define ASH_AUDIO_SOUNDS_H_ - -#include "ash/ash_export.h" -#include "media/audio/sounds/sounds_manager.h" - -namespace ash { - -// A wrapper around media::SoundsManager::Play() method, which plays sound -// identified by |key|. Returns true when sound is successfully played. -ASH_EXPORT bool PlaySystemSoundAlways(media::SoundsManager::SoundKey key); - -// A wrapper around media::SoundsManager::Play() method, which plays -// sound identified by |key| iff at least one of the following -// conditions is true: -// * ash::switches::kAshEnableSystemSounds flag is set -// * spoken feedback is enabled -// Returns true when sound is successfully played. -ASH_EXPORT bool PlaySystemSoundIfSpokenFeedback( - media::SoundsManager::SoundKey key); - -} // namespace ash - -#endif // ASH_AUDIO_SOUNDS_H_
diff --git a/ash/aura/wm_window_aura.cc b/ash/aura/wm_window_aura.cc index ade5c2c..412772b 100644 --- a/ash/aura/wm_window_aura.cc +++ b/ash/aura/wm_window_aura.cc
@@ -718,6 +718,12 @@ OnWindowVisibilityChanging(this, visible)); } +void WmWindowAura::OnWindowVisibilityChanged(aura::Window* window, + bool visible) { + FOR_EACH_OBSERVER(WmWindowObserver, observers_, + OnWindowVisibilityChanged(this, visible)); +} + void WmWindowAura::OnWindowTitleChanged(aura::Window* window) { FOR_EACH_OBSERVER(WmWindowObserver, observers_, OnWindowTitleChanged(this)); }
diff --git a/ash/aura/wm_window_aura.h b/ash/aura/wm_window_aura.h index f33c8d2..32ed9eee 100644 --- a/ash/aura/wm_window_aura.h +++ b/ash/aura/wm_window_aura.h
@@ -168,6 +168,7 @@ void OnWindowDestroying(aura::Window* window) override; void OnWindowDestroyed(aura::Window* window) override; void OnWindowVisibilityChanging(aura::Window* window, bool visible) override; + void OnWindowVisibilityChanged(aura::Window* window, bool visible) override; void OnWindowTitleChanged(aura::Window* window) override; aura::Window* window_;
diff --git a/ash/common/ash_switches.cc b/ash/common/ash_switches.cc index 650b54d..dee312a3 100644 --- a/ash/common/ash_switches.cc +++ b/ash/common/ash_switches.cc
@@ -75,13 +75,6 @@ // flag is removed. const char kAshEnableTouchViewTesting[] = "ash-enable-touch-view-testing"; -// When this flag is set, system sounds will not be played. -const char kAshDisableSystemSounds[] = "ash-disable-system-sounds"; - -// When this flag is set, system sounds will be played whether the -// ChromeVox is enabled or not. -const char kAshEnableSystemSounds[] = "ash-enable-system-sounds"; - // Hides notifications that are irrelevant to Chrome OS device factory testing, // such as battery level updates. const char kAshHideNotificationsForFactory[] =
diff --git a/ash/common/ash_switches.h b/ash/common/ash_switches.h index d6f29bf..90a8765 100644 --- a/ash/common/ash_switches.h +++ b/ash/common/ash_switches.h
@@ -36,8 +36,6 @@ ASH_EXPORT extern const char kAshDisableStableOverviewOrder[]; ASH_EXPORT extern const char kAshEnableStableOverviewOrder[]; ASH_EXPORT extern const char kAshEnableSoftwareMirroring[]; -ASH_EXPORT extern const char kAshDisableSystemSounds[]; -ASH_EXPORT extern const char kAshEnableSystemSounds[]; ASH_EXPORT extern const char kAshEnableTouchViewTesting[]; ASH_EXPORT extern const char kAshHideNotificationsForFactory[]; ASH_EXPORT extern const char kAshHostWindowBounds[];
diff --git a/ash/common/material_design/DEPS b/ash/common/material_design/DEPS deleted file mode 100644 index b2a6c4d..0000000 --- a/ash/common/material_design/DEPS +++ /dev/null
@@ -1,4 +0,0 @@ -include_rules = [ - "+ash/ash_switches.h", - "+ash/test", -]
diff --git a/ash/common/metrics/user_metrics_action.h b/ash/common/metrics/user_metrics_action.h index 38584ab..e989f99 100644 --- a/ash/common/metrics/user_metrics_action.h +++ b/ash/common/metrics/user_metrics_action.h
@@ -75,6 +75,11 @@ UMA_STATUS_AREA_DISABLE_SPOKEN_FEEDBACK, UMA_STATUS_AREA_DISABLE_WIFI, UMA_STATUS_AREA_DISABLE_VIRTUAL_KEYBOARD, + UMA_STATUS_AREA_DISPLAY_DEFAULT_SELECTED, + UMA_STATUS_AREA_DISPLAY_DEFAULT_SHOW_SETTINGS, + UMA_STATUS_AREA_DISPLAY_NOTIFICATION_CREATED, + UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SELECTED, + UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SHOW_SETTINGS, UMA_STATUS_AREA_DRIVE_CANCEL_OPERATION, UMA_STATUS_AREA_DRIVE_SETTINGS, UMA_STATUS_AREA_ENABLE_AUTO_CLICK,
diff --git a/ash/common/shelf/shelf_alignment_menu.cc b/ash/common/shelf/shelf_alignment_menu.cc index bf5f052..574317a 100644 --- a/ash/common/shelf/shelf_alignment_menu.cc +++ b/ash/common/shelf/shelf_alignment_menu.cc
@@ -47,7 +47,7 @@ bool ShelfAlignmentMenu::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; }
diff --git a/ash/common/shelf/shelf_alignment_menu.h b/ash/common/shelf/shelf_alignment_menu.h index c283466e..2686f3e 100644 --- a/ash/common/shelf/shelf_alignment_menu.h +++ b/ash/common/shelf/shelf_alignment_menu.h
@@ -24,7 +24,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; private:
diff --git a/ash/common/system/DEPS b/ash/common/system/DEPS deleted file mode 100644 index cb8bd0b5..0000000 --- a/ash/common/system/DEPS +++ /dev/null
@@ -1,6 +0,0 @@ -# NOTE: Files are migrating to this directory as part of the mus ash refactor. -# Talk to jamescook@ before adding deps. See http://crbug.com/619636 -include_rules = [ - # TODO(jamescook): Remove this. - "+ash/system/tray/system_tray.h", -] \ No newline at end of file
diff --git a/ash/common/system/cast/tray_cast.cc b/ash/common/system/cast/tray_cast.cc index 4bc1711..7fe11386 100644 --- a/ash/common/system/cast/tray_cast.cc +++ b/ash/common/system/cast/tray_cast.cc
@@ -11,6 +11,7 @@ #include "ash/common/system/tray/fixed_sized_image_view.h" #include "ash/common/system/tray/fixed_sized_scroll_view.h" #include "ash/common/system/tray/hover_highlight_view.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/throbber_view.h" #include "ash/common/system/tray/tray_constants.h" @@ -20,7 +21,6 @@ #include "ash/common/system/tray/tray_popup_label_button.h" #include "ash/common/system/tray/view_click_listener.h" #include "ash/common/wm_shell.h" -#include "ash/system/tray/system_tray.h" #include "base/bind.h" #include "grit/ash_resources.h" #include "grit/ash_strings.h"
diff --git a/ash/common/system/chromeos/bluetooth/tray_bluetooth.cc b/ash/common/system/chromeos/bluetooth/tray_bluetooth.cc index cae780c..482d4f0 100644 --- a/ash/common/system/chromeos/bluetooth/tray_bluetooth.cc +++ b/ash/common/system/chromeos/bluetooth/tray_bluetooth.cc
@@ -7,6 +7,7 @@ #include "ash/common/session/session_state_delegate.h" #include "ash/common/system/tray/fixed_sized_scroll_view.h" #include "ash/common/system/tray/hover_highlight_view.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/system_tray_notifier.h" #include "ash/common/system/tray/throbber_view.h" @@ -16,7 +17,6 @@ #include "ash/common/system/tray/tray_popup_header_button.h" #include "ash/common/system/tray/view_click_listener.h" #include "ash/common/wm_shell.h" -#include "ash/system/tray/system_tray.h" #include "grit/ash_resources.h" #include "grit/ash_strings.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/ash/common/system/chromeos/media_security/multi_profile_media_tray_item.cc b/ash/common/system/chromeos/media_security/multi_profile_media_tray_item.cc new file mode 100644 index 0000000..fa32b6a --- /dev/null +++ b/ash/common/system/chromeos/media_security/multi_profile_media_tray_item.cc
@@ -0,0 +1,78 @@ +// 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. + +#include "ash/common/system/chromeos/media_security/multi_profile_media_tray_item.h" + +#include "ash/common/ash_view_ids.h" +#include "ash/common/media_delegate.h" +#include "ash/common/session/session_state_delegate.h" +#include "ash/common/system/chromeos/media_security/media_capture_observer.h" +#include "ash/common/system/tray/system_tray_notifier.h" +#include "ash/common/system/tray/tray_item_view.h" +#include "ash/common/wm_shell.h" +#include "grit/ash_resources.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/views/controls/image_view.h" +#include "ui/views/layout/fill_layout.h" + +namespace ash { +namespace tray { + +class MultiProfileMediaTrayView : public TrayItemView, + public MediaCaptureObserver { + public: + explicit MultiProfileMediaTrayView(SystemTrayItem* system_tray_item) + : TrayItemView(system_tray_item) { + SetLayoutManager(new views::FillLayout); + views::ImageView* icon = new views::ImageView; + ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); + icon->SetImage( + bundle.GetImageNamed(IDR_AURA_UBER_TRAY_RECORDING).ToImageSkia()); + AddChildView(icon); + OnMediaCaptureChanged(); + WmShell::Get()->system_tray_notifier()->AddMediaCaptureObserver(this); + set_id(VIEW_ID_MEDIA_TRAY_VIEW); + } + + ~MultiProfileMediaTrayView() override { + WmShell::Get()->system_tray_notifier()->RemoveMediaCaptureObserver(this); + } + + // MediaCaptureObserver: + void OnMediaCaptureChanged() override { + MediaDelegate* media_delegate = WmShell::Get()->media_delegate(); + SessionStateDelegate* session_state_delegate = + WmShell::Get()->GetSessionStateDelegate(); + // The user at 0 is the current desktop user. + for (UserIndex index = 1; + index < session_state_delegate->NumberOfLoggedInUsers(); ++index) { + if (media_delegate->GetMediaCaptureState(index) != MEDIA_CAPTURE_NONE) { + SetVisible(true); + return; + } + } + SetVisible(false); + } + + private: + DISALLOW_COPY_AND_ASSIGN(MultiProfileMediaTrayView); +}; + +} // namespace tray + +MultiProfileMediaTrayItem::MultiProfileMediaTrayItem(SystemTray* system_tray) + : SystemTrayItem(system_tray), tray_view_(nullptr) {} + +MultiProfileMediaTrayItem::~MultiProfileMediaTrayItem() {} + +views::View* MultiProfileMediaTrayItem::CreateTrayView(LoginStatus status) { + tray_view_ = new tray::MultiProfileMediaTrayView(this); + return tray_view_; +} + +void MultiProfileMediaTrayItem::DestroyTrayView() { + tray_view_ = nullptr; +} + +} // namespace ash
diff --git a/ash/common/system/chromeos/media_security/multi_profile_media_tray_item.h b/ash/common/system/chromeos/media_security/multi_profile_media_tray_item.h new file mode 100644 index 0000000..7d985d1 --- /dev/null +++ b/ash/common/system/chromeos/media_security/multi_profile_media_tray_item.h
@@ -0,0 +1,35 @@ +// 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 ASH_COMMON_SYSTEM_CHROMEOS_MEDIA_SECURITY_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_ +#define ASH_COMMON_SYSTEM_CHROMEOS_MEDIA_SECURITY_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_ + +#include "ash/common/system/tray/system_tray_item.h" +#include "base/macros.h" + +namespace ash { + +namespace tray { +class MultiProfileMediaTrayView; +} + +// The tray item for media recording. +class ASH_EXPORT MultiProfileMediaTrayItem : public SystemTrayItem { + public: + explicit MultiProfileMediaTrayItem(SystemTray* system_tray); + ~MultiProfileMediaTrayItem() override; + + // SystemTrayItem: + views::View* CreateTrayView(LoginStatus status) override; + void DestroyTrayView() override; + + private: + tray::MultiProfileMediaTrayView* tray_view_; + + DISALLOW_COPY_AND_ASSIGN(MultiProfileMediaTrayItem); +}; + +} // namespace ash + +#endif // ASH_COMMON_SYSTEM_CHROMEOS_MEDIA_SECURITY_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_
diff --git a/ash/common/system/chromeos/network/network_state_list_detailed_view.cc b/ash/common/system/chromeos/network/network_state_list_detailed_view.cc index e2a64ed7..b946ab5 100644 --- a/ash/common/system/chromeos/network/network_state_list_detailed_view.cc +++ b/ash/common/system/chromeos/network/network_state_list_detailed_view.cc
@@ -16,6 +16,7 @@ #include "ash/common/system/tray/fixed_sized_image_view.h" #include "ash/common/system/tray/fixed_sized_scroll_view.h" #include "ash/common/system/tray/hover_highlight_view.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/throbber_view.h" #include "ash/common/system/tray/tray_constants.h" @@ -26,7 +27,6 @@ #include "ash/common/wm_root_window_controller.h" #include "ash/common/wm_shell.h" #include "ash/common/wm_window.h" -#include "ash/system/tray/system_tray.h" #include "base/command_line.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h"
diff --git a/ash/common/system/chromeos/network/tray_network.cc b/ash/common/system/chromeos/network/tray_network.cc index 77adb96..318b5eb 100644 --- a/ash/common/system/chromeos/network/tray_network.cc +++ b/ash/common/system/chromeos/network/tray_network.cc
@@ -8,6 +8,7 @@ #include "ash/common/shelf/wm_shelf_util.h" #include "ash/common/system/chromeos/network/network_state_list_detailed_view.h" #include "ash/common/system/chromeos/network/tray_network_state_observer.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/system_tray_notifier.h" #include "ash/common/system/tray/tray_constants.h" @@ -15,7 +16,6 @@ #include "ash/common/system/tray/tray_item_view.h" #include "ash/common/system/tray/tray_utils.h" #include "ash/common/wm_shell.h" -#include "ash/system/tray/system_tray.h" #include "base/command_line.h" #include "base/strings/utf_string_conversions.h" #include "chromeos/network/network_state.h"
diff --git a/ash/common/system/chromeos/network/tray_network_state_observer.cc b/ash/common/system/chromeos/network/tray_network_state_observer.cc index 25cfa01..549401ad 100644 --- a/ash/common/system/chromeos/network/tray_network_state_observer.cc +++ b/ash/common/system/chromeos/network/tray_network_state_observer.cc
@@ -7,7 +7,7 @@ #include <set> #include <string> -#include "ash/system/tray/system_tray.h" +#include "ash/common/system/tray/system_tray.h" #include "base/location.h" #include "chromeos/network/network_state.h" #include "chromeos/network/network_state_handler.h"
diff --git a/ash/common/system/chromeos/network/tray_sms.cc b/ash/common/system/chromeos/network/tray_sms.cc index ddbafaa..77e58cad 100644 --- a/ash/common/system/chromeos/network/tray_sms.cc +++ b/ash/common/system/chromeos/network/tray_sms.cc
@@ -7,6 +7,7 @@ #include "ash/common/material_design/material_design_controller.h" #include "ash/common/metrics/user_metrics_action.h" #include "ash/common/system/tray/fixed_sized_scroll_view.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_bubble.h" #include "ash/common/system/tray/tray_constants.h" #include "ash/common/system/tray/tray_details_view.h" @@ -15,7 +16,6 @@ #include "ash/common/system/tray/tray_notification_view.h" #include "ash/common/system/tray/view_click_listener.h" #include "ash/common/wm_shell.h" -#include "ash/system/tray/system_tray.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "chromeos/network/network_event_log.h"
diff --git a/ash/common/system/chromeos/network/tray_vpn.cc b/ash/common/system/chromeos/network/tray_vpn.cc index ac40d94..ac80f52 100644 --- a/ash/common/system/chromeos/network/tray_vpn.cc +++ b/ash/common/system/chromeos/network/tray_vpn.cc
@@ -7,12 +7,12 @@ #include "ash/common/session/session_state_delegate.h" #include "ash/common/system/chromeos/network/network_state_list_detailed_view.h" #include "ash/common/system/chromeos/network/vpn_delegate.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/tray_constants.h" #include "ash/common/system/tray/tray_item_more.h" #include "ash/common/system/tray/tray_popup_label_button.h" #include "ash/common/wm_shell.h" -#include "ash/system/tray/system_tray.h" #include "chromeos/network/network_state.h" #include "chromeos/network/network_state_handler.h" #include "grit/ash_strings.h"
diff --git a/ash/common/system/chromeos/screen_security/screen_tray_item.h b/ash/common/system/chromeos/screen_security/screen_tray_item.h index 817e65af..8d01d2fd 100644 --- a/ash/common/system/chromeos/screen_security/screen_tray_item.h +++ b/ash/common/system/chromeos/screen_security/screen_tray_item.h
@@ -7,11 +7,11 @@ #include <string> +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_item.h" #include "ash/common/system/tray/tray_item_view.h" #include "ash/common/system/tray/tray_notification_view.h" #include "ash/common/system/tray/tray_popup_label_button.h" -#include "ash/system/tray/system_tray.h" #include "base/macros.h" #include "ui/message_center/notification_delegate.h" #include "ui/views/controls/button/button.h"
diff --git a/ash/common/system/chromeos/session/tray_session_length_limit.cc b/ash/common/system/chromeos/session/tray_session_length_limit.cc index da59774f..766b142 100644 --- a/ash/common/system/chromeos/session/tray_session_length_limit.cc +++ b/ash/common/system/chromeos/session/tray_session_length_limit.cc
@@ -10,10 +10,10 @@ #include "ash/common/system/system_notifier.h" #include "ash/common/system/tray/label_tray_view.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/system_tray_notifier.h" #include "ash/common/wm_shell.h" -#include "ash/system/tray/system_tray.h" #include "base/logging.h" #include "base/strings/utf_string_conversions.h" #include "grit/ash_resources.h"
diff --git a/ash/common/system/chromeos/session/tray_session_length_limit_unittest.cc b/ash/common/system/chromeos/session/tray_session_length_limit_unittest.cc index 64132cc..092aa8ca 100644 --- a/ash/common/system/chromeos/session/tray_session_length_limit_unittest.cc +++ b/ash/common/system/chromeos/session/tray_session_length_limit_unittest.cc
@@ -4,7 +4,7 @@ #include "ash/common/system/chromeos/session/tray_session_length_limit.h" -#include "ash/system/tray/system_tray.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/test/ash_test_base.h" #include "ash/test/test_system_tray_delegate.h" #include "base/time/time.h"
diff --git a/ash/common/system/chromeos/tray_tracing.cc b/ash/common/system/chromeos/tray_tracing.cc index 54fef40f..011feb6 100644 --- a/ash/common/system/chromeos/tray_tracing.cc +++ b/ash/common/system/chromeos/tray_tracing.cc
@@ -8,11 +8,11 @@ #include "ash/common/metrics/user_metrics_action.h" #include "ash/common/system/tray/actionable_view.h" #include "ash/common/system/tray/fixed_sized_image_view.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/system_tray_notifier.h" #include "ash/common/system/tray/tray_constants.h" #include "ash/common/wm_shell.h" -#include "ash/system/tray/system_tray.h" #include "grit/ash_resources.h" #include "grit/ash_strings.h" #include "ui/base/resource/resource_bundle.h"
diff --git a/ash/common/system/date/tray_date.cc b/ash/common/system/date/tray_date.cc index 87047e3..d2c0ec5 100644 --- a/ash/common/system/date/tray_date.cc +++ b/ash/common/system/date/tray_date.cc
@@ -7,10 +7,10 @@ #include "ash/common/shelf/wm_shelf_util.h" #include "ash/common/system/date/date_default_view.h" #include "ash/common/system/date/date_view.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_notifier.h" #include "ash/common/system/tray/tray_item_view.h" #include "ash/common/wm_shell.h" -#include "ash/system/tray/system_tray.h" #if defined(OS_CHROMEOS) #include "ash/common/system/chromeos/system_clock_observer.h"
diff --git a/ash/common/system/ime/tray_ime_chromeos.cc b/ash/common/system/ime/tray_ime_chromeos.cc index 32d448c..f0f08ded 100644 --- a/ash/common/system/ime/tray_ime_chromeos.cc +++ b/ash/common/system/ime/tray_ime_chromeos.cc
@@ -8,6 +8,7 @@ #include "ash/common/session/session_state_delegate.h" #include "ash/common/system/tray/hover_highlight_view.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/system_tray_notifier.h" #include "ash/common/system/tray/tray_constants.h" @@ -17,7 +18,6 @@ #include "ash/common/system/tray/tray_utils.h" #include "ash/common/system/tray_accessibility.h" #include "ash/common/wm_shell.h" -#include "ash/system/tray/system_tray.h" #include "base/logging.h" #include "base/strings/utf_string_conversions.h" #include "grit/ash_resources.h"
diff --git a/ash/common/system/ime/tray_ime_chromeos_unittest.cc b/ash/common/system/ime/tray_ime_chromeos_unittest.cc index 87f1b42..5c7617d1 100644 --- a/ash/common/system/ime/tray_ime_chromeos_unittest.cc +++ b/ash/common/system/ime/tray_ime_chromeos_unittest.cc
@@ -10,8 +10,8 @@ #include "ash/common/system/tray/tray_details_view.h" #include "ash/common/wm_shell.h" #include "ash/test/ash_test_base.h" -#include "ash/test/virtual_keyboard_test_helper.h" #include "base/command_line.h" +#include "ui/events/devices/device_data_manager.h" #include "ui/keyboard/keyboard_util.h" namespace ash { @@ -38,6 +38,9 @@ // index. views::View* GetScrollChildView(int index); + void SuppressKeyboard(); + void RestoreKeyboard(); + // test::AshTestBase: void SetUp() override; void TearDown() override; @@ -46,6 +49,12 @@ std::unique_ptr<TrayIME> tray_; std::unique_ptr<views::View> default_view_; std::unique_ptr<views::View> detailed_view_; + + bool keyboard_suppressed_ = false; + std::vector<ui::TouchscreenDevice> touchscreen_devices_to_restore_; + std::vector<ui::InputDevice> keyboard_devices_to_restore_; + + DISALLOW_COPY_AND_ASSIGN(TrayIMETest); }; void TrayIMETest::SetAccessibilityKeyboardEnabled(bool enabled) { @@ -75,6 +84,36 @@ return content->child_at(index); } +void TrayIMETest::SuppressKeyboard() { + DCHECK(!keyboard_suppressed_); + keyboard_suppressed_ = true; + + ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance(); + touchscreen_devices_to_restore_ = device_manager->GetTouchscreenDevices(); + keyboard_devices_to_restore_ = device_manager->GetKeyboardDevices(); + + ui::DeviceHotplugEventObserver* manager = + ui::DeviceDataManager::GetInstance(); + std::vector<ui::TouchscreenDevice> screens; + screens.push_back( + ui::TouchscreenDevice(1, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, + "Touchscreen", gfx::Size(1024, 768), 0)); + manager->OnTouchscreenDevicesUpdated(screens); + + std::vector<ui::InputDevice> keyboards; + keyboards.push_back(ui::InputDevice( + 2, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, "keyboard")); + manager->OnKeyboardDevicesUpdated(keyboards); +} + +void TrayIMETest::RestoreKeyboard() { + DCHECK(keyboard_suppressed_); + ui::DeviceHotplugEventObserver* manager = + ui::DeviceDataManager::GetInstance(); + manager->OnTouchscreenDevicesUpdated(touchscreen_devices_to_restore_); + manager->OnKeyboardDevicesUpdated(keyboard_devices_to_restore_); +} + void TrayIMETest::SetUp() { test::AshTestBase::SetUp(); tray_.reset(new TrayIME(GetPrimarySystemTray())); @@ -83,6 +122,8 @@ } void TrayIMETest::TearDown() { + if (keyboard_suppressed_) + RestoreKeyboard(); SetAccessibilityKeyboardEnabled(false); tray_.reset(); default_view_.reset(); @@ -105,7 +146,7 @@ // enabled. TEST_F(TrayIMETest, HidesOnA11yEnabled) { SetIMELength(0); - test::VirtualKeyboardTestHelper::SuppressKeyboard(); + SuppressKeyboard(); EXPECT_TRUE(default_view()->visible()); // Enable a11y keyboard. SetAccessibilityKeyboardEnabled(true); @@ -119,7 +160,7 @@ // to toggle between enabled and disabled. TEST_F(TrayIMETest, PerformActionOnDetailedView) { SetIMELength(0); - test::VirtualKeyboardTestHelper::SuppressKeyboard(); + SuppressKeyboard(); EXPECT_FALSE(keyboard::IsKeyboardEnabled()); views::View* toggle = GetScrollChildView(0); ui::GestureEvent tap(0, 0, 0, base::TimeTicks(),
diff --git a/ash/common/system/status_area_widget.cc b/ash/common/system/status_area_widget.cc new file mode 100644 index 0000000..a74c1457 --- /dev/null +++ b/ash/common/system/status_area_widget.cc
@@ -0,0 +1,208 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/common/system/status_area_widget.h" + +#include "ash/common/shelf/wm_shelf.h" +#include "ash/common/shell_window_ids.h" +#include "ash/common/system/overview/overview_button_tray.h" +#include "ash/common/system/status_area_widget_delegate.h" +#include "ash/common/system/tray/system_tray.h" +#include "ash/common/system/tray/system_tray_delegate.h" +#include "ash/common/system/web_notification/web_notification_tray.h" +#include "ash/common/wm_lookup.h" +#include "ash/common/wm_root_window_controller.h" +#include "ash/common/wm_shell.h" +#include "ash/common/wm_window.h" +#include "base/i18n/time_formatting.h" + +#if defined(OS_CHROMEOS) +#include "ash/common/system/chromeos/session/logout_button_tray.h" +#include "ash/common/system/chromeos/virtual_keyboard/virtual_keyboard_tray.h" +#endif + +namespace ash { + +StatusAreaWidget::StatusAreaWidget(WmWindow* status_container, + WmShelf* wm_shelf) + : status_area_widget_delegate_(new StatusAreaWidgetDelegate), + overview_button_tray_(NULL), + system_tray_(NULL), + web_notification_tray_(NULL), +#if defined(OS_CHROMEOS) + logout_button_tray_(NULL), + virtual_keyboard_tray_(NULL), +#endif + login_status_(LoginStatus::NOT_LOGGED_IN), + wm_shelf_(wm_shelf) { + views::Widget::InitParams params( + views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); + params.delegate = status_area_widget_delegate_; + params.name = "StatusAreaWidget"; + params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; + status_container->GetRootWindowController() + ->ConfigureWidgetInitParamsForContainer( + this, status_container->GetShellWindowId(), ¶ms); + Init(params); + set_focus_on_creation(false); + SetContentsView(status_area_widget_delegate_); +} + +StatusAreaWidget::~StatusAreaWidget() {} + +void StatusAreaWidget::CreateTrayViews() { + AddOverviewButtonTray(); + AddSystemTray(); + AddWebNotificationTray(); +#if defined(OS_CHROMEOS) + AddLogoutButtonTray(); + AddVirtualKeyboardTray(); +#endif + + SystemTrayDelegate* delegate = WmShell::Get()->system_tray_delegate(); + DCHECK(delegate); + // Initialize after all trays have been created. + system_tray_->InitializeTrayItems(delegate, web_notification_tray_); + web_notification_tray_->Initialize(); +#if defined(OS_CHROMEOS) + logout_button_tray_->Initialize(); + virtual_keyboard_tray_->Initialize(); +#endif + overview_button_tray_->Initialize(); + SetShelfAlignment(system_tray_->shelf_alignment()); + UpdateAfterLoginStatusChange(delegate->GetUserLoginStatus()); +} + +void StatusAreaWidget::Shutdown() { + system_tray_->Shutdown(); + // Destroy the trays early, causing them to be removed from the view + // hierarchy. Do not used scoped pointers since we don't want to destroy them + // in the destructor if Shutdown() is not called (e.g. in tests). + delete web_notification_tray_; + web_notification_tray_ = NULL; + // Must be destroyed after |web_notification_tray_|. + delete system_tray_; + system_tray_ = NULL; +#if defined(OS_CHROMEOS) + delete virtual_keyboard_tray_; + virtual_keyboard_tray_ = NULL; + delete logout_button_tray_; + logout_button_tray_ = NULL; +#endif + delete overview_button_tray_; + overview_button_tray_ = NULL; +} + +bool StatusAreaWidget::ShouldShowShelf() const { + if ((system_tray_ && system_tray_->ShouldShowShelf()) || + (web_notification_tray_ && + web_notification_tray_->ShouldBlockShelfAutoHide())) + return true; + + if (!wm_shelf_->IsVisible()) + return false; + + // If the shelf is currently visible, don't hide the shelf if the mouse + // is in any of the notification bubbles. + return (system_tray_ && system_tray_->IsMouseInNotificationBubble()) || + (web_notification_tray_ && + web_notification_tray_->IsMouseInNotificationBubble()); +} + +bool StatusAreaWidget::IsMessageBubbleShown() const { + return ((system_tray_ && system_tray_->IsAnyBubbleVisible()) || + (web_notification_tray_ && + web_notification_tray_->IsMessageCenterBubbleVisible())); +} + +void StatusAreaWidget::SchedulePaint() { + status_area_widget_delegate_->SchedulePaint(); + web_notification_tray_->SchedulePaint(); + system_tray_->SchedulePaint(); +#if defined(OS_CHROMEOS) + virtual_keyboard_tray_->SchedulePaint(); + logout_button_tray_->SchedulePaint(); +#endif + overview_button_tray_->SchedulePaint(); +} + +void StatusAreaWidget::OnNativeWidgetActivationChanged(bool active) { + Widget::OnNativeWidgetActivationChanged(active); + if (active) + status_area_widget_delegate_->SetPaneFocusAndFocusDefault(); +} + +void StatusAreaWidget::OnMouseEvent(ui::MouseEvent* event) { + Widget::OnMouseEvent(event); + wm_shelf_->UpdateAutoHideForMouseEvent(event); +} + +void StatusAreaWidget::OnGestureEvent(ui::GestureEvent* event) { + Widget::OnGestureEvent(event); + wm_shelf_->UpdateAutoHideForGestureEvent(event); +} + +void StatusAreaWidget::AddSystemTray() { + system_tray_ = new SystemTray(wm_shelf_); + status_area_widget_delegate_->AddTray(system_tray_); +} + +void StatusAreaWidget::AddWebNotificationTray() { + DCHECK(system_tray_); + web_notification_tray_ = new WebNotificationTray( + wm_shelf_, WmLookup::Get()->GetWindowForWidget(this), system_tray_); + status_area_widget_delegate_->AddTray(web_notification_tray_); +} + +#if defined(OS_CHROMEOS) +void StatusAreaWidget::AddLogoutButtonTray() { + logout_button_tray_ = new LogoutButtonTray(wm_shelf_); + status_area_widget_delegate_->AddTray(logout_button_tray_); +} + +void StatusAreaWidget::AddVirtualKeyboardTray() { + virtual_keyboard_tray_ = new VirtualKeyboardTray(wm_shelf_); + status_area_widget_delegate_->AddTray(virtual_keyboard_tray_); +} +#endif + +void StatusAreaWidget::AddOverviewButtonTray() { + overview_button_tray_ = new OverviewButtonTray(wm_shelf_); + status_area_widget_delegate_->AddTray(overview_button_tray_); +} + +void StatusAreaWidget::SetShelfAlignment(ShelfAlignment alignment) { + status_area_widget_delegate_->set_alignment(alignment); + if (system_tray_) + system_tray_->SetShelfAlignment(alignment); + if (web_notification_tray_) + web_notification_tray_->SetShelfAlignment(alignment); +#if defined(OS_CHROMEOS) + if (logout_button_tray_) + logout_button_tray_->SetShelfAlignment(alignment); + if (virtual_keyboard_tray_) + virtual_keyboard_tray_->SetShelfAlignment(alignment); +#endif + if (overview_button_tray_) + overview_button_tray_->SetShelfAlignment(alignment); + status_area_widget_delegate_->UpdateLayout(); +} + +void StatusAreaWidget::UpdateAfterLoginStatusChange(LoginStatus login_status) { + if (login_status_ == login_status) + return; + login_status_ = login_status; + if (system_tray_) + system_tray_->UpdateAfterLoginStatusChange(login_status); + if (web_notification_tray_) + web_notification_tray_->UpdateAfterLoginStatusChange(login_status); +#if defined(OS_CHROMEOS) + if (logout_button_tray_) + logout_button_tray_->UpdateAfterLoginStatusChange(login_status); +#endif + if (overview_button_tray_) + overview_button_tray_->UpdateAfterLoginStatusChange(login_status); +} + +} // namespace ash
diff --git a/ash/common/system/status_area_widget.h b/ash/common/system/status_area_widget.h new file mode 100644 index 0000000..8fa40c4 --- /dev/null +++ b/ash/common/system/status_area_widget.h
@@ -0,0 +1,103 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_COMMON_SYSTEM_STATUS_AREA_WIDGET_H_ +#define ASH_COMMON_SYSTEM_STATUS_AREA_WIDGET_H_ + +#include "ash/ash_export.h" +#include "ash/common/login_status.h" +#include "ash/common/shelf/shelf_types.h" +#include "base/macros.h" +#include "ui/views/widget/widget.h" + +namespace ash { +class OverviewButtonTray; +class ShellDelegate; +class StatusAreaWidgetDelegate; +class SystemTray; +class WebNotificationTray; +class WmShelf; +class WmWindow; +#if defined(OS_CHROMEOS) +class LogoutButtonTray; +class VirtualKeyboardTray; +#endif + +class ASH_EXPORT StatusAreaWidget : public views::Widget { + public: + StatusAreaWidget(WmWindow* status_container, WmShelf* wm_shelf); + ~StatusAreaWidget() override; + + // Creates the SystemTray, WebNotificationTray and LogoutButtonTray. + void CreateTrayViews(); + + // Destroys the system tray and web notification tray. Called before + // tearing down the windows to avoid shutdown ordering issues. + void Shutdown(); + + // Update the alignment of the widget and tray views. + void SetShelfAlignment(ShelfAlignment alignment); + + // Called by the client when the login status changes. Caches login_status + // and calls UpdateAfterLoginStatusChange for the system tray and the web + // notification tray. + void UpdateAfterLoginStatusChange(LoginStatus login_status); + + StatusAreaWidgetDelegate* status_area_widget_delegate() { + return status_area_widget_delegate_; + } + SystemTray* system_tray() { return system_tray_; } + WebNotificationTray* web_notification_tray() { + return web_notification_tray_; + } + OverviewButtonTray* overview_button_tray() { return overview_button_tray_; } + WmShelf* wm_shelf() { return wm_shelf_; } + + LoginStatus login_status() const { return login_status_; } + + // Returns true if the shelf should be visible. This is used when the + // shelf is configured to auto-hide and test if the shelf should force + // the shelf to remain visible. + bool ShouldShowShelf() const; + + // True if any message bubble is shown. + bool IsMessageBubbleShown() const; + + // Notifies child trays, and the |status_area_widget_delegate_| to schedule a + // paint. + void SchedulePaint(); + + // Overridden from views::Widget: + void OnNativeWidgetActivationChanged(bool active) override; + void OnMouseEvent(ui::MouseEvent* event) override; + void OnGestureEvent(ui::GestureEvent* event) override; + + private: + void AddSystemTray(); + void AddWebNotificationTray(); +#if defined(OS_CHROMEOS) + void AddLogoutButtonTray(); + void AddVirtualKeyboardTray(); +#endif + void AddOverviewButtonTray(); + + // Weak pointers to View classes that are parented to StatusAreaWidget: + StatusAreaWidgetDelegate* status_area_widget_delegate_; + OverviewButtonTray* overview_button_tray_; + SystemTray* system_tray_; + WebNotificationTray* web_notification_tray_; +#if defined(OS_CHROMEOS) + LogoutButtonTray* logout_button_tray_; + VirtualKeyboardTray* virtual_keyboard_tray_; +#endif + LoginStatus login_status_; + + WmShelf* wm_shelf_; + + DISALLOW_COPY_AND_ASSIGN(StatusAreaWidget); +}; + +} // namespace ash + +#endif // ASH_COMMON_SYSTEM_STATUS_AREA_WIDGET_H_
diff --git a/ash/common/system/system_notifier.cc b/ash/common/system/system_notifier.cc index 94472e9..b85815e 100644 --- a/ash/common/system/system_notifier.cc +++ b/ash/common/system/system_notifier.cc
@@ -77,6 +77,7 @@ const char kNotifierMultiProfileFirstRun[] = "ash.multi-profile.first-run"; const char kNotifierNetworkPortalDetector[] = "ash.network.portal-detector"; const char kNotifierPower[] = "ash.power"; +const char kNotifierQuickUnlock[] = "ash.quickunlock"; const char kNotifierScreenshot[] = "ash.screenshot"; const char kNotifierScreenCapture[] = "ash.screen-capture"; const char kNotifierScreenShare[] = "ash.screen-share";
diff --git a/ash/common/system/system_notifier.h b/ash/common/system/system_notifier.h index dc5dfd1..e8bbb30 100644 --- a/ash/common/system/system_notifier.h +++ b/ash/common/system/system_notifier.h
@@ -29,6 +29,7 @@ ASH_EXPORT extern const char kNotifierNetworkError[]; ASH_EXPORT extern const char kNotifierNetworkPortalDetector[]; ASH_EXPORT extern const char kNotifierPower[]; +ASH_EXPORT extern const char kNotifierQuickUnlock[]; ASH_EXPORT extern const char kNotifierScreenshot[]; ASH_EXPORT extern const char kNotifierScreenCapture[]; ASH_EXPORT extern const char kNotifierScreenShare[];
diff --git a/ash/system/toast/OWNERS b/ash/common/system/toast/OWNERS similarity index 100% rename from ash/system/toast/OWNERS rename to ash/common/system/toast/OWNERS
diff --git a/ash/common/system/toast/toast_data.cc b/ash/common/system/toast/toast_data.cc new file mode 100644 index 0000000..5fec6c7 --- /dev/null +++ b/ash/common/system/toast/toast_data.cc
@@ -0,0 +1,22 @@ +// 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 "ash/common/system/toast/toast_data.h" + +#include <utility> + +namespace ash { + +ToastData::ToastData(std::string id, + std::string text, + int32_t duration_ms, + std::string dismiss_text) + : id(std::move(id)), + text(std::move(text)), + duration_ms(duration_ms), + dismiss_text(std::move(dismiss_text)) {} + +ToastData::ToastData(const ToastData& other) = default; + +} // namespace ash
diff --git a/ash/common/system/toast/toast_data.h b/ash/common/system/toast/toast_data.h new file mode 100644 index 0000000..66f6e474 --- /dev/null +++ b/ash/common/system/toast/toast_data.h
@@ -0,0 +1,33 @@ +// 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 ASH_COMMON_SYSTEM_TOAST_TOAST_DATA_H_ +#define ASH_COMMON_SYSTEM_TOAST_TOAST_DATA_H_ + +#include <string> + +#include "ash/ash_export.h" + +namespace ash { + +struct ASH_EXPORT ToastData { + // "|duration_ms| == -1" means the toast view should be displayed until the + // dismiss button is clicked. + static const int32_t kInfiniteDuration = -1; + + ToastData(std::string id, + std::string text, + int32_t duration_ms, + std::string dismiss_text); + ToastData(const ToastData& other); + + std::string id; + std::string text; + int32_t duration_ms; + std::string dismiss_text; +}; + +} // namespace ash + +#endif // ASH_COMMON_SYSTEM_TOAST_TOAST_DATA_H_
diff --git a/ash/common/system/toast/toast_manager.cc b/ash/common/system/toast/toast_manager.cc new file mode 100644 index 0000000..37a9ea2 --- /dev/null +++ b/ash/common/system/toast/toast_manager.cc
@@ -0,0 +1,97 @@ +// 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 "ash/common/system/toast/toast_manager.h" + +#include <algorithm> + +#include "base/bind.h" +#include "base/location.h" +#include "base/threading/thread_task_runner_handle.h" + +namespace ash { + +namespace { + +// Minimum duration for a toast to be visible (in millisecond). +const int32_t kMinimumDurationMs = 200; + +} // anonymous namespace + +ToastManager::ToastManager() : weak_ptr_factory_(this) {} + +ToastManager::~ToastManager() {} + +void ToastManager::Show(const ToastData& data) { + const std::string& id = data.id; + DCHECK(!id.empty()); + + if (current_toast_id_ == id) { + // TODO(yoshiki): Replaces the visible toast. + return; + } + + auto existing_toast = + std::find_if(queue_.begin(), queue_.end(), + [&id](const ToastData& data) { return data.id == id; }); + + if (existing_toast == queue_.end()) { + queue_.emplace_back(data); + } else { + *existing_toast = data; + } + + if (queue_.size() == 1 && overlay_ == nullptr) + ShowLatest(); +} + +void ToastManager::Cancel(const std::string& id) { + if (id == current_toast_id_) { + overlay_->Show(false); + return; + } + + auto cancelled_toast = + std::find_if(queue_.begin(), queue_.end(), + [&id](const ToastData& data) { return data.id == id; }); + if (cancelled_toast != queue_.end()) + queue_.erase(cancelled_toast); +} + +void ToastManager::OnClosed() { + overlay_.reset(); + current_toast_id_.clear(); + + // Show the next toast if available. + if (!queue_.empty()) + ShowLatest(); +} + +void ToastManager::ShowLatest() { + DCHECK(!overlay_); + + const ToastData data = std::move(queue_.front()); + queue_.pop_front(); + + current_toast_id_ = data.id; + serial_++; + + overlay_.reset(new ToastOverlay(this, data.text, data.dismiss_text)); + overlay_->Show(true); + + if (data.duration_ms != ToastData::kInfiniteDuration) { + int32_t duration_ms = std::max(data.duration_ms, kMinimumDurationMs); + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, base::Bind(&ToastManager::OnDurationPassed, + weak_ptr_factory_.GetWeakPtr(), serial_), + base::TimeDelta::FromMilliseconds(duration_ms)); + } +} + +void ToastManager::OnDurationPassed(int toast_number) { + if (overlay_ && serial_ == toast_number) + overlay_->Show(false); +} + +} // namespace ash
diff --git a/ash/common/system/toast/toast_manager.h b/ash/common/system/toast/toast_manager.h new file mode 100644 index 0000000..26b72a68 --- /dev/null +++ b/ash/common/system/toast/toast_manager.h
@@ -0,0 +1,58 @@ +// 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 ASH_COMMON_SYSTEM_TOAST_TOAST_MANAGER_H_ +#define ASH_COMMON_SYSTEM_TOAST_TOAST_MANAGER_H_ + +#include <deque> +#include <memory> +#include <string> + +#include "ash/ash_export.h" +#include "ash/common/system/toast/toast_data.h" +#include "ash/common/system/toast/toast_overlay.h" +#include "base/memory/weak_ptr.h" + +namespace ash { + +// Class managing toast requests. +class ASH_EXPORT ToastManager : public ToastOverlay::Delegate { + public: + ToastManager(); + ~ToastManager() override; + + // Show a toast. If there are queued toasts, succeeding toasts are queued as + // well, and are shown one by one. + void Show(const ToastData& data); + + void Cancel(const std::string& id); + + // ToastOverlay::Delegate overrides: + void OnClosed() override; + + private: + friend class ToastManagerTest; + + void ShowLatest(); + void OnDurationPassed(int toast_number); + + ToastOverlay* GetCurrentOverlayForTesting() { return overlay_.get(); } + int serial_for_testing() const { return serial_; } + void ResetSerialForTesting() { serial_ = 0; } + + // ID of the toast which is currently shown. Empty if no toast is visible. + std::string current_toast_id_; + + int serial_ = 0; + std::deque<ToastData> queue_; + std::unique_ptr<ToastOverlay> overlay_; + + base::WeakPtrFactory<ToastManager> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(ToastManager); +}; + +} // namespace ash + +#endif // ASH_COMMON_SYSTEM_TOAST_TOAST_MANAGER_H_
diff --git a/ash/common/system/toast/toast_overlay.cc b/ash/common/system/toast/toast_overlay.cc new file mode 100644 index 0000000..87d49c6 --- /dev/null +++ b/ash/common/system/toast/toast_overlay.cc
@@ -0,0 +1,298 @@ +// 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 "ash/common/system/toast/toast_overlay.h" + +#include "ash/common/shelf/wm_shelf.h" +#include "ash/common/shell_window_ids.h" +#include "ash/common/wm_lookup.h" +#include "ash/common/wm_root_window_controller.h" +#include "ash/common/wm_shell.h" +#include "ash/common/wm_window.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/threading/thread_task_runner_handle.h" +#include "grit/ash_strings.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/font_list.h" +#include "ui/views/border.h" +#include "ui/views/controls/button/label_button.h" +#include "ui/views/controls/label.h" +#include "ui/views/layout/box_layout.h" +#include "ui/views/view.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_delegate.h" +#include "ui/wm/core/window_animations.h" + +namespace ash { + +namespace { + +// Offset of the overlay from the edge of the work area. +const int kOffset = 5; + +// Font style used for modifier key labels. +const ui::ResourceBundle::FontStyle kTextFontStyle = + ui::ResourceBundle::MediumFont; + +// Duration of slide animation when overlay is shown or hidden. +const int kSlideAnimationDurationMs = 100; + +// Colors for the dismiss button. +const SkColor kButtonBackgroundColor = SkColorSetARGB(0xFF, 0x32, 0x32, 0x32); +const SkColor kButtonTextColor = SkColorSetARGB(0xFF, 0x7B, 0xAA, 0xF7); + +// These values are in DIP. +const int kToastHorizontalSpacing = 16; +const int kToastVerticalSpacing = 16; +const int kToastMaximumWidth = 568; +const int kToastMinimumWidth = 288; + +// Returns the work area bounds for the root window where new windows are added +// (including new toasts). +gfx::Rect GetUserWorkAreaBounds() { + return WmShell::Get() + ->GetRootWindowForNewWindows() + ->GetRootWindowController() + ->GetShelf() + ->GetUserWorkAreaBounds(); +} + +} // anonymous namespace + +/////////////////////////////////////////////////////////////////////////////// +// ToastOverlayLabel +class ToastOverlayLabel : public views::Label { + public: + explicit ToastOverlayLabel(const std::string& label); + ~ToastOverlayLabel() override; + + private: + DISALLOW_COPY_AND_ASSIGN(ToastOverlayLabel); +}; + +ToastOverlayLabel::ToastOverlayLabel(const std::string& label) { + ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); + + SetText(base::UTF8ToUTF16(label)); + SetHorizontalAlignment(gfx::ALIGN_LEFT); + SetFontList(rb->GetFontList(kTextFontStyle)); + SetAutoColorReadabilityEnabled(false); + SetMultiLine(true); + SetEnabledColor(SK_ColorWHITE); + SetDisabledColor(SK_ColorWHITE); + SetSubpixelRenderingEnabled(false); + + int verticalSpacing = + kToastVerticalSpacing - (GetPreferredSize().height() - GetBaseline()); + SetBorder(views::Border::CreateEmptyBorder( + verticalSpacing, kToastHorizontalSpacing, verticalSpacing, + kToastHorizontalSpacing)); +} + +ToastOverlayLabel::~ToastOverlayLabel() {} + +/////////////////////////////////////////////////////////////////////////////// +// ToastOverlayButton +class ToastOverlayButton : public views::LabelButton { + public: + explicit ToastOverlayButton(views::ButtonListener* listener, + const base::string16& label); + ~ToastOverlayButton() override {} + + private: + friend class ToastOverlay; // for ToastOverlay::ClickDismissButtonForTesting. + + DISALLOW_COPY_AND_ASSIGN(ToastOverlayButton); +}; + +ToastOverlayButton::ToastOverlayButton(views::ButtonListener* listener, + const base::string16& text) + : views::LabelButton(listener, text) { + SetInkDropMode(InkDropMode::ON); + set_has_ink_drop_action_on_click(true); + set_ink_drop_base_color(SK_ColorWHITE); + + ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); + + SetEnabledTextColors(kButtonTextColor); + SetFontList(rb->GetFontList(kTextFontStyle)); + + // Treat the space below the baseline as a margin. + int verticalSpacing = kToastVerticalSpacing - + (GetPreferredSize().height() - label()->GetBaseline()); + SetBorder(views::Border::CreateEmptyBorder( + verticalSpacing, kToastHorizontalSpacing, verticalSpacing, + kToastHorizontalSpacing)); +} + +/////////////////////////////////////////////////////////////////////////////// +// ToastOverlayView +class ToastOverlayView : public views::View, public views::ButtonListener { + public: + // This object is not owned by the views hiearchy or by the widget. + ToastOverlayView(ToastOverlay* overlay, + const std::string& text, + const std::string& dismiss_text); + ~ToastOverlayView() override; + + // views::View overrides: + void OnPaint(gfx::Canvas* canvas) override; + + ToastOverlayButton* button() { return button_; } + + private: + ToastOverlay* overlay_; // weak + ToastOverlayButton* button_; // weak + + gfx::Size GetMaximumSize() const override; + gfx::Size GetMinimumSize() const override; + + void ButtonPressed(views::Button* sender, const ui::Event& event) override; + + DISALLOW_COPY_AND_ASSIGN(ToastOverlayView); +}; + +ToastOverlayView::ToastOverlayView(ToastOverlay* overlay, + const std::string& text, + const std::string& dismiss_text) + : overlay_(overlay), + button_(new ToastOverlayButton( + this, + dismiss_text.empty() + ? l10n_util::GetStringUTF16(IDS_ASH_TOAST_DISMISS_BUTTON) + : base::UTF8ToUTF16(dismiss_text))) { + ToastOverlayLabel* label = new ToastOverlayLabel(text); + label->SetMaximumWidth( + GetMaximumSize().width() - button_->GetPreferredSize().width() - + kToastHorizontalSpacing * 2 - kToastHorizontalSpacing * 2); + AddChildView(label); + + AddChildView(button_); + + auto* layout = new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0); + SetLayoutManager(layout); + layout->SetFlexForView(label, 1); + layout->SetFlexForView(button_, 0); +} + +ToastOverlayView::~ToastOverlayView() {} + +void ToastOverlayView::OnPaint(gfx::Canvas* canvas) { + SkPaint paint; + paint.setStyle(SkPaint::kFill_Style); + paint.setColor(kButtonBackgroundColor); + canvas->DrawRoundRect(GetLocalBounds(), 2, paint); + views::View::OnPaint(canvas); +} + +gfx::Size ToastOverlayView::GetMinimumSize() const { + return gfx::Size(kToastMinimumWidth, 0); +} + +gfx::Size ToastOverlayView::GetMaximumSize() const { + gfx::Rect work_area_bounds = GetUserWorkAreaBounds(); + return gfx::Size(kToastMaximumWidth, work_area_bounds.height() - kOffset * 2); +} + +void ToastOverlayView::ButtonPressed(views::Button* sender, + const ui::Event& event) { + overlay_->Show(false); +} + +/////////////////////////////////////////////////////////////////////////////// +// ToastOverlay +ToastOverlay::ToastOverlay(Delegate* delegate, + const std::string& text, + const std::string& dismiss_text) + : delegate_(delegate), + text_(text), + dismiss_text_(dismiss_text), + overlay_widget_(new views::Widget), + overlay_view_(new ToastOverlayView(this, text, dismiss_text)), + widget_size_(overlay_view_->GetPreferredSize()) { + views::Widget::InitParams params; + params.type = views::Widget::InitParams::TYPE_POPUP; + params.name = "ToastOverlay"; + params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + params.accept_events = true; + params.keep_on_top = true; + params.remove_standard_frame = true; + params.bounds = CalculateOverlayBounds(); + // Show toasts above the app list and below the lock screen. + WmShell::Get() + ->GetRootWindowForNewWindows() + ->GetRootWindowController() + ->ConfigureWidgetInitParamsForContainer( + overlay_widget_.get(), kShellWindowId_SystemModalContainer, ¶ms); + overlay_widget_->Init(params); + overlay_widget_->SetVisibilityChangedAnimationsEnabled(true); + overlay_widget_->SetContentsView(overlay_view_.get()); + overlay_widget_->SetBounds(CalculateOverlayBounds()); + + WmWindow* overlay_window = + WmLookup::Get()->GetWindowForWidget(overlay_widget_.get()); + overlay_window->SetVisibilityAnimationType( + ::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL); + overlay_window->SetVisibilityAnimationDuration( + base::TimeDelta::FromMilliseconds(kSlideAnimationDurationMs)); +} + +ToastOverlay::~ToastOverlay() { + overlay_widget_->Close(); +} + +void ToastOverlay::Show(bool visible) { + if (overlay_widget_->GetLayer()->GetTargetVisibility() == visible) + return; + + ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator(); + DCHECK(animator); + + base::TimeDelta original_duration = animator->GetTransitionDuration(); + ui::ScopedLayerAnimationSettings animation_settings(animator); + // ScopedLayerAnimationSettings ctor chanes the transition duration, so change + // back it to the original value (should be zero). + animation_settings.SetTransitionDuration(original_duration); + + animation_settings.AddObserver(this); + + if (visible) { + overlay_widget_->Show(); + + // Notify accessibility about the overlay. + overlay_view_->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, false); + } else { + overlay_widget_->Hide(); + } +} + +gfx::Rect ToastOverlay::CalculateOverlayBounds() { + gfx::Rect bounds = GetUserWorkAreaBounds(); + int target_y = bounds.bottom() - widget_size_.height() - kOffset; + bounds.ClampToCenteredSize(widget_size_); + bounds.set_y(target_y); + return bounds; +} + +void ToastOverlay::OnImplicitAnimationsScheduled() {} + +void ToastOverlay::OnImplicitAnimationsCompleted() { + if (!overlay_widget_->GetLayer()->GetTargetVisibility()) + delegate_->OnClosed(); +} + +views::Widget* ToastOverlay::widget_for_testing() { + return overlay_widget_.get(); +} + +void ToastOverlay::ClickDismissButtonForTesting(const ui::Event& event) { + overlay_view_->button()->NotifyClick(event); +} + +} // namespace ash
diff --git a/ash/common/system/toast/toast_overlay.h b/ash/common/system/toast/toast_overlay.h new file mode 100644 index 0000000..fce4168 --- /dev/null +++ b/ash/common/system/toast/toast_overlay.h
@@ -0,0 +1,75 @@ +// 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 ASH_COMMON_SYSTEM_TOAST_TOAST_OVERLAY_H_ +#define ASH_COMMON_SYSTEM_TOAST_TOAST_OVERLAY_H_ + +#include <memory> +#include <string> + +#include "ash/ash_export.h" +#include "ui/compositor/layer_animation_observer.h" +#include "ui/events/event.h" +#include "ui/events/event_constants.h" +#include "ui/gfx/geometry/size.h" + +namespace gfx { +class Rect; +} + +namespace views { +class Widget; +} + +namespace ash { + +class ToastManagerTest; +class ToastOverlayView; +class ToastOverlayButton; + +class ASH_EXPORT ToastOverlay : public ui::ImplicitAnimationObserver { + public: + class ASH_EXPORT Delegate { + public: + virtual ~Delegate() {} + virtual void OnClosed() = 0; + }; + + // Creates the Toast overlay UI. |text| is the message to be shown, and + // |dismiss_text| is the message for the button to dismiss the toast message. + // |dismiss_text| is optional. If empty, the default text is used. + ToastOverlay(Delegate* delegate, + const std::string& text, + const std::string& dismiss_text); + ~ToastOverlay() override; + + // Shows or hides the overlay. + void Show(bool visible); + + private: + friend class ToastManagerTest; + + // Returns the current bounds of the overlay, which is based on visibility. + gfx::Rect CalculateOverlayBounds(); + + // ui::ImplicitAnimationObserver: + void OnImplicitAnimationsScheduled() override; + void OnImplicitAnimationsCompleted() override; + + views::Widget* widget_for_testing(); + void ClickDismissButtonForTesting(const ui::Event& event); + + Delegate* const delegate_; + const std::string text_; + const std::string dismiss_text_; + std::unique_ptr<views::Widget> overlay_widget_; + std::unique_ptr<ToastOverlayView> overlay_view_; + gfx::Size widget_size_; + + DISALLOW_COPY_AND_ASSIGN(ToastOverlay); +}; + +} // namespace ash + +#endif // ASH_COMMON_SYSTEM_TOAST_TOAST_OVERLAY_H_
diff --git a/ash/common/system/tray/hover_highlight_view.cc b/ash/common/system/tray/hover_highlight_view.cc index 30cd548..dfcc8a72 100644 --- a/ash/common/system/tray/hover_highlight_view.cc +++ b/ash/common/system/tray/hover_highlight_view.cc
@@ -34,16 +34,7 @@ namespace ash { HoverHighlightView::HoverHighlightView(ViewClickListener* listener) - : listener_(listener), - text_label_(NULL), - highlight_color_(kHoverBackgroundColor), - default_color_(0), - text_highlight_color_(0), - text_default_color_(0), - hover_(false), - expandable_(false), - checkable_(false), - checked_(false) { + : listener_(listener), highlight_color_(kHoverBackgroundColor) { set_notify_enter_exit_on_child(true); } @@ -57,26 +48,48 @@ return true; } +void HoverHighlightView::AddRightIcon(const gfx::ImageSkia& image) { + DCHECK(box_layout_); + DCHECK(!right_icon_); + + right_icon_ = new FixedSizedImageView(kTrayPopupDetailsIconWidth, 0); + right_icon_->SetImage(image); + right_icon_->SetEnabled(enabled()); + AddChildView(right_icon_); +} + +void HoverHighlightView::SetRightIconVisible(bool visible) { + if (!right_icon_) + return; + + right_icon_->SetVisible(visible); + Layout(); +} + void HoverHighlightView::AddIconAndLabel(const gfx::ImageSkia& image, const base::string16& text, bool highlight) { - SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 3, - kTrayPopupPaddingBetweenItems)); + box_layout_ = new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 3, + kTrayPopupPaddingBetweenItems); + SetLayoutManager(box_layout_); DoAddIconAndLabel(image, text, highlight); } void HoverHighlightView::AddIndentedIconAndLabel(const gfx::ImageSkia& image, const base::string16& text, bool highlight) { - SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, - kTrayPopupPaddingHorizontal, 0, - kTrayPopupPaddingBetweenItems)); + box_layout_ = new views::BoxLayout(views::BoxLayout::kHorizontal, + kTrayPopupPaddingHorizontal, 0, + kTrayPopupPaddingBetweenItems); + SetLayoutManager(box_layout_); DoAddIconAndLabel(image, text, highlight); } void HoverHighlightView::DoAddIconAndLabel(const gfx::ImageSkia& image, const base::string16& text, bool highlight) { + DCHECK(box_layout_); + views::ImageView* image_view = new FixedSizedImageView(kTrayPopupDetailsIconWidth, 0); image_view->SetImage(image); @@ -90,6 +103,7 @@ text_label_->SetEnabledColor(text_default_color_); text_label_->SetEnabled(enabled()); AddChildView(text_label_); + box_layout_->SetFlexForView(text_label_, 1); SetAccessibleName(text); } @@ -97,7 +111,8 @@ views::Label* HoverHighlightView::AddLabel(const base::string16& text, gfx::HorizontalAlignment alignment, bool highlight) { - SetLayoutManager(new views::FillLayout()); + box_layout_ = new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0); + SetLayoutManager(box_layout_); text_label_ = new views::Label(text); int left_margin = kTrayPopupPaddingHorizontal; int right_margin = kTrayPopupPaddingHorizontal; @@ -118,6 +133,7 @@ text_label_->SetEnabledColor(text_default_color_); text_label_->SetEnabled(enabled()); AddChildView(text_label_); + box_layout_->SetFlexForView(text_label_, 1); SetAccessibleName(text); return text_label_; @@ -164,6 +180,12 @@ } } +void HoverHighlightView::SetHighlight(bool highlight) { + DCHECK(text_label_); + text_label_->SetFontList(GetFontList(highlight)); + text_label_->InvalidateLayout(); +} + void HoverHighlightView::SetHoverHighlight(bool hover) { if (!enabled() && hover) return;
diff --git a/ash/common/system/tray/hover_highlight_view.h b/ash/common/system/tray/hover_highlight_view.h index 2a54e8e..bdb3e642 100644 --- a/ash/common/system/tray/hover_highlight_view.h +++ b/ash/common/system/tray/hover_highlight_view.h
@@ -11,7 +11,9 @@ #include "ui/gfx/text_constants.h" namespace views { +class ImageView; class Label; +class BoxLayout; } namespace ash { @@ -43,7 +45,7 @@ bool highlight); // Convenience function for adding a label with padding on the left for a - // blank icon. This also sets the accessible name. Returns label after + // blank icon. This also sets the accessible name. Returns label after // parenting it. views::Label* AddLabel(const base::string16& text, gfx::HorizontalAlignment alignment, @@ -56,10 +58,21 @@ bool highlight, bool checked); + // Add an optional right icon to an already established view (call one of + // the other Add* functions first). + void AddRightIcon(const gfx::ImageSkia& image); + + // Hide or show the right icon. + void SetRightIconVisible(bool visible); + // Allows view to expand its height. // Size of unexapandable view is fixed and equals to kTrayPopupItemHeight. void SetExpandable(bool expandable); + // Enables or disable highlighting on the label, where a highlighted label + // just uses a bold font. + void SetHighlight(bool hightlight); + void set_highlight_color(SkColor color) { highlight_color_ = color; } void set_default_color(SkColor color) { default_color_ = color; } void set_text_highlight_color(SkColor c) { text_highlight_color_ = c; } @@ -98,16 +111,18 @@ void OnPaintBackground(gfx::Canvas* canvas) override; void OnFocus() override; - ViewClickListener* listener_; - views::Label* text_label_; - SkColor highlight_color_; - SkColor default_color_; - SkColor text_highlight_color_; - SkColor text_default_color_; - bool hover_; - bool expandable_; - bool checkable_; - bool checked_; + ViewClickListener* listener_ = nullptr; + views::Label* text_label_ = nullptr; + views::BoxLayout* box_layout_ = nullptr; + views::ImageView* right_icon_ = nullptr; + SkColor highlight_color_ = 0; + SkColor default_color_ = 0; + SkColor text_highlight_color_ = 0; + SkColor text_default_color_ = 0; + bool hover_ = false; + bool expandable_ = false; + bool checkable_ = false; + bool checked_ = false; base::string16 tooltip_; DISALLOW_COPY_AND_ASSIGN(HoverHighlightView);
diff --git a/ash/common/system/tray/system_tray.cc b/ash/common/system/tray/system_tray.cc new file mode 100644 index 0000000..97ddaa0 --- /dev/null +++ b/ash/common/system/tray/system_tray.cc
@@ -0,0 +1,776 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/common/system/tray/system_tray.h" + +#include "ash/common/ash_switches.h" +#include "ash/common/login_status.h" +#include "ash/common/session/session_state_delegate.h" +#include "ash/common/shelf/wm_shelf.h" +#include "ash/common/shelf/wm_shelf_util.h" +#include "ash/common/shell_window_ids.h" +#include "ash/common/system/cast/tray_cast.h" +#include "ash/common/system/date/tray_date.h" +#include "ash/common/system/tray/system_tray_delegate.h" +#include "ash/common/system/tray/system_tray_item.h" +#include "ash/common/system/tray/tray_bubble_wrapper.h" +#include "ash/common/system/tray/tray_constants.h" +#include "ash/common/system/tray_accessibility.h" +#include "ash/common/system/update/tray_update.h" +#include "ash/common/system/user/tray_user.h" +#include "ash/common/system/user/tray_user_separator.h" +#include "ash/common/system/web_notification/web_notification_tray.h" +#include "ash/common/wm_lookup.h" +#include "ash/common/wm_root_window_controller.h" +#include "ash/common/wm_shell.h" +#include "ash/common/wm_window.h" +#include "base/logging.h" +#include "base/metrics/histogram.h" +#include "base/strings/utf_string_conversions.h" +#include "base/timer/timer.h" +#include "grit/ash_strings.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/compositor/layer.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" +#include "ui/events/event_constants.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/skia_util.h" +#include "ui/views/border.h" +#include "ui/views/controls/label.h" +#include "ui/views/layout/box_layout.h" +#include "ui/views/layout/fill_layout.h" +#include "ui/views/view.h" + +#if defined(OS_CHROMEOS) +#include "ash/common/system/chromeos/audio/tray_audio_chromeos.h" +#include "ash/common/system/chromeos/bluetooth/tray_bluetooth.h" +#include "ash/common/system/chromeos/brightness/tray_brightness.h" +#include "ash/common/system/chromeos/enterprise/tray_enterprise.h" +#include "ash/common/system/chromeos/media_security/multi_profile_media_tray_item.h" +#include "ash/common/system/chromeos/network/tray_network.h" +#include "ash/common/system/chromeos/network/tray_sms.h" +#include "ash/common/system/chromeos/network/tray_vpn.h" +#include "ash/common/system/chromeos/power/power_status.h" +#include "ash/common/system/chromeos/power/tray_power.h" +#include "ash/common/system/chromeos/screen_security/screen_capture_tray_item.h" +#include "ash/common/system/chromeos/screen_security/screen_share_tray_item.h" +#include "ash/common/system/chromeos/session/tray_session_length_limit.h" +#include "ash/common/system/chromeos/settings/tray_settings.h" +#include "ash/common/system/chromeos/supervised/tray_supervised_user.h" +#include "ash/common/system/chromeos/tray_caps_lock.h" +#include "ash/common/system/chromeos/tray_tracing.h" +#include "ash/common/system/ime/tray_ime_chromeos.h" +#include "ui/message_center/message_center.h" +#endif + +using views::TrayBubbleView; + +namespace ash { + +// The minimum width of the system tray menu width. +const int kMinimumSystemTrayMenuWidth = 300; + +// Class to initialize and manage the SystemTrayBubble and TrayBubbleWrapper +// instances for a bubble. + +class SystemBubbleWrapper { + public: + // Takes ownership of |bubble|. + explicit SystemBubbleWrapper(SystemTrayBubble* bubble) + : bubble_(bubble), is_persistent_(false) {} + + // Initializes the bubble view and creates |bubble_wrapper_|. + void InitView(TrayBackgroundView* tray, + views::View* anchor, + TrayBubbleView::InitParams* init_params, + bool is_persistent) { + DCHECK(anchor); + LoginStatus login_status = + WmShell::Get()->system_tray_delegate()->GetUserLoginStatus(); + bubble_->InitView(anchor, login_status, init_params); + bubble_wrapper_.reset(new TrayBubbleWrapper(tray, bubble_->bubble_view())); + // The system bubble should not have an arrow. + bubble_->bubble_view()->SetArrowPaintType(views::BubbleBorder::PAINT_NONE); + is_persistent_ = is_persistent; + + // If ChromeVox is enabled, focus the default item if no item is focused and + // there isn't a delayed close. + if (WmShell::Get()->GetAccessibilityDelegate()->IsSpokenFeedbackEnabled() && + !is_persistent) { + bubble_->FocusDefaultIfNeeded(); + } + } + + // Convenience accessors: + SystemTrayBubble* bubble() const { return bubble_.get(); } + SystemTrayBubble::BubbleType bubble_type() const { + return bubble_->bubble_type(); + } + TrayBubbleView* bubble_view() const { return bubble_->bubble_view(); } + bool is_persistent() const { return is_persistent_; } + + private: + std::unique_ptr<SystemTrayBubble> bubble_; + std::unique_ptr<TrayBubbleWrapper> bubble_wrapper_; + bool is_persistent_; + + DISALLOW_COPY_AND_ASSIGN(SystemBubbleWrapper); +}; + +// SystemTray + +SystemTray::SystemTray(WmShelf* wm_shelf) + : TrayBackgroundView(wm_shelf), + web_notification_tray_(nullptr), + detailed_item_(nullptr), + default_bubble_height_(0), + hide_notifications_(false), + full_system_tray_menu_(false), + tray_accessibility_(nullptr), + tray_cast_(nullptr), + tray_date_(nullptr), + tray_update_(nullptr), + screen_capture_tray_item_(nullptr), + screen_share_tray_item_(nullptr) { + SetContentsBackground(); +} + +SystemTray::~SystemTray() { + // Destroy any child views that might have back pointers before ~View(). + system_bubble_.reset(); + notification_bubble_.reset(); + for (std::vector<SystemTrayItem*>::iterator it = items_.begin(); + it != items_.end(); ++it) { + (*it)->DestroyTrayView(); + } +} + +void SystemTray::InitializeTrayItems( + SystemTrayDelegate* delegate, + WebNotificationTray* web_notification_tray) { + DCHECK(web_notification_tray); + web_notification_tray_ = web_notification_tray; + TrayBackgroundView::Initialize(); + CreateItems(delegate); +} + +void SystemTray::Shutdown() { + DCHECK(web_notification_tray_); + web_notification_tray_ = nullptr; +} + +void SystemTray::CreateItems(SystemTrayDelegate* delegate) { + WmShell* wm_shell = WmShell::Get(); +#if !defined(OS_WIN) + // Create user items for each possible user. + int maximum_user_profiles = + wm_shell->GetSessionStateDelegate()->GetMaximumNumberOfLoggedInUsers(); + for (int i = 0; i < maximum_user_profiles; i++) + AddTrayItem(new TrayUser(this, i)); + + if (maximum_user_profiles > 1) { + // Add a special double line separator between users and the rest of the + // menu if more then one user is logged in. + AddTrayItem(new TrayUserSeparator(this)); + } +#endif + + tray_accessibility_ = new TrayAccessibility(this); + tray_date_ = new TrayDate(this); + tray_update_ = new TrayUpdate(this); + +#if defined(OS_CHROMEOS) + AddTrayItem(new TraySessionLengthLimit(this)); + AddTrayItem(new TrayEnterprise(this)); + AddTrayItem(new TraySupervisedUser(this)); + AddTrayItem(new TrayIME(this)); + AddTrayItem(tray_accessibility_); + AddTrayItem(new TrayTracing(this)); + AddTrayItem(new TrayPower(this, message_center::MessageCenter::Get())); + AddTrayItem(new TrayNetwork(this)); + AddTrayItem(new TrayVPN(this)); + AddTrayItem(new TraySms(this)); + AddTrayItem(new TrayBluetooth(this)); + tray_cast_ = new TrayCast(this); + AddTrayItem(tray_cast_); + // TODO(jamescook): Remove this when mus has support for display management + // and we have a DisplayManager equivalent. See http://crbug.com/548429 + std::unique_ptr<SystemTrayItem> tray_display = + delegate->CreateDisplayTrayItem(this); + if (tray_display) + AddTrayItem(tray_display.release()); + screen_capture_tray_item_ = new ScreenCaptureTrayItem(this); + AddTrayItem(screen_capture_tray_item_); + screen_share_tray_item_ = new ScreenShareTrayItem(this); + AddTrayItem(screen_share_tray_item_); + AddTrayItem(new MultiProfileMediaTrayItem(this)); + AddTrayItem(new TrayAudioChromeOs(this)); + AddTrayItem(new TrayBrightness(this)); + AddTrayItem(new TrayCapsLock(this)); + // TODO(jamescook): Remove this when mus has support for display management + // and we have a DisplayManager equivalent. See http://crbug.com/548429 + std::unique_ptr<SystemTrayItem> tray_rotation_lock = + delegate->CreateRotationLockTrayItem(this); + if (tray_rotation_lock) + AddTrayItem(tray_rotation_lock.release()); + AddTrayItem(new TraySettings(this)); + AddTrayItem(tray_update_); + AddTrayItem(tray_date_); +#elif defined(OS_WIN) + AddTrayItem(tray_accessibility_); + AddTrayItem(tray_update_); + AddTrayItem(tray_date_); +#endif + + SetVisible(wm_shell->system_tray_delegate()->GetTrayVisibilityOnStartup()); +} + +void SystemTray::AddTrayItem(SystemTrayItem* item) { + items_.push_back(item); + + SystemTrayDelegate* delegate = WmShell::Get()->system_tray_delegate(); + views::View* tray_item = item->CreateTrayView(delegate->GetUserLoginStatus()); + item->UpdateAfterShelfAlignmentChange(shelf_alignment()); + + if (tray_item) { + tray_container()->AddChildViewAt(tray_item, 0); + PreferredSizeChanged(); + tray_item_map_[item] = tray_item; + } +} + +const std::vector<SystemTrayItem*>& SystemTray::GetTrayItems() const { + return items_.get(); +} + +void SystemTray::ShowDefaultView(BubbleCreationType creation_type) { + ShowDefaultViewWithOffset( + creation_type, TrayBubbleView::InitParams::kArrowDefaultOffset, false); +} + +void SystemTray::ShowPersistentDefaultView() { + ShowItems(items_.get(), false, false, BUBBLE_CREATE_NEW, + TrayBubbleView::InitParams::kArrowDefaultOffset, true); +} + +void SystemTray::ShowDetailedView(SystemTrayItem* item, + int close_delay, + bool activate, + BubbleCreationType creation_type) { + std::vector<SystemTrayItem*> items; + // The detailed view with timeout means a UI to show the current system state, + // like the audio level or brightness. Such UI should behave as persistent and + // keep its own logic for the appearance. + bool persistent = + (!activate && close_delay > 0 && creation_type == BUBBLE_CREATE_NEW); + items.push_back(item); + ShowItems(items, true, activate, creation_type, GetTrayXOffset(item), + persistent); + if (system_bubble_) + system_bubble_->bubble()->StartAutoCloseTimer(close_delay); +} + +void SystemTray::SetDetailedViewCloseDelay(int close_delay) { + if (HasSystemBubbleType(SystemTrayBubble::BUBBLE_TYPE_DETAILED)) + system_bubble_->bubble()->StartAutoCloseTimer(close_delay); +} + +void SystemTray::HideDetailedView(SystemTrayItem* item) { + if (item != detailed_item_) + return; + DestroySystemBubble(); + UpdateNotificationBubble(); +} + +void SystemTray::ShowNotificationView(SystemTrayItem* item) { + if (std::find(notification_items_.begin(), notification_items_.end(), item) != + notification_items_.end()) + return; + notification_items_.push_back(item); + UpdateNotificationBubble(); +} + +void SystemTray::HideNotificationView(SystemTrayItem* item) { + std::vector<SystemTrayItem*>::iterator found_iter = + std::find(notification_items_.begin(), notification_items_.end(), item); + if (found_iter == notification_items_.end()) + return; + notification_items_.erase(found_iter); + // Only update the notification bubble if visible (i.e. don't create one). + if (notification_bubble_) + UpdateNotificationBubble(); +} + +void SystemTray::UpdateAfterLoginStatusChange(LoginStatus login_status) { + DestroySystemBubble(); + UpdateNotificationBubble(); + + for (SystemTrayItem* item : items_) + item->UpdateAfterLoginStatusChange(login_status); + + // Items default to SHELF_ALIGNMENT_BOTTOM. Update them if the initial + // position of the shelf differs. + if (!IsHorizontalAlignment(shelf_alignment())) + UpdateAfterShelfAlignmentChange(shelf_alignment()); + + SetVisible(true); + PreferredSizeChanged(); +} + +void SystemTray::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) { + for (SystemTrayItem* item : items_) + item->UpdateAfterShelfAlignmentChange(alignment); +} + +void SystemTray::SetHideNotifications(bool hide_notifications) { + if (notification_bubble_) + notification_bubble_->bubble()->SetVisible(!hide_notifications); + hide_notifications_ = hide_notifications; +} + +bool SystemTray::ShouldShowShelf() const { + return system_bubble_.get() && system_bubble_->bubble()->ShouldShowShelf(); +} + +bool SystemTray::HasSystemBubble() const { + return system_bubble_.get() != NULL; +} + +bool SystemTray::HasNotificationBubble() const { + return notification_bubble_.get() != NULL; +} + +SystemTrayBubble* SystemTray::GetSystemBubble() { + if (!system_bubble_) + return NULL; + return system_bubble_->bubble(); +} + +bool SystemTray::IsAnyBubbleVisible() const { + return ((system_bubble_.get() && system_bubble_->bubble()->IsVisible()) || + (notification_bubble_.get() && + notification_bubble_->bubble()->IsVisible())); +} + +bool SystemTray::IsMouseInNotificationBubble() const { + if (!notification_bubble_) + return false; + return notification_bubble_->bubble_view()->GetBoundsInScreen().Contains( + display::Screen::GetScreen()->GetCursorScreenPoint()); +} + +bool SystemTray::CloseSystemBubble() const { + if (!system_bubble_) + return false; + system_bubble_->bubble()->Close(); + return true; +} + +views::View* SystemTray::GetHelpButtonView() const { + return tray_date_->GetHelpButtonView(); +} + +bool SystemTray::CloseNotificationBubbleForTest() const { + if (!notification_bubble_) + return false; + notification_bubble_->bubble()->Close(); + return true; +} + +// Private methods. + +bool SystemTray::HasSystemBubbleType(SystemTrayBubble::BubbleType type) { + DCHECK(type != SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION); + return system_bubble_.get() && system_bubble_->bubble_type() == type; +} + +void SystemTray::DestroySystemBubble() { + CloseSystemBubbleAndDeactivateSystemTray(); + detailed_item_ = NULL; + UpdateWebNotifications(); +} + +void SystemTray::DestroyNotificationBubble() { + if (notification_bubble_) { + notification_bubble_.reset(); + UpdateWebNotifications(); + } +} + +base::string16 SystemTray::GetAccessibleNameForTray() { + base::string16 time = GetAccessibleTimeString(base::Time::Now()); + base::string16 battery = base::ASCIIToUTF16(""); +#if defined(OS_CHROMEOS) + battery = PowerStatus::Get()->GetAccessibleNameString(false); +#endif + return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBLE_DESCRIPTION, + time, battery); +} + +int SystemTray::GetTrayXOffset(SystemTrayItem* item) const { + // Don't attempt to align the arrow if the shelf is on the left or right. + if (!IsHorizontalAlignment(shelf_alignment())) + return TrayBubbleView::InitParams::kArrowDefaultOffset; + + std::map<SystemTrayItem*, views::View*>::const_iterator it = + tray_item_map_.find(item); + if (it == tray_item_map_.end()) + return TrayBubbleView::InitParams::kArrowDefaultOffset; + + const views::View* item_view = it->second; + if (item_view->bounds().IsEmpty()) { + // The bounds of item could be still empty if it does not have a visible + // tray view. In that case, use the default (minimum) offset. + return TrayBubbleView::InitParams::kArrowDefaultOffset; + } + + gfx::Point point(item_view->width() / 2, 0); + ConvertPointToWidget(item_view, &point); + return point.x(); +} + +void SystemTray::ShowDefaultViewWithOffset(BubbleCreationType creation_type, + int arrow_offset, + bool persistent) { + if (creation_type != BUBBLE_USE_EXISTING) + WmShell::Get()->RecordUserMetricsAction(UMA_STATUS_AREA_MENU_OPENED); + ShowItems(items_.get(), false, true, creation_type, arrow_offset, persistent); +} + +void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items, + bool detailed, + bool can_activate, + BubbleCreationType creation_type, + int arrow_offset, + bool persistent) { + // No system tray bubbles in kiosk mode. + if (WmShell::Get()->system_tray_delegate()->GetUserLoginStatus() == + LoginStatus::KIOSK_APP) { + return; + } + + // Destroy any existing bubble and create a new one. + SystemTrayBubble::BubbleType bubble_type = + detailed ? SystemTrayBubble::BUBBLE_TYPE_DETAILED + : SystemTrayBubble::BUBBLE_TYPE_DEFAULT; + + // Destroy the notification bubble here so that it doesn't get rebuilt + // while we add items to the main bubble_ (e.g. in HideNotificationView). + notification_bubble_.reset(); + if (system_bubble_.get() && creation_type == BUBBLE_USE_EXISTING) { + system_bubble_->bubble()->UpdateView(items, bubble_type); + // If ChromeVox is enabled, focus the default item if no item is focused. + if (WmShell::Get()->GetAccessibilityDelegate()->IsSpokenFeedbackEnabled()) + system_bubble_->bubble()->FocusDefaultIfNeeded(); + } else { + // Cleanup the existing bubble before showing a new one. Otherwise, it's + // possible to confuse the new system bubble with the old one during + // destruction, leading to subtle errors/crashes such as crbug.com/545166. + DestroySystemBubble(); + + // Remember if the menu is a single property (like e.g. volume) or the + // full tray menu. Note that in case of the |BUBBLE_USE_EXISTING| case + // above, |full_system_tray_menu_| does not get changed since the fact that + // the menu is full (or not) doesn't change even if a "single property" + // (like network) replaces most of the menu. + full_system_tray_menu_ = items.size() > 1; + // The menu width is fixed, and it is a per language setting. + int menu_width = std::max( + kMinimumSystemTrayMenuWidth, + WmShell::Get()->system_tray_delegate()->GetSystemTrayMenuWidth()); + + TrayBubbleView::InitParams init_params(TrayBubbleView::ANCHOR_TYPE_TRAY, + GetAnchorAlignment(), menu_width, + kTrayPopupMaxWidth); + init_params.can_activate = can_activate; + init_params.first_item_has_no_margin = true; + if (detailed) { + // This is the case where a volume control or brightness control bubble + // is created. + init_params.max_height = default_bubble_height_; + init_params.arrow_color = kBackgroundColor; + } else { + init_params.arrow_color = kHeaderBackgroundColor; + } + init_params.arrow_offset = arrow_offset; + if (bubble_type == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) + init_params.close_on_deactivate = !persistent; + // For Volume and Brightness we don't want to show an arrow when + // they are shown in a bubble by themselves. + init_params.arrow_paint_type = views::BubbleBorder::PAINT_NORMAL; + if (items.size() == 1 && items[0]->ShouldHideArrow()) + init_params.arrow_paint_type = views::BubbleBorder::PAINT_TRANSPARENT; + SystemTrayBubble* bubble = new SystemTrayBubble(this, items, bubble_type); + + system_bubble_.reset(new SystemBubbleWrapper(bubble)); + system_bubble_->InitView(this, tray_container(), &init_params, persistent); + + // Record metrics for the system menu when the default view is invoked. + if (!detailed) + RecordSystemMenuMetrics(); + } + // Save height of default view for creating detailed views directly. + if (!detailed) + default_bubble_height_ = system_bubble_->bubble_view()->height(); + + if (detailed && items.size() > 0) + detailed_item_ = items[0]; + else + detailed_item_ = NULL; + + UpdateNotificationBubble(); // State changed, re-create notifications. + if (!notification_bubble_) + UpdateWebNotifications(); + shelf()->UpdateAutoHideState(); + + // When we show the system menu in our alternate shelf layout, we need to + // tint the background. + if (full_system_tray_menu_) + SetDrawBackgroundAsActive(true); +} + +void SystemTray::UpdateNotificationBubble() { + // Only show the notification bubble if we have notifications. + if (notification_items_.empty()) { + DestroyNotificationBubble(); + return; + } + // Destroy the existing bubble before constructing a new one. + notification_bubble_.reset(); + SystemTrayBubble* notification_bubble; + notification_bubble = new SystemTrayBubble( + this, notification_items_, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION); + views::View* anchor; + TrayBubbleView::AnchorType anchor_type; + // Tray items might want to show notifications while we are creating and + // initializing the |system_bubble_| - but it might not be fully initialized + // when coming here - this would produce a crashed like crbug.com/247416. + // As such we check the existence of the widget here. + if (system_bubble_.get() && system_bubble_->bubble_view() && + system_bubble_->bubble_view()->GetWidget()) { + anchor = system_bubble_->bubble_view(); + anchor_type = TrayBubbleView::ANCHOR_TYPE_BUBBLE; + } else { + anchor = tray_container(); + anchor_type = TrayBubbleView::ANCHOR_TYPE_TRAY; + } + TrayBubbleView::InitParams init_params(anchor_type, GetAnchorAlignment(), + kTrayPopupMinWidth, + kTrayPopupMaxWidth); + init_params.first_item_has_no_margin = true; + init_params.arrow_color = kBackgroundColor; + init_params.arrow_offset = GetTrayXOffset(notification_items_[0]); + notification_bubble_.reset(new SystemBubbleWrapper(notification_bubble)); + notification_bubble_->InitView(this, anchor, &init_params, false); + + if (notification_bubble->bubble_view()->child_count() == 0) { + // It is possible that none of the items generated actual notifications. + DestroyNotificationBubble(); + return; + } + if (hide_notifications_) + notification_bubble->SetVisible(false); + else + UpdateWebNotifications(); +} + +void SystemTray::UpdateWebNotifications() { + TrayBubbleView* bubble_view = NULL; + if (notification_bubble_) + bubble_view = notification_bubble_->bubble_view(); + else if (system_bubble_) + bubble_view = system_bubble_->bubble_view(); + + int height = 0; + if (bubble_view) { + gfx::Rect work_area = + display::Screen::GetScreen() + ->GetDisplayNearestWindow(bubble_view->GetWidget()->GetNativeView()) + .work_area(); + height = + std::max(0, work_area.height() - bubble_view->GetBoundsInScreen().y()); + } + if (web_notification_tray_) + web_notification_tray_->SetTrayBubbleHeight(height); +} + +base::string16 SystemTray::GetAccessibleTimeString( + const base::Time& now) const { + base::HourClockType hour_type = + WmShell::Get()->system_tray_delegate()->GetHourClockType(); + return base::TimeFormatTimeOfDayWithHourClockType(now, hour_type, + base::kKeepAmPm); +} + +void SystemTray::SetShelfAlignment(ShelfAlignment alignment) { + if (alignment == shelf_alignment()) + return; + TrayBackgroundView::SetShelfAlignment(alignment); + UpdateAfterShelfAlignmentChange(alignment); + // Destroy any existing bubble so that it is rebuilt correctly. + CloseSystemBubbleAndDeactivateSystemTray(); + // Rebuild any notification bubble. + if (notification_bubble_) { + notification_bubble_.reset(); + UpdateNotificationBubble(); + // UpdateWebNotifications() should be called in UpdateNotificationBubble(). + } else if (!hide_notifications_) { + UpdateWebNotifications(); + } +} + +void SystemTray::AnchorUpdated() { + if (notification_bubble_) { + notification_bubble_->bubble_view()->UpdateBubble(); + // Ensure that the notification buble is above the shelf/status area. + notification_bubble_->bubble_view()->GetWidget()->StackAtTop(); + UpdateBubbleViewArrow(notification_bubble_->bubble_view()); + } + if (system_bubble_) { + system_bubble_->bubble_view()->UpdateBubble(); + UpdateBubbleViewArrow(system_bubble_->bubble_view()); + } +} + +void SystemTray::BubbleResized(const TrayBubbleView* bubble_view) { + UpdateWebNotifications(); +} + +void SystemTray::HideBubbleWithView(const TrayBubbleView* bubble_view) { + if (system_bubble_.get() && bubble_view == system_bubble_->bubble_view()) { + DestroySystemBubble(); + UpdateNotificationBubble(); // State changed, re-create notifications. + shelf()->UpdateAutoHideState(); + } else if (notification_bubble_.get() && + bubble_view == notification_bubble_->bubble_view()) { + DestroyNotificationBubble(); + } +} + +void SystemTray::ClickedOutsideBubble() { + if (!system_bubble_ || system_bubble_->is_persistent()) + return; + HideBubbleWithView(system_bubble_->bubble_view()); +} + +void SystemTray::BubbleViewDestroyed() { + if (system_bubble_) { + system_bubble_->bubble()->DestroyItemViews(); + system_bubble_->bubble()->BubbleViewDestroyed(); + } +} + +void SystemTray::OnMouseEnteredView() { + if (system_bubble_) + system_bubble_->bubble()->StopAutoCloseTimer(); +} + +void SystemTray::OnMouseExitedView() { + if (system_bubble_) + system_bubble_->bubble()->RestartAutoCloseTimer(); +} + +base::string16 SystemTray::GetAccessibleNameForBubble() { + return GetAccessibleNameForTray(); +} + +gfx::Rect SystemTray::GetAnchorRect( + views::Widget* anchor_widget, + TrayBubbleView::AnchorType anchor_type, + TrayBubbleView::AnchorAlignment anchor_alignment) const { + return GetBubbleAnchorRect(anchor_widget, anchor_type, anchor_alignment); +} + +void SystemTray::OnBeforeBubbleWidgetInit( + views::Widget* anchor_widget, + views::Widget* bubble_widget, + views::Widget::InitParams* params) const { + // Place the bubble in the same root window as |anchor_widget|. + WmLookup::Get() + ->GetWindowForWidget(anchor_widget) + ->GetRootWindowController() + ->ConfigureWidgetInitParamsForContainer( + bubble_widget, kShellWindowId_SettingBubbleContainer, params); +} + +void SystemTray::HideBubble(const TrayBubbleView* bubble_view) { + HideBubbleWithView(bubble_view); +} + +views::View* SystemTray::GetTrayItemViewForTest(SystemTrayItem* item) { + std::map<SystemTrayItem*, views::View*>::iterator it = + tray_item_map_.find(item); + return it == tray_item_map_.end() ? NULL : it->second; +} + +TrayCast* SystemTray::GetTrayCastForTesting() const { + return tray_cast_; +} + +TrayDate* SystemTray::GetTrayDateForTesting() const { + return tray_date_; +} + +TrayUpdate* SystemTray::GetTrayUpdateForTesting() const { + return tray_update_; +} + +bool SystemTray::PerformAction(const ui::Event& event) { + // If we're already showing the default view, hide it; otherwise, show it + // (and hide any popup that's currently shown). + if (HasSystemBubbleType(SystemTrayBubble::BUBBLE_TYPE_DEFAULT)) { + system_bubble_->bubble()->Close(); + } else { + int arrow_offset = TrayBubbleView::InitParams::kArrowDefaultOffset; + if (event.IsMouseEvent() || event.type() == ui::ET_GESTURE_TAP) { + const ui::LocatedEvent& located_event = + static_cast<const ui::LocatedEvent&>(event); + if (IsHorizontalAlignment(shelf_alignment())) { + gfx::Point point(located_event.x(), 0); + ConvertPointToWidget(this, &point); + arrow_offset = point.x(); + } + } + ShowDefaultViewWithOffset(BUBBLE_CREATE_NEW, arrow_offset, false); + } + return true; +} + +void SystemTray::CloseSystemBubbleAndDeactivateSystemTray() { + system_bubble_.reset(); + // When closing a system bubble with the alternate shelf layout, we need to + // turn off the active tinting of the shelf. + if (full_system_tray_menu_) { + SetDrawBackgroundAsActive(false); + full_system_tray_menu_ = false; + } +} + +void SystemTray::RecordSystemMenuMetrics() { + DCHECK(system_bubble_); + + TrayBubbleView* bubble_view = system_bubble_->bubble_view(); + int num_rows = 0; + for (int i = 0; i < bubble_view->child_count(); i++) { + // Certain menu rows are attached by default but can set themselves as + // invisible (IME is one such example). Count only user-visible rows. + if (bubble_view->child_at(i)->visible()) + num_rows++; + } + UMA_HISTOGRAM_COUNTS_100("Ash.SystemMenu.Rows", num_rows); + + int work_area_height = + display::Screen::GetScreen() + ->GetDisplayNearestWindow(bubble_view->GetWidget()->GetNativeView()) + .work_area() + .height(); + if (work_area_height > 0) { + UMA_HISTOGRAM_CUSTOM_COUNTS( + "Ash.SystemMenu.PercentageOfWorkAreaHeightCoveredByMenu", + 100 * bubble_view->height() / work_area_height, 1, 300, 100); + } +} + +} // namespace ash
diff --git a/ash/common/system/tray/system_tray.h b/ash/common/system/tray/system_tray.h new file mode 100644 index 0000000..9029cb1 --- /dev/null +++ b/ash/common/system/tray/system_tray.h
@@ -0,0 +1,264 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_COMMON_SYSTEM_TRAY_SYSTEM_TRAY_H_ +#define ASH_COMMON_SYSTEM_TRAY_SYSTEM_TRAY_H_ + +#include <map> +#include <memory> +#include <vector> + +#include "ash/ash_export.h" +#include "ash/common/system/tray/system_tray_bubble.h" +#include "ash/common/system/tray/tray_background_view.h" +#include "base/macros.h" +#include "base/memory/scoped_vector.h" +#include "ui/views/bubble/tray_bubble_view.h" +#include "ui/views/view.h" + +namespace ash { + +enum class LoginStatus; +class ScreenTrayItem; +class SystemBubbleWrapper; +class SystemTrayDelegate; +class SystemTrayItem; +class TrayAccessibility; +class TrayCast; +class TrayDate; +class TrayUpdate; +class TrayUser; +class WebNotificationTray; + +// There are different methods for creating bubble views. +enum BubbleCreationType { + BUBBLE_CREATE_NEW, // Closes any existing bubble and creates a new one. + BUBBLE_USE_EXISTING, // Uses any existing bubble, or creates a new one. +}; + +class ASH_EXPORT SystemTray : public TrayBackgroundView, + public views::TrayBubbleView::Delegate { + public: + explicit SystemTray(WmShelf* wm_shelf); + ~SystemTray() override; + + // Calls TrayBackgroundView::Initialize(), creates the tray items, and + // adds them to SystemTrayNotifier. + void InitializeTrayItems(SystemTrayDelegate* delegate, + WebNotificationTray* web_notification_tray); + + // Resets internal pointers. + void Shutdown(); + + // Adds a new item in the tray. Takes ownership. + void AddTrayItem(SystemTrayItem* item); + + // Returns all tray items that has been added to system tray. + const std::vector<SystemTrayItem*>& GetTrayItems() const; + + // Shows the default view of all items. + void ShowDefaultView(BubbleCreationType creation_type); + + // Shows default view that ingnores outside clicks and activation loss. + void ShowPersistentDefaultView(); + + // Shows details of a particular item. If |close_delay_in_seconds| is + // non-zero, then the view is automatically closed after the specified time. + void ShowDetailedView(SystemTrayItem* item, + int close_delay_in_seconds, + bool activate, + BubbleCreationType creation_type); + + // Continue showing the existing detailed view, if any, for |close_delay| + // seconds. + void SetDetailedViewCloseDelay(int close_delay); + + // Hides the detailed view for |item|. + void HideDetailedView(SystemTrayItem* item); + + // Shows the notification view for |item|. + void ShowNotificationView(SystemTrayItem* item); + + // Hides the notification view for |item|. + void HideNotificationView(SystemTrayItem* item); + + // Updates the items when the login status of the system changes. + void UpdateAfterLoginStatusChange(LoginStatus login_status); + + // Updates the items when the shelf alignment changes. + void UpdateAfterShelfAlignmentChange(ShelfAlignment alignment); + + // Temporarily hides/unhides the notification bubble. + void SetHideNotifications(bool hidden); + + // Returns true if the shelf should be forced visible when auto-hidden. + bool ShouldShowShelf() const; + + // Returns true if there is a system bubble (already visible or in the process + // of being created). + bool HasSystemBubble() const; + + // Returns true if there is a notification bubble. + bool HasNotificationBubble() const; + + // Returns true if the system_bubble_ exists and is of type |type|. + bool HasSystemBubbleType(SystemTrayBubble::BubbleType type); + + // Returns a pointer to the system bubble or NULL if none. + SystemTrayBubble* GetSystemBubble(); + + // Returns true if any bubble is visible. + bool IsAnyBubbleVisible() const; + + // Returns true if the mouse is inside the notification bubble. + bool IsMouseInNotificationBubble() const; + + // Closes system bubble and returns true if it did exist. + bool CloseSystemBubble() const; + + // Returns view for help button if default view is shown. Returns NULL + // otherwise. + views::View* GetHelpButtonView() const; + + // Accessors for testing. + + // Returns true if the bubble exists. + bool CloseNotificationBubbleForTest() const; + + // Overridden from TrayBackgroundView. + void SetShelfAlignment(ShelfAlignment alignment) override; + void AnchorUpdated() override; + base::string16 GetAccessibleNameForTray() override; + void BubbleResized(const views::TrayBubbleView* bubble_view) override; + void HideBubbleWithView(const views::TrayBubbleView* bubble_view) override; + void ClickedOutsideBubble() override; + + // views::TrayBubbleView::Delegate: + void BubbleViewDestroyed() override; + void OnMouseEnteredView() override; + void OnMouseExitedView() override; + base::string16 GetAccessibleNameForBubble() override; + gfx::Rect GetAnchorRect(views::Widget* anchor_widget, + AnchorType anchor_type, + AnchorAlignment anchor_alignment) const override; + void OnBeforeBubbleWidgetInit( + views::Widget* anchor_widget, + views::Widget* bubble_widget, + views::Widget::InitParams* params) const override; + void HideBubble(const views::TrayBubbleView* bubble_view) override; + + ScreenTrayItem* GetScreenShareItem() { return screen_share_tray_item_; } + ScreenTrayItem* GetScreenCaptureItem() { return screen_capture_tray_item_; } + + TrayAccessibility* GetTrayAccessibilityForTest() { + return tray_accessibility_; + } + + // Get the tray item view (or NULL) for a given |tray_item| in a unit test. + views::View* GetTrayItemViewForTest(SystemTrayItem* tray_item); + + TrayCast* GetTrayCastForTesting() const; + TrayDate* GetTrayDateForTesting() const; + TrayUpdate* GetTrayUpdateForTesting() const; + + private: + // Creates the default set of items for the sytem tray. + void CreateItems(SystemTrayDelegate* delegate); + + // Resets |system_bubble_| and clears any related state. + void DestroySystemBubble(); + + // Resets |notification_bubble_| and clears any related state. + void DestroyNotificationBubble(); + + // Returns a string with the current time for accessibility on the status + // tray bar. + base::string16 GetAccessibleTimeString(const base::Time& now) const; + + // Calculates the x-offset for the item in the tray. Returns -1 if its tray + // item view is not visible. + int GetTrayXOffset(SystemTrayItem* item) const; + + // Shows the default view and its arrow position is shifted by |x_offset|. + void ShowDefaultViewWithOffset(BubbleCreationType creation_type, + int x_offset, + bool persistent); + + // Constructs or re-constructs |system_bubble_| and populates it with |items|. + // Specify |change_tray_status| to true if want to change the tray background + // status. + void ShowItems(const std::vector<SystemTrayItem*>& items, + bool details, + bool activate, + BubbleCreationType creation_type, + int x_offset, + bool persistent); + + // Constructs or re-constructs |notification_bubble_| and populates it with + // |notification_items_|, or destroys it if there are no notification items. + void UpdateNotificationBubble(); + + // Checks the current status of the system tray and updates the web + // notification tray according to the current status. + void UpdateWebNotifications(); + + // Deactivate the system tray in the shelf if it was active before. + void CloseSystemBubbleAndDeactivateSystemTray(); + + // Records UMA metrics for the number of user-visible rows in the system menu + // and the percentage of the work area height covered by the system menu. + void RecordSystemMenuMetrics(); + + const ScopedVector<SystemTrayItem>& items() const { return items_; } + + // Overridden from ActionableView. + bool PerformAction(const ui::Event& event) override; + + // The web notification tray view that appears adjacent to this view. + WebNotificationTray* web_notification_tray_; + + // Owned items. + ScopedVector<SystemTrayItem> items_; + + // Pointers to members of |items_|. + SystemTrayItem* detailed_item_; + std::vector<SystemTrayItem*> notification_items_; + + // Mappings of system tray item and it's view in the tray. + std::map<SystemTrayItem*, views::View*> tray_item_map_; + + // Bubble for default and detailed views. + std::unique_ptr<SystemBubbleWrapper> system_bubble_; + + // Bubble for notifications. + std::unique_ptr<SystemBubbleWrapper> notification_bubble_; + + // Keep track of the default view height so that when we create detailed + // views directly (e.g. from a notification) we know what height to use. + int default_bubble_height_; + + // Set to true when system notifications should be hidden (e.g. web + // notification bubble is visible). + bool hide_notifications_; + + // This is true when the displayed system tray menu is a full tray menu, + // otherwise a single line item menu like the volume slider is shown. + // Note that the value is only valid when |system_bubble_| is true. + bool full_system_tray_menu_; + + TrayAccessibility* tray_accessibility_; // not owned + TrayCast* tray_cast_; + TrayDate* tray_date_; + TrayUpdate* tray_update_; + + // A reference to the Screen share and capture item. + ScreenTrayItem* screen_capture_tray_item_; // not owned + ScreenTrayItem* screen_share_tray_item_; // not owned + + DISALLOW_COPY_AND_ASSIGN(SystemTray); +}; + +} // namespace ash + +#endif // ASH_COMMON_SYSTEM_TRAY_SYSTEM_TRAY_H_
diff --git a/ash/common/system/tray/system_tray_bubble.cc b/ash/common/system/tray/system_tray_bubble.cc index 09ac6d5b..ebe9414 100644 --- a/ash/common/system/tray/system_tray_bubble.cc +++ b/ash/common/system/tray/system_tray_bubble.cc
@@ -4,13 +4,13 @@ #include "ash/common/system/tray/system_tray_bubble.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/system_tray_item.h" #include "ash/common/system/tray/tray_bubble_wrapper.h" #include "ash/common/system/tray/tray_constants.h" #include "ash/common/system/tray/tray_popup_item_container.h" #include "ash/common/wm_shell.h" -#include "ash/system/tray/system_tray.h" #include "base/threading/thread_task_runner_handle.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_animation_observer.h"
diff --git a/ash/common/system/tray/system_tray_delegate.cc b/ash/common/system/tray/system_tray_delegate.cc index ee83a0f..a886d28a 100644 --- a/ash/common/system/tray/system_tray_delegate.cc +++ b/ash/common/system/tray/system_tray_delegate.cc
@@ -4,6 +4,8 @@ #include "ash/common/system/tray/system_tray_delegate.h" +#include "ash/common/system/tray/system_tray_item.h" + namespace ash { NetworkIconInfo::NetworkIconInfo() @@ -234,4 +236,14 @@ return nullptr; } +std::unique_ptr<SystemTrayItem> SystemTrayDelegate::CreateDisplayTrayItem( + SystemTray* tray) { + return nullptr; +} + +std::unique_ptr<SystemTrayItem> SystemTrayDelegate::CreateRotationLockTrayItem( + SystemTray* tray) { + return nullptr; +} + } // namespace ash
diff --git a/ash/common/system/tray/system_tray_delegate.h b/ash/common/system/tray/system_tray_delegate.h index 5c4de80..077401a 100644 --- a/ash/common/system/tray/system_tray_delegate.h +++ b/ash/common/system/tray/system_tray_delegate.h
@@ -29,6 +29,8 @@ class CustodianInfoTrayObserver; class ShutdownPolicyObserver; +class SystemTray; +class SystemTrayItem; struct ASH_EXPORT NetworkIconInfo { NetworkIconInfo(); @@ -335,6 +337,18 @@ // Returns VPNDelegate. May return nullptr. virtual VPNDelegate* GetVPNDelegate() const; + + // Creates a system tray item for display settings. + // TODO(jamescook): Remove this when mus has support for display management + // and we have a DisplayManager equivalent. See http://crbug.com/548429 + virtual std::unique_ptr<SystemTrayItem> CreateDisplayTrayItem( + SystemTray* tray); + + // Creates a system tray item for display rotation lock. + // TODO(jamescook): Remove this when mus has support for display management + // and we have a DisplayManager equivalent. See http://crbug.com/548429 + virtual std::unique_ptr<SystemTrayItem> CreateRotationLockTrayItem( + SystemTray* tray); }; } // namespace ash
diff --git a/ash/common/system/tray/system_tray_item.cc b/ash/common/system/tray/system_tray_item.cc index 83f54c1..629c4f8c 100644 --- a/ash/common/system/tray/system_tray_item.cc +++ b/ash/common/system/tray/system_tray_item.cc
@@ -4,8 +4,8 @@ #include "ash/common/system/tray/system_tray_item.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" -#include "ash/system/tray/system_tray.h" #include "ui/views/view.h" namespace ash {
diff --git a/ash/common/system/tray/system_tray_unittest.cc b/ash/common/system/tray/system_tray_unittest.cc new file mode 100644 index 0000000..4f20c19 --- /dev/null +++ b/ash/common/system/tray/system_tray_unittest.cc
@@ -0,0 +1,571 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/common/system/tray/system_tray.h" + +#include <vector> + +#include "ash/common/accessibility_delegate.h" +#include "ash/common/shelf/wm_shelf.h" +#include "ash/common/shell_window_ids.h" +#include "ash/common/system/status_area_widget.h" +#include "ash/common/system/tray/system_tray_bubble.h" +#include "ash/common/system/tray/system_tray_item.h" +#include "ash/common/system/tray/tray_constants.h" +#include "ash/common/system/tray/tray_popup_item_container.h" +#include "ash/common/system/web_notification/web_notification_tray.h" +#include "ash/common/wm_root_window_controller.h" +#include "ash/common/wm_shell.h" +#include "ash/common/wm_window.h" +#include "ash/test/ash_test_base.h" +#include "ash/test/status_area_widget_test_helper.h" +#include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "ui/base/ui_base_types.h" +#include "ui/compositor/scoped_animation_duration_scale_mode.h" +#include "ui/events/test/event_generator.h" +#include "ui/gfx/geometry/point.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/views/controls/label.h" +#include "ui/views/layout/fill_layout.h" +#include "ui/views/view.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_delegate.h" + +#if defined(OS_WIN) +#include "base/win/windows_version.h" +#endif + +namespace ash { +namespace test { + +namespace { + +std::unique_ptr<views::Widget> CreateTestWidget(views::WidgetDelegate* delegate, + int container_id) { + std::unique_ptr<views::Widget> widget(new views::Widget); + views::Widget::InitParams params; + params.delegate = delegate; + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; + params.bounds = gfx::Rect(0, 0, 100, 100); + WmShell::Get() + ->GetPrimaryRootWindow() + ->GetRootWindowController() + ->ConfigureWidgetInitParamsForContainer(widget.get(), container_id, + ¶ms); + widget->Init(params); + widget->Show(); + return widget; +} + +// Trivial item implementation that tracks its views for testing. +class TestItem : public SystemTrayItem { + public: + TestItem() + : SystemTrayItem(AshTestBase::GetPrimarySystemTray()), + tray_view_(nullptr), + default_view_(nullptr), + detailed_view_(nullptr), + notification_view_(nullptr) {} + + views::View* CreateTrayView(LoginStatus status) override { + tray_view_ = new views::View; + // Add a label so it has non-zero width. + tray_view_->SetLayoutManager(new views::FillLayout); + tray_view_->AddChildView(new views::Label(base::UTF8ToUTF16("Tray"))); + return tray_view_; + } + + views::View* CreateDefaultView(LoginStatus status) override { + default_view_ = new views::View; + default_view_->SetLayoutManager(new views::FillLayout); + default_view_->AddChildView(new views::Label(base::UTF8ToUTF16("Default"))); + return default_view_; + } + + views::View* CreateDetailedView(LoginStatus status) override { + detailed_view_ = new views::View; + detailed_view_->SetLayoutManager(new views::FillLayout); + detailed_view_->AddChildView( + new views::Label(base::UTF8ToUTF16("Detailed"))); + return detailed_view_; + } + + views::View* CreateNotificationView(LoginStatus status) override { + notification_view_ = new views::View; + return notification_view_; + } + + void DestroyTrayView() override { tray_view_ = NULL; } + + void DestroyDefaultView() override { default_view_ = NULL; } + + void DestroyDetailedView() override { detailed_view_ = NULL; } + + void DestroyNotificationView() override { notification_view_ = NULL; } + + void UpdateAfterLoginStatusChange(LoginStatus status) override {} + + views::View* tray_view() const { return tray_view_; } + views::View* default_view() const { return default_view_; } + views::View* detailed_view() const { return detailed_view_; } + views::View* notification_view() const { return notification_view_; } + + private: + views::View* tray_view_; + views::View* default_view_; + views::View* detailed_view_; + views::View* notification_view_; +}; + +// Trivial item implementation that returns NULL from tray/default/detailed +// view creation methods. +class TestNoViewItem : public SystemTrayItem { + public: + TestNoViewItem() : SystemTrayItem(AshTestBase::GetPrimarySystemTray()) {} + + views::View* CreateTrayView(LoginStatus status) override { return nullptr; } + + views::View* CreateDefaultView(LoginStatus status) override { + return nullptr; + } + + views::View* CreateDetailedView(LoginStatus status) override { + return nullptr; + } + + views::View* CreateNotificationView(LoginStatus status) override { + return nullptr; + } + + void DestroyTrayView() override {} + void DestroyDefaultView() override {} + void DestroyDetailedView() override {} + void DestroyNotificationView() override {} + void UpdateAfterLoginStatusChange(LoginStatus status) override {} +}; + +class ModalWidgetDelegate : public views::WidgetDelegateView { + public: + ModalWidgetDelegate() {} + ~ModalWidgetDelegate() override {} + + views::View* GetContentsView() override { return this; } + ui::ModalType GetModalType() const override { return ui::MODAL_TYPE_SYSTEM; } + + private: + DISALLOW_COPY_AND_ASSIGN(ModalWidgetDelegate); +}; + +} // namespace + +typedef AshTestBase SystemTrayTest; + +TEST_F(SystemTrayTest, SystemTrayDefaultView) { + SystemTray* tray = GetPrimarySystemTray(); + ASSERT_TRUE(tray->GetWidget()); + + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + + // Ensure that closing the bubble destroys it. + ASSERT_TRUE(tray->CloseSystemBubble()); + RunAllPendingInMessageLoop(); + ASSERT_FALSE(tray->CloseSystemBubble()); +} + +// Opening and closing the bubble should change the coloring of the tray. +TEST_F(SystemTrayTest, SystemTrayColoring) { + SystemTray* tray = GetPrimarySystemTray(); + ASSERT_TRUE(tray->GetWidget()); + // At the beginning the tray coloring is not active. + ASSERT_FALSE(tray->draw_background_as_active()); + + // Showing the system bubble should show the background as active. + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + ASSERT_TRUE(tray->draw_background_as_active()); + + // Closing the system menu should change the coloring back to normal. + ASSERT_TRUE(tray->CloseSystemBubble()); + RunAllPendingInMessageLoop(); + ASSERT_FALSE(tray->draw_background_as_active()); +} + +// Closing the system bubble through an alignment change should change the +// system tray coloring back to normal. +TEST_F(SystemTrayTest, SystemTrayColoringAfterAlignmentChange) { + SystemTray* tray = GetPrimarySystemTray(); + ASSERT_TRUE(tray->GetWidget()); + WmShelf* shelf = GetPrimaryShelf(); + shelf->SetAlignment(SHELF_ALIGNMENT_BOTTOM); + // At the beginning the tray coloring is not active. + ASSERT_FALSE(tray->draw_background_as_active()); + + // Showing the system bubble should show the background as active. + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + ASSERT_TRUE(tray->draw_background_as_active()); + + // Changing the alignment should close the system bubble and change the + // background color. + shelf->SetAlignment(SHELF_ALIGNMENT_LEFT); + ASSERT_FALSE(tray->draw_background_as_active()); + RunAllPendingInMessageLoop(); + // The bubble should already be closed by now. + ASSERT_FALSE(tray->CloseSystemBubble()); +} + +TEST_F(SystemTrayTest, SystemTrayTestItems) { + SystemTray* tray = GetPrimarySystemTray(); + ASSERT_TRUE(tray->GetWidget()); + + TestItem* test_item = new TestItem; + TestItem* detailed_item = new TestItem; + tray->AddTrayItem(test_item); + tray->AddTrayItem(detailed_item); + + // Check items have been added + const std::vector<SystemTrayItem*>& items = tray->GetTrayItems(); + ASSERT_TRUE(std::find(items.begin(), items.end(), test_item) != items.end()); + ASSERT_TRUE(std::find(items.begin(), items.end(), detailed_item) != + items.end()); + + // Ensure the tray views are created. + ASSERT_TRUE(test_item->tray_view() != NULL); + ASSERT_TRUE(detailed_item->tray_view() != NULL); + + // Ensure a default views are created. + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + ASSERT_TRUE(test_item->default_view() != NULL); + ASSERT_TRUE(detailed_item->default_view() != NULL); + + // Show the detailed view, ensure it's created and the default view destroyed. + tray->ShowDetailedView(detailed_item, 0, false, BUBBLE_CREATE_NEW); + RunAllPendingInMessageLoop(); + ASSERT_TRUE(test_item->default_view() == NULL); + ASSERT_TRUE(detailed_item->detailed_view() != NULL); + + // Show the default view, ensure it's created and the detailed view destroyed. + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + RunAllPendingInMessageLoop(); + ASSERT_TRUE(test_item->default_view() != NULL); + ASSERT_TRUE(detailed_item->detailed_view() == NULL); +} + +TEST_F(SystemTrayTest, SystemTrayNoViewItems) { + SystemTray* tray = GetPrimarySystemTray(); + ASSERT_TRUE(tray->GetWidget()); + + // Verify that no crashes occur on items lacking some views. + TestNoViewItem* no_view_item = new TestNoViewItem; + tray->AddTrayItem(no_view_item); + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + tray->ShowDetailedView(no_view_item, 0, false, BUBBLE_USE_EXISTING); + RunAllPendingInMessageLoop(); +} + +TEST_F(SystemTrayTest, TrayWidgetAutoResizes) { + SystemTray* tray = GetPrimarySystemTray(); + ASSERT_TRUE(tray->GetWidget()); + + // Add an initial tray item so that the tray gets laid out correctly. + TestItem* initial_item = new TestItem; + tray->AddTrayItem(initial_item); + + gfx::Size initial_size = tray->GetWidget()->GetWindowBoundsInScreen().size(); + + TestItem* new_item = new TestItem; + tray->AddTrayItem(new_item); + + gfx::Size new_size = tray->GetWidget()->GetWindowBoundsInScreen().size(); + + // Adding the new item should change the size of the tray. + EXPECT_NE(initial_size.ToString(), new_size.ToString()); + + // Hiding the tray view of the new item should also change the size of the + // tray. + new_item->tray_view()->SetVisible(false); + EXPECT_EQ(initial_size.ToString(), + tray->GetWidget()->GetWindowBoundsInScreen().size().ToString()); + + new_item->tray_view()->SetVisible(true); + EXPECT_EQ(new_size.ToString(), + tray->GetWidget()->GetWindowBoundsInScreen().size().ToString()); +} + +TEST_F(SystemTrayTest, SystemTrayNotifications) { + SystemTray* tray = GetPrimarySystemTray(); + ASSERT_TRUE(tray->GetWidget()); + + TestItem* test_item = new TestItem; + TestItem* detailed_item = new TestItem; + tray->AddTrayItem(test_item); + tray->AddTrayItem(detailed_item); + + // Ensure the tray views are created. + ASSERT_TRUE(test_item->tray_view() != NULL); + ASSERT_TRUE(detailed_item->tray_view() != NULL); + + // Ensure a notification view is created. + tray->ShowNotificationView(test_item); + ASSERT_TRUE(test_item->notification_view() != NULL); + + // Show the default view, notification view should remain. + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + RunAllPendingInMessageLoop(); + ASSERT_TRUE(test_item->notification_view() != NULL); + + // Show the detailed view, ensure the notification view remains. + tray->ShowDetailedView(detailed_item, 0, false, BUBBLE_CREATE_NEW); + RunAllPendingInMessageLoop(); + ASSERT_TRUE(detailed_item->detailed_view() != NULL); + ASSERT_TRUE(test_item->notification_view() != NULL); + + // Hide the detailed view, ensure the notification view still exists. + ASSERT_TRUE(tray->CloseSystemBubble()); + RunAllPendingInMessageLoop(); + ASSERT_TRUE(detailed_item->detailed_view() == NULL); + ASSERT_TRUE(test_item->notification_view() != NULL); +} + +TEST_F(SystemTrayTest, BubbleCreationTypesTest) { + SystemTray* tray = GetPrimarySystemTray(); + ASSERT_TRUE(tray->GetWidget()); + + TestItem* test_item = new TestItem; + tray->AddTrayItem(test_item); + + // Ensure the tray views are created. + ASSERT_TRUE(test_item->tray_view() != NULL); + + // Show the default view, ensure the notification view is destroyed. + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + RunAllPendingInMessageLoop(); + + views::Widget* widget = test_item->default_view()->GetWidget(); + gfx::Rect bubble_bounds = widget->GetWindowBoundsInScreen(); + + tray->ShowDetailedView(test_item, 0, true, BUBBLE_USE_EXISTING); + RunAllPendingInMessageLoop(); + + EXPECT_FALSE(test_item->default_view()); + + EXPECT_EQ(bubble_bounds.ToString(), test_item->detailed_view() + ->GetWidget() + ->GetWindowBoundsInScreen() + .ToString()); + EXPECT_EQ(widget, test_item->detailed_view()->GetWidget()); + + tray->ShowDefaultView(BUBBLE_USE_EXISTING); + RunAllPendingInMessageLoop(); + + EXPECT_EQ(bubble_bounds.ToString(), test_item->default_view() + ->GetWidget() + ->GetWindowBoundsInScreen() + .ToString()); + EXPECT_EQ(widget, test_item->default_view()->GetWidget()); +} + +// Tests that the tray view is laid out properly and is fully contained within +// the shelf widget. +TEST_F(SystemTrayTest, TrayBoundsInWidget) { + WmShelf* shelf = GetPrimaryShelf(); + StatusAreaWidget* widget = StatusAreaWidgetTestHelper::GetStatusAreaWidget(); + SystemTray* tray = GetPrimarySystemTray(); + + // Test in bottom alignment. + shelf->SetAlignment(SHELF_ALIGNMENT_BOTTOM); + gfx::Rect window_bounds = widget->GetWindowBoundsInScreen(); + gfx::Rect tray_bounds = tray->GetBoundsInScreen(); + EXPECT_TRUE(window_bounds.Contains(tray_bounds)); + + // Test in locked alignment. + shelf->SetAlignment(SHELF_ALIGNMENT_BOTTOM_LOCKED); + window_bounds = widget->GetWindowBoundsInScreen(); + tray_bounds = tray->GetBoundsInScreen(); + EXPECT_TRUE(window_bounds.Contains(tray_bounds)); + + // Test in the left alignment. + shelf->SetAlignment(SHELF_ALIGNMENT_LEFT); + window_bounds = widget->GetWindowBoundsInScreen(); + tray_bounds = tray->GetBoundsInScreen(); + EXPECT_TRUE(window_bounds.Contains(tray_bounds)); + + // Test in the right alignment. + shelf->SetAlignment(SHELF_ALIGNMENT_LEFT); + window_bounds = widget->GetWindowBoundsInScreen(); + tray_bounds = tray->GetBoundsInScreen(); + EXPECT_TRUE(window_bounds.Contains(tray_bounds)); +} + +TEST_F(SystemTrayTest, PersistentBubble) { + SystemTray* tray = GetPrimarySystemTray(); + ASSERT_TRUE(tray->GetWidget()); + + TestItem* test_item = new TestItem; + tray->AddTrayItem(test_item); + + std::unique_ptr<views::Widget> widget( + CreateTestWidget(nullptr, kShellWindowId_DefaultContainer)); + + // Tests for usual default view while activating a window. + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + ASSERT_TRUE(tray->HasSystemBubble()); + widget->Activate(); + base::RunLoop().RunUntilIdle(); + ASSERT_FALSE(tray->HasSystemBubble()); + + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + ASSERT_TRUE(tray->HasSystemBubble()); + { + ui::test::EventGenerator& generator = GetEventGenerator(); + generator.set_current_location(gfx::Point(5, 5)); + generator.ClickLeftButton(); + ASSERT_FALSE(tray->HasSystemBubble()); + } + + // Same tests for persistent default view. + tray->ShowPersistentDefaultView(); + ASSERT_TRUE(tray->HasSystemBubble()); + widget->Activate(); + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(tray->HasSystemBubble()); + + { + ui::test::EventGenerator& generator = GetEventGenerator(); + generator.set_current_location(gfx::Point(5, 5)); + generator.ClickLeftButton(); + ASSERT_TRUE(tray->HasSystemBubble()); + } +} + +#if defined(OS_CHROMEOS) +// Accessibility/Settings tray items are available only on cros. +#define MAYBE_WithSystemModal WithSystemModal +#else +#define MAYBE_WithSystemModal DISABLED_WithSystemModal +#endif +TEST_F(SystemTrayTest, MAYBE_WithSystemModal) { + // Check if the accessibility item is created even with system modal dialog. + WmShell::Get()->GetAccessibilityDelegate()->SetVirtualKeyboardEnabled(true); + std::unique_ptr<views::Widget> widget(CreateTestWidget( + new ModalWidgetDelegate, kShellWindowId_SystemModalContainer)); + + SystemTray* tray = GetPrimarySystemTray(); + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + + ASSERT_TRUE(tray->HasSystemBubble()); + const views::View* accessibility = + tray->GetSystemBubble()->bubble_view()->GetViewByID( + test::kAccessibilityTrayItemViewId); + ASSERT_TRUE(accessibility); + EXPECT_TRUE(accessibility->visible()); + EXPECT_FALSE(tray->GetSystemBubble()->bubble_view()->GetViewByID( + test::kSettingsTrayItemViewId)); + + // Close the modal dialog. + widget.reset(); + + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + // System modal is gone. The bubble should now contains settings + // as well. + accessibility = tray->GetSystemBubble()->bubble_view()->GetViewByID( + test::kAccessibilityTrayItemViewId); + ASSERT_TRUE(accessibility); + EXPECT_TRUE(accessibility->visible()); + + const views::View* settings = + tray->GetSystemBubble()->bubble_view()->GetViewByID( + test::kSettingsTrayItemViewId); + ASSERT_TRUE(settings); + EXPECT_TRUE(settings->visible()); +} + +// Tests that if SetVisible(true) is called while animating to hidden that the +// tray becomes visible, and stops animating to hidden. +TEST_F(SystemTrayTest, SetVisibleDuringHideAnimation) { + SystemTray* tray = GetPrimarySystemTray(); + ASSERT_TRUE(tray->visible()); + + std::unique_ptr<ui::ScopedAnimationDurationScaleMode> animation_duration; + animation_duration.reset(new ui::ScopedAnimationDurationScaleMode( + ui::ScopedAnimationDurationScaleMode::SLOW_DURATION)); + tray->SetVisible(false); + EXPECT_TRUE(tray->visible()); + EXPECT_EQ(0.0f, tray->layer()->GetTargetOpacity()); + + tray->SetVisible(true); + animation_duration.reset(); + tray->layer()->GetAnimator()->StopAnimating(); + EXPECT_TRUE(tray->visible()); + EXPECT_EQ(1.0f, tray->layer()->GetTargetOpacity()); +} + +#if defined(OS_CHROMEOS) +// Tests that touch on an item in the system bubble triggers it to become +// active. +TEST_F(SystemTrayTest, TrayPopupItemContainerTouchFeedback) { + SystemTray* tray = GetPrimarySystemTray(); + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + + TrayPopupItemContainer* view = static_cast<TrayPopupItemContainer*>( + tray->GetSystemBubble()->bubble_view()->child_at(0)); + EXPECT_FALSE(view->active()); + + ui::test::EventGenerator& generator = GetEventGenerator(); + generator.set_current_location(view->GetBoundsInScreen().CenterPoint()); + generator.PressTouch(); + EXPECT_TRUE(view->active()); + + generator.ReleaseTouch(); + EXPECT_FALSE(view->active()); +} + +// Tests that touch events on an item in the system bubble cause it to stop +// being active. +TEST_F(SystemTrayTest, TrayPopupItemContainerTouchFeedbackCancellation) { + SystemTray* tray = GetPrimarySystemTray(); + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + + TrayPopupItemContainer* view = static_cast<TrayPopupItemContainer*>( + tray->GetSystemBubble()->bubble_view()->child_at(0)); + EXPECT_FALSE(view->active()); + + gfx::Rect view_bounds = view->GetBoundsInScreen(); + ui::test::EventGenerator& generator = GetEventGenerator(); + generator.set_current_location(view_bounds.CenterPoint()); + generator.PressTouch(); + EXPECT_TRUE(view->active()); + + gfx::Point move_point(view_bounds.x(), view_bounds.CenterPoint().y()); + generator.MoveTouch(move_point); + EXPECT_FALSE(view->active()); + + generator.set_current_location(move_point); + generator.ReleaseTouch(); + EXPECT_FALSE(view->active()); +} + +TEST_F(SystemTrayTest, SystemTrayHeightWithBubble) { + SystemTray* tray = GetPrimarySystemTray(); + WebNotificationTray* notification_tray = + StatusAreaWidgetTestHelper::GetStatusAreaWidget() + ->web_notification_tray(); + + // Ensure the initial tray bubble height is zero. + EXPECT_EQ(0, notification_tray->tray_bubble_height_for_test()); + + // Show the default view, ensure the tray bubble height is changed. + tray->ShowDefaultView(BUBBLE_CREATE_NEW); + RunAllPendingInMessageLoop(); + EXPECT_LT(0, notification_tray->tray_bubble_height_for_test()); + + // Hide the default view, ensure the tray bubble height is back to zero. + ASSERT_TRUE(tray->CloseSystemBubble()); + RunAllPendingInMessageLoop(); + + EXPECT_EQ(0, notification_tray->tray_bubble_height_for_test()); +} +#endif // OS_CHROMEOS + +} // namespace test +} // namespace ash
diff --git a/ash/common/system/tray/tray_background_view.cc b/ash/common/system/tray/tray_background_view.cc index 2192034ab..569e9393 100644 --- a/ash/common/system/tray/tray_background_view.cc +++ b/ash/common/system/tray/tray_background_view.cc
@@ -9,12 +9,12 @@ #include "ash/common/shelf/wm_shelf.h" #include "ash/common/shelf/wm_shelf_util.h" #include "ash/common/shell_window_ids.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/tray_constants.h" #include "ash/common/system/tray/tray_event_filter.h" #include "ash/common/wm_lookup.h" #include "ash/common/wm_shell.h" #include "ash/common/wm_window.h" -#include "ash/system/tray/system_tray.h" #include "grit/ash_resources.h" #include "ui/accessibility/ax_view_state.h" #include "ui/base/nine_image_painter_factory.h"
diff --git a/ash/common/system/tray/tray_details_view.cc b/ash/common/system/tray/tray_details_view.cc index 6352469..5a1df68 100644 --- a/ash/common/system/tray/tray_details_view.cc +++ b/ash/common/system/tray/tray_details_view.cc
@@ -5,9 +5,9 @@ #include "ash/common/system/tray/tray_details_view.h" #include "ash/common/system/tray/fixed_sized_scroll_view.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_item.h" #include "ash/common/system/tray/tray_constants.h" -#include "ash/system/tray/system_tray.h" #include "ui/gfx/canvas.h" #include "ui/views/background.h" #include "ui/views/border.h"
diff --git a/ash/common/system/tray/tray_details_view_unittest.cc b/ash/common/system/tray/tray_details_view_unittest.cc index c33bcf1..4b9f1db 100644 --- a/ash/common/system/tray/tray_details_view_unittest.cc +++ b/ash/common/system/tray/tray_details_view_unittest.cc
@@ -6,10 +6,10 @@ #include "ash/common/system/tray/hover_highlight_view.h" #include "ash/common/system/tray/special_popup_row.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_item.h" #include "ash/common/system/tray/tray_popup_header_button.h" #include "ash/common/system/tray/view_click_listener.h" -#include "ash/system/tray/system_tray.h" #include "ash/test/ash_test_base.h" #include "base/run_loop.h" #include "grit/ash_resources.h"
diff --git a/ash/common/system/tray/tray_image_item.cc b/ash/common/system/tray/tray_image_item.cc index 77f8b49..590be18f 100644 --- a/ash/common/system/tray/tray_image_item.cc +++ b/ash/common/system/tray/tray_image_item.cc
@@ -6,10 +6,10 @@ #include "ash/common/material_design/material_design_controller.h" #include "ash/common/shelf/wm_shelf_util.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/tray_constants.h" #include "ash/common/system/tray/tray_item_view.h" #include "ash/common/system/tray/tray_utils.h" -#include "ash/system/tray/system_tray.h" #include "grit/ash_resources.h" #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/image/image.h"
diff --git a/ash/common/system/tray/tray_item_view.cc b/ash/common/system/tray/tray_item_view.cc index 927e63f..53d5d27 100644 --- a/ash/common/system/tray/tray_item_view.cc +++ b/ash/common/system/tray/tray_item_view.cc
@@ -6,8 +6,8 @@ #include "ash/common/shelf/shelf_types.h" #include "ash/common/shelf/wm_shelf_util.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_item.h" -#include "ash/system/tray/system_tray.h" #include "ui/compositor/layer.h" #include "ui/gfx/animation/slide_animation.h" #include "ui/views/controls/image_view.h"
diff --git a/ash/common/system/tray_accessibility.cc b/ash/common/system/tray_accessibility.cc index b8413bf..b4074f1 100644 --- a/ash/common/system/tray_accessibility.cc +++ b/ash/common/system/tray_accessibility.cc
@@ -9,6 +9,7 @@ #include "ash/common/material_design/material_design_controller.h" #include "ash/common/session/session_state_delegate.h" #include "ash/common/system/tray/hover_highlight_view.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/system_tray_notifier.h" #include "ash/common/system/tray/tray_constants.h" @@ -16,7 +17,6 @@ #include "ash/common/system/tray/tray_item_more.h" #include "ash/common/system/tray/tray_popup_label_button.h" #include "ash/common/wm_shell.h" -#include "ash/system/tray/system_tray.h" #include "base/strings/utf_string_conversions.h" #include "grit/ash_resources.h" #include "grit/ash_strings.h"
diff --git a/ash/common/system/update/tray_update.cc b/ash/common/system/update/tray_update.cc index 5da745c3..b5d3b6a0a 100644 --- a/ash/common/system/update/tray_update.cc +++ b/ash/common/system/update/tray_update.cc
@@ -6,11 +6,11 @@ #include "ash/common/metrics/user_metrics_action.h" #include "ash/common/system/tray/fixed_sized_image_view.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/system_tray_notifier.h" #include "ash/common/system/tray/tray_constants.h" #include "ash/common/wm_shell.h" -#include "ash/system/tray/system_tray.h" #include "grit/ash_resources.h" #include "grit/ash_strings.h" #include "ui/base/resource/resource_bundle.h"
diff --git a/ash/common/system/update/tray_update_unittest.cc b/ash/common/system/update/tray_update_unittest.cc index 74e275f..53f1149 100644 --- a/ash/common/system/update/tray_update_unittest.cc +++ b/ash/common/system/update/tray_update_unittest.cc
@@ -4,9 +4,9 @@ #include "ash/common/system/update/tray_update.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_notifier.h" #include "ash/common/wm_shell.h" -#include "ash/system/tray/system_tray.h" #include "ash/test/ash_test_base.h" #include "ash/test/test_system_tray_delegate.h" #include "base/macros.h"
diff --git a/ash/common/system/user/tray_user.cc b/ash/common/system/user/tray_user.cc index 4633076..93f7064 100644 --- a/ash/common/system/user/tray_user.cc +++ b/ash/common/system/user/tray_user.cc
@@ -7,6 +7,7 @@ #include "ash/common/ash_switches.h" #include "ash/common/session/session_state_delegate.h" #include "ash/common/shelf/wm_shelf_util.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/system_tray_notifier.h" #include "ash/common/system/tray/tray_constants.h" @@ -15,7 +16,6 @@ #include "ash/common/system/user/rounded_image_view.h" #include "ash/common/system/user/user_view.h" #include "ash/common/wm_shell.h" -#include "ash/system/tray/system_tray.h" #include "base/logging.h" #include "base/strings/string16.h" #include "components/signin/core/account_id/account_id.h"
diff --git a/ash/common/system/user/tray_user_unittest.cc b/ash/common/system/user/tray_user_unittest.cc index b55ab9a..2c58c67 100644 --- a/ash/common/system/user/tray_user_unittest.cc +++ b/ash/common/system/user/tray_user_unittest.cc
@@ -5,12 +5,12 @@ #include <vector> #include "ash/common/shell_delegate.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/tray_constants.h" #include "ash/common/system/user/tray_user.h" #include "ash/common/system/user/tray_user_separator.h" #include "ash/common/system/user/user_view.h" #include "ash/common/wm_shell.h" -#include "ash/system/tray/system_tray.h" #include "ash/test/ash_test_base.h" #include "ash/test/ash_test_helper.h" #include "ash/test/test_session_state_delegate.h"
diff --git a/ash/common/system/user/user_view.cc b/ash/common/system/user/user_view.cc index 6bbb6a2..e48f160 100644 --- a/ash/common/system/user/user_view.cc +++ b/ash/common/system/user/user_view.cc
@@ -12,6 +12,7 @@ #include "ash/common/session/session_state_delegate.h" #include "ash/common/shell_delegate.h" #include "ash/common/shell_window_ids.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/tray_constants.h" #include "ash/common/system/tray/tray_popup_label_button.h" @@ -24,7 +25,6 @@ #include "ash/common/wm_root_window_controller.h" #include "ash/common/wm_shell.h" #include "ash/common/wm_window.h" -#include "ash/system/tray/system_tray.h" #include "components/signin/core/account_id/account_id.h" #include "components/user_manager/user_info.h" #include "grit/ash_resources.h"
diff --git a/ash/common/system/web_notification/web_notification_tray.cc b/ash/common/system/web_notification/web_notification_tray.cc index 787c46e..5ab3774 100644 --- a/ash/common/system/web_notification/web_notification_tray.cc +++ b/ash/common/system/web_notification/web_notification_tray.cc
@@ -11,6 +11,7 @@ #include "ash/common/shelf/wm_shelf.h" #include "ash/common/shelf/wm_shelf_util.h" #include "ash/common/shell_window_ids.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/tray_bubble_wrapper.h" #include "ash/common/system/tray/tray_constants.h" @@ -20,7 +21,6 @@ #include "ash/common/wm_root_window_controller.h" #include "ash/common/wm_shell.h" #include "ash/common/wm_window.h" -#include "ash/system/tray/system_tray.h" #include "base/auto_reset.h" #include "base/i18n/number_formatting.h" #include "base/i18n/rtl.h" @@ -139,7 +139,7 @@ unread_label_.set_owned_by_client(); SetupLabelForTray(&unread_label_); - AddChildView(&unread_label_); + AddChildView(&no_unread_icon_); } void SetBubbleVisible(bool visible) { @@ -450,7 +450,7 @@ bool WebNotificationTray::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; } @@ -516,9 +516,8 @@ bool WebNotificationTray::IsLoggedIn() const { WmShell* shell = WmShell::Get(); - LoginStatus status = shell->system_tray_delegate()->GetUserLoginStatus(); - return status != LoginStatus::NOT_LOGGED_IN && - status != LoginStatus::LOCKED && + return shell->system_tray_delegate()->GetUserLoginStatus() != + LoginStatus::NOT_LOGGED_IN && !shell->GetSessionStateDelegate()->IsInSecondaryLoginScreen(); }
diff --git a/ash/common/system/web_notification/web_notification_tray.h b/ash/common/system/web_notification/web_notification_tray.h index b4bd2f4..0527238 100644 --- a/ash/common/system/web_notification/web_notification_tray.h +++ b/ash/common/system/web_notification/web_notification_tray.h
@@ -123,7 +123,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; message_center::MessageCenter* message_center() const;
diff --git a/ash/common/wm/overview/scoped_transform_overview_window.cc b/ash/common/wm/overview/scoped_transform_overview_window.cc index 0816a10c..d68159f 100644 --- a/ash/common/wm/overview/scoped_transform_overview_window.cc +++ b/ash/common/wm/overview/scoped_transform_overview_window.cc
@@ -183,6 +183,7 @@ explicit OverviewContentMask(float radius); ~OverviewContentMask() override; + void set_radius(float radius) { radius_ = radius; } ui::Layer* layer() { return &layer_; } // Overridden from LayerDelegate. @@ -247,6 +248,7 @@ ScopedTransformOverviewWindow::ScopedTransformOverviewWindow(WmWindow* window) : window_(window), + determined_original_window_shape_(false), minimized_(window->GetShowState() == ui::SHOW_STATE_MINIMIZED), ignored_by_shelf_(window->GetWindowState()->ignored_by_shelf()), overview_started_(false), @@ -405,15 +407,22 @@ if (ash::MaterialDesignController::IsOverviewMaterial() && &transform != &original_transform_) { + if (!mask_) { + mask_.reset(new OverviewContentMask(radius)); + mask_->layer()->SetFillsBoundsOpaquely(false); + window()->GetLayer()->SetMaskLayer(mask_->layer()); + } gfx::Rect bounds(GetTargetBoundsInScreen().size()); - mask_.reset(new OverviewContentMask(radius)); - mask_->layer()->SetFillsBoundsOpaquely(false); mask_->layer()->SetBounds(bounds); - window()->GetLayer()->SetMaskLayer(mask_->layer()); + mask_->set_radius(radius); + window()->GetLayer()->SchedulePaint(bounds); - SkRegion* window_shape = window()->GetLayer()->alpha_shape(); - if (!original_window_shape_ && window_shape) - original_window_shape_.reset(new SkRegion(*window_shape)); + if (!determined_original_window_shape_) { + determined_original_window_shape_ = true; + SkRegion* window_shape = window()->GetLayer()->alpha_shape(); + if (!original_window_shape_ && window_shape) + original_window_shape_.reset(new SkRegion(*window_shape)); + } const int inset = window()->GetIntProperty(WmWindowProperty::TOP_VIEW_INSET); if (inset > 0) {
diff --git a/ash/common/wm/overview/scoped_transform_overview_window.h b/ash/common/wm/overview/scoped_transform_overview_window.h index e593106..adf25f20 100644 --- a/ash/common/wm/overview/scoped_transform_overview_window.h +++ b/ash/common/wm/overview/scoped_transform_overview_window.h
@@ -140,6 +140,10 @@ // Original window shape, if it was set on a window. std::unique_ptr<SkRegion> original_window_shape_; + // True after the |original_window_shape_| has been set or after it has + // been determined that window shape was not originally set on the |window_|. + bool determined_original_window_shape_; + // If true, the window was minimized and should be restored if the window // was not selected. bool minimized_;
diff --git a/ash/common/wm_window_observer.h b/ash/common/wm_window_observer.h index fd7250a..a50b00e 100644 --- a/ash/common/wm_window_observer.h +++ b/ash/common/wm_window_observer.h
@@ -46,6 +46,7 @@ const gfx::Rect& new_bounds) {} virtual void OnWindowVisibilityChanging(WmWindow* window, bool visible) {} + virtual void OnWindowVisibilityChanged(WmWindow* window, bool visible) {} virtual void OnWindowTitleChanged(WmWindow* window) {}
diff --git a/ash/content/screen_orientation_delegate_chromeos.cc b/ash/content/screen_orientation_delegate_chromeos.cc index 68777e67..93bc8c6 100644 --- a/ash/content/screen_orientation_delegate_chromeos.cc +++ b/ash/content/screen_orientation_delegate_chromeos.cc
@@ -4,6 +4,7 @@ #include "ash/content/screen_orientation_delegate_chromeos.h" +#include "ash/aura/wm_window_aura.h" #include "ash/display/screen_orientation_controller_chromeos.h" #include "ash/shell.h" #include "content/public/browser/screen_orientation_provider.h" @@ -14,6 +15,7 @@ ScreenOrientationDelegateChromeos::ScreenOrientationDelegateChromeos() { content::ScreenOrientationProvider::SetDelegate(this); } + ScreenOrientationDelegateChromeos::~ScreenOrientationDelegateChromeos() { content::ScreenOrientationProvider::SetDelegate(nullptr); } @@ -28,8 +30,8 @@ blink::WebScreenOrientationLockType lock_orientation) { Shell::GetInstance() ->screen_orientation_controller() - ->LockOrientationForWindow(web_contents->GetNativeView(), - lock_orientation); + ->LockOrientationForWindow( + WmWindowAura::Get(web_contents->GetNativeView()), lock_orientation); } bool ScreenOrientationDelegateChromeos::ScreenOrientationProviderSupported() { @@ -37,11 +39,13 @@ ->screen_orientation_controller() ->ScreenOrientationProviderSupported(); } + void ScreenOrientationDelegateChromeos::Unlock( content::WebContents* web_contents) { Shell::GetInstance() ->screen_orientation_controller() - ->UnlockOrientationForWindow(web_contents->GetNativeView()); + ->UnlockOrientationForWindow( + WmWindowAura::Get(web_contents->GetNativeView())); } } // namespace ash
diff --git a/ash/display/screen_orientation_controller_chromeos.cc b/ash/display/screen_orientation_controller_chromeos.cc index 10afdd43..41fd5aa 100644 --- a/ash/display/screen_orientation_controller_chromeos.cc +++ b/ash/display/screen_orientation_controller_chromeos.cc
@@ -8,6 +8,7 @@ #include "ash/common/display/display_info.h" #include "ash/common/wm/maximize_mode/maximize_mode_controller.h" #include "ash/common/wm_shell.h" +#include "ash/common/wm_window.h" #include "ash/display/display_configuration_controller.h" #include "ash/display/display_manager.h" #include "ash/shell.h" @@ -15,12 +16,11 @@ #include "base/command_line.h" #include "chromeos/accelerometer/accelerometer_reader.h" #include "chromeos/accelerometer/accelerometer_types.h" -#include "ui/aura/window.h" -#include "ui/aura/window_observer.h" #include "ui/chromeos/accelerometer/accelerometer_util.h" #include "ui/display/display.h" #include "ui/gfx/geometry/size.h" -#include "ui/wm/public/activation_client.h" + +namespace ash { namespace { @@ -39,9 +39,8 @@ if (!display::Display::HasInternalDisplay()) return blink::WebScreenOrientationLockLandscape; - ash::DisplayInfo info = - ash::Shell::GetInstance()->display_manager()->GetDisplayInfo( - display::Display::InternalDisplayId()); + DisplayInfo info = + WmShell::Get()->GetDisplayInfo(display::Display::InternalDisplayId()); gfx::Size size = info.size_in_pixel(); switch (info.GetActiveRotation()) { case display::Display::ROTATE_0: @@ -61,8 +60,6 @@ } // namespace -namespace ash { - ScreenOrientationController::ScreenOrientationController() : natural_orientation_(GetDisplayNaturalOrientation()), ignore_display_configuration_updates_(false), @@ -76,8 +73,8 @@ ScreenOrientationController::~ScreenOrientationController() { WmShell::Get()->RemoveShellObserver(this); chromeos::AccelerometerReader::GetInstance()->RemoveObserver(this); - Shell::GetInstance()->window_tree_host_manager()->RemoveObserver(this); - Shell::GetInstance()->activation_client()->RemoveObserver(this); + WmShell::Get()->RemoveDisplayObserver(this); + WmShell::Get()->RemoveActivationObserver(this); for (auto& windows : locking_windows_) windows.first->RemoveObserver(this); } @@ -91,10 +88,10 @@ } void ScreenOrientationController::LockOrientationForWindow( - aura::Window* requesting_window, + WmWindow* requesting_window, blink::WebScreenOrientationLockType lock_orientation) { if (locking_windows_.empty()) - Shell::GetInstance()->activation_client()->AddObserver(this); + WmShell::Get()->AddActivationObserver(this); if (!requesting_window->HasObserver(this)) requesting_window->AddObserver(this); @@ -103,11 +100,10 @@ ApplyLockForActiveWindow(); } -void ScreenOrientationController::UnlockOrientationForWindow( - aura::Window* window) { +void ScreenOrientationController::UnlockOrientationForWindow(WmWindow* window) { locking_windows_.erase(window); if (locking_windows_.empty()) - Shell::GetInstance()->activation_client()->RemoveObserver(this); + WmShell::Get()->RemoveActivationObserver(this); window->RemoveObserver(this); ApplyLockForActiveWindow(); } @@ -116,7 +112,7 @@ for (auto pair : locking_windows_) pair.first->RemoveObserver(this); locking_windows_.clear(); - Shell::GetInstance()->activation_client()->RemoveObserver(this); + WmShell::Get()->RemoveActivationObserver(this); SetRotationLocked(false); if (user_rotation_ != current_rotation_) SetDisplayRotation(user_rotation_, display::Display::ROTATION_SOURCE_USER); @@ -160,13 +156,15 @@ true /* user_action */); } -void ScreenOrientationController::OnWindowActivated( - aura::client::ActivationChangeObserver::ActivationReason reason, - aura::Window* gained_active, - aura::Window* lost_active) { +void ScreenOrientationController::OnWindowActivated(WmWindow* gained_active, + WmWindow* lost_active) { ApplyLockForActiveWindow(); } +void ScreenOrientationController::OnWindowDestroying(WmWindow* window) { + UnlockOrientationForWindow(window); +} + // Currently contents::WebContents will only be able to lock rotation while // fullscreen. In this state a user cannot click on the tab strip to change. If // this becomes supported for non-fullscreen tabs then the following interferes @@ -174,18 +172,13 @@ // down and mouse up. The rotation this triggers leads to a coordinate space // change in the middle of an event. Causes the tab to separate from the tab // strip. -void ScreenOrientationController::OnWindowVisibilityChanged( - aura::Window* window, - bool visible) { +void ScreenOrientationController::OnWindowVisibilityChanged(WmWindow* window, + bool visible) { if (locking_windows_.find(window) == locking_windows_.end()) return; ApplyLockForActiveWindow(); } -void ScreenOrientationController::OnWindowDestroying(aura::Window* window) { - UnlockOrientationForWindow(window); -} - void ScreenOrientationController::OnAccelerometerUpdated( scoped_refptr<const chromeos::AccelerometerUpdate> update) { if (rotation_locked_ && !CanRotateInLockedState()) @@ -205,9 +198,9 @@ return; if (!display::Display::HasInternalDisplay()) return; - DisplayManager* display_manager = Shell::GetInstance()->display_manager(); display::Display::Rotation user_rotation = - display_manager->GetDisplayInfo(display::Display::InternalDisplayId()) + WmShell::Get() + ->GetDisplayInfo(display::Display::InternalDisplayId()) .GetActiveRotation(); if (user_rotation != current_rotation_) { // A user may change other display configuration settings. When the user @@ -224,20 +217,19 @@ // Always start observing. if (display::Display::HasInternalDisplay()) { current_rotation_ = user_rotation_ = - Shell::GetInstance() - ->display_manager() + WmShell::Get() ->GetDisplayInfo(display::Display::InternalDisplayId()) .GetActiveRotation(); } if (!rotation_locked_) LoadDisplayRotationProperties(); chromeos::AccelerometerReader::GetInstance()->AddObserver(this); - Shell::GetInstance()->window_tree_host_manager()->AddObserver(this); + WmShell::Get()->AddDisplayObserver(this); } void ScreenOrientationController::OnMaximizeModeEnded() { chromeos::AccelerometerReader::GetInstance()->RemoveObserver(this); - Shell::GetInstance()->window_tree_host_manager()->RemoveObserver(this); + WmShell::Get()->RemoveDisplayObserver(this); if (current_rotation_ != user_rotation_) SetDisplayRotation(user_rotation_, display::Display::ROTATION_SOURCE_USER); } @@ -309,9 +301,9 @@ if (!display::Display::HasInternalDisplay()) return; - DisplayManager* display_manager = Shell::GetInstance()->display_manager(); display::Display::Rotation rotation = - display_manager->GetDisplayInfo(display::Display::InternalDisplayId()) + WmShell::Get() + ->GetDisplayInfo(display::Display::InternalDisplayId()) .GetActiveRotation(); if (natural_orientation_ == lock_orientation) { if (rotation == display::Display::ROTATE_0 || @@ -394,11 +386,10 @@ } void ScreenOrientationController::ApplyLockForActiveWindow() { - aura::Window* active_window = - Shell::GetInstance()->activation_client()->GetActiveWindow(); + WmWindow* active_window = WmShell::Get()->GetActiveWindow(); if (active_window) { for (auto const& windows : locking_windows_) { - if (windows.first->TargetVisibility() && + if (windows.first->GetTargetVisibility() && active_window->Contains(windows.first)) { LockRotationToOrientation(windows.second); return;
diff --git a/ash/display/screen_orientation_controller_chromeos.h b/ash/display/screen_orientation_controller_chromeos.h index 3b92826..7a09c66 100644 --- a/ash/display/screen_orientation_controller_chromeos.h +++ b/ash/display/screen_orientation_controller_chromeos.h
@@ -9,28 +9,24 @@ #include "ash/ash_export.h" #include "ash/common/shell_observer.h" -#include "ash/display/window_tree_host_manager.h" +#include "ash/common/wm_activation_observer.h" +#include "ash/common/wm_display_observer.h" +#include "ash/common/wm_window_observer.h" #include "base/macros.h" #include "base/observer_list.h" #include "chromeos/accelerometer/accelerometer_reader.h" #include "chromeos/accelerometer/accelerometer_types.h" #include "third_party/WebKit/public/platform/modules/screen_orientation/WebScreenOrientationLockType.h" -#include "ui/aura/window_observer.h" #include "ui/display/display.h" -#include "ui/wm/public/activation_change_observer.h" - -namespace aura { -class Window; -} namespace ash { // Implements ChromeOS specific functionality for ScreenOrientationProvider. class ASH_EXPORT ScreenOrientationController - : public aura::client::ActivationChangeObserver, - public aura::WindowObserver, + : public WmActivationObserver, + public WmWindowObserver, public chromeos::AccelerometerReader::Observer, - public WindowTreeHostManager::Observer, + public WmDisplayObserver, public ShellObserver { public: // Observer that reports changes to the state of ScreenOrientationProvider's @@ -53,9 +49,9 @@ // Allows/unallows a window to lock the screen orientation. void LockOrientationForWindow( - aura::Window* requesting_windowwindow, + WmWindow* requesting_window, blink::WebScreenOrientationLockType lock_orientation); - void UnlockOrientationForWindow(aura::Window* window); + void UnlockOrientationForWindow(WmWindow* window); // Unlock all and set the rotation back to the user specified rotation. void UnlockAll(); @@ -80,21 +76,19 @@ void SetDisplayRotation(display::Display::Rotation rotation, display::Display::RotationSource source); - // aura::client::ActivationChangeObserver: - void OnWindowActivated( - aura::client::ActivationChangeObserver::ActivationReason reason, - aura::Window* gained_active, - aura::Window* lost_active) override; + // WmActivationObserver: + void OnWindowActivated(WmWindow* gained_active, + WmWindow* lost_active) override; - // aura::WindowObserver: - void OnWindowVisibilityChanged(aura::Window* window, bool visible) override; - void OnWindowDestroying(aura::Window* window) override; + // WmWindowObserver: + void OnWindowDestroying(WmWindow* window) override; + void OnWindowVisibilityChanged(WmWindow* window, bool visible) override; // chromeos::AccelerometerReader::Observer: void OnAccelerometerUpdated( scoped_refptr<const chromeos::AccelerometerUpdate> update) override; - // WindowTreeHostManager::Observer: + // WmDisplayObserver: void OnDisplayConfigurationChanged() override; // ShellObserver: @@ -180,7 +174,7 @@ // Tracks all windows that have requested a lock, as well as the requested // orientation. - std::map<aura::Window*, blink::WebScreenOrientationLockType> locking_windows_; + std::map<WmWindow*, blink::WebScreenOrientationLockType> locking_windows_; DISALLOW_COPY_AND_ASSIGN(ScreenOrientationController); };
diff --git a/ash/display/window_tree_host_manager.cc b/ash/display/window_tree_host_manager.cc index 233045a..79badc2 100644 --- a/ash/display/window_tree_host_manager.cc +++ b/ash/display/window_tree_host_manager.cc
@@ -11,6 +11,7 @@ #include <utility> #include "ash/common/ash_switches.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/display/cursor_window_controller.h" #include "ash/display/display_layout_store.h" #include "ash/display/display_manager.h" @@ -26,7 +27,6 @@ #include "ash/root_window_settings.h" #include "ash/screen_util.h" #include "ash/shell.h" -#include "ash/system/tray/system_tray.h" #include "ash/wm/window_util.h" #include "base/command_line.h" #include "base/stl_util.h"
diff --git a/ash/extended_desktop_unittest.cc b/ash/extended_desktop_unittest.cc index 595c60b..1d13390f 100644 --- a/ash/extended_desktop_unittest.cc +++ b/ash/extended_desktop_unittest.cc
@@ -4,12 +4,12 @@ #include "ash/aura/wm_window_aura.h" #include "ash/common/shell_window_ids.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/wm/root_window_finder.h" #include "ash/display/display_manager.h" #include "ash/root_window_controller.h" #include "ash/screen_util.h" #include "ash/shell.h" -#include "ash/system/tray/system_tray.h" #include "ash/test/ash_test_base.h" #include "ash/wm/window_properties.h" #include "ash/wm/window_util.h"
diff --git a/ash/first_run/first_run_helper_impl.cc b/ash/first_run/first_run_helper_impl.cc index 46dbd8c3..1576454 100644 --- a/ash/first_run/first_run_helper_impl.cc +++ b/ash/first_run/first_run_helper_impl.cc
@@ -5,10 +5,10 @@ #include "ash/first_run/first_run_helper_impl.h" #include "ash/common/shell_window_ids.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/shelf/app_list_button.h" #include "ash/shelf/shelf.h" #include "ash/shell.h" -#include "ash/system/tray/system_tray.h" #include "base/logging.h" #include "ui/app_list/views/app_list_view.h" #include "ui/aura/window.h"
diff --git a/ash/focus_cycler_unittest.cc b/ash/focus_cycler_unittest.cc index 3ab72cc..30c0dce 100644 --- a/ash/focus_cycler_unittest.cc +++ b/ash/focus_cycler_unittest.cc
@@ -6,12 +6,12 @@ #include <memory> +#include "ash/common/system/status_area_widget.h" #include "ash/common/system/status_area_widget_delegate.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/wm_shell.h" #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_widget.h" -#include "ash/system/status_area_widget.h" -#include "ash/system/tray/system_tray.h" #include "ash/test/ash_test_base.h" #include "ash/test/status_area_widget_test_helper.h" #include "ash/wm/window_util.h"
diff --git a/ash/metrics/user_metrics_recorder.cc b/ash/metrics/user_metrics_recorder.cc index b9a55499..7fe5858 100644 --- a/ash/metrics/user_metrics_recorder.cc +++ b/ash/metrics/user_metrics_recorder.cc
@@ -199,427 +199,385 @@ } void UserMetricsRecorder::RecordUserMetricsAction(UserMetricsAction action) { + using base::RecordAction; + using base::UserMetricsAction; + switch (action) { case UMA_ACCEL_KEYBOARD_BRIGHTNESS_DOWN_F6: - base::RecordAction( - base::UserMetricsAction("Accel_KeyboardBrightnessDown_F6")); + RecordAction(UserMetricsAction("Accel_KeyboardBrightnessDown_F6")); break; case UMA_ACCEL_KEYBOARD_BRIGHTNESS_UP_F7: - base::RecordAction( - base::UserMetricsAction("Accel_KeyboardBrightnessUp_F7")); + RecordAction(UserMetricsAction("Accel_KeyboardBrightnessUp_F7")); break; case UMA_ACCEL_LOCK_SCREEN_LOCK_BUTTON: - base::RecordAction( - base::UserMetricsAction("Accel_LockScreen_LockButton")); + RecordAction(UserMetricsAction("Accel_LockScreen_LockButton")); break; case UMA_ACCEL_LOCK_SCREEN_POWER_BUTTON: - base::RecordAction( - base::UserMetricsAction("Accel_LockScreen_PowerButton")); + RecordAction(UserMetricsAction("Accel_LockScreen_PowerButton")); break; case UMA_ACCEL_MAXIMIZE_RESTORE_F4: - base::RecordAction(base::UserMetricsAction("Accel_Maximize_Restore_F4")); + RecordAction(UserMetricsAction("Accel_Maximize_Restore_F4")); break; case UMA_ACCEL_PREVWINDOW_F5: - base::RecordAction(base::UserMetricsAction("Accel_PrevWindow_F5")); + RecordAction(UserMetricsAction("Accel_PrevWindow_F5")); break; case UMA_ACCEL_EXIT_FIRST_Q: - base::RecordAction(base::UserMetricsAction("Accel_Exit_First_Q")); + RecordAction(UserMetricsAction("Accel_Exit_First_Q")); break; case UMA_ACCEL_EXIT_SECOND_Q: - base::RecordAction(base::UserMetricsAction("Accel_Exit_Second_Q")); + RecordAction(UserMetricsAction("Accel_Exit_Second_Q")); break; case UMA_ACCEL_RESTART_POWER_BUTTON: - base::RecordAction(base::UserMetricsAction("Accel_Restart_PowerButton")); + RecordAction(UserMetricsAction("Accel_Restart_PowerButton")); break; case UMA_ACCEL_SHUT_DOWN_POWER_BUTTON: - base::RecordAction(base::UserMetricsAction("Accel_ShutDown_PowerButton")); + RecordAction(UserMetricsAction("Accel_ShutDown_PowerButton")); break; case UMA_CLOSE_THROUGH_CONTEXT_MENU: - base::RecordAction(base::UserMetricsAction("CloseFromContextMenu")); + RecordAction(UserMetricsAction("CloseFromContextMenu")); break; case UMA_DESKTOP_SWITCH_TASK: - base::RecordAction(base::UserMetricsAction("Desktop_SwitchTask")); + RecordAction(UserMetricsAction("Desktop_SwitchTask")); task_switch_metrics_recorder_.OnTaskSwitch( TaskSwitchMetricsRecorder::DESKTOP); break; case UMA_DRAG_MAXIMIZE_LEFT: - base::RecordAction(base::UserMetricsAction("WindowDrag_MaximizeLeft")); + RecordAction(UserMetricsAction("WindowDrag_MaximizeLeft")); break; case UMA_DRAG_MAXIMIZE_RIGHT: - base::RecordAction(base::UserMetricsAction("WindowDrag_MaximizeRight")); + RecordAction(UserMetricsAction("WindowDrag_MaximizeRight")); break; case UMA_LAUNCHER_BUTTON_PRESSED_WITH_MOUSE: - base::RecordAction( - base::UserMetricsAction("Launcher_ButtonPressed_Mouse")); + RecordAction(UserMetricsAction("Launcher_ButtonPressed_Mouse")); break; case UMA_LAUNCHER_BUTTON_PRESSED_WITH_TOUCH: - base::RecordAction( - base::UserMetricsAction("Launcher_ButtonPressed_Touch")); + RecordAction(UserMetricsAction("Launcher_ButtonPressed_Touch")); break; case UMA_LAUNCHER_CLICK_ON_APP: - base::RecordAction(base::UserMetricsAction("Launcher_ClickOnApp")); + RecordAction(UserMetricsAction("Launcher_ClickOnApp")); break; case UMA_LAUNCHER_CLICK_ON_APPLIST_BUTTON: - base::RecordAction( - base::UserMetricsAction("Launcher_ClickOnApplistButton")); + RecordAction(UserMetricsAction("Launcher_ClickOnApplistButton")); break; case UMA_LAUNCHER_LAUNCH_TASK: - base::RecordAction(base::UserMetricsAction("Launcher_LaunchTask")); + RecordAction(UserMetricsAction("Launcher_LaunchTask")); task_switch_metrics_recorder_.OnTaskSwitch( TaskSwitchMetricsRecorder::SHELF); break; case UMA_LAUNCHER_MINIMIZE_TASK: - base::RecordAction(base::UserMetricsAction("Launcher_MinimizeTask")); + RecordAction(UserMetricsAction("Launcher_MinimizeTask")); break; case UMA_LAUNCHER_SWITCH_TASK: - base::RecordAction(base::UserMetricsAction("Launcher_SwitchTask")); + RecordAction(UserMetricsAction("Launcher_SwitchTask")); task_switch_metrics_recorder_.OnTaskSwitch( TaskSwitchMetricsRecorder::SHELF); break; case UMA_MAXIMIZE_MODE_DISABLED: - base::RecordAction(base::UserMetricsAction("Touchview_Disabled")); + RecordAction(UserMetricsAction("Touchview_Disabled")); break; case UMA_MAXIMIZE_MODE_ENABLED: - base::RecordAction(base::UserMetricsAction("Touchview_Enabled")); + RecordAction(UserMetricsAction("Touchview_Enabled")); break; case UMA_MAXIMIZE_MODE_INITIALLY_DISABLED: - base::RecordAction( - base::UserMetricsAction("Touchview_Initially_Disabled")); + RecordAction(UserMetricsAction("Touchview_Initially_Disabled")); break; case UMA_MOUSE_DOWN: - base::RecordAction(base::UserMetricsAction("Mouse_Down")); + RecordAction(UserMetricsAction("Mouse_Down")); break; case UMA_PANEL_MINIMIZE_CAPTION_CLICK: - base::RecordAction( - base::UserMetricsAction("Panel_Minimize_Caption_Click")); + RecordAction(UserMetricsAction("Panel_Minimize_Caption_Click")); break; case UMA_PANEL_MINIMIZE_CAPTION_GESTURE: - base::RecordAction( - base::UserMetricsAction("Panel_Minimize_Caption_Gesture")); + RecordAction(UserMetricsAction("Panel_Minimize_Caption_Gesture")); break; case UMA_SHELF_ALIGNMENT_SET_BOTTOM: - base::RecordAction(base::UserMetricsAction("Shelf_AlignmentSetBottom")); + RecordAction(UserMetricsAction("Shelf_AlignmentSetBottom")); break; case UMA_SHELF_ALIGNMENT_SET_LEFT: - base::RecordAction(base::UserMetricsAction("Shelf_AlignmentSetLeft")); + RecordAction(UserMetricsAction("Shelf_AlignmentSetLeft")); break; case UMA_SHELF_ALIGNMENT_SET_RIGHT: - base::RecordAction(base::UserMetricsAction("Shelf_AlignmentSetRight")); + RecordAction(UserMetricsAction("Shelf_AlignmentSetRight")); break; case UMA_STATUS_AREA_AUDIO_CURRENT_INPUT_DEVICE: - base::RecordAction( - base::UserMetricsAction("StatusArea_Audio_CurrentInputDevice")); + RecordAction(UserMetricsAction("StatusArea_Audio_CurrentInputDevice")); break; case UMA_STATUS_AREA_AUDIO_CURRENT_OUTPUT_DEVICE: - base::RecordAction( - base::UserMetricsAction("StatusArea_Audio_CurrentOutputDevice")); + RecordAction(UserMetricsAction("StatusArea_Audio_CurrentOutputDevice")); break; case UMA_STATUS_AREA_AUDIO_SWITCH_INPUT_DEVICE: - base::RecordAction( - base::UserMetricsAction("StatusArea_Audio_SwitchInputDevice")); + RecordAction(UserMetricsAction("StatusArea_Audio_SwitchInputDevice")); break; case UMA_STATUS_AREA_AUDIO_SWITCH_OUTPUT_DEVICE: - base::RecordAction( - base::UserMetricsAction("StatusArea_Audio_SwitchOutputDevice")); + RecordAction(UserMetricsAction("StatusArea_Audio_SwitchOutputDevice")); break; case UMA_STATUS_AREA_BRIGHTNESS_CHANGED: - base::RecordAction( - base::UserMetricsAction("StatusArea_BrightnessChanged")); + RecordAction(UserMetricsAction("StatusArea_BrightnessChanged")); break; case UMA_STATUS_AREA_BLUETOOTH_CONNECT_KNOWN_DEVICE: - base::RecordAction( - base::UserMetricsAction("StatusArea_Bluetooth_Connect_Known")); + RecordAction(UserMetricsAction("StatusArea_Bluetooth_Connect_Known")); break; case UMA_STATUS_AREA_BLUETOOTH_CONNECT_UNKNOWN_DEVICE: - base::RecordAction( - base::UserMetricsAction("StatusArea_Bluetooth_Connect_Unknown")); + RecordAction(UserMetricsAction("StatusArea_Bluetooth_Connect_Unknown")); break; case UMA_STATUS_AREA_BLUETOOTH_DISABLED: - base::RecordAction( - base::UserMetricsAction("StatusArea_Bluetooth_Disabled")); + RecordAction(UserMetricsAction("StatusArea_Bluetooth_Disabled")); break; case UMA_STATUS_AREA_BLUETOOTH_ENABLED: - base::RecordAction( - base::UserMetricsAction("StatusArea_Bluetooth_Enabled")); + RecordAction(UserMetricsAction("StatusArea_Bluetooth_Enabled")); break; case UMA_STATUS_AREA_CAPS_LOCK_DETAILED: - base::RecordAction( - base::UserMetricsAction("StatusArea_CapsLock_Detailed")); + RecordAction(UserMetricsAction("StatusArea_CapsLock_Detailed")); break; case UMA_STATUS_AREA_CAPS_LOCK_DISABLED_BY_CLICK: - base::RecordAction( - base::UserMetricsAction("StatusArea_CapsLock_DisabledByClick")); + RecordAction(UserMetricsAction("StatusArea_CapsLock_DisabledByClick")); break; case UMA_STATUS_AREA_CAPS_LOCK_ENABLED_BY_CLICK: - base::RecordAction( - base::UserMetricsAction("StatusArea_CapsLock_EnabledByClick")); + RecordAction(UserMetricsAction("StatusArea_CapsLock_EnabledByClick")); break; case UMA_STATUS_AREA_CAPS_LOCK_POPUP: - base::RecordAction(base::UserMetricsAction("StatusArea_CapsLock_Popup")); + RecordAction(UserMetricsAction("StatusArea_CapsLock_Popup")); break; case UMA_STATUS_AREA_CAST_STOP_CAST: - base::RecordAction(base::UserMetricsAction("StatusArea_Cast_StopCast")); + RecordAction(UserMetricsAction("StatusArea_Cast_StopCast")); break; case UMA_STATUS_AREA_CONNECT_TO_CONFIGURED_NETWORK: - base::RecordAction( - base::UserMetricsAction("StatusArea_Network_ConnectConfigured")); + RecordAction(UserMetricsAction("StatusArea_Network_ConnectConfigured")); break; case UMA_STATUS_AREA_CONNECT_TO_UNCONFIGURED_NETWORK: - base::RecordAction( - base::UserMetricsAction("StatusArea_Network_ConnectUnconfigured")); + RecordAction(UserMetricsAction("StatusArea_Network_ConnectUnconfigured")); break; case UMA_STATUS_AREA_CONNECT_TO_VPN: - base::RecordAction( - base::UserMetricsAction("StatusArea_VPN_ConnectToNetwork")); + RecordAction(UserMetricsAction("StatusArea_VPN_ConnectToNetwork")); break; case UMA_STATUS_AREA_CHANGED_VOLUME_MENU: - base::RecordAction( - base::UserMetricsAction("StatusArea_Volume_ChangedMenu")); + RecordAction(UserMetricsAction("StatusArea_Volume_ChangedMenu")); break; case UMA_STATUS_AREA_CHANGED_VOLUME_POPUP: - base::RecordAction( - base::UserMetricsAction("StatusArea_Volume_ChangedPopup")); + RecordAction(UserMetricsAction("StatusArea_Volume_ChangedPopup")); break; case UMA_STATUS_AREA_DETAILED_ACCESSABILITY: - base::RecordAction( - base::UserMetricsAction("StatusArea_Accessability_DetailedView")); + RecordAction(UserMetricsAction("StatusArea_Accessability_DetailedView")); break; case UMA_STATUS_AREA_DETAILED_AUDIO_VIEW: - base::RecordAction(base::UserMetricsAction("StatusArea_Audio_Detailed")); + RecordAction(UserMetricsAction("StatusArea_Audio_Detailed")); break; case UMA_STATUS_AREA_DETAILED_BLUETOOTH_VIEW: - base::RecordAction( - base::UserMetricsAction("StatusArea_Bluetooth_Detailed")); + RecordAction(UserMetricsAction("StatusArea_Bluetooth_Detailed")); break; case UMA_STATUS_AREA_DETAILED_BRIGHTNESS_VIEW: - base::RecordAction( - base::UserMetricsAction("StatusArea_Brightness_Detailed")); + RecordAction(UserMetricsAction("StatusArea_Brightness_Detailed")); break; case UMA_STATUS_AREA_DETAILED_CAST_VIEW: - base::RecordAction(base::UserMetricsAction("StatusArea_Cast_Detailed")); + RecordAction(UserMetricsAction("StatusArea_Cast_Detailed")); break; case UMA_STATUS_AREA_DETAILED_CAST_VIEW_LAUNCH_CAST: - base::RecordAction( - base::UserMetricsAction("StatusArea_Cast_Detailed_Launch_Cast")); + RecordAction(UserMetricsAction("StatusArea_Cast_Detailed_Launch_Cast")); break; case UMA_STATUS_AREA_DETAILED_DRIVE_VIEW: - base::RecordAction(base::UserMetricsAction("StatusArea_Drive_Detailed")); + RecordAction(UserMetricsAction("StatusArea_Drive_Detailed")); break; case UMA_STATUS_AREA_DETAILED_NETWORK_VIEW: - base::RecordAction( - base::UserMetricsAction("StatusArea_Network_Detailed")); + RecordAction(UserMetricsAction("StatusArea_Network_Detailed")); break; case UMA_STATUS_AREA_DETAILED_SMS_VIEW: - base::RecordAction(base::UserMetricsAction("StatusArea_SMS_Detailed")); + RecordAction(UserMetricsAction("StatusArea_SMS_Detailed")); break; case UMA_STATUS_AREA_DETAILED_VPN_VIEW: - base::RecordAction(base::UserMetricsAction("StatusArea_VPN_Detailed")); + RecordAction(UserMetricsAction("StatusArea_VPN_Detailed")); break; case UMA_STATUS_AREA_DISABLE_AUTO_CLICK: - base::RecordAction( - base::UserMetricsAction("StatusArea_AutoClickDisabled")); + RecordAction(UserMetricsAction("StatusArea_AutoClickDisabled")); break; case UMA_STATUS_AREA_DISABLE_HIGH_CONTRAST: - base::RecordAction( - base::UserMetricsAction("StatusArea_HighContrastDisabled")); + RecordAction(UserMetricsAction("StatusArea_HighContrastDisabled")); break; case UMA_STATUS_AREA_DISABLE_LARGE_CURSOR: - base::RecordAction( - base::UserMetricsAction("StatusArea_LargeCursorDisabled")); + RecordAction(UserMetricsAction("StatusArea_LargeCursorDisabled")); break; case UMA_STATUS_AREA_DISABLE_MAGNIFIER: - base::RecordAction( - base::UserMetricsAction("StatusArea_MagnifierDisabled")); + RecordAction(UserMetricsAction("StatusArea_MagnifierDisabled")); break; case UMA_STATUS_AREA_DISABLE_SPOKEN_FEEDBACK: - base::RecordAction( - base::UserMetricsAction("StatusArea_SpokenFeedbackDisabled")); + RecordAction(UserMetricsAction("StatusArea_SpokenFeedbackDisabled")); break; case UMA_STATUS_AREA_DISABLE_VIRTUAL_KEYBOARD: - base::RecordAction( - base::UserMetricsAction("StatusArea_VirtualKeyboardDisabled")); + RecordAction(UserMetricsAction("StatusArea_VirtualKeyboardDisabled")); + break; + case UMA_STATUS_AREA_DISPLAY_DEFAULT_SELECTED: + RecordAction(UserMetricsAction("StatusArea_Display_Default_Selected")); + break; + case UMA_STATUS_AREA_DISPLAY_DEFAULT_SHOW_SETTINGS: + RecordAction( + UserMetricsAction("StatusArea_Display_Default_ShowSettings")); + break; + case UMA_STATUS_AREA_DISPLAY_NOTIFICATION_CREATED: + RecordAction( + UserMetricsAction("StatusArea_Display_Notification_Created")); + break; + case UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SELECTED: + RecordAction( + UserMetricsAction("StatusArea_Display_Notification_Selected")); + break; + case UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SHOW_SETTINGS: + RecordAction( + UserMetricsAction("StatusArea_Display_Notification_Show_Settings")); break; case UMA_STATUS_AREA_DISABLE_WIFI: - base::RecordAction( - base::UserMetricsAction("StatusArea_Network_WifiDisabled")); + RecordAction(UserMetricsAction("StatusArea_Network_WifiDisabled")); break; case UMA_STATUS_AREA_DRIVE_CANCEL_OPERATION: - base::RecordAction( - base::UserMetricsAction("StatusArea_Drive_CancelOperation")); + RecordAction(UserMetricsAction("StatusArea_Drive_CancelOperation")); break; case UMA_STATUS_AREA_DRIVE_SETTINGS: - base::RecordAction(base::UserMetricsAction("StatusArea_Drive_Settings")); + RecordAction(UserMetricsAction("StatusArea_Drive_Settings")); break; case UMA_STATUS_AREA_ENABLE_AUTO_CLICK: - base::RecordAction( - base::UserMetricsAction("StatusArea_AutoClickEnabled")); + RecordAction(UserMetricsAction("StatusArea_AutoClickEnabled")); break; case UMA_STATUS_AREA_ENABLE_HIGH_CONTRAST: - base::RecordAction( - base::UserMetricsAction("StatusArea_HighContrastEnabled")); + RecordAction(UserMetricsAction("StatusArea_HighContrastEnabled")); break; case UMA_STATUS_AREA_ENABLE_LARGE_CURSOR: - base::RecordAction( - base::UserMetricsAction("StatusArea_LargeCursorEnabled")); + RecordAction(UserMetricsAction("StatusArea_LargeCursorEnabled")); break; case UMA_STATUS_AREA_ENABLE_MAGNIFIER: - base::RecordAction( - base::UserMetricsAction("StatusArea_MagnifierEnabled")); + RecordAction(UserMetricsAction("StatusArea_MagnifierEnabled")); break; case UMA_STATUS_AREA_ENABLE_SPOKEN_FEEDBACK: - base::RecordAction( - base::UserMetricsAction("StatusArea_SpokenFeedbackEnabled")); + RecordAction(UserMetricsAction("StatusArea_SpokenFeedbackEnabled")); break; case UMA_STATUS_AREA_ENABLE_VIRTUAL_KEYBOARD: - base::RecordAction( - base::UserMetricsAction("StatusArea_VirtualKeyboardEnabled")); + RecordAction(UserMetricsAction("StatusArea_VirtualKeyboardEnabled")); break; case UMA_STATUS_AREA_ENABLE_WIFI: - base::RecordAction( - base::UserMetricsAction("StatusArea_Network_WifiEnabled")); + RecordAction(UserMetricsAction("StatusArea_Network_WifiEnabled")); break; case UMA_STATUS_AREA_IME_SHOW_DETAILED: - base::RecordAction(base::UserMetricsAction("StatusArea_IME_Detailed")); + RecordAction(UserMetricsAction("StatusArea_IME_Detailed")); break; case UMA_STATUS_AREA_IME_SWITCH_MODE: - base::RecordAction(base::UserMetricsAction("StatusArea_IME_SwitchMode")); + RecordAction(UserMetricsAction("StatusArea_IME_SwitchMode")); break; case UMA_STATUS_AREA_MENU_OPENED: - base::RecordAction(base::UserMetricsAction("StatusArea_MenuOpened")); + RecordAction(UserMetricsAction("StatusArea_MenuOpened")); break; case UMA_STATUS_AREA_NETWORK_JOIN_OTHER_CLICKED: - base::RecordAction( - base::UserMetricsAction("StatusArea_Network_JoinOther")); + RecordAction(UserMetricsAction("StatusArea_Network_JoinOther")); break; case UMA_STATUS_AREA_NETWORK_SETTINGS_CLICKED: - base::RecordAction( - base::UserMetricsAction("StatusArea_Network_Settings")); + RecordAction(UserMetricsAction("StatusArea_Network_Settings")); case UMA_STATUS_AREA_OS_UPDATE_DEFAULT_SELECTED: - base::RecordAction( - base::UserMetricsAction("StatusArea_OS_Update_Default_Selected")); + RecordAction(UserMetricsAction("StatusArea_OS_Update_Default_Selected")); break; case UMA_STATUS_AREA_SCREEN_CAPTURE_DEFAULT_STOP: - base::RecordAction( - base::UserMetricsAction("StatusArea_ScreenCapture_Default_Stop")); + RecordAction(UserMetricsAction("StatusArea_ScreenCapture_Default_Stop")); break; case UMA_STATUS_AREA_SCREEN_CAPTURE_NOTIFICATION_STOP: - base::RecordAction(base::UserMetricsAction( - "StatusArea_ScreenCapture_Notification_Stop")); + RecordAction( + UserMetricsAction("StatusArea_ScreenCapture_Notification_Stop")); break; case UMA_STATUS_AREA_SHOW_NETWORK_CONNECTION_DETAILS: - base::RecordAction( - base::UserMetricsAction("StatusArea_Network_ConnectionDetails")); + RecordAction(UserMetricsAction("StatusArea_Network_ConnectionDetails")); break; case UMA_STATUS_AREA_SHOW_VPN_CONNECTION_DETAILS: - base::RecordAction( - base::UserMetricsAction("StatusArea_VPN_ConnectionDetails")); + RecordAction(UserMetricsAction("StatusArea_VPN_ConnectionDetails")); break; case UMA_STATUS_AREA_SIGN_OUT: - base::RecordAction(base::UserMetricsAction("StatusArea_SignOut")); + RecordAction(UserMetricsAction("StatusArea_SignOut")); break; case UMA_STATUS_AREA_SMS_DETAILED_DISMISS_MSG: - base::RecordAction( - base::UserMetricsAction("StatusArea_SMS_Detailed_DismissMsg")); + RecordAction(UserMetricsAction("StatusArea_SMS_Detailed_DismissMsg")); break; case UMA_STATUS_AREA_SMS_NOTIFICATION_DISMISS_MSG: - base::RecordAction( - base::UserMetricsAction("StatusArea_SMS_Notification_DismissMsg")); + RecordAction(UserMetricsAction("StatusArea_SMS_Notification_DismissMsg")); break; case UMA_STATUS_AREA_TRACING_DEFAULT_SELECTED: - base::RecordAction( - base::UserMetricsAction("StatusArea_Tracing_Default_Selected")); + RecordAction(UserMetricsAction("StatusArea_Tracing_Default_Selected")); break; case UMA_STATUS_AREA_VPN_ADD_BUILT_IN_CLICKED: - base::RecordAction(base::UserMetricsAction("StatusArea_VPN_AddBuiltIn")); + RecordAction(UserMetricsAction("StatusArea_VPN_AddBuiltIn")); break; case UMA_STATUS_AREA_VPN_ADD_THIRD_PARTY_CLICKED: - base::RecordAction( - base::UserMetricsAction("StatusArea_VPN_AddThirdParty")); + RecordAction(UserMetricsAction("StatusArea_VPN_AddThirdParty")); break; case UMA_STATUS_AREA_VPN_DISCONNECT_CLICKED: - base::RecordAction(base::UserMetricsAction("StatusArea_VPN_Disconnect")); + RecordAction(UserMetricsAction("StatusArea_VPN_Disconnect")); break; case UMA_STATUS_AREA_VPN_SETTINGS_CLICKED: - base::RecordAction(base::UserMetricsAction("StatusArea_VPN_Settings")); + RecordAction(UserMetricsAction("StatusArea_VPN_Settings")); break; case UMA_TOGGLE_MAXIMIZE_CAPTION_CLICK: - base::RecordAction( - base::UserMetricsAction("Caption_ClickTogglesMaximize")); + RecordAction(UserMetricsAction("Caption_ClickTogglesMaximize")); break; case UMA_TOGGLE_MAXIMIZE_CAPTION_GESTURE: - base::RecordAction( - base::UserMetricsAction("Caption_GestureTogglesMaximize")); + RecordAction(UserMetricsAction("Caption_GestureTogglesMaximize")); break; case UMA_TOGGLE_SINGLE_AXIS_MAXIMIZE_BORDER_CLICK: - base::RecordAction(base::UserMetricsAction( - "WindowBorder_ClickTogglesSingleAxisMaximize")); + RecordAction( + UserMetricsAction("WindowBorder_ClickTogglesSingleAxisMaximize")); break; case UMA_TOUCHPAD_GESTURE_OVERVIEW: - base::RecordAction(base::UserMetricsAction("Touchpad_Gesture_Overview")); + RecordAction(UserMetricsAction("Touchpad_Gesture_Overview")); break; case UMA_TOUCHSCREEN_TAP_DOWN: - base::RecordAction(base::UserMetricsAction("Touchscreen_Down")); + RecordAction(UserMetricsAction("Touchscreen_Down")); break; case UMA_TRAY_HELP: - base::RecordAction(base::UserMetricsAction("Tray_Help")); + RecordAction(UserMetricsAction("Tray_Help")); break; case UMA_TRAY_LOCK_SCREEN: - base::RecordAction(base::UserMetricsAction("Tray_LockScreen")); + RecordAction(UserMetricsAction("Tray_LockScreen")); break; case UMA_TRAY_OVERVIEW: - base::RecordAction(base::UserMetricsAction("Tray_Overview")); + RecordAction(UserMetricsAction("Tray_Overview")); break; case UMA_TRAY_SHUT_DOWN: - base::RecordAction(base::UserMetricsAction("Tray_ShutDown")); + RecordAction(UserMetricsAction("Tray_ShutDown")); break; case UMA_WINDOW_APP_CLOSE_BUTTON_CLICK: - base::RecordAction(base::UserMetricsAction("AppCloseButton_Clk")); + RecordAction(UserMetricsAction("AppCloseButton_Clk")); break; case UMA_WINDOW_CLOSE_BUTTON_CLICK: - base::RecordAction(base::UserMetricsAction("CloseButton_Clk")); + RecordAction(UserMetricsAction("CloseButton_Clk")); break; case UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_EXIT_FULLSCREEN: - base::RecordAction(base::UserMetricsAction("MaxButton_Clk_ExitFS")); + RecordAction(UserMetricsAction("MaxButton_Clk_ExitFS")); break; case UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_RESTORE: - base::RecordAction(base::UserMetricsAction("MaxButton_Clk_Restore")); + RecordAction(UserMetricsAction("MaxButton_Clk_Restore")); break; case UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MAXIMIZE: - base::RecordAction(base::UserMetricsAction("MaxButton_Clk_Maximize")); + RecordAction(UserMetricsAction("MaxButton_Clk_Maximize")); break; case UMA_WINDOW_MAXIMIZE_BUTTON_CLICK_MINIMIZE: - base::RecordAction(base::UserMetricsAction("MinButton_Clk")); + RecordAction(UserMetricsAction("MinButton_Clk")); break; case UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_LEFT: - base::RecordAction(base::UserMetricsAction("MaxButton_MaxLeft")); + RecordAction(UserMetricsAction("MaxButton_MaxLeft")); break; case UMA_WINDOW_MAXIMIZE_BUTTON_MAXIMIZE_RIGHT: - base::RecordAction(base::UserMetricsAction("MaxButton_MaxRight")); + RecordAction(UserMetricsAction("MaxButton_MaxRight")); break; case UMA_WINDOW_CYCLE: - base::RecordAction( - base::UserMetricsAction("WindowCycleController_Cycle")); + RecordAction(UserMetricsAction("WindowCycleController_Cycle")); break; case UMA_WINDOW_OVERVIEW: - base::RecordAction(base::UserMetricsAction("WindowSelector_Overview")); + RecordAction(UserMetricsAction("WindowSelector_Overview")); break; case UMA_WINDOW_OVERVIEW_ACTIVE_WINDOW_CHANGED: - base::RecordAction( - base::UserMetricsAction("WindowSelector_ActiveWindowChanged")); + RecordAction(UserMetricsAction("WindowSelector_ActiveWindowChanged")); task_switch_metrics_recorder_.OnTaskSwitch( TaskSwitchMetricsRecorder::OVERVIEW_MODE); break; case UMA_WINDOW_OVERVIEW_ENTER_KEY: - base::RecordAction( - base::UserMetricsAction("WindowSelector_OverviewEnterKey")); + RecordAction(UserMetricsAction("WindowSelector_OverviewEnterKey")); break; case UMA_WINDOW_OVERVIEW_CLOSE_BUTTON: - base::RecordAction( - base::UserMetricsAction("WindowSelector_OverviewCloseButton")); + RecordAction(UserMetricsAction("WindowSelector_OverviewCloseButton")); break; case UMA_WINDOW_OVERVIEW_CLOSE_KEY: - base::RecordAction( - base::UserMetricsAction("WindowSelector_OverviewCloseKey")); + RecordAction(UserMetricsAction("WindowSelector_OverviewCloseKey")); break; } }
diff --git a/ash/mus/bridge/wm_shell_mus.cc b/ash/mus/bridge/wm_shell_mus.cc index 582e750..b962652 100644 --- a/ash/mus/bridge/wm_shell_mus.cc +++ b/ash/mus/bridge/wm_shell_mus.cc
@@ -22,9 +22,11 @@ #include "ash/mus/root_window_controller.h" #include "base/memory/ptr_util.h" #include "components/user_manager/user_info_impl.h" +#include "services/shell/public/cpp/connector.h" #include "services/ui/common/util.h" #include "services/ui/public/cpp/window.h" #include "services/ui/public/cpp/window_tree_client.h" +#include "services/ui/public/interfaces/accessibility_manager.mojom.h" namespace ash { namespace mus { @@ -90,11 +92,39 @@ DISALLOW_COPY_AND_ASSIGN(SessionStateDelegateStub); }; +class AccessibilityDelegateMus : public DefaultAccessibilityDelegate { + public: + explicit AccessibilityDelegateMus(shell::Connector* connector) + : connector_(connector) {} + ~AccessibilityDelegateMus() override {} + + private: + ui::mojom::AccessibilityManager* GetAccessibilityManager() { + if (!accessibility_manager_ptr_.is_bound()) + connector_->ConnectToInterface("mojo:ui", &accessibility_manager_ptr_); + return accessibility_manager_ptr_.get(); + } + + // DefaultAccessibilityDelegate: + void ToggleHighContrast() override { + DefaultAccessibilityDelegate::ToggleHighContrast(); + GetAccessibilityManager()->SetHighContrastMode(IsHighContrastEnabled()); + } + + ui::mojom::AccessibilityManagerPtr accessibility_manager_ptr_; + shell::Connector* connector_; + + DISALLOW_COPY_AND_ASSIGN(AccessibilityDelegateMus); +}; + } // namespace -WmShellMus::WmShellMus(ShellDelegate* delegate, ::ui::WindowTreeClient* client) +WmShellMus::WmShellMus(ShellDelegate* delegate, + ::ui::WindowTreeClient* client, + shell::Connector* connector) : WmShell(delegate), client_(client), + connector_(connector), session_state_delegate_(new SessionStateDelegateStub) { client_->AddObserver(this); WmShell::Set(this); @@ -103,7 +133,7 @@ CreateMruWindowTracker(); - accessibility_delegate_.reset(new DefaultAccessibilityDelegate); + accessibility_delegate_.reset(new AccessibilityDelegateMus(connector_)); SetSystemTrayDelegate(base::WrapUnique(new DefaultSystemTrayDelegate)); }
diff --git a/ash/mus/bridge/wm_shell_mus.h b/ash/mus/bridge/wm_shell_mus.h index 4ad4d41..c9a4c42a 100644 --- a/ash/mus/bridge/wm_shell_mus.h +++ b/ash/mus/bridge/wm_shell_mus.h
@@ -14,6 +14,10 @@ #include "base/observer_list.h" #include "services/ui/public/cpp/window_tree_client_observer.h" +namespace shell { +class Connector; +} + namespace ui { class WindowTreeClient; } @@ -27,7 +31,9 @@ // WmShell implementation for mus. class WmShellMus : public WmShell, public ::ui::WindowTreeClientObserver { public: - WmShellMus(ShellDelegate* delegate, ::ui::WindowTreeClient* client); + WmShellMus(ShellDelegate* delegate, + ::ui::WindowTreeClient* client, + shell::Connector* connector); ~WmShellMus() override; static WmShellMus* Get(); @@ -91,6 +97,7 @@ void OnDidDestroyClient(::ui::WindowTreeClient* client) override; ::ui::WindowTreeClient* client_; + shell::Connector* connector_; std::vector<WmRootWindowControllerMus*> root_window_controllers_;
diff --git a/ash/mus/manifest.json b/ash/mus/manifest.json index d2bfcf6..d7080ef 100644 --- a/ash/mus/manifest.json +++ b/ash/mus/manifest.json
@@ -7,8 +7,13 @@ "mus:window_manager" : [ "ui::mojom::AcceleratorRegistrar" ] }, "required": { - "*": { "classes": [ "app" ] }, - "mojo:ui": { "interfaces": [ "ui::mojom::WindowManagerWindowTreeFactory" ] } + "*": { "classes": [ "accessibility", "app" ] }, + "mojo:ui": { + "interfaces": [ + "ui::mojom::AccessibilityManager", + "ui::mojom::WindowManagerWindowTreeFactory" + ] + } } } }
diff --git a/ash/mus/window_manager.cc b/ash/mus/window_manager.cc index d0755a5..33d8806 100644 --- a/ash/mus/window_manager.cc +++ b/ash/mus/window_manager.cc
@@ -71,7 +71,7 @@ std::move(frame_decoration_values)); // TODO(msw): Provide a valid ShellDelegate here; maybe port ShellDelegateMus? - shell_.reset(new WmShellMus(nullptr, window_tree_client_)); + shell_.reset(new WmShellMus(nullptr, window_tree_client_, connector_)); lookup_.reset(new WmLookupMus); }
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc index 38c33459..fb60b34 100644 --- a/ash/root_window_controller.cc +++ b/ash/root_window_controller.cc
@@ -19,6 +19,7 @@ #include "ash/common/shelf/shelf_types.h" #include "ash/common/shell_delegate.h" #include "ash/common/shell_window_ids.h" +#include "ash/common/system/status_area_widget.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/wm/always_on_top_controller.h" #include "ash/common/wm/container_finder.h" @@ -43,7 +44,6 @@ #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_factory.h" -#include "ash/system/status_area_widget.h" #include "ash/touch/touch_hud_debug.h" #include "ash/touch/touch_hud_projection.h" #include "ash/touch/touch_observer_hud.h"
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc index 435c046..d89ffb2 100644 --- a/ash/shelf/shelf_layout_manager.cc +++ b/ash/shelf/shelf_layout_manager.cc
@@ -18,6 +18,7 @@ #include "ash/common/shelf/shelf_constants.h" #include "ash/common/shelf/wm_shelf_util.h" #include "ash/common/shell_window_ids.h" +#include "ash/common/system/status_area_widget.h" #include "ash/common/wm/mru_window_tracker.h" #include "ash/common/wm/window_state.h" #include "ash/common/wm_root_window_controller.h" @@ -32,7 +33,6 @@ #include "ash/shelf/shelf_util.h" #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" -#include "ash/system/status_area_widget.h" #include "ash/wm/gestures/shelf_gesture_handler.h" #include "ash/wm/lock_state_controller.h" #include "ash/wm/window_animations.h"
diff --git a/ash/shelf/shelf_layout_manager.h b/ash/shelf/shelf_layout_manager.h index 127fff86..5696b69 100644 --- a/ash/shelf/shelf_layout_manager.h +++ b/ash/shelf/shelf_layout_manager.h
@@ -12,12 +12,12 @@ #include "ash/common/session/session_state_observer.h" #include "ash/common/shelf/shelf_types.h" #include "ash/common/shell_observer.h" +#include "ash/common/system/status_area_widget.h" #include "ash/common/wm/background_animator.h" #include "ash/common/wm/dock/docked_window_layout_manager_observer.h" #include "ash/common/wm/workspace/workspace_types.h" #include "ash/shelf/shelf.h" #include "ash/snap_to_pixel_layout_manager.h" -#include "ash/system/status_area_widget.h" #include "ash/wm/gestures/shelf_gesture_handler.h" #include "ash/wm/lock_state_observer.h" #include "base/compiler_specific.h"
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc index 47a0b375..ff9aaaa5 100644 --- a/ash/shelf/shelf_layout_manager_unittest.cc +++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -12,6 +12,8 @@ #include "ash/common/session/session_state_delegate.h" #include "ash/common/shelf/shelf_constants.h" #include "ash/common/shell_window_ids.h" +#include "ash/common/system/status_area_widget.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_item.h" #include "ash/common/wm/window_state.h" #include "ash/common/wm_shell.h" @@ -24,8 +26,6 @@ #include "ash/shelf/shelf_view.h" #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" -#include "ash/system/status_area_widget.h" -#include "ash/system/tray/system_tray.h" #include "ash/test/ash_test_base.h" #include "ash/test/display_manager_test_api.h" #include "ash/test/shelf_test_api.h"
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index 43eba9d..90b3488 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -2052,7 +2052,7 @@ return command_id != 0; } bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override { + ui::Accelerator* accelerator) const override { return false; } void ExecuteCommand(int command_id, int event_flags) override {}
diff --git a/ash/shell.cc b/ash/shell.cc index 22501786..61caa6dc 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -25,6 +25,8 @@ #include "ash/common/shell_delegate.h" #include "ash/common/shell_window_ids.h" #include "ash/common/system/locale/locale_notification_controller.h" +#include "ash/common/system/status_area_widget.h" +#include "ash/common/system/toast/toast_manager.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/wm/maximize_mode/maximize_mode_controller.h" #include "ash/common/wm/maximize_mode/maximize_mode_window_manager.h" @@ -62,8 +64,6 @@ #include "ash/shelf/shelf_window_watcher.h" #include "ash/shell_factory.h" #include "ash/shell_init_params.h" -#include "ash/system/status_area_widget.h" -#include "ash/system/toast/toast_manager.h" #include "ash/utility/screenshot_controller.h" #include "ash/wm/ash_focus_rules.h" #include "ash/wm/ash_native_cursor_manager.h"
diff --git a/ash/shell/app_list.cc b/ash/shell/app_list.cc index 6b238a87..e4a066a3 100644 --- a/ash/shell/app_list.cc +++ b/ash/shell/app_list.cc
@@ -312,10 +312,6 @@ // Nothing needs to be done. } - void OpenSettings() override { - // Nothing needs to be done. - } - void OpenHelp() override { // Nothing needs to be done. }
diff --git a/ash/shell/context_menu.cc b/ash/shell/context_menu.cc index 0723b1cf..b0677b7 100644 --- a/ash/shell/context_menu.cc +++ b/ash/shell/context_menu.cc
@@ -35,8 +35,9 @@ return true; } -bool ContextMenu::GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) { +bool ContextMenu::GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const { return false; }
diff --git a/ash/shell/context_menu.h b/ash/shell/context_menu.h index c89a406..79cb582 100644 --- a/ash/shell/context_menu.h +++ b/ash/shell/context_menu.h
@@ -26,7 +26,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; private:
diff --git a/ash/shell/window_type_launcher.cc b/ash/shell/window_type_launcher.cc index c5c5052..f2b2c607 100644 --- a/ash/shell/window_type_launcher.cc +++ b/ash/shell/window_type_launcher.cc
@@ -8,6 +8,7 @@ #include "ash/common/session/session_state_delegate.h" #include "ash/common/shell_window_ids.h" +#include "ash/common/system/status_area_widget.h" #include "ash/common/system/web_notification/web_notification_tray.h" #include "ash/common/wm_shell.h" #include "ash/content/shell_content_state.h" @@ -17,7 +18,6 @@ #include "ash/shell/example_factory.h" #include "ash/shell/panel_window.h" #include "ash/shell/toplevel_window.h" -#include "ash/system/status_area_widget.h" #include "ash/test/child_modal_window.h" #include "base/strings/utf_string_conversions.h" #include "ui/aura/window.h"
diff --git a/ash/shell_unittest.cc b/ash/shell_unittest.cc index 8d659eda..694cc5c 100644 --- a/ash/shell_unittest.cc +++ b/ash/shell_unittest.cc
@@ -116,7 +116,7 @@ bool IsCommandIdEnabled(int command_id) const override { return true; } bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override { + ui::Accelerator* accelerator) const override { return false; }
diff --git a/ash/system/chromeos/media_security/multi_profile_media_tray_item.cc b/ash/system/chromeos/media_security/multi_profile_media_tray_item.cc deleted file mode 100644 index 4164e8bf..0000000 --- a/ash/system/chromeos/media_security/multi_profile_media_tray_item.cc +++ /dev/null
@@ -1,78 +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. - -#include "ash/system/chromeos/media_security/multi_profile_media_tray_item.h" - -#include "ash/common/ash_view_ids.h" -#include "ash/common/media_delegate.h" -#include "ash/common/session/session_state_delegate.h" -#include "ash/common/system/chromeos/media_security/media_capture_observer.h" -#include "ash/common/system/tray/system_tray_notifier.h" -#include "ash/common/system/tray/tray_item_view.h" -#include "ash/common/wm_shell.h" -#include "grit/ash_resources.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/views/controls/image_view.h" -#include "ui/views/layout/fill_layout.h" - -namespace ash { -namespace tray { - -class MultiProfileMediaTrayView : public TrayItemView, - public MediaCaptureObserver { - public: - explicit MultiProfileMediaTrayView(SystemTrayItem* system_tray_item) - : TrayItemView(system_tray_item) { - SetLayoutManager(new views::FillLayout); - views::ImageView* icon = new views::ImageView; - ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); - icon->SetImage( - bundle.GetImageNamed(IDR_AURA_UBER_TRAY_RECORDING).ToImageSkia()); - AddChildView(icon); - OnMediaCaptureChanged(); - WmShell::Get()->system_tray_notifier()->AddMediaCaptureObserver(this); - set_id(VIEW_ID_MEDIA_TRAY_VIEW); - } - - ~MultiProfileMediaTrayView() override { - WmShell::Get()->system_tray_notifier()->RemoveMediaCaptureObserver(this); - } - - // MediaCaptureObserver: - void OnMediaCaptureChanged() override { - MediaDelegate* media_delegate = WmShell::Get()->media_delegate(); - SessionStateDelegate* session_state_delegate = - WmShell::Get()->GetSessionStateDelegate(); - // The user at 0 is the current desktop user. - for (UserIndex index = 1; - index < session_state_delegate->NumberOfLoggedInUsers(); ++index) { - if (media_delegate->GetMediaCaptureState(index) != MEDIA_CAPTURE_NONE) { - SetVisible(true); - return; - } - } - SetVisible(false); - } - - private: - DISALLOW_COPY_AND_ASSIGN(MultiProfileMediaTrayView); -}; - -} // namespace tray - -MultiProfileMediaTrayItem::MultiProfileMediaTrayItem(SystemTray* system_tray) - : SystemTrayItem(system_tray), tray_view_(NULL) {} - -MultiProfileMediaTrayItem::~MultiProfileMediaTrayItem() {} - -views::View* MultiProfileMediaTrayItem::CreateTrayView(LoginStatus status) { - tray_view_ = new tray::MultiProfileMediaTrayView(this); - return tray_view_; -} - -void MultiProfileMediaTrayItem::DestroyTrayView() { - tray_view_ = NULL; -} - -} // namespace ash
diff --git a/ash/system/chromeos/media_security/multi_profile_media_tray_item.h b/ash/system/chromeos/media_security/multi_profile_media_tray_item.h deleted file mode 100644 index bbddc63..0000000 --- a/ash/system/chromeos/media_security/multi_profile_media_tray_item.h +++ /dev/null
@@ -1,36 +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 ASH_SYSTEM_CHROMEOS_MEDIA_SECURITY_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_ -#define ASH_SYSTEM_CHROMEOS_MEDIA_SECURITY_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_ - -#include "ash/common/system/tray/system_tray_item.h" -#include "base/macros.h" -#include "ui/message_center/notification_delegate.h" -#include "ui/views/view.h" - -namespace ash { -namespace tray { -class MultiProfileMediaTrayView; -} - -// The tray item for media recording. -class ASH_EXPORT MultiProfileMediaTrayItem : public SystemTrayItem { - public: - explicit MultiProfileMediaTrayItem(SystemTray* system_tray); - ~MultiProfileMediaTrayItem() override; - - // SystemTrayItem: - views::View* CreateTrayView(LoginStatus status) override; - void DestroyTrayView() override; - - private: - tray::MultiProfileMediaTrayView* tray_view_; - - DISALLOW_COPY_AND_ASSIGN(MultiProfileMediaTrayItem); -}; - -} // namespace ash - -#endif // ASH_SYSTEM_CHROMEOS_MEDIA_SECURITY_MULTI_PROFILE_MEDIA_TRAY_ITEM_H_
diff --git a/ash/system/chromeos/media_security/multi_profile_media_tray_item_unittest.cc b/ash/system/chromeos/media_security/multi_profile_media_tray_item_unittest.cc index 15072c7..dbd500ae 100644 --- a/ash/system/chromeos/media_security/multi_profile_media_tray_item_unittest.cc +++ b/ash/system/chromeos/media_security/multi_profile_media_tray_item_unittest.cc
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/chromeos/media_security/multi_profile_media_tray_item.h" +#include "ash/common/system/chromeos/media_security/multi_profile_media_tray_item.h" #include "ash/common/ash_view_ids.h" +#include "ash/common/system/status_area_widget.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_bubble.h" #include "ash/common/system/tray/tray_item_view.h" -#include "ash/system/status_area_widget.h" -#include "ash/system/tray/system_tray.h" #include "ash/test/ash_test_base.h" #include "ash/test/ash_test_helper.h" #include "ash/test/status_area_widget_test_helper.h" @@ -18,7 +18,7 @@ namespace ash { -typedef test::AshTestBase MultiProfileMediaTrayItemTest; +using MultiProfileMediaTrayItemTest = test::AshTestBase; TEST_F(MultiProfileMediaTrayItemTest, NotifyMediaCaptureChange) { TrayItemView::DisableAnimationsForTest();
diff --git a/ash/system/chromeos/multi_user/user_switch_util.cc b/ash/system/chromeos/multi_user/user_switch_util.cc deleted file mode 100644 index e29ad22e..0000000 --- a/ash/system/chromeos/multi_user/user_switch_util.cc +++ /dev/null
@@ -1,197 +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. - -#include "ash/system/chromeos/multi_user/user_switch_util.h" - -#include "ash/common/system/chromeos/screen_security/screen_tray_item.h" -#include "ash/shell.h" -#include "ash/system/tray/system_tray.h" -#include "grit/ash_strings.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/views/controls/label.h" -#include "ui/views/layout/grid_layout.h" -#include "ui/views/widget/widget.h" -#include "ui/views/window/dialog_delegate.h" - -namespace ash { - -namespace { - -// Default width/height of the dialog. -const int kDefaultWidth = 500; -const int kDefaultHeight = 150; - -const int kPaddingToMessage = 30; -const int kInset = 40; -const int kTopInset = 10; - -//////////////////////////////////////////////////////////////////////////////// -// Dialog for multi-profiles desktop casting warning. -class DesktopCastingWarningView : public views::DialogDelegateView { - public: - DesktopCastingWarningView(base::Callback<void()> on_accept); - ~DesktopCastingWarningView() override; - - static void ShowDialog(const base::Callback<void()> on_accept); - - // views::DialogDelegate overrides. - bool Accept() override; - base::string16 GetDialogButtonLabel(ui::DialogButton button) const override; - bool IsDialogButtonEnabled(ui::DialogButton button) const override; - int GetDefaultDialogButton() const override; - - // views::WidgetDelegate overrides. - ui::ModalType GetModalType() const override; - - // views::View overrides. - gfx::Size GetPreferredSize() const override; - - private: - void InitDialog(); - - const base::Callback<void()> on_switch_; - - DISALLOW_COPY_AND_ASSIGN(DesktopCastingWarningView); -}; - -// The current instance of the running dialog - or NULL. This is used for -// unittest related functions. -static DesktopCastingWarningView* instance_for_test; - -//////////////////////////////////////////////////////////////////////////////// -// DesktopCastingWarningView implementation. - -DesktopCastingWarningView::DesktopCastingWarningView( - const base::Callback<void()> on_switch) - : on_switch_(on_switch) { - DCHECK(!instance_for_test); - instance_for_test = this; -} - -DesktopCastingWarningView::~DesktopCastingWarningView() { - DCHECK(instance_for_test); - instance_for_test = NULL; -} - -// static -void DesktopCastingWarningView::ShowDialog( - const base::Callback<void()> on_accept) { - DesktopCastingWarningView* dialog_view = - new DesktopCastingWarningView(on_accept); - views::DialogDelegate::CreateDialogWidget( - dialog_view, ash::Shell::GetTargetRootWindow(), NULL); - dialog_view->InitDialog(); - views::Widget* widget = dialog_view->GetWidget(); - DCHECK(widget); - widget->Show(); -} - -bool DesktopCastingWarningView::Accept() { - // Stop screen sharing and capturing. - SystemTray* system_tray = ash::Shell::GetInstance()->GetPrimarySystemTray(); - if (system_tray->GetScreenShareItem()->is_started()) - system_tray->GetScreenShareItem()->Stop(); - if (system_tray->GetScreenCaptureItem()->is_started()) - system_tray->GetScreenCaptureItem()->Stop(); - - on_switch_.Run(); - return true; -} - -base::string16 DesktopCastingWarningView::GetDialogButtonLabel( - ui::DialogButton button) const { - return l10n_util::GetStringUTF16( - button == ui::DIALOG_BUTTON_OK - ? IDS_DESKTOP_CASTING_ACTIVE_BUTTON_SWITCH_USER - : IDS_DESKTOP_CASTING_ACTIVE_BUTTON_ABORT_USER_SWITCH); -} - -bool DesktopCastingWarningView::IsDialogButtonEnabled( - ui::DialogButton button) const { - return button == ui::DIALOG_BUTTON_OK || button == ui::DIALOG_BUTTON_CANCEL; -} - -int DesktopCastingWarningView::GetDefaultDialogButton() const { - // The default should turn off the casting. - return ui::DIALOG_BUTTON_CANCEL; -} - -ui::ModalType DesktopCastingWarningView::GetModalType() const { - return ui::MODAL_TYPE_SYSTEM; -} - -gfx::Size DesktopCastingWarningView::GetPreferredSize() const { - return gfx::Size(kDefaultWidth, kDefaultHeight); -} - -void DesktopCastingWarningView::InitDialog() { - const gfx::Insets kDialogInsets(kTopInset, kInset, kInset, kInset); - - // Create the views and layout manager and set them up. - views::GridLayout* grid_layout = views::GridLayout::CreatePanel(this); - grid_layout->SetInsets(kDialogInsets); - - views::ColumnSet* column_set = grid_layout->AddColumnSet(0); - column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, - views::GridLayout::USE_PREF, 0, 0); - - // Title - views::Label* title_label_ = new views::Label( - l10n_util::GetStringUTF16(IDS_DESKTOP_CASTING_ACTIVE_TITLE)); - title_label_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList( - ui::ResourceBundle::MediumBoldFont)); - title_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); - grid_layout->StartRow(0, 0); - grid_layout->AddView(title_label_); - grid_layout->AddPaddingRow(0, kPaddingToMessage); - - // Explanation string - views::Label* label = new views::Label( - l10n_util::GetStringUTF16(IDS_DESKTOP_CASTING_ACTIVE_MESSAGE)); - label->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList( - ui::ResourceBundle::MediumFont)); - label->SetMultiLine(true); - label->SetHorizontalAlignment(gfx::ALIGN_LEFT); - label->SetAllowCharacterBreak(true); - grid_layout->StartRow(0, 0); - grid_layout->AddView(label); - - SetLayoutManager(grid_layout); - Layout(); -} - -} // namespace - -//////////////////////////////////////////////////////////////////////////////// -// Factory function. - -void TrySwitchingActiveUser(const base::Callback<void()> on_switch) { - // Some unit tests do not have a shell. In that case simply execute. - if (!ash::Shell::HasInstance()) { - on_switch.Run(); - return; - } - // If neither screen sharing nor capturing is going on we can immediately - // switch users. - SystemTray* system_tray = ash::Shell::GetInstance()->GetPrimarySystemTray(); - if (!system_tray->GetScreenShareItem()->is_started() && - !system_tray->GetScreenCaptureItem()->is_started()) { - on_switch.Run(); - return; - } - DesktopCastingWarningView::ShowDialog(on_switch); -} - -bool TestAndTerminateDesktopCastingWarningForTest(bool accept) { - if (!instance_for_test) - return false; - if (accept) - instance_for_test->Accept(); - delete instance_for_test->GetWidget()->GetNativeWindow(); - CHECK(!instance_for_test); - return true; -} - -} // namespace chromeos
diff --git a/ash/system/chromeos/multi_user/user_switch_util.h b/ash/system/chromeos/multi_user/user_switch_util.h deleted file mode 100644 index 66e0073..0000000 --- a/ash/system/chromeos/multi_user/user_switch_util.h +++ /dev/null
@@ -1,26 +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 ASH_SYSTEM_CHROMEOS_MULTI_USER_MULTI_USER_SWITCH_UTIL_H_ -#define ASH_SYSTEM_CHROMEOS_MULTI_USER_MULTI_USER_SWITCH_UTIL_H_ - -#include "ash/ash_export.h" -#include "base/callback.h" - -namespace ash { - -// Tries to switch to a new user by first checking if desktop casting / sharing -// is going on, and let the user decide if he wants to terminate it or not. -// After terminating any desktop sharing operations, the |switch_user| function -// will be called. -void ASH_EXPORT -TrySwitchingActiveUser(const base::Callback<void()> switch_user); - -// Terminates the "DesktopCastingWarning" dialog from a unit tests and |accept|s -// it. False will be returned if there was no dialog shown. -bool ASH_EXPORT TestAndTerminateDesktopCastingWarningForTest(bool accept); - -} // namespace chromeos - -#endif // ASH_SYSTEM_CHROMEOS_MULTI_USER_MULTI_USER_SWITCH_UTIL_H_
diff --git a/ash/system/chromeos/multi_user/user_switch_util_unittest.cc b/ash/system/chromeos/multi_user/user_switch_util_unittest.cc deleted file mode 100644 index ef2f691e..0000000 --- a/ash/system/chromeos/multi_user/user_switch_util_unittest.cc +++ /dev/null
@@ -1,215 +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. - -#include "ash/common/system/chromeos/screen_security/screen_tray_item.h" -#include "ash/shell.h" -#include "ash/system/chromeos/multi_user/user_switch_util.h" -#include "ash/system/tray/system_tray.h" -#include "ash/test/ash_test_base.h" - -namespace ash { - -class TrySwitchingUserTest : public ash::test::AshTestBase { - public: - // The action type to perform / check for upon user switching. - enum ActionType { - NO_DIALOG, // No dialog should be shown. - ACCEPT_DIALOG, // A dialog should be shown and we should accept it. - DECLINE_DIALOG, // A dialog should be shown and we do not accept it. - }; - TrySwitchingUserTest() - : capture_item_(NULL), - share_item_(NULL), - stop_capture_callback_hit_count_(0), - stop_share_callback_hit_count_(0), - switch_callback_hit_count_(0) {} - ~TrySwitchingUserTest() override {} - - void SetUp() override { - test::AshTestBase::SetUp(); - TrayItemView::DisableAnimationsForTest(); - SystemTray* system_tray = Shell::GetInstance()->GetPrimarySystemTray(); - share_item_ = system_tray->GetScreenShareItem(); - capture_item_ = system_tray->GetScreenCaptureItem(); - EXPECT_TRUE(share_item_); - EXPECT_TRUE(capture_item_); - } - - // Accessing the capture session functionality. - // Simulates a screen capture session start. - void StartCaptureSession() { - capture_item_->Start(base::Bind(&TrySwitchingUserTest::StopCaptureCallback, - base::Unretained(this))); - } - - // The callback which gets called when the screen capture gets stopped. - void StopCaptureSession() { capture_item_->Stop(); } - - // Simulates a screen capture session stop. - void StopCaptureCallback() { stop_capture_callback_hit_count_++; } - - // Accessing the share session functionality. - // Simulate a Screen share session start. - void StartShareSession() { - share_item_->Start(base::Bind(&TrySwitchingUserTest::StopShareCallback, - base::Unretained(this))); - } - - // Simulates a screen share session stop. - void StopShareSession() { share_item_->Stop(); } - - // The callback which gets called when the screen share gets stopped. - void StopShareCallback() { stop_share_callback_hit_count_++; } - - // Issuing a switch user call which might or might not create a dialog. - // The passed |action| type parameter defines the outcome (which will be - // checked) and the action the user will choose. - void SwitchUser(ActionType action) { - TrySwitchingActiveUser(base::Bind(&TrySwitchingUserTest::SwitchCallback, - base::Unretained(this))); - switch (action) { - case NO_DIALOG: - EXPECT_TRUE(!TestAndTerminateDesktopCastingWarningForTest(true)); - return; - case ACCEPT_DIALOG: - EXPECT_TRUE(TestAndTerminateDesktopCastingWarningForTest(true)); - return; - case DECLINE_DIALOG: - EXPECT_TRUE(TestAndTerminateDesktopCastingWarningForTest(false)); - return; - } - } - - // Called when the user will get actually switched. - void SwitchCallback() { switch_callback_hit_count_++; } - - // Various counter accessors. - int stop_capture_callback_hit_count() const { - return stop_capture_callback_hit_count_; - } - int stop_share_callback_hit_count() const { - return stop_share_callback_hit_count_; - } - int switch_callback_hit_count() const { return switch_callback_hit_count_; } - - private: - // The two items from the SystemTray for the screen capture / share - // functionality. - ScreenTrayItem* capture_item_; - ScreenTrayItem* share_item_; - - // Various counters to query for. - int stop_capture_callback_hit_count_; - int stop_share_callback_hit_count_; - int switch_callback_hit_count_; - - DISALLOW_COPY_AND_ASSIGN(TrySwitchingUserTest); -}; - -// Test that when there is no screen operation going on the user switch will be -// performed as planned. -TEST_F(TrySwitchingUserTest, NoLock) { - EXPECT_EQ(0, switch_callback_hit_count()); - SwitchUser(TrySwitchingUserTest::NO_DIALOG); - EXPECT_EQ(1, switch_callback_hit_count()); -} - -// Test that with a screen capture operation going on, the user will need to -// confirm. Declining will neither change the running state or switch users. -TEST_F(TrySwitchingUserTest, CaptureActiveDeclined) { - EXPECT_EQ(0, switch_callback_hit_count()); - StartCaptureSession(); - SwitchUser(TrySwitchingUserTest::DECLINE_DIALOG); - EXPECT_EQ(0, switch_callback_hit_count()); - EXPECT_EQ(0, stop_capture_callback_hit_count()); - EXPECT_EQ(0, stop_share_callback_hit_count()); - StopCaptureSession(); - EXPECT_EQ(0, switch_callback_hit_count()); - EXPECT_EQ(1, stop_capture_callback_hit_count()); - EXPECT_EQ(0, stop_share_callback_hit_count()); -} - -// Test that with a screen share operation going on, the user will need to -// confirm. Declining will neither change the running state or switch users. -TEST_F(TrySwitchingUserTest, ShareActiveDeclined) { - EXPECT_EQ(0, switch_callback_hit_count()); - StartShareSession(); - SwitchUser(TrySwitchingUserTest::DECLINE_DIALOG); - EXPECT_EQ(0, switch_callback_hit_count()); - EXPECT_EQ(0, stop_capture_callback_hit_count()); - EXPECT_EQ(0, stop_share_callback_hit_count()); - StopShareSession(); - EXPECT_EQ(0, switch_callback_hit_count()); - EXPECT_EQ(0, stop_capture_callback_hit_count()); - EXPECT_EQ(1, stop_share_callback_hit_count()); -} - -// Test that with both operations going on, the user will need to confirm. -// Declining will neither change the running state or switch users. -TEST_F(TrySwitchingUserTest, BothActiveDeclined) { - EXPECT_EQ(0, switch_callback_hit_count()); - StartShareSession(); - StartCaptureSession(); - SwitchUser(TrySwitchingUserTest::DECLINE_DIALOG); - EXPECT_EQ(0, switch_callback_hit_count()); - EXPECT_EQ(0, stop_capture_callback_hit_count()); - EXPECT_EQ(0, stop_share_callback_hit_count()); - StopShareSession(); - StopCaptureSession(); - EXPECT_EQ(0, switch_callback_hit_count()); - EXPECT_EQ(1, stop_capture_callback_hit_count()); - EXPECT_EQ(1, stop_share_callback_hit_count()); -} - -// Test that with a screen capture operation going on, the user will need to -// confirm. Accepting will change to stopped state and switch users. -TEST_F(TrySwitchingUserTest, CaptureActiveAccepted) { - EXPECT_EQ(0, switch_callback_hit_count()); - StartCaptureSession(); - SwitchUser(TrySwitchingUserTest::ACCEPT_DIALOG); - EXPECT_EQ(1, switch_callback_hit_count()); - EXPECT_EQ(1, stop_capture_callback_hit_count()); - EXPECT_EQ(0, stop_share_callback_hit_count()); - // Another stop should have no effect. - StopCaptureSession(); - EXPECT_EQ(1, switch_callback_hit_count()); - EXPECT_EQ(1, stop_capture_callback_hit_count()); - EXPECT_EQ(0, stop_share_callback_hit_count()); -} - -// Test that with a screen share operation going on, the user will need to -// confirm. Accepting will change to stopped state and switch users. -TEST_F(TrySwitchingUserTest, ShareActiveAccepted) { - EXPECT_EQ(0, switch_callback_hit_count()); - StartShareSession(); - SwitchUser(TrySwitchingUserTest::ACCEPT_DIALOG); - EXPECT_EQ(1, switch_callback_hit_count()); - EXPECT_EQ(0, stop_capture_callback_hit_count()); - EXPECT_EQ(1, stop_share_callback_hit_count()); - // Another stop should have no effect. - StopShareSession(); - EXPECT_EQ(1, switch_callback_hit_count()); - EXPECT_EQ(0, stop_capture_callback_hit_count()); - EXPECT_EQ(1, stop_share_callback_hit_count()); -} - -// Test that with both operations going on, the user will need to confirm. -// Accepting will change to stopped state and switch users. -TEST_F(TrySwitchingUserTest, BothActiveAccepted) { - EXPECT_EQ(0, switch_callback_hit_count()); - StartShareSession(); - StartCaptureSession(); - SwitchUser(TrySwitchingUserTest::ACCEPT_DIALOG); - EXPECT_EQ(1, switch_callback_hit_count()); - EXPECT_EQ(1, stop_capture_callback_hit_count()); - EXPECT_EQ(1, stop_share_callback_hit_count()); - // Another stop should have no effect. - StopShareSession(); - StopCaptureSession(); - EXPECT_EQ(1, switch_callback_hit_count()); - EXPECT_EQ(1, stop_capture_callback_hit_count()); - EXPECT_EQ(1, stop_share_callback_hit_count()); -} - -} // namespace ash
diff --git a/ash/system/chromeos/rotation/tray_rotation_lock.cc b/ash/system/chromeos/rotation/tray_rotation_lock.cc index 07446a38..ffc1290 100644 --- a/ash/system/chromeos/rotation/tray_rotation_lock.cc +++ b/ash/system/chromeos/rotation/tray_rotation_lock.cc
@@ -5,13 +5,13 @@ #include "ash/system/chromeos/rotation/tray_rotation_lock.h" #include "ash/common/material_design/material_design_controller.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/tray_constants.h" #include "ash/common/system/tray/tray_item_more.h" #include "ash/common/wm/maximize_mode/maximize_mode_controller.h" #include "ash/common/wm_shell.h" #include "ash/display/screen_orientation_controller_chromeos.h" #include "ash/shell.h" -#include "ash/system/tray/system_tray.h" #include "grit/ash_resources.h" #include "grit/ash_strings.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/ash/system/chromeos/rotation/tray_rotation_lock_unittest.cc b/ash/system/chromeos/rotation/tray_rotation_lock_unittest.cc index 3ac3379..8bf0203 100644 --- a/ash/system/chromeos/rotation/tray_rotation_lock_unittest.cc +++ b/ash/system/chromeos/rotation/tray_rotation_lock_unittest.cc
@@ -7,6 +7,8 @@ #include <memory> #include "ash/common/ash_switches.h" +#include "ash/common/system/status_area_widget.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/wm/maximize_mode/maximize_mode_controller.h" #include "ash/common/wm_shell.h" @@ -14,8 +16,6 @@ #include "ash/display/screen_orientation_controller_chromeos.h" #include "ash/root_window_controller.h" #include "ash/shell.h" -#include "ash/system/status_area_widget.h" -#include "ash/system/tray/system_tray.h" #include "ash/test/ash_test_base.h" #include "ash/test/status_area_widget_test_helper.h" #include "base/command_line.h"
diff --git a/ash/system/chromeos/tray_display.cc b/ash/system/chromeos/tray_display.cc index 36790db..f595dedf 100644 --- a/ash/system/chromeos/tray_display.cc +++ b/ash/system/chromeos/tray_display.cc
@@ -8,10 +8,12 @@ #include <utility> #include <vector> +#include "ash/common/metrics/user_metrics_action.h" #include "ash/common/system/chromeos/devicetype_utils.h" #include "ash/common/system/system_notifier.h" #include "ash/common/system/tray/actionable_view.h" #include "ash/common/system/tray/fixed_sized_image_view.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/tray_constants.h" #include "ash/common/system/tray/tray_notification_view.h" @@ -19,7 +21,6 @@ #include "ash/display/display_manager.h" #include "ash/display/screen_orientation_controller_chromeos.h" #include "ash/shell.h" -#include "ash/system/tray/system_tray.h" #include "base/bind.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -111,13 +112,14 @@ return base::JoinString(lines, base::ASCIIToUTF16("\n")); } -void OpenSettings() { +// Attempts to open the display settings, returns true if successful. +bool OpenSettings() { // switch is intentionally introduced without default, to cause an error when // a new type of login status is introduced. switch (WmShell::Get()->system_tray_delegate()->GetUserLoginStatus()) { case LoginStatus::NOT_LOGGED_IN: case LoginStatus::LOCKED: - return; + return false; case LoginStatus::USER: case LoginStatus::OWNER: @@ -126,8 +128,22 @@ case LoginStatus::SUPERVISED: case LoginStatus::KIOSK_APP: SystemTrayDelegate* delegate = WmShell::Get()->system_tray_delegate(); - if (delegate->ShouldShowSettings()) + if (delegate->ShouldShowSettings()) { delegate->ShowDisplaySettings(); + return true; + } + } + + return false; +} + +// Callback to handle a user selecting the notification view. +void OpenSettingsFromNotification() { + WmShell::Get()->RecordUserMetricsAction( + UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SELECTED); + if (OpenSettings()) { + WmShell::Get()->RecordUserMetricsAction( + UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SHOW_SETTINGS); } } @@ -279,7 +295,12 @@ // Overridden from ActionableView. bool PerformAction(const ui::Event& event) override { - OpenSettings(); + WmShell::Get()->RecordUserMetricsAction( + UMA_STATUS_AREA_DISPLAY_DEFAULT_SELECTED); + if (OpenSettings()) { + WmShell::Get()->RecordUserMetricsAction( + UMA_STATUS_AREA_DISPLAY_DEFAULT_SHOW_SETTINGS); + } return true; } @@ -404,8 +425,10 @@ system_notifier::kNotifierDisplay), message_center::RichNotificationData(), new message_center::HandleNotificationClickedDelegate( - base::Bind(&OpenSettings)))); + base::Bind(&OpenSettingsFromNotification)))); + WmShell::Get()->RecordUserMetricsAction( + UMA_STATUS_AREA_DISPLAY_NOTIFICATION_CREATED); message_center::MessageCenter::Get()->AddNotification( std::move(notification)); }
diff --git a/ash/system/chromeos/tray_display_unittest.cc b/ash/system/chromeos/tray_display_unittest.cc index e6e9acdf..1b6a69a2 100644 --- a/ash/system/chromeos/tray_display_unittest.cc +++ b/ash/system/chromeos/tray_display_unittest.cc
@@ -5,10 +5,10 @@ #include "ash/system/chromeos/tray_display.h" #include "ash/common/system/chromeos/devicetype_utils.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/display/display_manager.h" #include "ash/screen_util.h" #include "ash/shell.h" -#include "ash/system/tray/system_tray.h" #include "ash/test/ash_test_base.h" #include "ash/test/display_manager_test_api.h" #include "ash/test/test_system_tray_delegate.h"
diff --git a/ash/system/overview/overview_button_tray_unittest.cc b/ash/system/overview/overview_button_tray_unittest.cc index 32f320e..262adf7 100644 --- a/ash/system/overview/overview_button_tray_unittest.cc +++ b/ash/system/overview/overview_button_tray_unittest.cc
@@ -7,6 +7,7 @@ #include "ash/common/ash_switches.h" #include "ash/common/login_status.h" #include "ash/common/shelf/shelf_types.h" +#include "ash/common/system/status_area_widget.h" #include "ash/common/wm/maximize_mode/maximize_mode_controller.h" #include "ash/common/wm/overview/window_selector_controller.h" #include "ash/common/wm_shell.h" @@ -14,7 +15,6 @@ #include "ash/root_window_controller.h" #include "ash/rotator/screen_rotation_animator.h" #include "ash/shell.h" -#include "ash/system/status_area_widget.h" #include "ash/test/ash_test_base.h" #include "ash/test/ash_test_helper.h" #include "ash/test/status_area_widget_test_helper.h"
diff --git a/ash/system/status_area_widget.cc b/ash/system/status_area_widget.cc deleted file mode 100644 index 0f91614..0000000 --- a/ash/system/status_area_widget.cc +++ /dev/null
@@ -1,208 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/system/status_area_widget.h" - -#include "ash/common/shelf/wm_shelf.h" -#include "ash/common/shell_window_ids.h" -#include "ash/common/system/overview/overview_button_tray.h" -#include "ash/common/system/status_area_widget_delegate.h" -#include "ash/common/system/tray/system_tray_delegate.h" -#include "ash/common/system/web_notification/web_notification_tray.h" -#include "ash/common/wm_lookup.h" -#include "ash/common/wm_root_window_controller.h" -#include "ash/common/wm_shell.h" -#include "ash/common/wm_window.h" -#include "ash/system/tray/system_tray.h" -#include "base/i18n/time_formatting.h" - -#if defined(OS_CHROMEOS) -#include "ash/common/system/chromeos/session/logout_button_tray.h" -#include "ash/common/system/chromeos/virtual_keyboard/virtual_keyboard_tray.h" -#endif - -namespace ash { - -StatusAreaWidget::StatusAreaWidget(WmWindow* status_container, - WmShelf* wm_shelf) - : status_area_widget_delegate_(new StatusAreaWidgetDelegate), - overview_button_tray_(NULL), - system_tray_(NULL), - web_notification_tray_(NULL), -#if defined(OS_CHROMEOS) - logout_button_tray_(NULL), - virtual_keyboard_tray_(NULL), -#endif - login_status_(LoginStatus::NOT_LOGGED_IN), - wm_shelf_(wm_shelf) { - views::Widget::InitParams params( - views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); - params.delegate = status_area_widget_delegate_; - params.name = "StatusAreaWidget"; - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - status_container->GetRootWindowController() - ->ConfigureWidgetInitParamsForContainer( - this, status_container->GetShellWindowId(), ¶ms); - Init(params); - set_focus_on_creation(false); - SetContentsView(status_area_widget_delegate_); -} - -StatusAreaWidget::~StatusAreaWidget() {} - -void StatusAreaWidget::CreateTrayViews() { - AddOverviewButtonTray(); - AddSystemTray(); - AddWebNotificationTray(); -#if defined(OS_CHROMEOS) - AddLogoutButtonTray(); - AddVirtualKeyboardTray(); -#endif - - SystemTrayDelegate* delegate = WmShell::Get()->system_tray_delegate(); - DCHECK(delegate); - // Initialize after all trays have been created. - system_tray_->InitializeTrayItems(delegate, web_notification_tray_); - web_notification_tray_->Initialize(); -#if defined(OS_CHROMEOS) - logout_button_tray_->Initialize(); - virtual_keyboard_tray_->Initialize(); -#endif - overview_button_tray_->Initialize(); - SetShelfAlignment(system_tray_->shelf_alignment()); - UpdateAfterLoginStatusChange(delegate->GetUserLoginStatus()); -} - -void StatusAreaWidget::Shutdown() { - system_tray_->Shutdown(); - // Destroy the trays early, causing them to be removed from the view - // hierarchy. Do not used scoped pointers since we don't want to destroy them - // in the destructor if Shutdown() is not called (e.g. in tests). - delete web_notification_tray_; - web_notification_tray_ = NULL; - // Must be destroyed after |web_notification_tray_|. - delete system_tray_; - system_tray_ = NULL; -#if defined(OS_CHROMEOS) - delete virtual_keyboard_tray_; - virtual_keyboard_tray_ = NULL; - delete logout_button_tray_; - logout_button_tray_ = NULL; -#endif - delete overview_button_tray_; - overview_button_tray_ = NULL; -} - -bool StatusAreaWidget::ShouldShowShelf() const { - if ((system_tray_ && system_tray_->ShouldShowShelf()) || - (web_notification_tray_ && - web_notification_tray_->ShouldBlockShelfAutoHide())) - return true; - - if (!wm_shelf_->IsVisible()) - return false; - - // If the shelf is currently visible, don't hide the shelf if the mouse - // is in any of the notification bubbles. - return (system_tray_ && system_tray_->IsMouseInNotificationBubble()) || - (web_notification_tray_ && - web_notification_tray_->IsMouseInNotificationBubble()); -} - -bool StatusAreaWidget::IsMessageBubbleShown() const { - return ((system_tray_ && system_tray_->IsAnyBubbleVisible()) || - (web_notification_tray_ && - web_notification_tray_->IsMessageCenterBubbleVisible())); -} - -void StatusAreaWidget::SchedulePaint() { - status_area_widget_delegate_->SchedulePaint(); - web_notification_tray_->SchedulePaint(); - system_tray_->SchedulePaint(); -#if defined(OS_CHROMEOS) - virtual_keyboard_tray_->SchedulePaint(); - logout_button_tray_->SchedulePaint(); -#endif - overview_button_tray_->SchedulePaint(); -} - -void StatusAreaWidget::OnNativeWidgetActivationChanged(bool active) { - Widget::OnNativeWidgetActivationChanged(active); - if (active) - status_area_widget_delegate_->SetPaneFocusAndFocusDefault(); -} - -void StatusAreaWidget::OnMouseEvent(ui::MouseEvent* event) { - Widget::OnMouseEvent(event); - wm_shelf_->UpdateAutoHideForMouseEvent(event); -} - -void StatusAreaWidget::OnGestureEvent(ui::GestureEvent* event) { - Widget::OnGestureEvent(event); - wm_shelf_->UpdateAutoHideForGestureEvent(event); -} - -void StatusAreaWidget::AddSystemTray() { - system_tray_ = new SystemTray(wm_shelf_); - status_area_widget_delegate_->AddTray(system_tray_); -} - -void StatusAreaWidget::AddWebNotificationTray() { - DCHECK(system_tray_); - web_notification_tray_ = new WebNotificationTray( - wm_shelf_, WmLookup::Get()->GetWindowForWidget(this), system_tray_); - status_area_widget_delegate_->AddTray(web_notification_tray_); -} - -#if defined(OS_CHROMEOS) -void StatusAreaWidget::AddLogoutButtonTray() { - logout_button_tray_ = new LogoutButtonTray(wm_shelf_); - status_area_widget_delegate_->AddTray(logout_button_tray_); -} - -void StatusAreaWidget::AddVirtualKeyboardTray() { - virtual_keyboard_tray_ = new VirtualKeyboardTray(wm_shelf_); - status_area_widget_delegate_->AddTray(virtual_keyboard_tray_); -} -#endif - -void StatusAreaWidget::AddOverviewButtonTray() { - overview_button_tray_ = new OverviewButtonTray(wm_shelf_); - status_area_widget_delegate_->AddTray(overview_button_tray_); -} - -void StatusAreaWidget::SetShelfAlignment(ShelfAlignment alignment) { - status_area_widget_delegate_->set_alignment(alignment); - if (system_tray_) - system_tray_->SetShelfAlignment(alignment); - if (web_notification_tray_) - web_notification_tray_->SetShelfAlignment(alignment); -#if defined(OS_CHROMEOS) - if (logout_button_tray_) - logout_button_tray_->SetShelfAlignment(alignment); - if (virtual_keyboard_tray_) - virtual_keyboard_tray_->SetShelfAlignment(alignment); -#endif - if (overview_button_tray_) - overview_button_tray_->SetShelfAlignment(alignment); - status_area_widget_delegate_->UpdateLayout(); -} - -void StatusAreaWidget::UpdateAfterLoginStatusChange(LoginStatus login_status) { - if (login_status_ == login_status) - return; - login_status_ = login_status; - if (system_tray_) - system_tray_->UpdateAfterLoginStatusChange(login_status); - if (web_notification_tray_) - web_notification_tray_->UpdateAfterLoginStatusChange(login_status); -#if defined(OS_CHROMEOS) - if (logout_button_tray_) - logout_button_tray_->UpdateAfterLoginStatusChange(login_status); -#endif - if (overview_button_tray_) - overview_button_tray_->UpdateAfterLoginStatusChange(login_status); -} - -} // namespace ash
diff --git a/ash/system/status_area_widget.h b/ash/system/status_area_widget.h deleted file mode 100644 index ce4eeb0f..0000000 --- a/ash/system/status_area_widget.h +++ /dev/null
@@ -1,103 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_SYSTEM_STATUS_AREA_WIDGET_H_ -#define ASH_SYSTEM_STATUS_AREA_WIDGET_H_ - -#include "ash/ash_export.h" -#include "ash/common/login_status.h" -#include "ash/common/shelf/shelf_types.h" -#include "base/macros.h" -#include "ui/views/widget/widget.h" - -namespace ash { -class OverviewButtonTray; -class ShellDelegate; -class StatusAreaWidgetDelegate; -class SystemTray; -class WebNotificationTray; -class WmShelf; -class WmWindow; -#if defined(OS_CHROMEOS) -class LogoutButtonTray; -class VirtualKeyboardTray; -#endif - -class ASH_EXPORT StatusAreaWidget : public views::Widget { - public: - StatusAreaWidget(WmWindow* status_container, WmShelf* wm_shelf); - ~StatusAreaWidget() override; - - // Creates the SystemTray, WebNotificationTray and LogoutButtonTray. - void CreateTrayViews(); - - // Destroys the system tray and web notification tray. Called before - // tearing down the windows to avoid shutdown ordering issues. - void Shutdown(); - - // Update the alignment of the widget and tray views. - void SetShelfAlignment(ShelfAlignment alignment); - - // Called by the client when the login status changes. Caches login_status - // and calls UpdateAfterLoginStatusChange for the system tray and the web - // notification tray. - void UpdateAfterLoginStatusChange(LoginStatus login_status); - - StatusAreaWidgetDelegate* status_area_widget_delegate() { - return status_area_widget_delegate_; - } - SystemTray* system_tray() { return system_tray_; } - WebNotificationTray* web_notification_tray() { - return web_notification_tray_; - } - OverviewButtonTray* overview_button_tray() { return overview_button_tray_; } - WmShelf* wm_shelf() { return wm_shelf_; } - - LoginStatus login_status() const { return login_status_; } - - // Returns true if the shelf should be visible. This is used when the - // shelf is configured to auto-hide and test if the shelf should force - // the shelf to remain visible. - bool ShouldShowShelf() const; - - // True if any message bubble is shown. - bool IsMessageBubbleShown() const; - - // Notifies child trays, and the |status_area_widget_delegate_| to schedule a - // paint. - void SchedulePaint(); - - // Overridden from views::Widget: - void OnNativeWidgetActivationChanged(bool active) override; - void OnMouseEvent(ui::MouseEvent* event) override; - void OnGestureEvent(ui::GestureEvent* event) override; - - private: - void AddSystemTray(); - void AddWebNotificationTray(); -#if defined(OS_CHROMEOS) - void AddLogoutButtonTray(); - void AddVirtualKeyboardTray(); -#endif - void AddOverviewButtonTray(); - - // Weak pointers to View classes that are parented to StatusAreaWidget: - StatusAreaWidgetDelegate* status_area_widget_delegate_; - OverviewButtonTray* overview_button_tray_; - SystemTray* system_tray_; - WebNotificationTray* web_notification_tray_; -#if defined(OS_CHROMEOS) - LogoutButtonTray* logout_button_tray_; - VirtualKeyboardTray* virtual_keyboard_tray_; -#endif - LoginStatus login_status_; - - WmShelf* wm_shelf_; - - DISALLOW_COPY_AND_ASSIGN(StatusAreaWidget); -}; - -} // namespace ash - -#endif // ASH_SYSTEM_STATUS_AREA_WIDGET_H_
diff --git a/ash/system/toast/toast_data.cc b/ash/system/toast/toast_data.cc deleted file mode 100644 index b1cf90d..0000000 --- a/ash/system/toast/toast_data.cc +++ /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. - -#include "ash/system/toast/toast_data.h" - -#include <utility> - -namespace ash { - -ToastData::ToastData(std::string id, - std::string text, - int32_t duration_ms, - std::string dismiss_text) - : id(std::move(id)), - text(std::move(text)), - duration_ms(duration_ms), - dismiss_text(std::move(dismiss_text)) {} - -ToastData::ToastData(const ToastData& other) = default; - -} // namespace ash
diff --git a/ash/system/toast/toast_data.h b/ash/system/toast/toast_data.h deleted file mode 100644 index 0389abc..0000000 --- a/ash/system/toast/toast_data.h +++ /dev/null
@@ -1,33 +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 ASH_SYSTEM_TOAST_TOAST_DATA_H_ -#define ASH_SYSTEM_TOAST_TOAST_DATA_H_ - -#include <string> - -#include "ash/ash_export.h" - -namespace ash { - -struct ASH_EXPORT ToastData { - // "|duration_ms| == -1" means the toast view should be displayed until the - // dismiss button is clicked. - static const int32_t kInfiniteDuration = -1; - - ToastData(std::string id, - std::string text, - int32_t duration_ms, - std::string dismiss_text); - ToastData(const ToastData& other); - - std::string id; - std::string text; - int32_t duration_ms; - std::string dismiss_text; -}; - -} // namespace ash - -#endif // ASH_SYSTEM_TOAST_TOAST_DATA_H_
diff --git a/ash/system/toast/toast_manager.cc b/ash/system/toast/toast_manager.cc deleted file mode 100644 index edb48526..0000000 --- a/ash/system/toast/toast_manager.cc +++ /dev/null
@@ -1,95 +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 "ash/system/toast/toast_manager.h" - -#include "base/bind.h" -#include "base/location.h" -#include "base/threading/thread_task_runner_handle.h" - -namespace ash { - -namespace { - -// Minimum duration for a toast to be visible (in millisecond). -const int32_t kMinimumDurationMs = 200; - -} // anonymous namespace - -ToastManager::ToastManager() : weak_ptr_factory_(this) {} - -ToastManager::~ToastManager() {} - -void ToastManager::Show(const ToastData& data) { - const std::string& id = data.id; - DCHECK(!id.empty()); - - if (current_toast_id_ == id) { - // TODO(yoshiki): Replaces the visible toast. - return; - } - - auto existing_toast = - std::find_if(queue_.begin(), queue_.end(), - [&id](const ToastData& data) { return data.id == id; }); - - if (existing_toast == queue_.end()) { - queue_.emplace_back(data); - } else { - *existing_toast = data; - } - - if (queue_.size() == 1 && overlay_ == nullptr) - ShowLatest(); -} - -void ToastManager::Cancel(const std::string& id) { - if (id == current_toast_id_) { - overlay_->Show(false); - return; - } - - auto cancelled_toast = - std::find_if(queue_.begin(), queue_.end(), - [&id](const ToastData& data) { return data.id == id; }); - if (cancelled_toast != queue_.end()) - queue_.erase(cancelled_toast); -} - -void ToastManager::OnClosed() { - overlay_.reset(); - current_toast_id_.clear(); - - // Show the next toast if available. - if (!queue_.empty()) - ShowLatest(); -} - -void ToastManager::ShowLatest() { - DCHECK(!overlay_); - - const ToastData data = std::move(queue_.front()); - queue_.pop_front(); - - current_toast_id_ = data.id; - serial_++; - - overlay_.reset(new ToastOverlay(this, data.text, data.dismiss_text)); - overlay_->Show(true); - - if (data.duration_ms != ToastData::kInfiniteDuration) { - int32_t duration_ms = std::max(data.duration_ms, kMinimumDurationMs); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&ToastManager::OnDurationPassed, - weak_ptr_factory_.GetWeakPtr(), serial_), - base::TimeDelta::FromMilliseconds(duration_ms)); - } -} - -void ToastManager::OnDurationPassed(int toast_number) { - if (overlay_ && serial_ == toast_number) - overlay_->Show(false); -} - -} // namespace ash
diff --git a/ash/system/toast/toast_manager.h b/ash/system/toast/toast_manager.h deleted file mode 100644 index d71fef4..0000000 --- a/ash/system/toast/toast_manager.h +++ /dev/null
@@ -1,60 +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 ASH_SYSTEM_TOAST_TOAST_MANAGER_H_ -#define ASH_SYSTEM_TOAST_TOAST_MANAGER_H_ - -#include <deque> -#include <memory> -#include <string> - -#include "ash/ash_export.h" -#include "ash/common/shell_observer.h" -#include "ash/system/toast/toast_data.h" -#include "ash/system/toast/toast_overlay.h" -#include "base/memory/weak_ptr.h" -#include "base/threading/thread_checker.h" - -namespace ash { - -// Class managing toast requests. -class ASH_EXPORT ToastManager : public ToastOverlay::Delegate { - public: - ToastManager(); - ~ToastManager() override; - - // Show a toast. If there are queued toasts, succeeding toasts are queued as - // well, and are shown one by one. - void Show(const ToastData& data); - - void Cancel(const std::string& id); - - // ToastOverlay::Delegate overrides: - void OnClosed() override; - - private: - friend class ToastManagerTest; - - void ShowLatest(); - void OnDurationPassed(int toast_number); - - ToastOverlay* GetCurrentOverlayForTesting() { return overlay_.get(); } - int serial_for_testing() const { return serial_; } - void ResetSerialForTesting() { serial_ = 0; } - - // ID of the toast which is currently shown. Empty if no toast is visible. - std::string current_toast_id_; - - int serial_ = 0; - std::deque<ToastData> queue_; - std::unique_ptr<ToastOverlay> overlay_; - - base::WeakPtrFactory<ToastManager> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(ToastManager); -}; - -} // namespace ash - -#endif // ASH_SYSTEM_TOAST_TOAST_MANAGER_H_
diff --git a/ash/system/toast/toast_manager_unittest.cc b/ash/system/toast/toast_manager_unittest.cc index f8d942b5..ed2a882 100644 --- a/ash/system/toast/toast_manager_unittest.cc +++ b/ash/system/toast/toast_manager_unittest.cc
@@ -4,10 +4,10 @@ #include "ash/common/shelf/shelf_constants.h" #include "ash/common/shelf/wm_shelf.h" +#include "ash/common/system/toast/toast_manager.h" #include "ash/display/display_manager.h" #include "ash/screen_util.h" #include "ash/shell.h" -#include "ash/system/toast/toast_manager.h" #include "ash/test/ash_test_base.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h"
diff --git a/ash/system/toast/toast_overlay.cc b/ash/system/toast/toast_overlay.cc deleted file mode 100644 index 97e3cb7..0000000 --- a/ash/system/toast/toast_overlay.cc +++ /dev/null
@@ -1,296 +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 "ash/system/toast/toast_overlay.h" - -#include "ash/common/shelf/wm_shelf.h" -#include "ash/common/shell_window_ids.h" -#include "ash/common/wm_root_window_controller.h" -#include "ash/common/wm_shell.h" -#include "ash/common/wm_window.h" -#include "ash/screen_util.h" -#include "ash/shell.h" -#include "ash/wm/window_animations.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/threading/thread_task_runner_handle.h" -#include "grit/ash_strings.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/font_list.h" -#include "ui/views/border.h" -#include "ui/views/controls/button/label_button.h" -#include "ui/views/controls/label.h" -#include "ui/views/layout/box_layout.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -namespace ash { - -namespace { - -// Offset of the overlay from the edge of the work area. -const int kOffset = 5; - -// Font style used for modifier key labels. -const ui::ResourceBundle::FontStyle kTextFontStyle = - ui::ResourceBundle::MediumFont; - -// Duration of slide animation when overlay is shown or hidden. -const int kSlideAnimationDurationMs = 100; - -// Colors for the dismiss button. -const SkColor kButtonBackgroundColor = SkColorSetARGB(0xFF, 0x32, 0x32, 0x32); -const SkColor kButtonTextColor = SkColorSetARGB(0xFF, 0x7B, 0xAA, 0xF7); - -// These values are in DIP. -const int kToastHorizontalSpacing = 16; -const int kToastVerticalSpacing = 16; -const int kToastMaximumWidth = 568; -const int kToastMinimumWidth = 288; - -// Returns the shelf for the primary display. -WmShelf* GetPrimaryShelf() { - return WmShell::Get() - ->GetPrimaryRootWindow() - ->GetRootWindowController() - ->GetShelf(); -} - -} // anonymous namespace - -/////////////////////////////////////////////////////////////////////////////// -// ToastOverlayLabel -class ToastOverlayLabel : public views::Label { - public: - explicit ToastOverlayLabel(const std::string& label); - ~ToastOverlayLabel() override; - - private: - DISALLOW_COPY_AND_ASSIGN(ToastOverlayLabel); -}; - -ToastOverlayLabel::ToastOverlayLabel(const std::string& label) { - ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); - - SetText(base::UTF8ToUTF16(label)); - SetHorizontalAlignment(gfx::ALIGN_LEFT); - SetFontList(rb->GetFontList(kTextFontStyle)); - SetAutoColorReadabilityEnabled(false); - SetMultiLine(true); - SetEnabledColor(SK_ColorWHITE); - SetDisabledColor(SK_ColorWHITE); - SetSubpixelRenderingEnabled(false); - - int verticalSpacing = - kToastVerticalSpacing - (GetPreferredSize().height() - GetBaseline()); - SetBorder(views::Border::CreateEmptyBorder( - verticalSpacing, kToastHorizontalSpacing, verticalSpacing, - kToastHorizontalSpacing)); -} - -ToastOverlayLabel::~ToastOverlayLabel() {} - -/////////////////////////////////////////////////////////////////////////////// -// ToastOverlayButton -class ToastOverlayButton : public views::LabelButton { - public: - explicit ToastOverlayButton(views::ButtonListener* listener, - const base::string16& label); - ~ToastOverlayButton() override {} - - private: - friend class ToastOverlay; // for ToastOverlay::ClickDismissButtonForTesting. - - DISALLOW_COPY_AND_ASSIGN(ToastOverlayButton); -}; - -ToastOverlayButton::ToastOverlayButton(views::ButtonListener* listener, - const base::string16& text) - : views::LabelButton(listener, text) { - SetInkDropMode(InkDropMode::ON); - set_has_ink_drop_action_on_click(true); - set_ink_drop_base_color(SK_ColorWHITE); - - ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance(); - - SetEnabledTextColors(kButtonTextColor); - SetFontList(rb->GetFontList(kTextFontStyle)); - - // Treat the space below the baseline as a margin. - int verticalSpacing = kToastVerticalSpacing - - (GetPreferredSize().height() - label()->GetBaseline()); - SetBorder(views::Border::CreateEmptyBorder( - verticalSpacing, kToastHorizontalSpacing, verticalSpacing, - kToastHorizontalSpacing)); -} - -/////////////////////////////////////////////////////////////////////////////// -// ToastOverlayView -class ToastOverlayView : public views::View, public views::ButtonListener { - public: - // This object is not owned by the views hiearchy or by the widget. - ToastOverlayView(ToastOverlay* overlay, - const std::string& text, - const std::string& dismiss_text); - ~ToastOverlayView() override; - - // views::View overrides: - void OnPaint(gfx::Canvas* canvas) override; - - ToastOverlayButton* button() { return button_; } - - private: - ToastOverlay* overlay_; // weak - ToastOverlayButton* button_; // weak - - gfx::Size GetMaximumSize() const override; - gfx::Size GetMinimumSize() const override; - - void ButtonPressed(views::Button* sender, const ui::Event& event) override; - - DISALLOW_COPY_AND_ASSIGN(ToastOverlayView); -}; - -ToastOverlayView::ToastOverlayView(ToastOverlay* overlay, - const std::string& text, - const std::string& dismiss_text) - : overlay_(overlay), - button_(new ToastOverlayButton( - this, - dismiss_text.empty() - ? l10n_util::GetStringUTF16(IDS_ASH_TOAST_DISMISS_BUTTON) - : base::UTF8ToUTF16(dismiss_text))) { - ToastOverlayLabel* label = new ToastOverlayLabel(text); - label->SetMaximumWidth( - GetMaximumSize().width() - button_->GetPreferredSize().width() - - kToastHorizontalSpacing * 2 - kToastHorizontalSpacing * 2); - AddChildView(label); - - AddChildView(button_); - - auto* layout = new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0); - SetLayoutManager(layout); - layout->SetFlexForView(label, 1); - layout->SetFlexForView(button_, 0); -} - -ToastOverlayView::~ToastOverlayView() {} - -void ToastOverlayView::OnPaint(gfx::Canvas* canvas) { - SkPaint paint; - paint.setStyle(SkPaint::kFill_Style); - paint.setColor(kButtonBackgroundColor); - canvas->DrawRoundRect(GetLocalBounds(), 2, paint); - views::View::OnPaint(canvas); -} - -gfx::Size ToastOverlayView::GetMinimumSize() const { - return gfx::Size(kToastMinimumWidth, 0); -} - -gfx::Size ToastOverlayView::GetMaximumSize() const { - gfx::Rect work_area_bounds = GetPrimaryShelf()->GetUserWorkAreaBounds(); - return gfx::Size(kToastMaximumWidth, work_area_bounds.height() - kOffset * 2); -} - -void ToastOverlayView::ButtonPressed(views::Button* sender, - const ui::Event& event) { - overlay_->Show(false); -} - -/////////////////////////////////////////////////////////////////////////////// -// ToastOverlay -ToastOverlay::ToastOverlay(Delegate* delegate, - const std::string& text, - const std::string& dismiss_text) - : delegate_(delegate), - text_(text), - dismiss_text_(dismiss_text), - overlay_view_(new ToastOverlayView(this, text, dismiss_text)), - widget_size_(overlay_view_->GetPreferredSize()) { - views::Widget::InitParams params; - params.type = views::Widget::InitParams::TYPE_POPUP; - params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; - params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; - params.accept_events = true; - params.keep_on_top = true; - params.remove_standard_frame = true; - params.bounds = CalculateOverlayBounds(); - // Show toasts above the app list and below the lock screen. - // TODO(jamescook): Either this should be the primary root window, or the - // work area bounds computation should be for the target root window. - params.parent = Shell::GetContainer(Shell::GetTargetRootWindow(), - kShellWindowId_SystemModalContainer); - overlay_widget_.reset(new views::Widget); - overlay_widget_->Init(params); - overlay_widget_->SetVisibilityChangedAnimationsEnabled(true); - overlay_widget_->SetContentsView(overlay_view_.get()); - overlay_widget_->SetBounds(CalculateOverlayBounds()); - overlay_widget_->GetNativeView()->SetName("ToastOverlay"); - - gfx::NativeWindow native_view = overlay_widget_->GetNativeView(); - ::wm::SetWindowVisibilityAnimationType( - native_view, ::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL); - ::wm::SetWindowVisibilityAnimationDuration( - native_view, - base::TimeDelta::FromMilliseconds(kSlideAnimationDurationMs)); -} - -ToastOverlay::~ToastOverlay() { - overlay_widget_->Close(); -} - -void ToastOverlay::Show(bool visible) { - if (overlay_widget_->GetLayer()->GetTargetVisibility() == visible) - return; - - ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator(); - DCHECK(animator); - - base::TimeDelta original_duration = animator->GetTransitionDuration(); - ui::ScopedLayerAnimationSettings animation_settings(animator); - // ScopedLayerAnimationSettings ctor chanes the transition duration, so change - // back it to the original value (should be zero). - animation_settings.SetTransitionDuration(original_duration); - - animation_settings.AddObserver(this); - - if (visible) { - overlay_widget_->Show(); - - // Notify accessibility about the overlay. - overlay_view_->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, false); - } else { - overlay_widget_->Hide(); - } -} - -gfx::Rect ToastOverlay::CalculateOverlayBounds() { - gfx::Rect bounds = GetPrimaryShelf()->GetUserWorkAreaBounds(); - int target_y = bounds.bottom() - widget_size_.height() - kOffset; - bounds.ClampToCenteredSize(widget_size_); - bounds.set_y(target_y); - return bounds; -} - -void ToastOverlay::OnImplicitAnimationsScheduled() {} - -void ToastOverlay::OnImplicitAnimationsCompleted() { - if (!overlay_widget_->GetLayer()->GetTargetVisibility()) - delegate_->OnClosed(); -} - -views::Widget* ToastOverlay::widget_for_testing() { - return overlay_widget_.get(); -} - -void ToastOverlay::ClickDismissButtonForTesting(const ui::Event& event) { - overlay_view_->button()->NotifyClick(event); -} - -} // namespace ash
diff --git a/ash/system/toast/toast_overlay.h b/ash/system/toast/toast_overlay.h deleted file mode 100644 index 2b4fbbd8..0000000 --- a/ash/system/toast/toast_overlay.h +++ /dev/null
@@ -1,74 +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 ASH_SYSTEM_TOAST_TOAST_OVERLAY_H_ -#define ASH_SYSTEM_TOAST_TOAST_OVERLAY_H_ - -#include <memory> - -#include "ash/ash_export.h" -#include "ui/compositor/layer_animation_observer.h" -#include "ui/events/event.h" -#include "ui/events/event_constants.h" -#include "ui/gfx/geometry/size.h" -#include "ui/views/view.h" - -namespace gfx { -class Rect; -} - -namespace views { -class Widget; -} - -namespace ash { - -class ToastManagerTest; -class ToastOverlayView; -class ToastOverlayButton; - -class ASH_EXPORT ToastOverlay : public ui::ImplicitAnimationObserver { - public: - class ASH_EXPORT Delegate { - public: - virtual ~Delegate() {} - virtual void OnClosed() = 0; - }; - - // Creates the Toast overlay UI. |text| is the message to be shown, and - // |dismiss_text| is the message for the button to dismiss the toast message. - // |dismiss_text| is optional. If empty, the default text is used. - ToastOverlay(Delegate* delegate, - const std::string& text, - const std::string& dismiss_text); - ~ToastOverlay() override; - - // Shows or hides the overlay. - void Show(bool visible); - - private: - friend class ToastManagerTest; - - // Returns the current bounds of the overlay, which is based on visibility. - gfx::Rect CalculateOverlayBounds(); - - void OnImplicitAnimationsScheduled() override; - void OnImplicitAnimationsCompleted() override; - - views::Widget* widget_for_testing(); - void ClickDismissButtonForTesting(const ui::Event& event); - - Delegate* const delegate_; - const std::string text_; - const std::string dismiss_text_; - std::unique_ptr<views::Widget> overlay_widget_; - std::unique_ptr<ToastOverlayView> overlay_view_; - gfx::Size widget_size_; - - DISALLOW_COPY_AND_ASSIGN(ToastOverlay); -}; - -} // namespace ash - -#endif // ASH_SYSTEM_TOAST_TOAST_OVERLAY_H_
diff --git a/ash/system/tray/DEPS b/ash/system/tray/DEPS deleted file mode 100644 index 4440a8fa..0000000 --- a/ash/system/tray/DEPS +++ /dev/null
@@ -1,4 +0,0 @@ -include_rules = [ - # NOTE: Use WmRootWindowController or WmShell instead. http://crbug.com/615502 - "-ash/root_window_controller.h", -]
diff --git a/ash/system/tray/system_tray.cc b/ash/system/tray/system_tray.cc deleted file mode 100644 index 7ff990768..0000000 --- a/ash/system/tray/system_tray.cc +++ /dev/null
@@ -1,772 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/system/tray/system_tray.h" - -#include "ash/common/ash_switches.h" -#include "ash/common/login_status.h" -#include "ash/common/session/session_state_delegate.h" -#include "ash/common/shelf/wm_shelf.h" -#include "ash/common/shelf/wm_shelf_util.h" -#include "ash/common/shell_window_ids.h" -#include "ash/common/system/cast/tray_cast.h" -#include "ash/common/system/date/tray_date.h" -#include "ash/common/system/tray/system_tray_delegate.h" -#include "ash/common/system/tray/system_tray_item.h" -#include "ash/common/system/tray/tray_bubble_wrapper.h" -#include "ash/common/system/tray/tray_constants.h" -#include "ash/common/system/tray_accessibility.h" -#include "ash/common/system/update/tray_update.h" -#include "ash/common/system/user/tray_user.h" -#include "ash/common/system/user/tray_user_separator.h" -#include "ash/common/system/web_notification/web_notification_tray.h" -#include "ash/common/wm_lookup.h" -#include "ash/common/wm_root_window_controller.h" -#include "ash/common/wm_shell.h" -#include "ash/common/wm_window.h" -#include "base/logging.h" -#include "base/metrics/histogram.h" -#include "base/strings/utf_string_conversions.h" -#include "base/timer/timer.h" -#include "grit/ash_strings.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/compositor/layer.h" -#include "ui/display/display.h" -#include "ui/display/screen.h" -#include "ui/events/event_constants.h" -#include "ui/gfx/canvas.h" -#include "ui/gfx/skia_util.h" -#include "ui/views/border.h" -#include "ui/views/controls/label.h" -#include "ui/views/layout/box_layout.h" -#include "ui/views/layout/fill_layout.h" -#include "ui/views/view.h" - -#if defined(OS_CHROMEOS) -#include "ash/common/system/chromeos/audio/tray_audio_chromeos.h" -#include "ash/common/system/chromeos/bluetooth/tray_bluetooth.h" -#include "ash/common/system/chromeos/brightness/tray_brightness.h" -#include "ash/common/system/chromeos/enterprise/tray_enterprise.h" -#include "ash/common/system/chromeos/network/tray_network.h" -#include "ash/common/system/chromeos/network/tray_sms.h" -#include "ash/common/system/chromeos/network/tray_vpn.h" -#include "ash/common/system/chromeos/power/power_status.h" -#include "ash/common/system/chromeos/power/tray_power.h" -#include "ash/common/system/chromeos/screen_security/screen_capture_tray_item.h" -#include "ash/common/system/chromeos/screen_security/screen_share_tray_item.h" -#include "ash/common/system/chromeos/session/tray_session_length_limit.h" -#include "ash/common/system/chromeos/settings/tray_settings.h" -#include "ash/common/system/chromeos/supervised/tray_supervised_user.h" -#include "ash/common/system/chromeos/tray_caps_lock.h" -#include "ash/common/system/chromeos/tray_tracing.h" -#include "ash/common/system/ime/tray_ime_chromeos.h" -#include "ash/system/chromeos/media_security/multi_profile_media_tray_item.h" -#include "ash/system/chromeos/rotation/tray_rotation_lock.h" -#include "ash/system/chromeos/tray_display.h" -#include "ui/message_center/message_center.h" -#endif - -using views::TrayBubbleView; - -namespace ash { - -// The minimum width of the system tray menu width. -const int kMinimumSystemTrayMenuWidth = 300; - -// Class to initialize and manage the SystemTrayBubble and TrayBubbleWrapper -// instances for a bubble. - -class SystemBubbleWrapper { - public: - // Takes ownership of |bubble|. - explicit SystemBubbleWrapper(SystemTrayBubble* bubble) - : bubble_(bubble), is_persistent_(false) {} - - // Initializes the bubble view and creates |bubble_wrapper_|. - void InitView(TrayBackgroundView* tray, - views::View* anchor, - TrayBubbleView::InitParams* init_params, - bool is_persistent) { - DCHECK(anchor); - LoginStatus login_status = - WmShell::Get()->system_tray_delegate()->GetUserLoginStatus(); - bubble_->InitView(anchor, login_status, init_params); - bubble_wrapper_.reset(new TrayBubbleWrapper(tray, bubble_->bubble_view())); - // The system bubble should not have an arrow. - bubble_->bubble_view()->SetArrowPaintType(views::BubbleBorder::PAINT_NONE); - is_persistent_ = is_persistent; - - // If ChromeVox is enabled, focus the default item if no item is focused and - // there isn't a delayed close. - if (WmShell::Get()->GetAccessibilityDelegate()->IsSpokenFeedbackEnabled() && - !is_persistent) { - bubble_->FocusDefaultIfNeeded(); - } - } - - // Convenience accessors: - SystemTrayBubble* bubble() const { return bubble_.get(); } - SystemTrayBubble::BubbleType bubble_type() const { - return bubble_->bubble_type(); - } - TrayBubbleView* bubble_view() const { return bubble_->bubble_view(); } - bool is_persistent() const { return is_persistent_; } - - private: - std::unique_ptr<SystemTrayBubble> bubble_; - std::unique_ptr<TrayBubbleWrapper> bubble_wrapper_; - bool is_persistent_; - - DISALLOW_COPY_AND_ASSIGN(SystemBubbleWrapper); -}; - -// SystemTray - -SystemTray::SystemTray(WmShelf* wm_shelf) - : TrayBackgroundView(wm_shelf), - web_notification_tray_(nullptr), - detailed_item_(nullptr), - default_bubble_height_(0), - hide_notifications_(false), - full_system_tray_menu_(false), - tray_accessibility_(nullptr), - tray_cast_(nullptr), - tray_date_(nullptr), - tray_update_(nullptr), - screen_capture_tray_item_(nullptr), - screen_share_tray_item_(nullptr) { - SetContentsBackground(); -} - -SystemTray::~SystemTray() { - // Destroy any child views that might have back pointers before ~View(). - system_bubble_.reset(); - notification_bubble_.reset(); - for (std::vector<SystemTrayItem*>::iterator it = items_.begin(); - it != items_.end(); ++it) { - (*it)->DestroyTrayView(); - } -} - -void SystemTray::InitializeTrayItems( - SystemTrayDelegate* delegate, - WebNotificationTray* web_notification_tray) { - DCHECK(web_notification_tray); - web_notification_tray_ = web_notification_tray; - TrayBackgroundView::Initialize(); - CreateItems(delegate); -} - -void SystemTray::Shutdown() { - DCHECK(web_notification_tray_); - web_notification_tray_ = nullptr; -} - -void SystemTray::CreateItems(SystemTrayDelegate* delegate) { - WmShell* wm_shell = WmShell::Get(); -#if !defined(OS_WIN) - // Create user items for each possible user. - int maximum_user_profiles = - wm_shell->GetSessionStateDelegate()->GetMaximumNumberOfLoggedInUsers(); - for (int i = 0; i < maximum_user_profiles; i++) - AddTrayItem(new TrayUser(this, i)); - - if (maximum_user_profiles > 1) { - // Add a special double line separator between users and the rest of the - // menu if more then one user is logged in. - AddTrayItem(new TrayUserSeparator(this)); - } -#endif - - tray_accessibility_ = new TrayAccessibility(this); - tray_date_ = new TrayDate(this); - tray_update_ = new TrayUpdate(this); - -#if defined(OS_CHROMEOS) - AddTrayItem(new TraySessionLengthLimit(this)); - AddTrayItem(new TrayEnterprise(this)); - AddTrayItem(new TraySupervisedUser(this)); - AddTrayItem(new TrayIME(this)); - AddTrayItem(tray_accessibility_); - AddTrayItem(new TrayTracing(this)); - AddTrayItem(new TrayPower(this, message_center::MessageCenter::Get())); - AddTrayItem(new TrayNetwork(this)); - AddTrayItem(new TrayVPN(this)); - AddTrayItem(new TraySms(this)); - AddTrayItem(new TrayBluetooth(this)); - tray_cast_ = new TrayCast(this); - AddTrayItem(tray_cast_); - AddTrayItem(new TrayDisplay(this)); - screen_capture_tray_item_ = new ScreenCaptureTrayItem(this); - AddTrayItem(screen_capture_tray_item_); - screen_share_tray_item_ = new ScreenShareTrayItem(this); - AddTrayItem(screen_share_tray_item_); - AddTrayItem(new MultiProfileMediaTrayItem(this)); - AddTrayItem(new TrayAudioChromeOs(this)); - AddTrayItem(new TrayBrightness(this)); - AddTrayItem(new TrayCapsLock(this)); - AddTrayItem(new TrayRotationLock(this)); - AddTrayItem(new TraySettings(this)); - AddTrayItem(tray_update_); - AddTrayItem(tray_date_); -#elif defined(OS_WIN) - AddTrayItem(tray_accessibility_); - AddTrayItem(tray_update_); - AddTrayItem(tray_date_); -#endif - - SetVisible(wm_shell->system_tray_delegate()->GetTrayVisibilityOnStartup()); -} - -void SystemTray::AddTrayItem(SystemTrayItem* item) { - items_.push_back(item); - - SystemTrayDelegate* delegate = WmShell::Get()->system_tray_delegate(); - views::View* tray_item = item->CreateTrayView(delegate->GetUserLoginStatus()); - item->UpdateAfterShelfAlignmentChange(shelf_alignment()); - - if (tray_item) { - tray_container()->AddChildViewAt(tray_item, 0); - PreferredSizeChanged(); - tray_item_map_[item] = tray_item; - } -} - -void SystemTray::RemoveTrayItem(SystemTrayItem* item) { - NOTIMPLEMENTED(); -} - -const std::vector<SystemTrayItem*>& SystemTray::GetTrayItems() const { - return items_.get(); -} - -void SystemTray::ShowDefaultView(BubbleCreationType creation_type) { - ShowDefaultViewWithOffset( - creation_type, TrayBubbleView::InitParams::kArrowDefaultOffset, false); -} - -void SystemTray::ShowPersistentDefaultView() { - ShowItems(items_.get(), false, false, BUBBLE_CREATE_NEW, - TrayBubbleView::InitParams::kArrowDefaultOffset, true); -} - -void SystemTray::ShowDetailedView(SystemTrayItem* item, - int close_delay, - bool activate, - BubbleCreationType creation_type) { - std::vector<SystemTrayItem*> items; - // The detailed view with timeout means a UI to show the current system state, - // like the audio level or brightness. Such UI should behave as persistent and - // keep its own logic for the appearance. - bool persistent = - (!activate && close_delay > 0 && creation_type == BUBBLE_CREATE_NEW); - items.push_back(item); - ShowItems(items, true, activate, creation_type, GetTrayXOffset(item), - persistent); - if (system_bubble_) - system_bubble_->bubble()->StartAutoCloseTimer(close_delay); -} - -void SystemTray::SetDetailedViewCloseDelay(int close_delay) { - if (HasSystemBubbleType(SystemTrayBubble::BUBBLE_TYPE_DETAILED)) - system_bubble_->bubble()->StartAutoCloseTimer(close_delay); -} - -void SystemTray::HideDetailedView(SystemTrayItem* item) { - if (item != detailed_item_) - return; - DestroySystemBubble(); - UpdateNotificationBubble(); -} - -void SystemTray::ShowNotificationView(SystemTrayItem* item) { - if (std::find(notification_items_.begin(), notification_items_.end(), item) != - notification_items_.end()) - return; - notification_items_.push_back(item); - UpdateNotificationBubble(); -} - -void SystemTray::HideNotificationView(SystemTrayItem* item) { - std::vector<SystemTrayItem*>::iterator found_iter = - std::find(notification_items_.begin(), notification_items_.end(), item); - if (found_iter == notification_items_.end()) - return; - notification_items_.erase(found_iter); - // Only update the notification bubble if visible (i.e. don't create one). - if (notification_bubble_) - UpdateNotificationBubble(); -} - -void SystemTray::UpdateAfterLoginStatusChange(LoginStatus login_status) { - DestroySystemBubble(); - UpdateNotificationBubble(); - - for (SystemTrayItem* item : items_) - item->UpdateAfterLoginStatusChange(login_status); - - // Items default to SHELF_ALIGNMENT_BOTTOM. Update them if the initial - // position of the shelf differs. - if (!IsHorizontalAlignment(shelf_alignment())) - UpdateAfterShelfAlignmentChange(shelf_alignment()); - - SetVisible(true); - PreferredSizeChanged(); -} - -void SystemTray::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) { - for (SystemTrayItem* item : items_) - item->UpdateAfterShelfAlignmentChange(alignment); -} - -void SystemTray::SetHideNotifications(bool hide_notifications) { - if (notification_bubble_) - notification_bubble_->bubble()->SetVisible(!hide_notifications); - hide_notifications_ = hide_notifications; -} - -bool SystemTray::ShouldShowShelf() const { - return system_bubble_.get() && system_bubble_->bubble()->ShouldShowShelf(); -} - -bool SystemTray::HasSystemBubble() const { - return system_bubble_.get() != NULL; -} - -bool SystemTray::HasNotificationBubble() const { - return notification_bubble_.get() != NULL; -} - -SystemTrayBubble* SystemTray::GetSystemBubble() { - if (!system_bubble_) - return NULL; - return system_bubble_->bubble(); -} - -bool SystemTray::IsAnyBubbleVisible() const { - return ((system_bubble_.get() && system_bubble_->bubble()->IsVisible()) || - (notification_bubble_.get() && - notification_bubble_->bubble()->IsVisible())); -} - -bool SystemTray::IsMouseInNotificationBubble() const { - if (!notification_bubble_) - return false; - return notification_bubble_->bubble_view()->GetBoundsInScreen().Contains( - display::Screen::GetScreen()->GetCursorScreenPoint()); -} - -bool SystemTray::CloseSystemBubble() const { - if (!system_bubble_) - return false; - system_bubble_->bubble()->Close(); - return true; -} - -views::View* SystemTray::GetHelpButtonView() const { - return tray_date_->GetHelpButtonView(); -} - -bool SystemTray::CloseNotificationBubbleForTest() const { - if (!notification_bubble_) - return false; - notification_bubble_->bubble()->Close(); - return true; -} - -// Private methods. - -bool SystemTray::HasSystemBubbleType(SystemTrayBubble::BubbleType type) { - DCHECK(type != SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION); - return system_bubble_.get() && system_bubble_->bubble_type() == type; -} - -void SystemTray::DestroySystemBubble() { - CloseSystemBubbleAndDeactivateSystemTray(); - detailed_item_ = NULL; - UpdateWebNotifications(); -} - -void SystemTray::DestroyNotificationBubble() { - if (notification_bubble_) { - notification_bubble_.reset(); - UpdateWebNotifications(); - } -} - -base::string16 SystemTray::GetAccessibleNameForTray() { - base::string16 time = GetAccessibleTimeString(base::Time::Now()); - base::string16 battery = base::ASCIIToUTF16(""); -#if defined(OS_CHROMEOS) - battery = PowerStatus::Get()->GetAccessibleNameString(false); -#endif - return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_ACCESSIBLE_DESCRIPTION, - time, battery); -} - -int SystemTray::GetTrayXOffset(SystemTrayItem* item) const { - // Don't attempt to align the arrow if the shelf is on the left or right. - if (!IsHorizontalAlignment(shelf_alignment())) - return TrayBubbleView::InitParams::kArrowDefaultOffset; - - std::map<SystemTrayItem*, views::View*>::const_iterator it = - tray_item_map_.find(item); - if (it == tray_item_map_.end()) - return TrayBubbleView::InitParams::kArrowDefaultOffset; - - const views::View* item_view = it->second; - if (item_view->bounds().IsEmpty()) { - // The bounds of item could be still empty if it does not have a visible - // tray view. In that case, use the default (minimum) offset. - return TrayBubbleView::InitParams::kArrowDefaultOffset; - } - - gfx::Point point(item_view->width() / 2, 0); - ConvertPointToWidget(item_view, &point); - return point.x(); -} - -void SystemTray::ShowDefaultViewWithOffset(BubbleCreationType creation_type, - int arrow_offset, - bool persistent) { - if (creation_type != BUBBLE_USE_EXISTING) - WmShell::Get()->RecordUserMetricsAction(UMA_STATUS_AREA_MENU_OPENED); - ShowItems(items_.get(), false, true, creation_type, arrow_offset, persistent); -} - -void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items, - bool detailed, - bool can_activate, - BubbleCreationType creation_type, - int arrow_offset, - bool persistent) { - // No system tray bubbles in kiosk mode. - if (WmShell::Get()->system_tray_delegate()->GetUserLoginStatus() == - LoginStatus::KIOSK_APP) { - return; - } - - // Destroy any existing bubble and create a new one. - SystemTrayBubble::BubbleType bubble_type = - detailed ? SystemTrayBubble::BUBBLE_TYPE_DETAILED - : SystemTrayBubble::BUBBLE_TYPE_DEFAULT; - - // Destroy the notification bubble here so that it doesn't get rebuilt - // while we add items to the main bubble_ (e.g. in HideNotificationView). - notification_bubble_.reset(); - if (system_bubble_.get() && creation_type == BUBBLE_USE_EXISTING) { - system_bubble_->bubble()->UpdateView(items, bubble_type); - // If ChromeVox is enabled, focus the default item if no item is focused. - if (WmShell::Get()->GetAccessibilityDelegate()->IsSpokenFeedbackEnabled()) - system_bubble_->bubble()->FocusDefaultIfNeeded(); - } else { - // Cleanup the existing bubble before showing a new one. Otherwise, it's - // possible to confuse the new system bubble with the old one during - // destruction, leading to subtle errors/crashes such as crbug.com/545166. - DestroySystemBubble(); - - // Remember if the menu is a single property (like e.g. volume) or the - // full tray menu. Note that in case of the |BUBBLE_USE_EXISTING| case - // above, |full_system_tray_menu_| does not get changed since the fact that - // the menu is full (or not) doesn't change even if a "single property" - // (like network) replaces most of the menu. - full_system_tray_menu_ = items.size() > 1; - // The menu width is fixed, and it is a per language setting. - int menu_width = std::max( - kMinimumSystemTrayMenuWidth, - WmShell::Get()->system_tray_delegate()->GetSystemTrayMenuWidth()); - - TrayBubbleView::InitParams init_params(TrayBubbleView::ANCHOR_TYPE_TRAY, - GetAnchorAlignment(), menu_width, - kTrayPopupMaxWidth); - init_params.can_activate = can_activate; - init_params.first_item_has_no_margin = true; - if (detailed) { - // This is the case where a volume control or brightness control bubble - // is created. - init_params.max_height = default_bubble_height_; - init_params.arrow_color = kBackgroundColor; - } else { - init_params.arrow_color = kHeaderBackgroundColor; - } - init_params.arrow_offset = arrow_offset; - if (bubble_type == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) - init_params.close_on_deactivate = !persistent; - // For Volume and Brightness we don't want to show an arrow when - // they are shown in a bubble by themselves. - init_params.arrow_paint_type = views::BubbleBorder::PAINT_NORMAL; - if (items.size() == 1 && items[0]->ShouldHideArrow()) - init_params.arrow_paint_type = views::BubbleBorder::PAINT_TRANSPARENT; - SystemTrayBubble* bubble = new SystemTrayBubble(this, items, bubble_type); - - system_bubble_.reset(new SystemBubbleWrapper(bubble)); - system_bubble_->InitView(this, tray_container(), &init_params, persistent); - - // Record metrics for the system menu when the default view is invoked. - if (!detailed) - RecordSystemMenuMetrics(); - } - // Save height of default view for creating detailed views directly. - if (!detailed) - default_bubble_height_ = system_bubble_->bubble_view()->height(); - - if (detailed && items.size() > 0) - detailed_item_ = items[0]; - else - detailed_item_ = NULL; - - UpdateNotificationBubble(); // State changed, re-create notifications. - if (!notification_bubble_) - UpdateWebNotifications(); - shelf()->UpdateAutoHideState(); - - // When we show the system menu in our alternate shelf layout, we need to - // tint the background. - if (full_system_tray_menu_) - SetDrawBackgroundAsActive(true); -} - -void SystemTray::UpdateNotificationBubble() { - // Only show the notification bubble if we have notifications. - if (notification_items_.empty()) { - DestroyNotificationBubble(); - return; - } - // Destroy the existing bubble before constructing a new one. - notification_bubble_.reset(); - SystemTrayBubble* notification_bubble; - notification_bubble = new SystemTrayBubble( - this, notification_items_, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION); - views::View* anchor; - TrayBubbleView::AnchorType anchor_type; - // Tray items might want to show notifications while we are creating and - // initializing the |system_bubble_| - but it might not be fully initialized - // when coming here - this would produce a crashed like crbug.com/247416. - // As such we check the existence of the widget here. - if (system_bubble_.get() && system_bubble_->bubble_view() && - system_bubble_->bubble_view()->GetWidget()) { - anchor = system_bubble_->bubble_view(); - anchor_type = TrayBubbleView::ANCHOR_TYPE_BUBBLE; - } else { - anchor = tray_container(); - anchor_type = TrayBubbleView::ANCHOR_TYPE_TRAY; - } - TrayBubbleView::InitParams init_params(anchor_type, GetAnchorAlignment(), - kTrayPopupMinWidth, - kTrayPopupMaxWidth); - init_params.first_item_has_no_margin = true; - init_params.arrow_color = kBackgroundColor; - init_params.arrow_offset = GetTrayXOffset(notification_items_[0]); - notification_bubble_.reset(new SystemBubbleWrapper(notification_bubble)); - notification_bubble_->InitView(this, anchor, &init_params, false); - - if (notification_bubble->bubble_view()->child_count() == 0) { - // It is possible that none of the items generated actual notifications. - DestroyNotificationBubble(); - return; - } - if (hide_notifications_) - notification_bubble->SetVisible(false); - else - UpdateWebNotifications(); -} - -void SystemTray::UpdateWebNotifications() { - TrayBubbleView* bubble_view = NULL; - if (notification_bubble_) - bubble_view = notification_bubble_->bubble_view(); - else if (system_bubble_) - bubble_view = system_bubble_->bubble_view(); - - int height = 0; - if (bubble_view) { - gfx::Rect work_area = - display::Screen::GetScreen() - ->GetDisplayNearestWindow(bubble_view->GetWidget()->GetNativeView()) - .work_area(); - height = - std::max(0, work_area.height() - bubble_view->GetBoundsInScreen().y()); - } - if (web_notification_tray_) - web_notification_tray_->SetTrayBubbleHeight(height); -} - -base::string16 SystemTray::GetAccessibleTimeString( - const base::Time& now) const { - base::HourClockType hour_type = - WmShell::Get()->system_tray_delegate()->GetHourClockType(); - return base::TimeFormatTimeOfDayWithHourClockType(now, hour_type, - base::kKeepAmPm); -} - -void SystemTray::SetShelfAlignment(ShelfAlignment alignment) { - if (alignment == shelf_alignment()) - return; - TrayBackgroundView::SetShelfAlignment(alignment); - UpdateAfterShelfAlignmentChange(alignment); - // Destroy any existing bubble so that it is rebuilt correctly. - CloseSystemBubbleAndDeactivateSystemTray(); - // Rebuild any notification bubble. - if (notification_bubble_) { - notification_bubble_.reset(); - UpdateNotificationBubble(); - // UpdateWebNotifications() should be called in UpdateNotificationBubble(). - } else if (!hide_notifications_) { - UpdateWebNotifications(); - } -} - -void SystemTray::AnchorUpdated() { - if (notification_bubble_) { - notification_bubble_->bubble_view()->UpdateBubble(); - // Ensure that the notification buble is above the shelf/status area. - notification_bubble_->bubble_view()->GetWidget()->StackAtTop(); - UpdateBubbleViewArrow(notification_bubble_->bubble_view()); - } - if (system_bubble_) { - system_bubble_->bubble_view()->UpdateBubble(); - UpdateBubbleViewArrow(system_bubble_->bubble_view()); - } -} - -void SystemTray::BubbleResized(const TrayBubbleView* bubble_view) { - UpdateWebNotifications(); -} - -void SystemTray::HideBubbleWithView(const TrayBubbleView* bubble_view) { - if (system_bubble_.get() && bubble_view == system_bubble_->bubble_view()) { - DestroySystemBubble(); - UpdateNotificationBubble(); // State changed, re-create notifications. - shelf()->UpdateAutoHideState(); - } else if (notification_bubble_.get() && - bubble_view == notification_bubble_->bubble_view()) { - DestroyNotificationBubble(); - } -} - -void SystemTray::ClickedOutsideBubble() { - if (!system_bubble_ || system_bubble_->is_persistent()) - return; - HideBubbleWithView(system_bubble_->bubble_view()); -} - -void SystemTray::BubbleViewDestroyed() { - if (system_bubble_) { - system_bubble_->bubble()->DestroyItemViews(); - system_bubble_->bubble()->BubbleViewDestroyed(); - } -} - -void SystemTray::OnMouseEnteredView() { - if (system_bubble_) - system_bubble_->bubble()->StopAutoCloseTimer(); -} - -void SystemTray::OnMouseExitedView() { - if (system_bubble_) - system_bubble_->bubble()->RestartAutoCloseTimer(); -} - -base::string16 SystemTray::GetAccessibleNameForBubble() { - return GetAccessibleNameForTray(); -} - -gfx::Rect SystemTray::GetAnchorRect( - views::Widget* anchor_widget, - TrayBubbleView::AnchorType anchor_type, - TrayBubbleView::AnchorAlignment anchor_alignment) const { - return GetBubbleAnchorRect(anchor_widget, anchor_type, anchor_alignment); -} - -void SystemTray::OnBeforeBubbleWidgetInit( - views::Widget* anchor_widget, - views::Widget* bubble_widget, - views::Widget::InitParams* params) const { - // Place the bubble in the same root window as |anchor_widget|. - WmLookup::Get() - ->GetWindowForWidget(anchor_widget) - ->GetRootWindowController() - ->ConfigureWidgetInitParamsForContainer( - bubble_widget, kShellWindowId_SettingBubbleContainer, params); -} - -void SystemTray::HideBubble(const TrayBubbleView* bubble_view) { - HideBubbleWithView(bubble_view); -} - -views::View* SystemTray::GetTrayItemViewForTest(SystemTrayItem* item) { - std::map<SystemTrayItem*, views::View*>::iterator it = - tray_item_map_.find(item); - return it == tray_item_map_.end() ? NULL : it->second; -} - -TrayCast* SystemTray::GetTrayCastForTesting() const { - return tray_cast_; -} - -TrayDate* SystemTray::GetTrayDateForTesting() const { - return tray_date_; -} - -TrayUpdate* SystemTray::GetTrayUpdateForTesting() const { - return tray_update_; -} - -bool SystemTray::PerformAction(const ui::Event& event) { - // If we're already showing the default view, hide it; otherwise, show it - // (and hide any popup that's currently shown). - if (HasSystemBubbleType(SystemTrayBubble::BUBBLE_TYPE_DEFAULT)) { - system_bubble_->bubble()->Close(); - } else { - int arrow_offset = TrayBubbleView::InitParams::kArrowDefaultOffset; - if (event.IsMouseEvent() || event.type() == ui::ET_GESTURE_TAP) { - const ui::LocatedEvent& located_event = - static_cast<const ui::LocatedEvent&>(event); - if (IsHorizontalAlignment(shelf_alignment())) { - gfx::Point point(located_event.x(), 0); - ConvertPointToWidget(this, &point); - arrow_offset = point.x(); - } - } - ShowDefaultViewWithOffset(BUBBLE_CREATE_NEW, arrow_offset, false); - } - return true; -} - -void SystemTray::CloseSystemBubbleAndDeactivateSystemTray() { - system_bubble_.reset(); - // When closing a system bubble with the alternate shelf layout, we need to - // turn off the active tinting of the shelf. - if (full_system_tray_menu_) { - SetDrawBackgroundAsActive(false); - full_system_tray_menu_ = false; - } -} - -void SystemTray::RecordSystemMenuMetrics() { - DCHECK(system_bubble_); - - TrayBubbleView* bubble_view = system_bubble_->bubble_view(); - int num_rows = 0; - for (int i = 0; i < bubble_view->child_count(); i++) { - // Certain menu rows are attached by default but can set themselves as - // invisible (IME is one such example). Count only user-visible rows. - if (bubble_view->child_at(i)->visible()) - num_rows++; - } - UMA_HISTOGRAM_COUNTS_100("Ash.SystemMenu.Rows", num_rows); - - int work_area_height = - display::Screen::GetScreen() - ->GetDisplayNearestWindow(bubble_view->GetWidget()->GetNativeView()) - .work_area() - .height(); - if (work_area_height > 0) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Ash.SystemMenu.PercentageOfWorkAreaHeightCoveredByMenu", - 100 * bubble_view->height() / work_area_height, 1, 300, 100); - } -} - -} // namespace ash
diff --git a/ash/system/tray/system_tray.h b/ash/system/tray/system_tray.h deleted file mode 100644 index 0bb4e657..0000000 --- a/ash/system/tray/system_tray.h +++ /dev/null
@@ -1,267 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_SYSTEM_TRAY_SYSTEM_TRAY_H_ -#define ASH_SYSTEM_TRAY_SYSTEM_TRAY_H_ - -#include <map> -#include <memory> -#include <vector> - -#include "ash/ash_export.h" -#include "ash/common/system/tray/system_tray_bubble.h" -#include "ash/common/system/tray/tray_background_view.h" -#include "base/macros.h" -#include "base/memory/scoped_vector.h" -#include "ui/views/bubble/tray_bubble_view.h" -#include "ui/views/view.h" - -namespace ash { - -enum class LoginStatus; -class ScreenTrayItem; -class SystemBubbleWrapper; -class SystemTrayDelegate; -class SystemTrayItem; -class TrayAccessibility; -class TrayCast; -class TrayDate; -class TrayUpdate; -class TrayUser; -class WebNotificationTray; - -// There are different methods for creating bubble views. -enum BubbleCreationType { - BUBBLE_CREATE_NEW, // Closes any existing bubble and creates a new one. - BUBBLE_USE_EXISTING, // Uses any existing bubble, or creates a new one. -}; - -class ASH_EXPORT SystemTray : public TrayBackgroundView, - public views::TrayBubbleView::Delegate { - public: - explicit SystemTray(WmShelf* wm_shelf); - ~SystemTray() override; - - // Calls TrayBackgroundView::Initialize(), creates the tray items, and - // adds them to SystemTrayNotifier. - void InitializeTrayItems(SystemTrayDelegate* delegate, - WebNotificationTray* web_notification_tray); - - // Resets internal pointers. - void Shutdown(); - - // Adds a new item in the tray. - void AddTrayItem(SystemTrayItem* item); - - // Removes an existing tray item. - void RemoveTrayItem(SystemTrayItem* item); - - // Returns all tray items that has been added to system tray. - const std::vector<SystemTrayItem*>& GetTrayItems() const; - - // Shows the default view of all items. - void ShowDefaultView(BubbleCreationType creation_type); - - // Shows default view that ingnores outside clicks and activation loss. - void ShowPersistentDefaultView(); - - // Shows details of a particular item. If |close_delay_in_seconds| is - // non-zero, then the view is automatically closed after the specified time. - void ShowDetailedView(SystemTrayItem* item, - int close_delay_in_seconds, - bool activate, - BubbleCreationType creation_type); - - // Continue showing the existing detailed view, if any, for |close_delay| - // seconds. - void SetDetailedViewCloseDelay(int close_delay); - - // Hides the detailed view for |item|. - void HideDetailedView(SystemTrayItem* item); - - // Shows the notification view for |item|. - void ShowNotificationView(SystemTrayItem* item); - - // Hides the notification view for |item|. - void HideNotificationView(SystemTrayItem* item); - - // Updates the items when the login status of the system changes. - void UpdateAfterLoginStatusChange(LoginStatus login_status); - - // Updates the items when the shelf alignment changes. - void UpdateAfterShelfAlignmentChange(ShelfAlignment alignment); - - // Temporarily hides/unhides the notification bubble. - void SetHideNotifications(bool hidden); - - // Returns true if the shelf should be forced visible when auto-hidden. - bool ShouldShowShelf() const; - - // Returns true if there is a system bubble (already visible or in the process - // of being created). - bool HasSystemBubble() const; - - // Returns true if there is a notification bubble. - bool HasNotificationBubble() const; - - // Returns true if the system_bubble_ exists and is of type |type|. - bool HasSystemBubbleType(SystemTrayBubble::BubbleType type); - - // Returns a pointer to the system bubble or NULL if none. - SystemTrayBubble* GetSystemBubble(); - - // Returns true if any bubble is visible. - bool IsAnyBubbleVisible() const; - - // Returns true if the mouse is inside the notification bubble. - bool IsMouseInNotificationBubble() const; - - // Closes system bubble and returns true if it did exist. - bool CloseSystemBubble() const; - - // Returns view for help button if default view is shown. Returns NULL - // otherwise. - views::View* GetHelpButtonView() const; - - // Accessors for testing. - - // Returns true if the bubble exists. - bool CloseNotificationBubbleForTest() const; - - // Overridden from TrayBackgroundView. - void SetShelfAlignment(ShelfAlignment alignment) override; - void AnchorUpdated() override; - base::string16 GetAccessibleNameForTray() override; - void BubbleResized(const views::TrayBubbleView* bubble_view) override; - void HideBubbleWithView(const views::TrayBubbleView* bubble_view) override; - void ClickedOutsideBubble() override; - - // views::TrayBubbleView::Delegate: - void BubbleViewDestroyed() override; - void OnMouseEnteredView() override; - void OnMouseExitedView() override; - base::string16 GetAccessibleNameForBubble() override; - gfx::Rect GetAnchorRect(views::Widget* anchor_widget, - AnchorType anchor_type, - AnchorAlignment anchor_alignment) const override; - void OnBeforeBubbleWidgetInit( - views::Widget* anchor_widget, - views::Widget* bubble_widget, - views::Widget::InitParams* params) const override; - void HideBubble(const views::TrayBubbleView* bubble_view) override; - - ScreenTrayItem* GetScreenShareItem() { return screen_share_tray_item_; } - ScreenTrayItem* GetScreenCaptureItem() { return screen_capture_tray_item_; } - - TrayAccessibility* GetTrayAccessibilityForTest() { - return tray_accessibility_; - } - - // Get the tray item view (or NULL) for a given |tray_item| in a unit test. - views::View* GetTrayItemViewForTest(SystemTrayItem* tray_item); - - TrayCast* GetTrayCastForTesting() const; - TrayDate* GetTrayDateForTesting() const; - TrayUpdate* GetTrayUpdateForTesting() const; - - private: - // Creates the default set of items for the sytem tray. - void CreateItems(SystemTrayDelegate* delegate); - - // Resets |system_bubble_| and clears any related state. - void DestroySystemBubble(); - - // Resets |notification_bubble_| and clears any related state. - void DestroyNotificationBubble(); - - // Returns a string with the current time for accessibility on the status - // tray bar. - base::string16 GetAccessibleTimeString(const base::Time& now) const; - - // Calculates the x-offset for the item in the tray. Returns -1 if its tray - // item view is not visible. - int GetTrayXOffset(SystemTrayItem* item) const; - - // Shows the default view and its arrow position is shifted by |x_offset|. - void ShowDefaultViewWithOffset(BubbleCreationType creation_type, - int x_offset, - bool persistent); - - // Constructs or re-constructs |system_bubble_| and populates it with |items|. - // Specify |change_tray_status| to true if want to change the tray background - // status. - void ShowItems(const std::vector<SystemTrayItem*>& items, - bool details, - bool activate, - BubbleCreationType creation_type, - int x_offset, - bool persistent); - - // Constructs or re-constructs |notification_bubble_| and populates it with - // |notification_items_|, or destroys it if there are no notification items. - void UpdateNotificationBubble(); - - // Checks the current status of the system tray and updates the web - // notification tray according to the current status. - void UpdateWebNotifications(); - - // Deactivate the system tray in the shelf if it was active before. - void CloseSystemBubbleAndDeactivateSystemTray(); - - // Records UMA metrics for the number of user-visible rows in the system menu - // and the percentage of the work area height covered by the system menu. - void RecordSystemMenuMetrics(); - - const ScopedVector<SystemTrayItem>& items() const { return items_; } - - // Overridden from ActionableView. - bool PerformAction(const ui::Event& event) override; - - // The web notification tray view that appears adjacent to this view. - WebNotificationTray* web_notification_tray_; - - // Owned items. - ScopedVector<SystemTrayItem> items_; - - // Pointers to members of |items_|. - SystemTrayItem* detailed_item_; - std::vector<SystemTrayItem*> notification_items_; - - // Mappings of system tray item and it's view in the tray. - std::map<SystemTrayItem*, views::View*> tray_item_map_; - - // Bubble for default and detailed views. - std::unique_ptr<SystemBubbleWrapper> system_bubble_; - - // Bubble for notifications. - std::unique_ptr<SystemBubbleWrapper> notification_bubble_; - - // Keep track of the default view height so that when we create detailed - // views directly (e.g. from a notification) we know what height to use. - int default_bubble_height_; - - // Set to true when system notifications should be hidden (e.g. web - // notification bubble is visible). - bool hide_notifications_; - - // This is true when the displayed system tray menu is a full tray menu, - // otherwise a single line item menu like the volume slider is shown. - // Note that the value is only valid when |system_bubble_| is true. - bool full_system_tray_menu_; - - TrayAccessibility* tray_accessibility_; // not owned - TrayCast* tray_cast_; - TrayDate* tray_date_; - TrayUpdate* tray_update_; - - // A reference to the Screen share and capture item. - ScreenTrayItem* screen_capture_tray_item_; // not owned - ScreenTrayItem* screen_share_tray_item_; // not owned - - DISALLOW_COPY_AND_ASSIGN(SystemTray); -}; - -} // namespace ash - -#endif // ASH_SYSTEM_TRAY_SYSTEM_TRAY_H_
diff --git a/ash/system/tray/system_tray_unittest.cc b/ash/system/tray/system_tray_unittest.cc deleted file mode 100644 index d775923..0000000 --- a/ash/system/tray/system_tray_unittest.cc +++ /dev/null
@@ -1,555 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/system/tray/system_tray.h" - -#include <vector> - -#include "ash/common/accessibility_delegate.h" -#include "ash/common/shelf/wm_shelf.h" -#include "ash/common/system/tray/system_tray_bubble.h" -#include "ash/common/system/tray/system_tray_item.h" -#include "ash/common/system/tray/tray_constants.h" -#include "ash/common/system/tray/tray_popup_item_container.h" -#include "ash/common/system/web_notification/web_notification_tray.h" -#include "ash/common/wm_shell.h" -#include "ash/shell.h" -#include "ash/system/status_area_widget.h" -#include "ash/test/ash_test_base.h" -#include "ash/test/status_area_widget_test_helper.h" -#include "ash/wm/window_util.h" -#include "base/run_loop.h" -#include "base/strings/utf_string_conversions.h" -#include "ui/aura/window.h" -#include "ui/base/ui_base_types.h" -#include "ui/compositor/scoped_animation_duration_scale_mode.h" -#include "ui/events/test/event_generator.h" -#include "ui/gfx/geometry/point.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/views/controls/label.h" -#include "ui/views/layout/fill_layout.h" -#include "ui/views/view.h" -#include "ui/views/widget/widget.h" -#include "ui/views/widget/widget_delegate.h" - -#if defined(OS_WIN) -#include "base/win/windows_version.h" -#endif - -namespace ash { -namespace test { - -namespace { - -// Trivial item implementation that tracks its views for testing. -class TestItem : public SystemTrayItem { - public: - TestItem() - : SystemTrayItem(AshTestBase::GetPrimarySystemTray()), - tray_view_(nullptr), - default_view_(nullptr), - detailed_view_(nullptr), - notification_view_(nullptr) {} - - views::View* CreateTrayView(LoginStatus status) override { - tray_view_ = new views::View; - // Add a label so it has non-zero width. - tray_view_->SetLayoutManager(new views::FillLayout); - tray_view_->AddChildView(new views::Label(base::UTF8ToUTF16("Tray"))); - return tray_view_; - } - - views::View* CreateDefaultView(LoginStatus status) override { - default_view_ = new views::View; - default_view_->SetLayoutManager(new views::FillLayout); - default_view_->AddChildView(new views::Label(base::UTF8ToUTF16("Default"))); - return default_view_; - } - - views::View* CreateDetailedView(LoginStatus status) override { - detailed_view_ = new views::View; - detailed_view_->SetLayoutManager(new views::FillLayout); - detailed_view_->AddChildView( - new views::Label(base::UTF8ToUTF16("Detailed"))); - return detailed_view_; - } - - views::View* CreateNotificationView(LoginStatus status) override { - notification_view_ = new views::View; - return notification_view_; - } - - void DestroyTrayView() override { tray_view_ = NULL; } - - void DestroyDefaultView() override { default_view_ = NULL; } - - void DestroyDetailedView() override { detailed_view_ = NULL; } - - void DestroyNotificationView() override { notification_view_ = NULL; } - - void UpdateAfterLoginStatusChange(LoginStatus status) override {} - - views::View* tray_view() const { return tray_view_; } - views::View* default_view() const { return default_view_; } - views::View* detailed_view() const { return detailed_view_; } - views::View* notification_view() const { return notification_view_; } - - private: - views::View* tray_view_; - views::View* default_view_; - views::View* detailed_view_; - views::View* notification_view_; -}; - -// Trivial item implementation that returns NULL from tray/default/detailed -// view creation methods. -class TestNoViewItem : public SystemTrayItem { - public: - TestNoViewItem() : SystemTrayItem(AshTestBase::GetPrimarySystemTray()) {} - - views::View* CreateTrayView(LoginStatus status) override { return nullptr; } - - views::View* CreateDefaultView(LoginStatus status) override { - return nullptr; - } - - views::View* CreateDetailedView(LoginStatus status) override { - return nullptr; - } - - views::View* CreateNotificationView(LoginStatus status) override { - return nullptr; - } - - void DestroyTrayView() override {} - void DestroyDefaultView() override {} - void DestroyDetailedView() override {} - void DestroyNotificationView() override {} - void UpdateAfterLoginStatusChange(LoginStatus status) override {} -}; - -class ModalWidgetDelegate : public views::WidgetDelegateView { - public: - ModalWidgetDelegate() {} - ~ModalWidgetDelegate() override {} - - views::View* GetContentsView() override { return this; } - ui::ModalType GetModalType() const override { return ui::MODAL_TYPE_SYSTEM; } - - private: - DISALLOW_COPY_AND_ASSIGN(ModalWidgetDelegate); -}; - -} // namespace - -typedef AshTestBase SystemTrayTest; - -TEST_F(SystemTrayTest, SystemTrayDefaultView) { - SystemTray* tray = GetPrimarySystemTray(); - ASSERT_TRUE(tray->GetWidget()); - - tray->ShowDefaultView(BUBBLE_CREATE_NEW); - - // Ensure that closing the bubble destroys it. - ASSERT_TRUE(tray->CloseSystemBubble()); - RunAllPendingInMessageLoop(); - ASSERT_FALSE(tray->CloseSystemBubble()); -} - -// Opening and closing the bubble should change the coloring of the tray. -TEST_F(SystemTrayTest, SystemTrayColoring) { - SystemTray* tray = GetPrimarySystemTray(); - ASSERT_TRUE(tray->GetWidget()); - // At the beginning the tray coloring is not active. - ASSERT_FALSE(tray->draw_background_as_active()); - - // Showing the system bubble should show the background as active. - tray->ShowDefaultView(BUBBLE_CREATE_NEW); - ASSERT_TRUE(tray->draw_background_as_active()); - - // Closing the system menu should change the coloring back to normal. - ASSERT_TRUE(tray->CloseSystemBubble()); - RunAllPendingInMessageLoop(); - ASSERT_FALSE(tray->draw_background_as_active()); -} - -// Closing the system bubble through an alignment change should change the -// system tray coloring back to normal. -TEST_F(SystemTrayTest, SystemTrayColoringAfterAlignmentChange) { - SystemTray* tray = GetPrimarySystemTray(); - ASSERT_TRUE(tray->GetWidget()); - WmShelf* shelf = GetPrimaryShelf(); - shelf->SetAlignment(SHELF_ALIGNMENT_BOTTOM); - // At the beginning the tray coloring is not active. - ASSERT_FALSE(tray->draw_background_as_active()); - - // Showing the system bubble should show the background as active. - tray->ShowDefaultView(BUBBLE_CREATE_NEW); - ASSERT_TRUE(tray->draw_background_as_active()); - - // Changing the alignment should close the system bubble and change the - // background color. - shelf->SetAlignment(SHELF_ALIGNMENT_LEFT); - ASSERT_FALSE(tray->draw_background_as_active()); - RunAllPendingInMessageLoop(); - // The bubble should already be closed by now. - ASSERT_FALSE(tray->CloseSystemBubble()); -} - -TEST_F(SystemTrayTest, SystemTrayTestItems) { - SystemTray* tray = GetPrimarySystemTray(); - ASSERT_TRUE(tray->GetWidget()); - - TestItem* test_item = new TestItem; - TestItem* detailed_item = new TestItem; - tray->AddTrayItem(test_item); - tray->AddTrayItem(detailed_item); - - // Check items have been added - const std::vector<SystemTrayItem*>& items = tray->GetTrayItems(); - ASSERT_TRUE(std::find(items.begin(), items.end(), test_item) != items.end()); - ASSERT_TRUE(std::find(items.begin(), items.end(), detailed_item) != - items.end()); - - // Ensure the tray views are created. - ASSERT_TRUE(test_item->tray_view() != NULL); - ASSERT_TRUE(detailed_item->tray_view() != NULL); - - // Ensure a default views are created. - tray->ShowDefaultView(BUBBLE_CREATE_NEW); - ASSERT_TRUE(test_item->default_view() != NULL); - ASSERT_TRUE(detailed_item->default_view() != NULL); - - // Show the detailed view, ensure it's created and the default view destroyed. - tray->ShowDetailedView(detailed_item, 0, false, BUBBLE_CREATE_NEW); - RunAllPendingInMessageLoop(); - ASSERT_TRUE(test_item->default_view() == NULL); - ASSERT_TRUE(detailed_item->detailed_view() != NULL); - - // Show the default view, ensure it's created and the detailed view destroyed. - tray->ShowDefaultView(BUBBLE_CREATE_NEW); - RunAllPendingInMessageLoop(); - ASSERT_TRUE(test_item->default_view() != NULL); - ASSERT_TRUE(detailed_item->detailed_view() == NULL); -} - -TEST_F(SystemTrayTest, SystemTrayNoViewItems) { - SystemTray* tray = GetPrimarySystemTray(); - ASSERT_TRUE(tray->GetWidget()); - - // Verify that no crashes occur on items lacking some views. - TestNoViewItem* no_view_item = new TestNoViewItem; - tray->AddTrayItem(no_view_item); - tray->ShowDefaultView(BUBBLE_CREATE_NEW); - tray->ShowDetailedView(no_view_item, 0, false, BUBBLE_USE_EXISTING); - RunAllPendingInMessageLoop(); -} - -TEST_F(SystemTrayTest, TrayWidgetAutoResizes) { - SystemTray* tray = GetPrimarySystemTray(); - ASSERT_TRUE(tray->GetWidget()); - - // Add an initial tray item so that the tray gets laid out correctly. - TestItem* initial_item = new TestItem; - tray->AddTrayItem(initial_item); - - gfx::Size initial_size = tray->GetWidget()->GetWindowBoundsInScreen().size(); - - TestItem* new_item = new TestItem; - tray->AddTrayItem(new_item); - - gfx::Size new_size = tray->GetWidget()->GetWindowBoundsInScreen().size(); - - // Adding the new item should change the size of the tray. - EXPECT_NE(initial_size.ToString(), new_size.ToString()); - - // Hiding the tray view of the new item should also change the size of the - // tray. - new_item->tray_view()->SetVisible(false); - EXPECT_EQ(initial_size.ToString(), - tray->GetWidget()->GetWindowBoundsInScreen().size().ToString()); - - new_item->tray_view()->SetVisible(true); - EXPECT_EQ(new_size.ToString(), - tray->GetWidget()->GetWindowBoundsInScreen().size().ToString()); -} - -TEST_F(SystemTrayTest, SystemTrayNotifications) { - SystemTray* tray = GetPrimarySystemTray(); - ASSERT_TRUE(tray->GetWidget()); - - TestItem* test_item = new TestItem; - TestItem* detailed_item = new TestItem; - tray->AddTrayItem(test_item); - tray->AddTrayItem(detailed_item); - - // Ensure the tray views are created. - ASSERT_TRUE(test_item->tray_view() != NULL); - ASSERT_TRUE(detailed_item->tray_view() != NULL); - - // Ensure a notification view is created. - tray->ShowNotificationView(test_item); - ASSERT_TRUE(test_item->notification_view() != NULL); - - // Show the default view, notification view should remain. - tray->ShowDefaultView(BUBBLE_CREATE_NEW); - RunAllPendingInMessageLoop(); - ASSERT_TRUE(test_item->notification_view() != NULL); - - // Show the detailed view, ensure the notification view remains. - tray->ShowDetailedView(detailed_item, 0, false, BUBBLE_CREATE_NEW); - RunAllPendingInMessageLoop(); - ASSERT_TRUE(detailed_item->detailed_view() != NULL); - ASSERT_TRUE(test_item->notification_view() != NULL); - - // Hide the detailed view, ensure the notification view still exists. - ASSERT_TRUE(tray->CloseSystemBubble()); - RunAllPendingInMessageLoop(); - ASSERT_TRUE(detailed_item->detailed_view() == NULL); - ASSERT_TRUE(test_item->notification_view() != NULL); -} - -TEST_F(SystemTrayTest, BubbleCreationTypesTest) { - SystemTray* tray = GetPrimarySystemTray(); - ASSERT_TRUE(tray->GetWidget()); - - TestItem* test_item = new TestItem; - tray->AddTrayItem(test_item); - - // Ensure the tray views are created. - ASSERT_TRUE(test_item->tray_view() != NULL); - - // Show the default view, ensure the notification view is destroyed. - tray->ShowDefaultView(BUBBLE_CREATE_NEW); - RunAllPendingInMessageLoop(); - - views::Widget* widget = test_item->default_view()->GetWidget(); - gfx::Rect bubble_bounds = widget->GetWindowBoundsInScreen(); - - tray->ShowDetailedView(test_item, 0, true, BUBBLE_USE_EXISTING); - RunAllPendingInMessageLoop(); - - EXPECT_FALSE(test_item->default_view()); - - EXPECT_EQ(bubble_bounds.ToString(), test_item->detailed_view() - ->GetWidget() - ->GetWindowBoundsInScreen() - .ToString()); - EXPECT_EQ(widget, test_item->detailed_view()->GetWidget()); - - tray->ShowDefaultView(BUBBLE_USE_EXISTING); - RunAllPendingInMessageLoop(); - - EXPECT_EQ(bubble_bounds.ToString(), test_item->default_view() - ->GetWidget() - ->GetWindowBoundsInScreen() - .ToString()); - EXPECT_EQ(widget, test_item->default_view()->GetWidget()); -} - -// Tests that the tray view is laid out properly and is fully contained within -// the shelf widget. -TEST_F(SystemTrayTest, TrayBoundsInWidget) { - WmShelf* shelf = GetPrimaryShelf(); - StatusAreaWidget* widget = StatusAreaWidgetTestHelper::GetStatusAreaWidget(); - SystemTray* tray = GetPrimarySystemTray(); - - // Test in bottom alignment. - shelf->SetAlignment(SHELF_ALIGNMENT_BOTTOM); - gfx::Rect window_bounds = widget->GetWindowBoundsInScreen(); - gfx::Rect tray_bounds = tray->GetBoundsInScreen(); - EXPECT_TRUE(window_bounds.Contains(tray_bounds)); - - // Test in locked alignment. - shelf->SetAlignment(SHELF_ALIGNMENT_BOTTOM_LOCKED); - window_bounds = widget->GetWindowBoundsInScreen(); - tray_bounds = tray->GetBoundsInScreen(); - EXPECT_TRUE(window_bounds.Contains(tray_bounds)); - - // Test in the left alignment. - shelf->SetAlignment(SHELF_ALIGNMENT_LEFT); - window_bounds = widget->GetWindowBoundsInScreen(); - tray_bounds = tray->GetBoundsInScreen(); - EXPECT_TRUE(window_bounds.Contains(tray_bounds)); - - // Test in the right alignment. - shelf->SetAlignment(SHELF_ALIGNMENT_LEFT); - window_bounds = widget->GetWindowBoundsInScreen(); - tray_bounds = tray->GetBoundsInScreen(); - EXPECT_TRUE(window_bounds.Contains(tray_bounds)); -} - -TEST_F(SystemTrayTest, PersistentBubble) { - SystemTray* tray = GetPrimarySystemTray(); - ASSERT_TRUE(tray->GetWidget()); - - TestItem* test_item = new TestItem; - tray->AddTrayItem(test_item); - - std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0)); - - // Tests for usual default view. - // Activating window. - tray->ShowDefaultView(BUBBLE_CREATE_NEW); - ASSERT_TRUE(tray->HasSystemBubble()); - wm::ActivateWindow(window.get()); - base::RunLoop().RunUntilIdle(); - ASSERT_FALSE(tray->HasSystemBubble()); - - tray->ShowDefaultView(BUBBLE_CREATE_NEW); - ASSERT_TRUE(tray->HasSystemBubble()); - { - ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - gfx::Point(5, 5)); - generator.ClickLeftButton(); - ASSERT_FALSE(tray->HasSystemBubble()); - } - - // Same tests for persistent default view. - tray->ShowPersistentDefaultView(); - ASSERT_TRUE(tray->HasSystemBubble()); - wm::ActivateWindow(window.get()); - base::RunLoop().RunUntilIdle(); - ASSERT_TRUE(tray->HasSystemBubble()); - - { - ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), - gfx::Point(5, 5)); - generator.ClickLeftButton(); - ASSERT_TRUE(tray->HasSystemBubble()); - } -} - -#if defined(OS_CHROMEOS) -// Accessibility/Settings tray items are available only on cros. -#define MAYBE_WithSystemModal WithSystemModal -#else -#define MAYBE_WithSystemModal DISABLED_WithSystemModal -#endif -TEST_F(SystemTrayTest, MAYBE_WithSystemModal) { - // Check if the accessibility item is created even with system modal dialog. - WmShell::Get()->GetAccessibilityDelegate()->SetVirtualKeyboardEnabled(true); - views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds( - new ModalWidgetDelegate(), Shell::GetPrimaryRootWindow(), - gfx::Rect(0, 0, 100, 100)); - widget->Show(); - - SystemTray* tray = GetPrimarySystemTray(); - tray->ShowDefaultView(BUBBLE_CREATE_NEW); - - ASSERT_TRUE(tray->HasSystemBubble()); - const views::View* accessibility = - tray->GetSystemBubble()->bubble_view()->GetViewByID( - test::kAccessibilityTrayItemViewId); - ASSERT_TRUE(accessibility); - EXPECT_TRUE(accessibility->visible()); - EXPECT_FALSE(tray->GetSystemBubble()->bubble_view()->GetViewByID( - test::kSettingsTrayItemViewId)); - - widget->Close(); - - tray->ShowDefaultView(BUBBLE_CREATE_NEW); - // System modal is gone. The bubble should now contains settings - // as well. - accessibility = tray->GetSystemBubble()->bubble_view()->GetViewByID( - test::kAccessibilityTrayItemViewId); - ASSERT_TRUE(accessibility); - EXPECT_TRUE(accessibility->visible()); - - const views::View* settings = - tray->GetSystemBubble()->bubble_view()->GetViewByID( - test::kSettingsTrayItemViewId); - ASSERT_TRUE(settings); - EXPECT_TRUE(settings->visible()); -} - -// Tests that if SetVisible(true) is called while animating to hidden that the -// tray becomes visible, and stops animating to hidden. -TEST_F(SystemTrayTest, SetVisibleDuringHideAnimation) { - SystemTray* tray = GetPrimarySystemTray(); - ASSERT_TRUE(tray->visible()); - - std::unique_ptr<ui::ScopedAnimationDurationScaleMode> animation_duration; - animation_duration.reset(new ui::ScopedAnimationDurationScaleMode( - ui::ScopedAnimationDurationScaleMode::SLOW_DURATION)); - tray->SetVisible(false); - EXPECT_TRUE(tray->visible()); - EXPECT_EQ(0.0f, tray->layer()->GetTargetOpacity()); - - tray->SetVisible(true); - animation_duration.reset(); - tray->layer()->GetAnimator()->StopAnimating(); - EXPECT_TRUE(tray->visible()); - EXPECT_EQ(1.0f, tray->layer()->GetTargetOpacity()); -} - -#if defined(OS_CHROMEOS) -// Tests that touch on an item in the system bubble triggers it to become -// active. -TEST_F(SystemTrayTest, TrayPopupItemContainerTouchFeedback) { - SystemTray* tray = GetPrimarySystemTray(); - tray->ShowDefaultView(BUBBLE_CREATE_NEW); - - TrayPopupItemContainer* view = static_cast<TrayPopupItemContainer*>( - tray->GetSystemBubble()->bubble_view()->child_at(0)); - EXPECT_FALSE(view->active()); - - ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); - generator.set_current_location(view->GetBoundsInScreen().CenterPoint()); - generator.PressTouch(); - EXPECT_TRUE(view->active()); - - generator.ReleaseTouch(); - EXPECT_FALSE(view->active()); -} - -// Tests that touch events on an item in the system bubble cause it to stop -// being active. -TEST_F(SystemTrayTest, TrayPopupItemContainerTouchFeedbackCancellation) { - SystemTray* tray = GetPrimarySystemTray(); - tray->ShowDefaultView(BUBBLE_CREATE_NEW); - - TrayPopupItemContainer* view = static_cast<TrayPopupItemContainer*>( - tray->GetSystemBubble()->bubble_view()->child_at(0)); - EXPECT_FALSE(view->active()); - - gfx::Rect view_bounds = view->GetBoundsInScreen(); - ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); - generator.set_current_location(view_bounds.CenterPoint()); - generator.PressTouch(); - EXPECT_TRUE(view->active()); - - gfx::Point move_point(view_bounds.x(), view_bounds.CenterPoint().y()); - generator.MoveTouch(move_point); - EXPECT_FALSE(view->active()); - - generator.set_current_location(move_point); - generator.ReleaseTouch(); - EXPECT_FALSE(view->active()); -} - -TEST_F(SystemTrayTest, SystemTrayHeightWithBubble) { - SystemTray* tray = GetPrimarySystemTray(); - WebNotificationTray* notification_tray = - StatusAreaWidgetTestHelper::GetStatusAreaWidget() - ->web_notification_tray(); - - // Ensure the initial tray bubble height is zero. - EXPECT_EQ(0, notification_tray->tray_bubble_height_for_test()); - - // Show the default view, ensure the tray bubble height is changed. - tray->ShowDefaultView(BUBBLE_CREATE_NEW); - RunAllPendingInMessageLoop(); - EXPECT_LT(0, notification_tray->tray_bubble_height_for_test()); - - // Hide the default view, ensure the tray bubble height is back to zero. - ASSERT_TRUE(tray->CloseSystemBubble()); - RunAllPendingInMessageLoop(); - - EXPECT_EQ(0, notification_tray->tray_bubble_height_for_test()); -} -#endif // OS_CHROMEOS - -} // namespace test -} // namespace ash
diff --git a/ash/system/web_notification/web_notification_tray_unittest.cc b/ash/system/web_notification/web_notification_tray_unittest.cc index 5523bb3..96714da 100644 --- a/ash/system/web_notification/web_notification_tray_unittest.cc +++ b/ash/system/web_notification/web_notification_tray_unittest.cc
@@ -9,6 +9,8 @@ #include "ash/common/shelf/wm_shelf.h" #include "ash/common/shell_window_ids.h" +#include "ash/common/system/status_area_widget.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_item.h" #include "ash/common/system/web_notification/ash_popup_alignment_delegate.h" #include "ash/common/wm/window_state.h" @@ -18,8 +20,6 @@ #include "ash/common/wm_window.h" #include "ash/display/display_manager.h" #include "ash/shell.h" -#include "ash/system/status_area_widget.h" -#include "ash/system/tray/system_tray.h" #include "ash/test/ash_test_base.h" #include "ash/test/status_area_widget_test_helper.h" #include "ash/test/test_system_tray_delegate.h"
diff --git a/ash/sysui/context_menu_mus.cc b/ash/sysui/context_menu_mus.cc index 928de76..52ddd93 100644 --- a/ash/sysui/context_menu_mus.cc +++ b/ash/sysui/context_menu_mus.cc
@@ -41,8 +41,9 @@ return true; } -bool ContextMenuMus::GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) { +bool ContextMenuMus::GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const { return false; }
diff --git a/ash/sysui/context_menu_mus.h b/ash/sysui/context_menu_mus.h index 03776e0..d8592d7 100644 --- a/ash/sysui/context_menu_mus.h +++ b/ash/sysui/context_menu_mus.h
@@ -25,7 +25,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; private:
diff --git a/ash/sysui/shelf_delegate_mus.cc b/ash/sysui/shelf_delegate_mus.cc index 773a9ad..a1c229d 100644 --- a/ash/sysui/shelf_delegate_mus.cc +++ b/ash/sysui/shelf_delegate_mus.cc
@@ -89,8 +89,9 @@ bool IsCommandIdEnabled(int command_id) const override { return command_id > 0; } - bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override { + bool GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const override { return false; } void ExecuteCommand(int command_id, int event_flags) override {
diff --git a/ash/test/status_area_widget_test_helper.cc b/ash/test/status_area_widget_test_helper.cc index 82837c6..229df075 100644 --- a/ash/test/status_area_widget_test_helper.cc +++ b/ash/test/status_area_widget_test_helper.cc
@@ -4,12 +4,12 @@ #include "ash/test/status_area_widget_test_helper.h" +#include "ash/common/system/status_area_widget.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/wm_shell.h" #include "ash/root_window_controller.h" #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" -#include "ash/system/status_area_widget.h" namespace ash {
diff --git a/ash/test/test_system_tray_delegate.cc b/ash/test/test_system_tray_delegate.cc index 6074b39..4d812b50 100644 --- a/ash/test/test_system_tray_delegate.cc +++ b/ash/test/test_system_tray_delegate.cc
@@ -13,6 +13,14 @@ #include "base/message_loop/message_loop.h" #include "base/time/time.h" +#if defined(OS_CHROMEOS) +#include "ash/system/chromeos/rotation/tray_rotation_lock.h" +#include "ash/system/chromeos/tray_display.h" +#include "base/memory/ptr_util.h" +#else +#include "ash/common/system/tray/system_tray_item.h" +#endif + namespace ash { namespace test { @@ -108,5 +116,23 @@ base::MessageLoop::current()->QuitWhenIdle(); } +std::unique_ptr<SystemTrayItem> TestSystemTrayDelegate::CreateDisplayTrayItem( + SystemTray* tray) { +#if defined(OS_CHROMEOS) + return base::MakeUnique<TrayDisplay>(tray); +#else + return nullptr; +#endif +} + +std::unique_ptr<SystemTrayItem> +TestSystemTrayDelegate::CreateRotationLockTrayItem(SystemTray* tray) { +#if defined(OS_CHROMEOS) + return base::MakeUnique<TrayRotationLock>(tray); +#else + return nullptr; +#endif +} + } // namespace test } // namespace ash
diff --git a/ash/test/test_system_tray_delegate.h b/ash/test/test_system_tray_delegate.h index f83022fb..69ec1d5 100644 --- a/ash/test/test_system_tray_delegate.h +++ b/ash/test/test_system_tray_delegate.h
@@ -55,6 +55,10 @@ bool GetSessionStartTime(base::TimeTicks* session_start_time) override; bool GetSessionLengthLimit(base::TimeDelta* session_length_limit) override; void SignOut() override; + std::unique_ptr<SystemTrayItem> CreateDisplayTrayItem( + SystemTray* tray) override; + std::unique_ptr<SystemTrayItem> CreateRotationLockTrayItem( + SystemTray* tray) override; private: bool should_show_display_notification_;
diff --git a/ash/test/tray_cast_test_api.cc b/ash/test/tray_cast_test_api.cc index 96dc0ef..79c62ebb 100644 --- a/ash/test/tray_cast_test_api.cc +++ b/ash/test/tray_cast_test_api.cc
@@ -5,9 +5,9 @@ #include "ash/test/tray_cast_test_api.h" #include "ash/common/cast_config_delegate.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/wm_shell.h" -#include "ash/system/tray/system_tray.h" #include "ui/views/view.h" namespace ash {
diff --git a/ash/test/virtual_keyboard_test_helper.cc b/ash/test/virtual_keyboard_test_helper.cc deleted file mode 100644 index f4ebb40..0000000 --- a/ash/test/virtual_keyboard_test_helper.cc +++ /dev/null
@@ -1,31 +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. - -#include "ash/test/virtual_keyboard_test_helper.h" - -#include "ui/events/devices/device_data_manager.h" -#include "ui/events/devices/device_hotplug_event_observer.h" -#include "ui/events/devices/input_device.h" -#include "ui/events/devices/touchscreen_device.h" - -namespace ash { -namespace test { - -void VirtualKeyboardTestHelper::SuppressKeyboard() { - ui::DeviceHotplugEventObserver* manager = - ui::DeviceDataManager::GetInstance(); - std::vector<ui::TouchscreenDevice> screens; - screens.push_back( - ui::TouchscreenDevice(1, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, - "Touchscreen", gfx::Size(1024, 768), 0)); - manager->OnTouchscreenDevicesUpdated(screens); - - std::vector<ui::InputDevice> keyboards; - keyboards.push_back(ui::InputDevice( - 2, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, "keyboard")); - manager->OnKeyboardDevicesUpdated(keyboards); -} - -} // namespace test -} // namespace ash
diff --git a/ash/test/virtual_keyboard_test_helper.h b/ash/test/virtual_keyboard_test_helper.h deleted file mode 100644 index 92111ed..0000000 --- a/ash/test/virtual_keyboard_test_helper.h +++ /dev/null
@@ -1,21 +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 ASH_TEST_VIRTUAL_KEYBOARD_TEST_HELPER_H_ -#define ASH_TEST_VIRTUAL_KEYBOARD_TEST_HELPER_H_ - -namespace ash { -namespace test { - -class VirtualKeyboardTestHelper { - public: - // Mocks the input device configuration so that the on-screen keyboard is - // suppressed. - static void SuppressKeyboard(); -}; - -} // namespace test -} // namespace ash - -#endif // ASH_TEST_VIRTUAL_KEYBOARD_TEST_HELPER_H_
diff --git a/ash/wm/gestures/shelf_gesture_handler.cc b/ash/wm/gestures/shelf_gesture_handler.cc index 9e11783..1996ad5b 100644 --- a/ash/wm/gestures/shelf_gesture_handler.cc +++ b/ash/wm/gestures/shelf_gesture_handler.cc
@@ -6,12 +6,12 @@ #include "ash/common/session/session_state_delegate.h" #include "ash/common/shelf/shelf_types.h" +#include "ash/common/system/status_area_widget.h" #include "ash/common/wm/window_state.h" #include "ash/common/wm_shell.h" #include "ash/root_window_controller.h" #include "ash/shelf/shelf_layout_manager.h" #include "ash/shelf/shelf_widget.h" -#include "ash/system/status_area_widget.h" #include "ash/wm/window_state_aura.h" #include "ash/wm/window_util.h" #include "ui/aura/window.h"
diff --git a/ash/wm/lock_state_controller.cc b/ash/wm/lock_state_controller.cc index 2ad8a59..e0bb6008 100644 --- a/ash/wm/lock_state_controller.cc +++ b/ash/wm/lock_state_controller.cc
@@ -31,11 +31,6 @@ #if defined(OS_CHROMEOS) #include "base/sys_info.h" -#include "media/audio/sounds/sounds_manager.h" -#endif - -#if defined(OS_CHROMEOS) -using media::SoundsManager; #endif #define UMA_HISTOGRAM_LOCK_TIMES(name, sample) \
diff --git a/ash/wm/status_area_layout_manager.cc b/ash/wm/status_area_layout_manager.cc index 218dbbb..8eb8bc2 100644 --- a/ash/wm/status_area_layout_manager.cc +++ b/ash/wm/status_area_layout_manager.cc
@@ -4,9 +4,9 @@ #include "ash/wm/status_area_layout_manager.h" +#include "ash/common/system/status_area_widget.h" #include "ash/shelf/shelf_layout_manager.h" #include "ash/shelf/shelf_widget.h" -#include "ash/system/status_area_widget.h" #include "base/auto_reset.h" #include "ui/aura/window.h" #include "ui/views/widget/widget.h"
diff --git a/ash/wm/video_detector.cc b/ash/wm/video_detector.cc index e4355bc..777f36f6 100644 --- a/ash/wm/video_detector.cc +++ b/ash/wm/video_detector.cc
@@ -22,6 +22,7 @@ const int VideoDetector::kMinUpdateHeight = 250; const int VideoDetector::kMinFramesPerSecond = 15; const int VideoDetector::kVideoTimeoutMs = 1000; +const int VideoDetector::kMinVideoDurationMs = 3000; // Stores information about updates to a window and determines whether it's // likely that a video is playing in it. @@ -45,8 +46,18 @@ update_times_[(buffer_start_ + buffer_size_) % kMinFramesPerSecond] = now; buffer_size_++; - return buffer_size_ == static_cast<size_t>(kMinFramesPerSecond) && - (now - update_times_[buffer_start_]).InSecondsF() <= 1.0; + const bool in_video = + (buffer_size_ == static_cast<size_t>(kMinFramesPerSecond)) && + ((now - update_times_[buffer_start_]).InSecondsF() <= 1.0); + + if (in_video && video_start_time_.is_null()) + video_start_time_ = update_times_[buffer_start_]; + else if (!in_video && !video_start_time_.is_null()) + video_start_time_ = base::TimeTicks(); + + const base::TimeDelta elapsed = now - video_start_time_; + return in_video && + elapsed >= base::TimeDelta::FromMilliseconds(kMinVideoDurationMs); } private: @@ -54,6 +65,10 @@ // |kMinFramesPerSecond|) video-sized updates to this window. base::TimeTicks update_times_[kMinFramesPerSecond]; + // Time at which the current sequence of updates that looks like video + // started. Empty if video isn't currently playing. + base::TimeTicks video_start_time_; + // Index into |update_times_| of the oldest update. size_t buffer_start_; @@ -90,7 +105,7 @@ if (!video_inactive_timer_.IsRunning()) return false; - video_inactive_timer_.Reset(); + video_inactive_timer_.Stop(); HandleVideoInactive(); return true; }
diff --git a/ash/wm/video_detector.h b/ash/wm/video_detector.h index 6672239..5ccad54 100644 --- a/ash/wm/video_detector.h +++ b/ash/wm/video_detector.h
@@ -72,6 +72,10 @@ // Timeout after which video is no longer considered to be playing. static const int kVideoTimeoutMs; + // Duration video must be playing in a window before it is reported to + // observers. + static const int kMinVideoDurationMs; + VideoDetector(); ~VideoDetector() override;
diff --git a/ash/wm/video_detector_unittest.cc b/ash/wm/video_detector_unittest.cc index 103bda8f..e0b384d 100644 --- a/ash/wm/video_detector_unittest.cc +++ b/ash/wm/video_detector_unittest.cc
@@ -55,7 +55,16 @@ class VideoDetectorTest : public AshTestBase { public: - VideoDetectorTest() {} + VideoDetectorTest() + : kMinFps(VideoDetector::kMinFramesPerSecond), + kMinRect(gfx::Point(0, 0), + gfx::Size(VideoDetector::kMinUpdateWidth, + VideoDetector::kMinUpdateHeight)), + kMinDuration(base::TimeDelta::FromMilliseconds( + VideoDetector::kMinVideoDurationMs)), + kTimeout( + base::TimeDelta::FromMilliseconds(VideoDetector::kVideoTimeoutMs)), + next_window_id_(1000) {} ~VideoDetectorTest() override {} void SetUp() override { @@ -80,204 +89,204 @@ detector_->set_now_for_test(now_); } - VideoDetector* detector_; // not owned + // Creates and returns a new window with |bounds|. + std::unique_ptr<aura::Window> CreateTestWindow(const gfx::Rect& bounds) { + return std::unique_ptr<aura::Window>( + CreateTestWindowInShell(SK_ColorRED, next_window_id_++, bounds)); + } + // Report updates to |window| of area |region| at a rate of + // |updates_per_second| over |duration|. The first update will be sent + // immediately and |now_| will incremented by |duration| upon returning. + void SendUpdates(aura::Window* window, + const gfx::Rect& region, + int updates_per_second, + base::TimeDelta duration) { + const base::TimeDelta time_between_updates = + base::TimeDelta::FromSecondsD(1.0 / updates_per_second); + const base::TimeTicks end_time = now_ + duration; + while (now_ < end_time) { + detector_->OnDelegatedFrameDamage(window, region); + AdvanceTime(time_between_updates); + } + now_ = end_time; + detector_->set_now_for_test(now_); + } + + // Constants placed here for convenience. + const int kMinFps; + const gfx::Rect kMinRect; + const base::TimeDelta kMinDuration; + const base::TimeDelta kTimeout; + + VideoDetector* detector_; // not owned std::unique_ptr<TestObserver> observer_; + // The current (fake) time used by |detector_|. base::TimeTicks now_; + // Next ID to be assigned by CreateTestWindow(). + int next_window_id_; + private: DISALLOW_COPY_AND_ASSIGN(VideoDetectorTest); }; -TEST_F(VideoDetectorTest, Basic) { - gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); - std::unique_ptr<aura::Window> window( - CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); - - // Send enough updates, but make them be too small to trigger detection. - gfx::Rect update_region(gfx::Point(), - gfx::Size(VideoDetector::kMinUpdateWidth - 1, - VideoDetector::kMinUpdateHeight)); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnDelegatedFrameDamage(window.get(), update_region); - EXPECT_TRUE(observer_->empty()); - - // The inactivity timer shouldn't be running yet. - EXPECT_FALSE(detector_->TriggerTimeoutForTest()); - EXPECT_TRUE(observer_->empty()); - - // Send not-quite-enough adaquately-sized updates. - observer_->reset(); - AdvanceTime(base::TimeDelta::FromSeconds(2)); - update_region.set_size(gfx::Size(VideoDetector::kMinUpdateWidth, - VideoDetector::kMinUpdateHeight)); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond - 1; ++i) - detector_->OnDelegatedFrameDamage(window.get(), update_region); - EXPECT_TRUE(observer_->empty()); - - // We should get notified after the next update, but not in response to - // additional updates. - detector_->OnDelegatedFrameDamage(window.get(), update_region); - EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState()); - detector_->OnDelegatedFrameDamage(window.get(), update_region); - EXPECT_TRUE(observer_->empty()); - - // Wait and check that the observer is notified about inactivity. - AdvanceTime(base::TimeDelta::FromSeconds(VideoDetector::kVideoTimeoutMs)); - ASSERT_TRUE(detector_->TriggerTimeoutForTest()); - EXPECT_EQ(VideoDetector::State::NOT_PLAYING, observer_->PopState()); - - // Spread out the frames over a longer period of time, but send enough - // over a one-second window that the observer should be notified. - observer_->reset(); - detector_->OnDelegatedFrameDamage(window.get(), update_region); - EXPECT_TRUE(observer_->empty()); - - AdvanceTime(base::TimeDelta::FromMilliseconds(500)); - const int kNumFrames = VideoDetector::kMinFramesPerSecond + 1; - base::TimeDelta kInterval = - base::TimeDelta::FromMilliseconds(1000 / kNumFrames); - for (int i = 0; i < kNumFrames; ++i) { - AdvanceTime(kInterval); - detector_->OnDelegatedFrameDamage(window.get(), update_region); - } - EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState()); - - // Let the activity time out again. - AdvanceTime(base::TimeDelta::FromSeconds(VideoDetector::kVideoTimeoutMs)); - ASSERT_TRUE(detector_->TriggerTimeoutForTest()); - EXPECT_EQ(VideoDetector::State::NOT_PLAYING, observer_->PopState()); - - // Send updates at a slower rate and check that the observer isn't notified. - observer_->reset(); - base::TimeDelta kSlowInterval = base::TimeDelta::FromMilliseconds( - 1000 / (VideoDetector::kMinFramesPerSecond - 2)); - for (int i = 0; i < kNumFrames; ++i) { - AdvanceTime(kSlowInterval); - detector_->OnDelegatedFrameDamage(window.get(), update_region); - } +TEST_F(VideoDetectorTest, DontReportWhenRegionTooSmall) { + std::unique_ptr<aura::Window> window = + CreateTestWindow(gfx::Rect(0, 0, 1024, 768)); + gfx::Rect rect = kMinRect; + rect.Inset(0, 0, 1, 0); + SendUpdates(window.get(), rect, 2 * kMinFps, 2 * kMinDuration); EXPECT_TRUE(observer_->empty()); } -TEST_F(VideoDetectorTest, Shutdown) { - gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); - std::unique_ptr<aura::Window> window( - CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); - gfx::Rect update_region(gfx::Point(), - gfx::Size(VideoDetector::kMinUpdateWidth, - VideoDetector::kMinUpdateHeight)); - - // It should not detect video during the shutdown. - Shell::GetInstance()->OnAppTerminating(); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnDelegatedFrameDamage(window.get(), update_region); +TEST_F(VideoDetectorTest, DontReportWhenFramerateTooLow) { + std::unique_ptr<aura::Window> window = + CreateTestWindow(gfx::Rect(0, 0, 1024, 768)); + SendUpdates(window.get(), kMinRect, kMinFps - 5, 2 * kMinDuration); EXPECT_TRUE(observer_->empty()); } -TEST_F(VideoDetectorTest, WindowNotVisible) { - gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); - std::unique_ptr<aura::Window> window( - CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); +TEST_F(VideoDetectorTest, DontReportWhenNotPlayingLongEnough) { + std::unique_ptr<aura::Window> window = + CreateTestWindow(gfx::Rect(0, 0, 1024, 768)); + SendUpdates(window.get(), kMinRect, 2 * kMinFps, 0.5 * kMinDuration); + EXPECT_TRUE(observer_->empty()); + // Continue playing. + SendUpdates(window.get(), kMinRect, 2 * kMinFps, 0.6 * kMinDuration); + EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState()); + EXPECT_TRUE(observer_->empty()); +} + +TEST_F(VideoDetectorTest, DontReportWhenWindowOffscreen) { + std::unique_ptr<aura::Window> window = + CreateTestWindow(gfx::Rect(0, 0, 1024, 768)); + window->SetBounds( + gfx::Rect(gfx::Point(Shell::GetPrimaryRootWindow()->bounds().width(), 0), + window->bounds().size())); + SendUpdates(window.get(), kMinRect, 2 * kMinFps, 2 * kMinDuration); + EXPECT_TRUE(observer_->empty()); + + // Move the window onscreen. + window->SetBounds(gfx::Rect(gfx::Point(0, 0), window->bounds().size())); + SendUpdates(window.get(), kMinRect, 2 * kMinFps, 2 * kMinDuration); + EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState()); + EXPECT_TRUE(observer_->empty()); +} + +TEST_F(VideoDetectorTest, DontReportWhenWindowHidden) { + std::unique_ptr<aura::Window> window = + CreateTestWindow(gfx::Rect(0, 0, 1024, 768)); // Reparent the window to the root to make sure that visibility changes aren't // animated. Shell::GetPrimaryRootWindow()->AddChild(window.get()); - - // We shouldn't report video that's played in a hidden window. window->Hide(); - gfx::Rect update_region(gfx::Point(), - gfx::Size(VideoDetector::kMinUpdateWidth, - VideoDetector::kMinUpdateHeight)); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnDelegatedFrameDamage(window.get(), update_region); + SendUpdates(window.get(), kMinRect, kMinFps + 5, 2 * kMinDuration); EXPECT_TRUE(observer_->empty()); - // Make the window visible and send more updates. + // Make the window visible. observer_->reset(); - AdvanceTime(base::TimeDelta::FromSeconds(2)); + AdvanceTime(kTimeout); window->Show(); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnDelegatedFrameDamage(window.get(), update_region); + SendUpdates(window.get(), kMinRect, kMinFps + 5, 2 * kMinDuration); EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState()); - - AdvanceTime(base::TimeDelta::FromSeconds(VideoDetector::kVideoTimeoutMs)); - ASSERT_TRUE(detector_->TriggerTimeoutForTest()); - EXPECT_EQ(VideoDetector::State::NOT_PLAYING, observer_->PopState()); - - // We also shouldn't report video in a window that's fully offscreen. - observer_->reset(); - gfx::Rect offscreen_bounds( - gfx::Point(Shell::GetPrimaryRootWindow()->bounds().width(), 0), - window_bounds.size()); - window->SetBounds(offscreen_bounds); - ASSERT_EQ(offscreen_bounds, window->bounds()); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnDelegatedFrameDamage(window.get(), update_region); EXPECT_TRUE(observer_->empty()); } -TEST_F(VideoDetectorTest, MultipleWindows) { - // Create two windows. - gfx::Rect window_bounds(gfx::Point(), gfx::Size(1024, 768)); - std::unique_ptr<aura::Window> window1( - CreateTestWindowInShell(SK_ColorRED, 12345, window_bounds)); - std::unique_ptr<aura::Window> window2( - CreateTestWindowInShell(SK_ColorBLUE, 23456, window_bounds)); - - // Even if there's video playing in both, the observer should only receive a - // single notification. - gfx::Rect update_region(gfx::Point(), - gfx::Size(VideoDetector::kMinUpdateWidth, - VideoDetector::kMinUpdateHeight)); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnDelegatedFrameDamage(window1.get(), update_region); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnDelegatedFrameDamage(window2.get(), update_region); - EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState()); +TEST_F(VideoDetectorTest, DontReportDuringShutdown) { + std::unique_ptr<aura::Window> window = + CreateTestWindow(gfx::Rect(0, 0, 1024, 768)); + Shell::GetInstance()->OnAppTerminating(); + SendUpdates(window.get(), kMinRect, kMinFps + 5, 2 * kMinDuration); + EXPECT_TRUE(observer_->empty()); } -// Test that the observer receives the appropriate notification when the window -// is fullscreen. -TEST_F(VideoDetectorTest, FullscreenWindow) { +TEST_F(VideoDetectorTest, ReportStartAndStop) { + const base::TimeDelta kDuration = + kMinDuration + base::TimeDelta::FromMilliseconds(100); + std::unique_ptr<aura::Window> window = + CreateTestWindow(gfx::Rect(0, 0, 1024, 768)); + SendUpdates(window.get(), kMinRect, kMinFps + 5, kDuration); + EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState()); + EXPECT_TRUE(observer_->empty()); + + AdvanceTime(kTimeout); + EXPECT_TRUE(detector_->TriggerTimeoutForTest()); + EXPECT_EQ(VideoDetector::State::NOT_PLAYING, observer_->PopState()); + EXPECT_TRUE(observer_->empty()); + + // The timer shouldn't be running anymore. + EXPECT_FALSE(detector_->TriggerTimeoutForTest()); + + // Start playing again. + SendUpdates(window.get(), kMinRect, kMinFps + 5, kDuration); + EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState()); + EXPECT_TRUE(observer_->empty()); + + AdvanceTime(kTimeout); + EXPECT_TRUE(detector_->TriggerTimeoutForTest()); + EXPECT_EQ(VideoDetector::State::NOT_PLAYING, observer_->PopState()); + EXPECT_TRUE(observer_->empty()); +} + +TEST_F(VideoDetectorTest, ReportOnceForMultipleWindows) { + gfx::Rect kWindowBounds(gfx::Point(), gfx::Size(1024, 768)); + std::unique_ptr<aura::Window> window1 = CreateTestWindow(kWindowBounds); + std::unique_ptr<aura::Window> window2 = CreateTestWindow(kWindowBounds); + + // Even if there's video playing in both windows, the observer should only + // receive a single notification. + const int fps = 2 * kMinFps; + const base::TimeDelta time_between_updates = + base::TimeDelta::FromSecondsD(1.0 / fps); + const base::TimeTicks start_time = now_; + while (now_ < start_time + 2 * kMinDuration) { + detector_->OnDelegatedFrameDamage(window1.get(), kMinRect); + detector_->OnDelegatedFrameDamage(window2.get(), kMinRect); + AdvanceTime(time_between_updates); + } + EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState()); + EXPECT_TRUE(observer_->empty()); +} + +TEST_F(VideoDetectorTest, ReportFullscreen) { if (!SupportsMultipleDisplays()) return; UpdateDisplay("1024x768,1024x768"); - const gfx::Rect kLeftBounds(gfx::Point(), gfx::Size(1024, 768)); - std::unique_ptr<aura::Window> window( - CreateTestWindowInShell(SK_ColorRED, 12345, kLeftBounds)); + std::unique_ptr<aura::Window> window = + CreateTestWindow(gfx::Rect(0, 0, 1024, 768)); wm::WindowState* window_state = wm::GetWindowState(window.get()); const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN); window_state->OnWMEvent(&toggle_fullscreen_event); ASSERT_TRUE(window_state->IsFullscreen()); window->Focus(); - const gfx::Rect kUpdateRegion(gfx::Point(), - gfx::Size(VideoDetector::kMinUpdateWidth, - VideoDetector::kMinUpdateHeight)); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnDelegatedFrameDamage(window.get(), kUpdateRegion); + SendUpdates(window.get(), kMinRect, 2 * kMinFps, 2 * kMinDuration); EXPECT_EQ(VideoDetector::State::PLAYING_FULLSCREEN, observer_->PopState()); + EXPECT_TRUE(observer_->empty()); - // Make the first window non-fullscreen. + // Make the window non-fullscreen. + observer_->reset(); window_state->OnWMEvent(&toggle_fullscreen_event); ASSERT_FALSE(window_state->IsFullscreen()); EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState()); + EXPECT_TRUE(observer_->empty()); // Open a second, fullscreen window. Fullscreen video should still be reported // due to the second window being fullscreen. This avoids situations where // non-fullscreen video could be reported when multiple videos are playing in // fullscreen and non-fullscreen windows. - const gfx::Rect kRightBounds(gfx::Point(1024, 0), gfx::Size(1024, 768)); - std::unique_ptr<aura::Window> other_window( - CreateTestWindowInShell(SK_ColorBLUE, 6789, kRightBounds)); + observer_->reset(); + std::unique_ptr<aura::Window> other_window = + CreateTestWindow(gfx::Rect(1024, 0, 1024, 768)); wm::WindowState* other_window_state = wm::GetWindowState(other_window.get()); other_window_state->OnWMEvent(&toggle_fullscreen_event); ASSERT_TRUE(other_window_state->IsFullscreen()); - for (int i = 0; i < VideoDetector::kMinFramesPerSecond; ++i) - detector_->OnDelegatedFrameDamage(window.get(), kUpdateRegion); EXPECT_EQ(VideoDetector::State::PLAYING_FULLSCREEN, observer_->PopState()); + EXPECT_TRUE(observer_->empty()); // Make the second window non-fullscreen and check that the observer is // immediately notified about windowed video. @@ -285,6 +294,7 @@ other_window_state->OnWMEvent(&toggle_fullscreen_event); ASSERT_FALSE(other_window_state->IsFullscreen()); EXPECT_EQ(VideoDetector::State::PLAYING_WINDOWED, observer_->PopState()); + EXPECT_TRUE(observer_->empty()); } } // namespace test
diff --git a/ash/wm/workspace_controller_unittest.cc b/ash/wm/workspace_controller_unittest.cc index 2d23a7b..7b90197 100644 --- a/ash/wm/workspace_controller_unittest.cc +++ b/ash/wm/workspace_controller_unittest.cc
@@ -8,6 +8,7 @@ #include "ash/aura/wm_window_aura.h" #include "ash/common/shell_window_ids.h" +#include "ash/common/system/status_area_widget.h" #include "ash/common/wm/panels/panel_layout_manager.h" #include "ash/common/wm/window_state.h" #include "ash/common/wm/workspace/workspace_window_resizer.h" @@ -16,7 +17,6 @@ #include "ash/shelf/shelf_layout_manager.h" #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" -#include "ash/system/status_area_widget.h" #include "ash/test/ash_test_base.h" #include "ash/test/shell_test_api.h" #include "ash/test/test_shelf_delegate.h"
diff --git a/base/BUILD.gn b/base/BUILD.gn index e44570c..b30ca3c 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -161,6 +161,8 @@ "android/context_utils.h", "android/cpu_features.cc", "android/cxa_demangle_stub.cc", + "android/early_trace_event_binding.cc", + "android/early_trace_event_binding.h", "android/event_log.cc", "android/event_log.h", "android/field_trial_list.cc", @@ -1979,6 +1981,8 @@ "win/wrapped_window_proc_unittest.cc", ] + defines = [] + deps = [ ":base", ":i18n", @@ -2009,7 +2013,7 @@ # Allow more direct string conversions on platforms with native utf8 # strings if (is_mac || is_ios || is_chromeos || is_chromecast) { - defines = [ "SYSTEM_NATIVE_UTF8" ] + defines += [ "SYSTEM_NATIVE_UTF8" ] } if (is_android) { @@ -2114,6 +2118,11 @@ # data += [ "$root_out_dir/base_unittests.dSYM/" ] } } + + if (use_cfi_cast) { + # TODO(krasin): remove CFI_CAST_CHECK, see https://crbug.com/626794. + defines += [ "CFI_CAST_CHECK" ] + } } action("build_date") { @@ -2171,6 +2180,7 @@ "android/java/src/org/chromium/base/ContentUriUtils.java", "android/java/src/org/chromium/base/ContextUtils.java", "android/java/src/org/chromium/base/CpuFeatures.java", + "android/java/src/org/chromium/base/EarlyTraceEvent.java", "android/java/src/org/chromium/base/EventLog.java", "android/java/src/org/chromium/base/FieldTrialList.java", "android/java/src/org/chromium/base/ImportantFileWriterAndroid.java", @@ -2232,6 +2242,7 @@ "android/java/src/org/chromium/base/ContentUriUtils.java", "android/java/src/org/chromium/base/ContextUtils.java", "android/java/src/org/chromium/base/CpuFeatures.java", + "android/java/src/org/chromium/base/EarlyTraceEvent.java", "android/java/src/org/chromium/base/EventLog.java", "android/java/src/org/chromium/base/FieldTrialList.java", "android/java/src/org/chromium/base/FileUtils.java",
diff --git a/base/android/base_jni_registrar.cc b/base/android/base_jni_registrar.cc index bc34979c..0142647 100644 --- a/base/android/base_jni_registrar.cc +++ b/base/android/base_jni_registrar.cc
@@ -13,6 +13,7 @@ #include "base/android/content_uri_utils.h" #include "base/android/context_utils.h" #include "base/android/cpu_features.h" +#include "base/android/early_trace_event_binding.h" #include "base/android/event_log.h" #include "base/android/field_trial_list.h" #include "base/android/important_file_writer_android.h" @@ -50,6 +51,7 @@ {"ContentUriUtils", base::RegisterContentUriUtils}, {"ContextUtils", base::android::RegisterContextUtils}, {"CpuFeatures", base::android::RegisterCpuFeatures}, + {"EarlyTraceEvent", base::android::RegisterEarlyTraceEvent}, {"EventLog", base::android::RegisterEventLog}, {"FieldTrialList", base::android::RegisterFieldTrialList}, {"ImportantFileWriterAndroid",
diff --git a/base/android/early_trace_event_binding.cc b/base/android/early_trace_event_binding.cc new file mode 100644 index 0000000..19e5d8d --- /dev/null +++ b/base/android/early_trace_event_binding.cc
@@ -0,0 +1,46 @@ +// 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 "base/android/early_trace_event_binding.h" + +#include <stdint.h> + +#include "base/android/jni_string.h" +#include "base/time/time.h" +#include "base/trace_event/trace_event.h" +#include "jni/EarlyTraceEvent_jni.h" + +namespace base { +namespace android { + +const char kEarlyJavaCategory[] = "EarlyJava"; + +static jlong GetTimeTicksNowUs(JNIEnv* env, const JavaParamRef<jclass>& clazz) { + return TimeTicks::Now().ToInternalValue(); +} + +static void RecordEarlyEvent(JNIEnv* env, + const JavaParamRef<jclass>& clazz, + const JavaParamRef<jstring>& jname, + jlong begin_time_ms, + jlong end_time_ms, + jint thread_id) { + std::string name = ConvertJavaStringToUTF8(env, jname); + int64_t begin_us = begin_time_ms * 1000; + int64_t end_us = end_time_ms * 1000; + + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( + TRACE_EVENT_PHASE_BEGIN, kEarlyJavaCategory, name.c_str(), + trace_event_internal::kNoId, thread_id, begin_us, TRACE_EVENT_FLAG_COPY); + INTERNAL_TRACE_EVENT_ADD_WITH_ID_TID_AND_TIMESTAMP( + TRACE_EVENT_PHASE_END, kEarlyJavaCategory, name.c_str(), + trace_event_internal::kNoId, thread_id, end_us, TRACE_EVENT_FLAG_COPY); +} + +bool RegisterEarlyTraceEvent(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace android +} // namespace base
diff --git a/base/android/early_trace_event_binding.h b/base/android/early_trace_event_binding.h new file mode 100644 index 0000000..796544c9 --- /dev/null +++ b/base/android/early_trace_event_binding.h
@@ -0,0 +1,18 @@ +// 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 BASE_ANDROID_EARLY_TRACE_EVENT_BINDING_H_ +#define BASE_ANDROID_EARLY_TRACE_EVENT_BINDING_H_ + +#include <jni.h> + +namespace base { +namespace android { + +bool RegisterEarlyTraceEvent(JNIEnv* env); + +} // namespace android +} // namespace base + +#endif // BASE_ANDROID_EARLY_TRACE_EVENT_BINDING_H_
diff --git a/base/android/java/src/org/chromium/base/EarlyTraceEvent.java b/base/android/java/src/org/chromium/base/EarlyTraceEvent.java new file mode 100644 index 0000000..383a5e2 --- /dev/null +++ b/base/android/java/src/org/chromium/base/EarlyTraceEvent.java
@@ -0,0 +1,179 @@ +// 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. + +package org.chromium.base; + +import android.os.Process; +import android.os.StrictMode; +import android.os.SystemClock; + +import org.chromium.base.annotations.JNINamespace; +import org.chromium.base.annotations.SuppressFBWarnings; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** Support for early tracing, before the native library is loaded. + * + * This is limited, as: + * - Arguments are not supported + * - Thread time is not reported + * - Two events with the same name cannot be in progress at the same time. + * + * Events recorded here are buffered in Java until the native library is available. Then it waits + * for the completion of pending events, and sends the events to the native side. + * + * Locking: This class is threadsafe. It is enabled when general tracing is, and then disabled when + * tracing is enabled from the native side. Event completions are still processed as long + * as some are pending, then early tracing is permanently disabled after dumping the + * events. This means that if any early event is still pending when tracing is disabled, + * all early events are dropped. + */ +@JNINamespace("base::android") +public class EarlyTraceEvent { + // Must be kept in sync with the native kAndroidTraceConfigFile. + private static final String TRACE_CONFIG_FILENAME = "/data/local/chrome-trace-config.json"; + + /** Single trace event. */ + @VisibleForTesting + static final class Event { + final String mName; + final int mThreadId; + final long mBeginTimeMs; + long mEndTimeMs; + + Event(String name) { + mName = name; + mThreadId = Process.myTid(); + mBeginTimeMs = SystemClock.elapsedRealtime(); + } + + void end() { + assert mEndTimeMs == 0; + mEndTimeMs = SystemClock.elapsedRealtime(); + } + } + + // State transitions are: + // - enable(): DISABLED -> ENABLED + // - disable(): ENABLED -> FINISHING + // - Once there are no pending events: FINISHING -> FINISHED. + @VisibleForTesting static final int STATE_DISABLED = 0; + @VisibleForTesting static final int STATE_ENABLED = 1; + @VisibleForTesting static final int STATE_FINISHING = 2; + @VisibleForTesting static final int STATE_FINISHED = 3; + + // Locks the fields below. + private static final Object sLock = new Object(); + + @VisibleForTesting static volatile int sState = STATE_DISABLED; + // Not final as these object are not likely to be used at all. + @VisibleForTesting static List<Event> sCompletedEvents; + @VisibleForTesting static Map<String, Event> sPendingEvents; + + /** @see TraceEvent#MaybeEnableEarlyTracing(). + */ + @SuppressFBWarnings("DMI_HARDCODED_ABSOLUTE_FILENAME") + static void maybeEnable() { + boolean shouldEnable = false; + // Checking for the trace config filename touches the disk. + StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); + try { + if (CommandLine.isInitialized() + && CommandLine.getInstance().hasSwitch("trace-startup")) { + shouldEnable = true; + } else { + try { + shouldEnable = (new File(TRACE_CONFIG_FILENAME)).exists(); + } catch (SecurityException e) { + // Access denied, not enabled. + } + } + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } + if (shouldEnable) enable(); + } + + @VisibleForTesting + static void enable() { + synchronized (sLock) { + if (sState != STATE_DISABLED) return; + sCompletedEvents = new ArrayList<Event>(); + sPendingEvents = new HashMap<String, Event>(); + sState = STATE_ENABLED; + } + } + + /** + * Disables Early tracing. + * + * Once this is called, no new event will be registered. However, end() calls are still recorded + * as long as there are pending events. Once there are none left, pass the events to the native + * side. + */ + static void disable() { + synchronized (sLock) { + if (sState != STATE_ENABLED) return; + sState = STATE_FINISHING; + maybeFinishLocked(); + } + } + + /** @see {@link TraceEvent#begin()}. */ + public static void begin(String name) { + // begin() and end() are going to be called once per TraceEvent, this avoids entering a + // synchronized block at each and every call. + if (sState != STATE_ENABLED) return; + Event event = new Event(name); + Event conflictingEvent; + synchronized (sLock) { + if (sState != STATE_ENABLED) return; + conflictingEvent = sPendingEvents.put(name, event); + } + if (conflictingEvent != null) { + throw new IllegalArgumentException( + "Multiple pending trace events can't have the same name"); + } + } + + /** @see {@link TraceEvent#end()}. */ + public static void end(String name) { + int state = sState; + if (state != STATE_ENABLED && state != STATE_FINISHING) return; + synchronized (sLock) { + if (sState != STATE_ENABLED && sState != STATE_FINISHING) return; + Event event = sPendingEvents.remove(name); + if (event == null) return; + event.end(); + sCompletedEvents.add(event); + if (sState == STATE_FINISHING) maybeFinishLocked(); + } + } + + private static void maybeFinishLocked() { + if (!sPendingEvents.isEmpty()) return; + sState = STATE_FINISHED; + dumpEvents(sCompletedEvents); + sCompletedEvents = null; + sPendingEvents = null; + } + + private static void dumpEvents(List<Event> events) { + long nativeNowUs = nativeGetTimeTicksNowUs(); + long javaNowUs = SystemClock.elapsedRealtime() * 1000; + long offsetMs = (nativeNowUs - javaNowUs) / 1000; + for (Event event : events) { + nativeRecordEarlyEvent(event.mName, event.mBeginTimeMs + offsetMs, + event.mEndTimeMs + offsetMs, event.mThreadId); + } + } + + private static native long nativeGetTimeTicksNowUs(); + private static native void nativeRecordEarlyEvent( + String name, long beginTimeMs, long endTimeMs, int threadId); +}
diff --git a/base/android/java/src/org/chromium/base/TraceEvent.java b/base/android/java/src/org/chromium/base/TraceEvent.java index 878275c2..95d01dc 100644 --- a/base/android/java/src/org/chromium/base/TraceEvent.java +++ b/base/android/java/src/org/chromium/base/TraceEvent.java
@@ -16,8 +16,8 @@ * Java mirror of Chrome trace event API. See base/trace_event/trace_event.h. Unlike the native * version, Java does not have stack objects, so a TRACE_EVENT() which does both TRACE_EVENT_BEGIN() * and TRACE_EVENT_END() in ctor/dtor is not possible. - * It is OK to use tracing before the native library has loaded, but such traces will - * be ignored. (Perhaps we could devise to buffer them up in future?). + * It is OK to use tracing before the native library has loaded, in a slightly restricted fashion. + * @see EarlyTraceEvent for details. */ @JNINamespace("base::android") public class TraceEvent { @@ -179,6 +179,7 @@ */ @CalledByNative public static void setEnabled(boolean enabled) { + if (enabled) EarlyTraceEvent.disable(); sEnabled = enabled; // Android M+ systrace logs this on its own. Only log it if not writing to Android systrace. if (sATraceEnabled) return; @@ -187,6 +188,15 @@ } /** + * May enable early tracing depending on the environment. + * + * Must be called after the command-line has been read. + */ + public static void maybeEnableEarlyTracing() { + EarlyTraceEvent.maybeEnable(); + } + + /** * Enables or disabled Android systrace path of Chrome tracing. If enabled, all Chrome * traces will be also output to Android systrace. Because of the overhead of Android * systrace, this is for WebView only. @@ -254,7 +264,7 @@ * @param name The name of the event. */ public static void begin(String name) { - if (sEnabled) nativeBegin(name, null); + begin(name, null); } /** @@ -263,6 +273,7 @@ * @param arg The arguments of the event. */ public static void begin(String name, String arg) { + EarlyTraceEvent.begin(name); if (sEnabled) nativeBegin(name, arg); } @@ -271,7 +282,7 @@ * @param name The name of the event. */ public static void end(String name) { - if (sEnabled) nativeEnd(name, null); + end(name, null); } /** @@ -280,6 +291,7 @@ * @param arg The arguments of the event. */ public static void end(String name, String arg) { + EarlyTraceEvent.end(name); if (sEnabled) nativeEnd(name, arg); }
diff --git a/base/android/javatests/src/org/chromium/base/EarlyTraceEventTest.java b/base/android/javatests/src/org/chromium/base/EarlyTraceEventTest.java new file mode 100644 index 0000000..c2efb9e --- /dev/null +++ b/base/android/javatests/src/org/chromium/base/EarlyTraceEventTest.java
@@ -0,0 +1,152 @@ +// 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. + +package org.chromium.base; + +import android.os.Process; +import android.os.SystemClock; +import android.test.InstrumentationTestCase; +import android.test.suitebuilder.annotation.SmallTest; + +import org.chromium.base.library_loader.LibraryLoader; +import org.chromium.base.library_loader.LibraryProcessType; +import org.chromium.base.test.util.Feature; + +/** + * Tests for {@link EarlyTraceEvent}. + */ +public class EarlyTraceEventTest extends InstrumentationTestCase { + private static final String EVENT_NAME = "MyEvent"; + private static final String EVENT_NAME2 = "MyOtherEvent"; + + @Override + protected void setUp() throws Exception { + super.setUp(); + LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER) + .ensureInitialized(getInstrumentation().getTargetContext()); + + EarlyTraceEvent.sState = EarlyTraceEvent.STATE_DISABLED; + EarlyTraceEvent.sCompletedEvents = null; + EarlyTraceEvent.sPendingEvents = null; + } + + @SmallTest + @Feature({"Android-AppBase"}) + public void testCanRecordEvent() { + EarlyTraceEvent.enable(); + long myThreadId = Process.myTid(); + long beforeMs = SystemClock.elapsedRealtime(); + EarlyTraceEvent.begin(EVENT_NAME); + EarlyTraceEvent.end(EVENT_NAME); + long afterMs = SystemClock.elapsedRealtime(); + + assertEquals(1, EarlyTraceEvent.sCompletedEvents.size()); + assertTrue(EarlyTraceEvent.sPendingEvents.isEmpty()); + EarlyTraceEvent.Event event = EarlyTraceEvent.sCompletedEvents.get(0); + assertEquals(EVENT_NAME, event.mName); + assertEquals(myThreadId, event.mThreadId); + assertTrue(beforeMs <= event.mBeginTimeMs && event.mBeginTimeMs <= afterMs); + assertTrue(event.mBeginTimeMs <= event.mEndTimeMs); + assertTrue(beforeMs <= event.mEndTimeMs && event.mEndTimeMs <= afterMs); + } + + @SmallTest + @Feature({"Android-AppBase"}) + public void testIncompleteEvent() { + EarlyTraceEvent.enable(); + EarlyTraceEvent.begin(EVENT_NAME); + + assertTrue(EarlyTraceEvent.sCompletedEvents.isEmpty()); + assertEquals(1, EarlyTraceEvent.sPendingEvents.size()); + EarlyTraceEvent.Event event = EarlyTraceEvent.sPendingEvents.get(EVENT_NAME); + assertEquals(EVENT_NAME, event.mName); + } + + @SmallTest + @Feature({"Android-AppBase"}) + public void testNoDuplicatePendingEvents() { + EarlyTraceEvent.enable(); + EarlyTraceEvent.begin(EVENT_NAME); + try { + EarlyTraceEvent.begin(EVENT_NAME); + } catch (IllegalArgumentException e) { + // Expected. + return; + } + fail(); + } + + @SmallTest + @Feature({"Android-AppBase"}) + public void testIgnoreEventsWhenDisabled() { + EarlyTraceEvent.begin(EVENT_NAME); + EarlyTraceEvent.end(EVENT_NAME); + assertNull(EarlyTraceEvent.sCompletedEvents); + } + + @SmallTest + @Feature({"Android-AppBase"}) + public void testIgnoreNewEventsWhenFinishing() { + EarlyTraceEvent.enable(); + EarlyTraceEvent.begin(EVENT_NAME); + EarlyTraceEvent.disable(); + + assertEquals(EarlyTraceEvent.STATE_FINISHING, EarlyTraceEvent.sState); + EarlyTraceEvent.begin(EVENT_NAME2); + EarlyTraceEvent.end(EVENT_NAME2); + + assertEquals(1, EarlyTraceEvent.sPendingEvents.size()); + assertTrue(EarlyTraceEvent.sCompletedEvents.isEmpty()); + } + + @SmallTest + @Feature({"Android-AppBase"}) + public void testFinishingToFinished() { + EarlyTraceEvent.enable(); + EarlyTraceEvent.begin(EVENT_NAME); + EarlyTraceEvent.disable(); + + assertEquals(EarlyTraceEvent.STATE_FINISHING, EarlyTraceEvent.sState); + EarlyTraceEvent.begin(EVENT_NAME2); + EarlyTraceEvent.end(EVENT_NAME2); + EarlyTraceEvent.end(EVENT_NAME); + + assertEquals(EarlyTraceEvent.STATE_FINISHED, EarlyTraceEvent.sState); + } + + @SmallTest + @Feature({"Android-AppBase"}) + public void testCannotBeReenabledOnceFinished() { + EarlyTraceEvent.enable(); + EarlyTraceEvent.begin(EVENT_NAME); + EarlyTraceEvent.end(EVENT_NAME); + EarlyTraceEvent.disable(); + assertEquals(EarlyTraceEvent.STATE_FINISHED, EarlyTraceEvent.sState); + + EarlyTraceEvent.enable(); + assertEquals(EarlyTraceEvent.STATE_FINISHED, EarlyTraceEvent.sState); + } + + @SmallTest + @Feature({"Android-AppBase"}) + public void testThreadIdIsRecorded() throws Exception { + EarlyTraceEvent.enable(); + final long[] threadId = {0}; + + Thread thread = new Thread() { + @Override + public void run() { + TraceEvent.begin(EVENT_NAME); + threadId[0] = Process.myTid(); + TraceEvent.end(EVENT_NAME); + } + }; + thread.start(); + thread.join(); + + assertEquals(1, EarlyTraceEvent.sCompletedEvents.size()); + EarlyTraceEvent.Event event = EarlyTraceEvent.sCompletedEvents.get(0); + assertEquals(threadId[0], event.mThreadId); + } +}
diff --git a/base/base.gyp b/base/base.gyp index 0c1ad352..a534d5c 100644 --- a/base/base.gyp +++ b/base/base.gyp
@@ -639,6 +639,12 @@ 'module_dir': 'base' }, 'conditions': [ + ['cfi_vptr==1 and cfi_cast==1', { + 'defines': [ + # TODO(krasin): remove CFI_CAST_CHECK, see https://crbug.com/626794. + 'CFI_CAST_CHECK', + ], + }], ['OS == "ios" or OS == "mac"', { 'dependencies': [ 'base_unittests_arc',
diff --git a/base/metrics/histogram_base.h b/base/metrics/histogram_base.h index 58a9ab2e..d240099 100644 --- a/base/metrics/histogram_base.h +++ b/base/metrics/histogram_base.h
@@ -135,10 +135,6 @@ COUNT_LOW_ERROR = 0x8, NEVER_EXCEEDED_VALUE = 0x10, - - // This value is used only in HistogramSnapshotManager for marking - // internally when new inconsistencies are found. - NEW_INCONSISTENCY_FOUND = 0x8000000 }; explicit HistogramBase(const std::string& name);
diff --git a/base/metrics/histogram_snapshot_manager.cc b/base/metrics/histogram_snapshot_manager.cc index dc6cb8a..340505e 100644 --- a/base/metrics/histogram_snapshot_manager.cc +++ b/base/metrics/histogram_snapshot_manager.cc
@@ -16,91 +16,20 @@ HistogramSnapshotManager::HistogramSnapshotManager( HistogramFlattener* histogram_flattener) - : preparing_deltas_(false), - histogram_flattener_(histogram_flattener) { + : histogram_flattener_(histogram_flattener) { DCHECK(histogram_flattener_); } HistogramSnapshotManager::~HistogramSnapshotManager() { } -void HistogramSnapshotManager::StartDeltas() { - // Ensure that start/finish calls do not get nested. - DCHECK(!preparing_deltas_); - preparing_deltas_ = true; - - DCHECK(owned_histograms_.empty()); - -#if DCHECK_IS_ON() - for (const auto& hash_and_info : known_histograms_) { - DCHECK(!hash_and_info.second.histogram); - DCHECK(!hash_and_info.second.accumulated_samples); - DCHECK(!(hash_and_info.second.inconsistencies & - HistogramBase::NEW_INCONSISTENCY_FOUND)); - } -#endif -} - void HistogramSnapshotManager::PrepareDelta(HistogramBase* histogram) { PrepareSamples(histogram, histogram->SnapshotDelta()); } -void HistogramSnapshotManager::PrepareDeltaTakingOwnership( - std::unique_ptr<HistogramBase> histogram) { - PrepareSamples(histogram.get(), histogram->SnapshotDelta()); - owned_histograms_.push_back(std::move(histogram)); -} - -void HistogramSnapshotManager::PrepareAbsolute(const HistogramBase* histogram) { - PrepareSamples(histogram, histogram->SnapshotSamples()); -} - -void HistogramSnapshotManager::PrepareAbsoluteTakingOwnership( - std::unique_ptr<const HistogramBase> histogram) { - PrepareSamples(histogram.get(), histogram->SnapshotSamples()); - owned_histograms_.push_back(std::move(histogram)); -} - -void HistogramSnapshotManager::PrepareFinalDeltaTakingOwnership( - std::unique_ptr<const HistogramBase> histogram) { - PrepareSamples(histogram.get(), histogram->SnapshotFinalDelta()); - owned_histograms_.push_back(std::move(histogram)); -} - -void HistogramSnapshotManager::FinishDeltas() { - DCHECK(preparing_deltas_); - - // Iterate over all known histograms to see what should be recorded. - for (auto& hash_and_info : known_histograms_) { - SampleInfo* sample_info = &hash_and_info.second; - - // First, record any histograms in which corruption was detected. - if (sample_info->inconsistencies & HistogramBase::NEW_INCONSISTENCY_FOUND) { - sample_info->inconsistencies &= ~HistogramBase::NEW_INCONSISTENCY_FOUND; - histogram_flattener_->UniqueInconsistencyDetected( - static_cast<HistogramBase::Inconsistency>( - sample_info->inconsistencies)); - } - - // Second, record actual accumulated deltas. - if (sample_info->accumulated_samples) { - // TODO(bcwhite): Investigate using redundant_count() below to avoid - // additional pass through all the samples to calculate real total. - if (sample_info->accumulated_samples->TotalCount() > 0) { - histogram_flattener_->RecordDelta(*sample_info->histogram, - *sample_info->accumulated_samples); - } - delete sample_info->accumulated_samples; - sample_info->accumulated_samples = nullptr; - } - - // The Histogram pointer must be cleared at this point because the owner - // is only required to keep it alive until FinishDeltas() completes. - sample_info->histogram = nullptr; - } - - owned_histograms_.clear(); - preparing_deltas_ = false; +void HistogramSnapshotManager::PrepareFinalDelta( + const HistogramBase* histogram) { + PrepareSamples(histogram, histogram->SnapshotFinalDelta()); } void HistogramSnapshotManager::PrepareSamples( @@ -108,28 +37,32 @@ std::unique_ptr<HistogramSamples> samples) { DCHECK(histogram_flattener_); - // Get information known about this histogram. + // Get information known about this histogram. If it did not previously + // exist, one will be created and initialized. SampleInfo* sample_info = &known_histograms_[histogram->name_hash()]; - if (sample_info->histogram) { - DCHECK_EQ(sample_info->histogram->histogram_name(), - histogram->histogram_name()) << "hash collision"; - } else { - // First time this histogram has been seen; datafill. - sample_info->histogram = histogram; - } // Crash if we detect that our histograms have been overwritten. This may be // a fair distance from the memory smasher, but we hope to correlate these // crashes with other events, such as plugins, or usage patterns, etc. uint32_t corruption = histogram->FindCorruption(*samples); if (HistogramBase::BUCKET_ORDER_ERROR & corruption) { + // Extract fields useful during debug. + const BucketRanges* ranges = + static_cast<const Histogram*>(histogram)->bucket_ranges(); + std::vector<HistogramBase::Sample> ranges_copy; + for (size_t i = 0; i < ranges->size(); ++i) + ranges_copy.push_back(ranges->range(i)); + HistogramBase::Sample* ranges_ptr = &ranges_copy[0]; + const char* histogram_name = histogram->histogram_name().c_str(); + int32_t flags = histogram->flags(); // The checksum should have caught this, so crash separately if it didn't. CHECK_NE(0U, HistogramBase::RANGE_CHECKSUM_ERROR & corruption); CHECK(false); // Crash for the bucket order corruption. // Ensure that compiler keeps around pointers to |histogram| and its // internal |bucket_ranges_| for any minidumps. - base::debug::Alias( - static_cast<const Histogram*>(histogram)->bucket_ranges()); + base::debug::Alias(&ranges_ptr); + base::debug::Alias(&histogram_name); + base::debug::Alias(&flags); } // Checksum corruption might not have caused order corruption. CHECK_EQ(0U, HistogramBase::RANGE_CHECKSUM_ERROR & corruption); @@ -146,19 +79,14 @@ const uint32_t old_corruption = sample_info->inconsistencies; if (old_corruption == (corruption | old_corruption)) return; // We've already seen this corruption for this histogram. - sample_info->inconsistencies |= - corruption | HistogramBase::NEW_INCONSISTENCY_FOUND; - // TODO(bcwhite): Can we clear the inconsistency for future collection? + sample_info->inconsistencies |= corruption; + histogram_flattener_->UniqueInconsistencyDetected( + static_cast<HistogramBase::Inconsistency>(corruption)); return; } - if (!sample_info->accumulated_samples) { - // This histogram has not been seen before; add it as a new entry. - sample_info->accumulated_samples = samples.release(); - } else { - // There are previous values from this histogram; add them together. - sample_info->accumulated_samples->Add(*samples); - } + if (samples->TotalCount() > 0) + histogram_flattener_->RecordDelta(*histogram, *samples); } void HistogramSnapshotManager::InspectLoggedSamplesInconsistency(
diff --git a/base/metrics/histogram_snapshot_manager.h b/base/metrics/histogram_snapshot_manager.h index 83bd5fe..26fb93f 100644 --- a/base/metrics/histogram_snapshot_manager.h +++ b/base/metrics/histogram_snapshot_manager.h
@@ -37,16 +37,12 @@ // |required_flags| is used to select histograms to be recorded. // Only histograms that have all the flags specified by the argument will be // chosen. If all histograms should be recorded, set it to - // |Histogram::kNoFlags|. Though any "forward" iterator will work, the - // histograms over which it iterates *must* remain valid until this method - // returns; the iterator cannot deallocate histograms once it iterates past - // them and FinishDeltas() has been called after. StartDeltas() must be - // called before. + // |Histogram::kNoFlags|. template <class ForwardHistogramIterator> - void PrepareDeltasWithoutStartFinish(ForwardHistogramIterator begin, - ForwardHistogramIterator end, - HistogramBase::Flags flags_to_set, - HistogramBase::Flags required_flags) { + void PrepareDeltas(ForwardHistogramIterator begin, + ForwardHistogramIterator end, + HistogramBase::Flags flags_to_set, + HistogramBase::Flags required_flags) { for (ForwardHistogramIterator it = begin; it != end; ++it) { (*it)->SetFlags(flags_to_set); if (((*it)->flags() & required_flags) == required_flags) @@ -54,59 +50,21 @@ } } - // As above but also calls StartDeltas() and FinishDeltas(). - template <class ForwardHistogramIterator> - void PrepareDeltas(ForwardHistogramIterator begin, - ForwardHistogramIterator end, - HistogramBase::Flags flags_to_set, - HistogramBase::Flags required_flags) { - StartDeltas(); - PrepareDeltasWithoutStartFinish(begin, end, flags_to_set, required_flags); - FinishDeltas(); - } - // When the collection is not so simple as can be done using a single // iterator, the steps can be performed separately. Call PerpareDelta() - // as many times as necessary with a single StartDeltas() before and - // a single FinishDeltas() after. All passed histograms must live - // until FinishDeltas() completes. PrepareAbsolute() works the same - // but assumes there were no previous logged values and no future deltas - // will be created (and thus can work on read-only histograms). - // PrepareFinalDelta() works like PrepareDelta() except that it does - // not update the previous logged values and can thus be used with - // read-only files. - // Use Prepare*TakingOwnership() if it is desireable to have this class - // automatically delete the histogram once it is "finished". - void StartDeltas(); + // as many times as necessary. PrepareFinalDelta() works like PrepareDelta() + // except that it does not update the previous logged values and can thus + // be used with read-only files. void PrepareDelta(HistogramBase* histogram); - void PrepareDeltaTakingOwnership(std::unique_ptr<HistogramBase> histogram); - void PrepareAbsolute(const HistogramBase* histogram); - void PrepareAbsoluteTakingOwnership( - std::unique_ptr<const HistogramBase> histogram); - void PrepareFinalDeltaTakingOwnership( - std::unique_ptr<const HistogramBase> histogram); - void FinishDeltas(); + void PrepareFinalDelta(const HistogramBase* histogram); private: FRIEND_TEST_ALL_PREFIXES(HistogramSnapshotManagerTest, CheckMerge); // During a snapshot, samples are acquired and aggregated. This structure - // contains all the information collected for a given histogram. Once a - // snapshot operation is finished, it is generally emptied except for - // information that must persist from one report to the next, such as - // the "inconsistencies". + // contains all the information for a given histogram that persists between + // collections. struct SampleInfo { - // A histogram associated with this sample; it may be one of many if - // several have been aggregated into the same "accumulated" sample set. - // Ownership of the histogram remains elsewhere and this pointer is - // cleared by FinishDeltas(). - const HistogramBase* histogram = nullptr; - - // The current snapshot-delta values being accumulated. - // TODO(bcwhite): Change this to a scoped_ptr once all build architectures - // support such as the value of a std::map. - HistogramSamples* accumulated_samples = nullptr; - // The set of inconsistencies (flags) already seen for the histogram. // See HistogramBase::Inconsistency for values. uint32_t inconsistencies = 0; @@ -126,13 +84,6 @@ // by the hash of the histogram name. std::map<uint64_t, SampleInfo> known_histograms_; - // Collection of histograms of which ownership has been passed to this - // object. They will be deleted by FinishDeltas(). - std::vector<std::unique_ptr<const HistogramBase>> owned_histograms_; - - // Indicates if deltas are currently being prepared. - bool preparing_deltas_; - // |histogram_flattener_| handles the logistics of recording the histogram // deltas. HistogramFlattener* histogram_flattener_; // Weak.
diff --git a/base/metrics/histogram_snapshot_manager_unittest.cc b/base/metrics/histogram_snapshot_manager_unittest.cc index 6d53c86a..3c13e1a5 100644 --- a/base/metrics/histogram_snapshot_manager_unittest.cc +++ b/base/metrics/histogram_snapshot_manager_unittest.cc
@@ -24,8 +24,9 @@ void RecordDelta(const HistogramBase& histogram, const HistogramSamples& snapshot) override { recorded_delta_histogram_names_.push_back(histogram.histogram_name()); - ASSERT_FALSE(ContainsKey(recorded_delta_histogram_sum_, - histogram.histogram_name())); + // Use CHECK instead of ASSERT to get full stack-trace and thus origin. + CHECK(!ContainsKey(recorded_delta_histogram_sum_, + histogram.histogram_name())); // Keep pointer to snapshot for testing. This really isn't ideal but the // snapshot-manager keeps the snapshot alive until it's "forgotten". recorded_delta_histogram_sum_[histogram.histogram_name()] = snapshot.sum(); @@ -125,35 +126,4 @@ EXPECT_EQ("UmaStabilityHistogram", histograms[0]); } -TEST_F(HistogramSnapshotManagerTest, CheckMerge) { - UMA_HISTOGRAM_ENUMERATION("UmaHistogram", 1, 4); - UMA_STABILITY_HISTOGRAM_ENUMERATION("UmaStabilityHistogram", 1, 2); - - base::HistogramBase* h1 = base::LinearHistogram::FactoryGet( - "UmaHistogram", 1, 4, 5, 0); - ASSERT_TRUE(h1); - base::HistogramBase* h2 = base::LinearHistogram::FactoryGet( - "UmaStabilityHistogram", 1, 2, 3, 0); - ASSERT_TRUE(h2); - - histogram_snapshot_manager_.StartDeltas(); - histogram_snapshot_manager_.PrepareDelta(h1); - histogram_snapshot_manager_.PrepareDelta(h1); // Delta will be zero. - histogram_snapshot_manager_.PrepareDelta(h2); - h1->Add(2); - h2->Add(1); - histogram_snapshot_manager_.PrepareDelta(h2); - histogram_snapshot_manager_.PrepareDelta(h1); - histogram_snapshot_manager_.FinishDeltas(); - { - const std::vector<std::string> histograms = - histogram_flattener_delta_recorder_.GetRecordedDeltaHistogramNames(); - EXPECT_EQ(2U, histograms.size()); - EXPECT_EQ(3, histogram_flattener_delta_recorder_. - GetRecordedDeltaHistogramSum("UmaHistogram")); - EXPECT_EQ(2, histogram_flattener_delta_recorder_. - GetRecordedDeltaHistogramSum("UmaStabilityHistogram")); - } -} - } // namespace base
diff --git a/base/metrics/user_metrics.h b/base/metrics/user_metrics.h index c80bac0..93701e8 100644 --- a/base/metrics/user_metrics.h +++ b/base/metrics/user_metrics.h
@@ -26,9 +26,9 @@ // not good: "SSLDialogShown", "PageLoaded", "DiskFull" // We use this to gather anonymized information about how users are // interacting with the browser. -// WARNING: In calls to this function, UserMetricsAction and a -// string literal parameter must be on the same line, e.g. -// RecordAction(UserMetricsAction("my extremely long action name")); +// WARNING: In calls to this function, UserMetricsAction should be followed by a +// string literal parameter and not a variable e.g. +// RecordAction(UserMetricsAction("my action name")); // This ensures that our processing scripts can associate this action's hash // with its metric name. Therefore, it will be possible to retrieve the metric // name from the hash later on.
diff --git a/base/metrics/user_metrics_action.h b/base/metrics/user_metrics_action.h index 8c195b3..3eca3ddb 100644 --- a/base/metrics/user_metrics_action.h +++ b/base/metrics/user_metrics_action.h
@@ -10,13 +10,12 @@ // UserMetricsAction exists purely to standardize on the parameters passed to // UserMetrics. That way, our toolset can scan the source code reliable for // constructors and extract the associated string constants. -// WARNING: When using UserMetricsAction, UserMetricsAction and a string literal -// parameter must be on the same line, e.g. -// RecordAction(UserMetricsAction("my extremely long action name")); -// or -// RenderThread::Get()->RecordAction( -// UserMetricsAction("my extremely long action name")); -// because otherwise our processing scripts won't pick up on new actions. +// WARNING: When using UserMetricsAction you should use a string literal +// parameter e.g. +// RecordAction(UserMetricsAction("my action name")); +// This ensures that our processing scripts can associate this action's hash +// with its metric name. Therefore, it will be possible to retrieve the metric +// name from the hash later on. // Please see tools/metrics/actions/extract_actions.py for details. struct UserMetricsAction { const char* str_;
diff --git a/base/observer_list.h b/base/observer_list.h index 3156421..afe1f46c 100644 --- a/base/observer_list.h +++ b/base/observer_list.h
@@ -236,8 +236,8 @@ #define FOR_EACH_OBSERVER(ObserverType, observer_list, func) \ do { \ if ((observer_list).might_have_observers()) { \ - base::ObserverListBase<ObserverType>::Iterator it_inside_observer_macro( \ - &observer_list); \ + typename base::ObserverListBase<ObserverType>::Iterator \ + it_inside_observer_macro(&observer_list); \ ObserverType* obs; \ while ((obs = it_inside_observer_macro.GetNext()) != nullptr) \ obs->func; \
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn index 0283c67..7e2c4ac6 100644 --- a/base/test/BUILD.gn +++ b/base/test/BUILD.gn
@@ -9,7 +9,7 @@ import("//build/config/android/rules.gni") } -source_set("test_config") { +static_library("test_config") { testonly = true sources = [ "test_switches.cc", @@ -23,7 +23,7 @@ } # GYP: //base/base.gyp:test_support_base -source_set("test_support") { +static_library("test_support") { testonly = true sources = [ "gtest_util.cc", @@ -216,6 +216,9 @@ defines = [ "PERF_TEST" ] } +# This is a source set instead of a static library because it seems like some +# linkers get confused when "main" is in a static library, and if you link to +# this, you always want the object file anyway. source_set("test_support_perf") { testonly = true sources = [ @@ -230,7 +233,7 @@ public_configs = [ ":perf_test_config" ] } -source_set("test_launcher_nacl_nonsfi") { +static_library("test_launcher_nacl_nonsfi") { testonly = true sources = [ "launcher/test_launcher_nacl_nonsfi.cc", @@ -241,7 +244,7 @@ ] } -source_set("run_all_unittests") { +static_library("run_all_unittests") { testonly = true sources = [ "run_all_unittests.cc",
diff --git a/base/test/gtest_xml_util.cc b/base/test/gtest_xml_util.cc index 5426a24..f5464c0 100644 --- a/base/test/gtest_xml_util.cc +++ b/base/test/gtest_xml_util.cc
@@ -126,9 +126,8 @@ result.status = TestResult::TEST_SUCCESS; if (!results->empty() && - results->at(results->size() - 1).full_name == result.full_name && - results->at(results->size() - 1).status == - TestResult::TEST_CRASH) { + results->back().full_name == result.full_name && + results->back().status == TestResult::TEST_CRASH) { // Erase the fail-safe "crashed" result - now we know the test did // not crash. results->pop_back(); @@ -141,7 +140,7 @@ return false; DCHECK(!results->empty()); - results->at(results->size() - 1).status = TestResult::TEST_FAILURE; + results->back().status = TestResult::TEST_FAILURE; state = STATE_FAILURE; } else if (node_name == "testcase" && xml_reader.IsClosingElement()) {
diff --git a/base/test/test_reg_util_win.cc b/base/test/test_reg_util_win.cc index d6706f9..f58b280b 100644 --- a/base/test/test_reg_util_win.cc +++ b/base/test/test_reg_util_win.cc
@@ -99,9 +99,16 @@ RegistryOverrideManager::~RegistryOverrideManager() {} void RegistryOverrideManager::OverrideRegistry(HKEY override) { + OverrideRegistry(override, nullptr); +} + +void RegistryOverrideManager::OverrideRegistry(HKEY override, + base::string16* override_path) { base::string16 key_path = GenerateTempKeyPath(test_key_root_, timestamp_); overrides_.push_back( base::WrapUnique(new ScopedRegistryKeyOverride(override, key_path))); + if (override_path) + override_path->assign(key_path); } base::string16 GenerateTempKeyPath() {
diff --git a/base/test/test_reg_util_win.h b/base/test/test_reg_util_win.h index 587e28f..33bcd21 100644 --- a/base/test/test_reg_util_win.h +++ b/base/test/test_reg_util_win.h
@@ -38,7 +38,9 @@ // Override the given registry hive using a randomly generated temporary key. // Multiple overrides to the same hive are not supported and lead to undefined // behavior. + // Optional return of the registry override path. void OverrideRegistry(HKEY override); + void OverrideRegistry(HKEY override, base::string16* override_path); private: friend class RegistryOverrideManagerTest;
diff --git a/base/third_party/symbolize/README.chromium b/base/third_party/symbolize/README.chromium index 64a62472..a2185fd 100644 --- a/base/third_party/symbolize/README.chromium +++ b/base/third_party/symbolize/README.chromium
@@ -11,6 +11,9 @@ - symbolize.cc - symbolize.h +Cherry picked upstream change https://github.com/google/glog/pull/115 to +fix a symbolization issue when using lld. + The following files are minimal stubs created for use in Chromium: - config.h
diff --git a/base/third_party/symbolize/symbolize.cc b/base/third_party/symbolize/symbolize.cc index db82b04..d767895 100644 --- a/base/third_party/symbolize/symbolize.cc +++ b/base/third_party/symbolize/symbolize.cc
@@ -327,7 +327,7 @@ // false. static bool GetSymbolFromObjectFile(const int fd, uint64_t pc, char *out, int out_size, - uint64_t map_start_address) { + uint64_t map_base_address) { // Read the ELF header. ElfW(Ehdr) elf_header; if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) { @@ -336,7 +336,28 @@ uint64_t symbol_offset = 0; if (elf_header.e_type == ET_DYN) { // DSO needs offset adjustment. - symbol_offset = map_start_address; + ElfW(Phdr) phdr; + // We need to find the PT_LOAD segment corresponding to the read-execute + // file mapping in order to correctly perform the offset adjustment. + for (unsigned i = 0; i != elf_header.e_phnum; ++i) { + if (!ReadFromOffsetExact(fd, &phdr, sizeof(phdr), + elf_header.e_phoff + i * sizeof(phdr))) + return false; + if (phdr.p_type == PT_LOAD && + (phdr.p_flags & (PF_R | PF_X)) == (PF_R | PF_X)) { + // Find the mapped address corresponding to virtual address zero. We do + // this by first adding p_offset. This gives us the mapped address of + // the start of the segment, or in other words the mapped address + // corresponding to the virtual address of the segment. (Note that this + // is distinct from the start address, as p_offset is not guaranteed to + // be page aligned.) We then subtract p_vaddr, which takes us to virtual + // address zero. + symbol_offset = map_base_address + phdr.p_offset - phdr.p_vaddr; + break; + } + } + if (symbol_offset == 0) + return false; } ElfW(Shdr) symtab, strtab; @@ -783,7 +804,7 @@ } } if (!GetSymbolFromObjectFile(wrapped_object_fd.get(), pc0, - out, out_size, start_address)) { + out, out_size, base_address)) { return false; }
diff --git a/base/tools_sanity_unittest.cc b/base/tools_sanity_unittest.cc index 8d13837..9075d16 100644 --- a/base/tools_sanity_unittest.cc +++ b/base/tools_sanity_unittest.cc
@@ -343,6 +343,8 @@ } #if defined(CFI_ENFORCEMENT) +// TODO(krasin): remove CFI_CAST_CHECK, see https://crbug.com/626794. +#if defined(CFI_CAST_CHECK) TEST(ToolsSanityTest, BadCast) { class A { virtual void f() {} @@ -355,6 +357,32 @@ A a; EXPECT_DEATH((void)(B*)&a, "ILL_ILLOPN"); } -#endif +#endif // CFI_CAST_CHECK + +class A { + public: + A(): n_(0) {} + virtual void f() { n_++; } + protected: + int n_; +}; + +class B: public A { + public: + void f() override { n_--; } +}; + +NOINLINE void KillVptrAndCall(A *obj) { + *reinterpret_cast<void **>(obj) = 0; + obj->f(); +} + +TEST(ToolsSanityTest, BadVirtualCall) { + A a; + B b; + EXPECT_DEATH({ KillVptrAndCall(&a); KillVptrAndCall(&b); }, "ILL_ILLOPN"); +} + +#endif // CFI_ENFORCEMENT } // namespace base
diff --git a/base/trace_event/trace_config.cc b/base/trace_event/trace_config.cc index ebdddd3..b343ea00 100644 --- a/base/trace_event/trace_config.cc +++ b/base/trace_event/trace_config.cc
@@ -69,6 +69,7 @@ explicit ConvertableTraceConfigToTraceFormat(const TraceConfig& trace_config) : trace_config_(trace_config) {} ~ConvertableTraceConfigToTraceFormat() override {} + void AppendAsTraceFormat(std::string* out) const override { out->append(trace_config_.ToString()); } @@ -88,9 +89,8 @@ } // namespace - -TraceConfig::MemoryDumpConfig::HeapProfiler::HeapProfiler() : - breakdown_threshold_bytes(kDefaultBreakdownThresholdBytes) {}; +TraceConfig::MemoryDumpConfig::HeapProfiler::HeapProfiler() + : breakdown_threshold_bytes(kDefaultBreakdownThresholdBytes) {} void TraceConfig::MemoryDumpConfig::HeapProfiler::Clear() { breakdown_threshold_bytes = kDefaultBreakdownThresholdBytes; @@ -102,12 +102,12 @@ memory_dump_config_ = memory_dump_config; } -TraceConfig::MemoryDumpConfig::MemoryDumpConfig() {}; +TraceConfig::MemoryDumpConfig::MemoryDumpConfig() {} TraceConfig::MemoryDumpConfig::MemoryDumpConfig( const MemoryDumpConfig& other) = default; -TraceConfig::MemoryDumpConfig::~MemoryDumpConfig() {}; +TraceConfig::MemoryDumpConfig::~MemoryDumpConfig() {} void TraceConfig::MemoryDumpConfig::Clear() { allowed_dump_modes.clear(); @@ -119,12 +119,12 @@ InitializeDefault(); } -TraceConfig::TraceConfig(const std::string& category_filter_string, - const std::string& trace_options_string) { +TraceConfig::TraceConfig(StringPiece category_filter_string, + StringPiece trace_options_string) { InitializeFromStrings(category_filter_string, trace_options_string); } -TraceConfig::TraceConfig(const std::string& category_filter_string, +TraceConfig::TraceConfig(StringPiece category_filter_string, TraceRecordMode record_mode) { std::string trace_options_string; switch (record_mode) { @@ -150,7 +150,7 @@ InitializeFromConfigDict(config); } -TraceConfig::TraceConfig(const std::string& config_string) { +TraceConfig::TraceConfig(StringPiece config_string) { if (!config_string.empty()) InitializeFromConfigString(config_string); else @@ -192,12 +192,9 @@ } std::string TraceConfig::ToString() const { - base::DictionaryValue dict; - ToDict(dict); - + std::unique_ptr<DictionaryValue> dict = ToDict(); std::string json; - base::JSONWriter::Write(dict, &json); - + JSONWriter::Write(*dict, &json); return json; } @@ -222,20 +219,18 @@ bool had_enabled_by_default = false; DCHECK(category_group_name); - CStringTokenizer category_group_tokens( - category_group_name, category_group_name + strlen(category_group_name), - ","); + std::string category_group_name_str = category_group_name; + StringTokenizer category_group_tokens(category_group_name_str, ","); while (category_group_tokens.GetNext()) { std::string category_group_token = category_group_tokens.token(); // Don't allow empty tokens, nor tokens with leading or trailing space. DCHECK(!TraceConfig::IsEmptyOrContainsLeadingOrTrailingWhitespace( category_group_token)) << "Disallowed category string"; - if (IsCategoryEnabled(category_group_token.c_str())) { + if (IsCategoryEnabled(category_group_token.c_str())) return true; - } - if (!base::MatchPattern(category_group_token.c_str(), - TRACE_DISABLED_BY_DEFAULT("*"))) + + if (!MatchPattern(category_group_token, TRACE_DISABLED_BY_DEFAULT("*"))) had_enabled_by_default = true; } // Do a second pass to check for explicitly disabled categories @@ -244,10 +239,8 @@ bool category_group_disabled = false; while (category_group_tokens.GetNext()) { std::string category_group_token = category_group_tokens.token(); - for (StringList::const_iterator ci = excluded_categories_.begin(); - ci != excluded_categories_.end(); - ++ci) { - if (base::MatchPattern(category_group_token.c_str(), ci->c_str())) { + for (const std::string& category : excluded_categories_) { + if (MatchPattern(category_group_token, category)) { // Current token of category_group_name is present in excluded_list. // Flag the exclusion and proceed further to check if any of the // remaining categories of category_group_name is not present in the @@ -259,8 +252,7 @@ // excluded_ list. So, if it's not a disabled-by-default category, // it has to be included_ list. Enable the category_group_name // for recording. - if (!base::MatchPattern(category_group_token.c_str(), - TRACE_DISABLED_BY_DEFAULT("*"))) { + if (!MatchPattern(category_group_token, TRACE_DISABLED_BY_DEFAULT("*"))) { category_group_disabled = false; } } @@ -273,8 +265,8 @@ // If the category group is not excluded, and there are no included patterns // we consider this category group enabled, as long as it had categories // other than disabled-by-default. - return !category_group_disabled && - included_categories_.empty() && had_enabled_by_default; + return !category_group_disabled && had_enabled_by_default && + included_categories_.empty(); } void TraceConfig::Merge(const TraceConfig& config) { @@ -346,25 +338,13 @@ } } - bool enable_sampling; - if (!dict.GetBoolean(kEnableSamplingParam, &enable_sampling)) - enable_sampling_ = false; - else - enable_sampling_ = enable_sampling; + bool val; + enable_sampling_ = dict.GetBoolean(kEnableSamplingParam, &val) ? val : false; + enable_systrace_ = dict.GetBoolean(kEnableSystraceParam, &val) ? val : false; + enable_argument_filter_ = + dict.GetBoolean(kEnableArgumentFilterParam, &val) ? val : false; - bool enable_systrace; - if (!dict.GetBoolean(kEnableSystraceParam, &enable_systrace)) - enable_systrace_ = false; - else - enable_systrace_ = enable_systrace; - - bool enable_argument_filter; - if (!dict.GetBoolean(kEnableArgumentFilterParam, &enable_argument_filter)) - enable_argument_filter_ = false; - else - enable_argument_filter_ = enable_argument_filter; - - const base::ListValue* category_list = nullptr; + const ListValue* category_list = nullptr; if (dict.GetList(kIncludedCategoriesParam, &category_list)) SetCategoriesFromIncludedList(*category_list); if (dict.GetList(kExcludedCategoriesParam, &category_list)) @@ -375,7 +355,7 @@ if (IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) { // If dump triggers not set, the client is using the legacy with just // category enabled. So, use the default periodic dump config. - const base::DictionaryValue* memory_dump_config = nullptr; + const DictionaryValue* memory_dump_config = nullptr; if (dict.GetDictionary(kMemoryDumpConfigParam, &memory_dump_config)) SetMemoryDumpConfigFromConfigDict(*memory_dump_config); else @@ -383,51 +363,39 @@ } } -void TraceConfig::InitializeFromConfigString(const std::string& config_string) { - std::unique_ptr<Value> value(JSONReader::Read(config_string)); - if (!value) - return InitializeDefault(); - - const DictionaryValue* dict = nullptr; - bool is_dict = value->GetAsDictionary(&dict); - - if (!is_dict) - return InitializeDefault(); - - DCHECK(dict); - InitializeFromConfigDict(*dict); +void TraceConfig::InitializeFromConfigString(StringPiece config_string) { + auto dict = DictionaryValue::From(JSONReader::Read(config_string)); + if (dict) + InitializeFromConfigDict(*dict); + else + InitializeDefault(); } -void TraceConfig::InitializeFromStrings( - const std::string& category_filter_string, - const std::string& trace_options_string) { +void TraceConfig::InitializeFromStrings(StringPiece category_filter_string, + StringPiece trace_options_string) { if (!category_filter_string.empty()) { - std::vector<std::string> split = base::SplitString( - category_filter_string, ",", base::TRIM_WHITESPACE, - base::SPLIT_WANT_ALL); - std::vector<std::string>::iterator iter; - for (iter = split.begin(); iter != split.end(); ++iter) { - std::string category = *iter; + std::vector<std::string> split = SplitString( + category_filter_string, ",", TRIM_WHITESPACE, SPLIT_WANT_ALL); + for (const std::string& category : split) { // Ignore empty categories. if (category.empty()) continue; // Synthetic delays are of the form 'DELAY(delay;option;option;...)'. - if (base::StartsWith(category, kSyntheticDelayCategoryFilterPrefix, - base::CompareCase::SENSITIVE) && - category.at(category.size() - 1) == ')') { - category = category.substr( + if (StartsWith(category, kSyntheticDelayCategoryFilterPrefix, + CompareCase::SENSITIVE) && + category.back() == ')') { + std::string synthetic_category = category.substr( strlen(kSyntheticDelayCategoryFilterPrefix), category.size() - strlen(kSyntheticDelayCategoryFilterPrefix) - 1); - size_t name_length = category.find(';'); + size_t name_length = synthetic_category.find(';'); if (name_length != std::string::npos && name_length > 0 && - name_length != category.size() - 1) { - synthetic_delays_.push_back(category); + name_length != synthetic_category.size() - 1) { + synthetic_delays_.push_back(synthetic_category); } - } else if (category.at(0) == '-') { + } else if (category.front() == '-') { // Excluded categories start with '-'. // Remove '-' from category string. - category = category.substr(1); - excluded_categories_.push_back(category); + excluded_categories_.push_back(category.substr(1)); } else if (category.compare(0, strlen(TRACE_DISABLED_BY_DEFAULT("")), TRACE_DISABLED_BY_DEFAULT("")) == 0) { disabled_categories_.push_back(category); @@ -441,24 +409,23 @@ enable_sampling_ = false; enable_systrace_ = false; enable_argument_filter_ = false; - if(!trace_options_string.empty()) { - std::vector<std::string> split = base::SplitString( - trace_options_string, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - std::vector<std::string>::iterator iter; - for (iter = split.begin(); iter != split.end(); ++iter) { - if (*iter == kRecordUntilFull) { + if (!trace_options_string.empty()) { + std::vector<std::string> split = + SplitString(trace_options_string, ",", TRIM_WHITESPACE, SPLIT_WANT_ALL); + for (const std::string& token : split) { + if (token == kRecordUntilFull) { record_mode_ = RECORD_UNTIL_FULL; - } else if (*iter == kRecordContinuously) { + } else if (token == kRecordContinuously) { record_mode_ = RECORD_CONTINUOUSLY; - } else if (*iter == kTraceToConsole) { + } else if (token == kTraceToConsole) { record_mode_ = ECHO_TO_CONSOLE; - } else if (*iter == kRecordAsMuchAsPossible) { + } else if (token == kRecordAsMuchAsPossible) { record_mode_ = RECORD_AS_MUCH_AS_POSSIBLE; - } else if (*iter == kEnableSampling) { + } else if (token == kEnableSampling) { enable_sampling_ = true; - } else if (*iter == kEnableSystrace) { + } else if (token == kEnableSystrace) { enable_systrace_ = true; - } else if (*iter == kEnableArgumentFilter) { + } else if (token == kEnableArgumentFilter) { enable_argument_filter_ = true; } } @@ -470,7 +437,7 @@ } void TraceConfig::SetCategoriesFromIncludedList( - const base::ListValue& included_list) { + const ListValue& included_list) { included_categories_.clear(); for (size_t i = 0; i < included_list.GetSize(); ++i) { std::string category; @@ -486,7 +453,7 @@ } void TraceConfig::SetCategoriesFromExcludedList( - const base::ListValue& excluded_list) { + const ListValue& excluded_list) { excluded_categories_.clear(); for (size_t i = 0; i < excluded_list.GetSize(); ++i) { std::string category; @@ -495,7 +462,7 @@ } } -void TraceConfig::SetSyntheticDelaysFromList(const base::ListValue& list) { +void TraceConfig::SetSyntheticDelaysFromList(const ListValue& list) { synthetic_delays_.clear(); for (size_t i = 0; i < list.GetSize(); ++i) { std::string delay; @@ -510,27 +477,23 @@ } } -void TraceConfig::AddCategoryToDict(base::DictionaryValue& dict, +void TraceConfig::AddCategoryToDict(DictionaryValue* dict, const char* param, const StringList& categories) const { if (categories.empty()) return; - std::unique_ptr<base::ListValue> list(new base::ListValue()); - for (StringList::const_iterator ci = categories.begin(); - ci != categories.end(); - ++ci) { - list->AppendString(*ci); - } - - dict.Set(param, std::move(list)); + auto list = MakeUnique<ListValue>(); + for (const std::string& category : categories) + list->AppendString(category); + dict->Set(param, std::move(list)); } void TraceConfig::SetMemoryDumpConfigFromConfigDict( - const base::DictionaryValue& memory_dump_config) { + const DictionaryValue& memory_dump_config) { // Set allowed dump modes. memory_dump_config_.allowed_dump_modes.clear(); - const base::ListValue* allowed_modes_list; + const ListValue* allowed_modes_list; if (memory_dump_config.GetList(kAllowedDumpModesParam, &allowed_modes_list)) { for (size_t i = 0; i < allowed_modes_list->GetSize(); ++i) { std::string level_of_detail_str; @@ -545,21 +508,20 @@ // Set triggers memory_dump_config_.triggers.clear(); - const base::ListValue* trigger_list = nullptr; + const ListValue* trigger_list = nullptr; if (memory_dump_config.GetList(kTriggersParam, &trigger_list) && trigger_list->GetSize() > 0) { for (size_t i = 0; i < trigger_list->GetSize(); ++i) { - const base::DictionaryValue* trigger = nullptr; + const DictionaryValue* trigger = nullptr; if (!trigger_list->GetDictionary(i, &trigger)) continue; - MemoryDumpConfig::Trigger dump_config; int interval = 0; - - if (!trigger->GetInteger(kPeriodicIntervalParam, &interval)) { + if (!trigger->GetInteger(kPeriodicIntervalParam, &interval)) continue; - } + DCHECK_GT(interval, 0); + MemoryDumpConfig::Trigger dump_config; dump_config.periodic_interval_ms = static_cast<uint32_t>(interval); std::string level_of_detail_str; trigger->GetString(kModeParam, &level_of_detail_str); @@ -570,7 +532,7 @@ } // Set heap profiler options - const base::DictionaryValue* heap_profiler_options = nullptr; + const DictionaryValue* heap_profiler_options = nullptr; if (memory_dump_config.GetDictionary(kHeapProfilerOptions, &heap_profiler_options)) { int min_size_bytes = 0; @@ -593,64 +555,48 @@ memory_dump_config_.allowed_dump_modes = GetDefaultAllowedMemoryDumpModes(); } -void TraceConfig::ToDict(base::DictionaryValue& dict) const { +std::unique_ptr<DictionaryValue> TraceConfig::ToDict() const { + auto dict = MakeUnique<DictionaryValue>(); switch (record_mode_) { case RECORD_UNTIL_FULL: - dict.SetString(kRecordModeParam, kRecordUntilFull); + dict->SetString(kRecordModeParam, kRecordUntilFull); break; case RECORD_CONTINUOUSLY: - dict.SetString(kRecordModeParam, kRecordContinuously); + dict->SetString(kRecordModeParam, kRecordContinuously); break; case RECORD_AS_MUCH_AS_POSSIBLE: - dict.SetString(kRecordModeParam, kRecordAsMuchAsPossible); + dict->SetString(kRecordModeParam, kRecordAsMuchAsPossible); break; case ECHO_TO_CONSOLE: - dict.SetString(kRecordModeParam, kTraceToConsole); + dict->SetString(kRecordModeParam, kTraceToConsole); break; default: NOTREACHED(); } - if (enable_sampling_) - dict.SetBoolean(kEnableSamplingParam, true); - else - dict.SetBoolean(kEnableSamplingParam, false); - - if (enable_systrace_) - dict.SetBoolean(kEnableSystraceParam, true); - else - dict.SetBoolean(kEnableSystraceParam, false); - - if (enable_argument_filter_) - dict.SetBoolean(kEnableArgumentFilterParam, true); - else - dict.SetBoolean(kEnableArgumentFilterParam, false); + dict->SetBoolean(kEnableSamplingParam, enable_sampling_); + dict->SetBoolean(kEnableSystraceParam, enable_systrace_); + dict->SetBoolean(kEnableArgumentFilterParam, enable_argument_filter_); StringList categories(included_categories_); categories.insert(categories.end(), disabled_categories_.begin(), disabled_categories_.end()); - AddCategoryToDict(dict, kIncludedCategoriesParam, categories); - AddCategoryToDict(dict, kExcludedCategoriesParam, excluded_categories_); - AddCategoryToDict(dict, kSyntheticDelaysParam, synthetic_delays_); + AddCategoryToDict(dict.get(), kIncludedCategoriesParam, categories); + AddCategoryToDict(dict.get(), kExcludedCategoriesParam, excluded_categories_); + AddCategoryToDict(dict.get(), kSyntheticDelaysParam, synthetic_delays_); if (IsCategoryEnabled(MemoryDumpManager::kTraceCategory)) { - std::unique_ptr<base::DictionaryValue> memory_dump_config( - new base::DictionaryValue()); - std::unique_ptr<base::ListValue> allowed_modes_list(new base::ListValue()); - for (MemoryDumpLevelOfDetail dump_mode : - memory_dump_config_.allowed_dump_modes) { - allowed_modes_list->AppendString( - MemoryDumpLevelOfDetailToString(dump_mode)); - } - memory_dump_config->Set(kAllowedDumpModesParam, - std::move(allowed_modes_list)); + auto allowed_modes = MakeUnique<ListValue>(); + for (auto dump_mode : memory_dump_config_.allowed_dump_modes) + allowed_modes->AppendString(MemoryDumpLevelOfDetailToString(dump_mode)); - std::unique_ptr<base::ListValue> triggers_list(new base::ListValue()); - for (const MemoryDumpConfig::Trigger& config - : memory_dump_config_.triggers) { - std::unique_ptr<base::DictionaryValue> trigger_dict( - new base::DictionaryValue()); + auto memory_dump_config = MakeUnique<DictionaryValue>(); + memory_dump_config->Set(kAllowedDumpModesParam, std::move(allowed_modes)); + + auto triggers_list = MakeUnique<ListValue>(); + for (const auto& config : memory_dump_config_.triggers) { + auto trigger_dict = MakeUnique<DictionaryValue>(); trigger_dict->SetInteger(kPeriodicIntervalParam, static_cast<int>(config.periodic_interval_ms)); trigger_dict->SetString( @@ -664,16 +610,15 @@ if (memory_dump_config_.heap_profiler_options.breakdown_threshold_bytes != MemoryDumpConfig::HeapProfiler::kDefaultBreakdownThresholdBytes) { - std::unique_ptr<base::DictionaryValue> heap_profiler_options( - new base::DictionaryValue()); - heap_profiler_options->SetInteger( + auto options = MakeUnique<DictionaryValue>(); + options->SetInteger( kBreakdownThresholdBytes, memory_dump_config_.heap_profiler_options.breakdown_threshold_bytes); - memory_dump_config->Set(kHeapProfilerOptions, - std::move(heap_profiler_options)); + memory_dump_config->Set(kHeapProfilerOptions, std::move(options)); } - dict.Set(kMemoryDumpConfigParam, std::move(memory_dump_config)); + dict->Set(kMemoryDumpConfigParam, std::move(memory_dump_config)); } + return dict; } std::string TraceConfig::ToTraceOptionsString() const { @@ -708,11 +653,10 @@ bool included) const { bool prepend_comma = !out->empty(); int token_cnt = 0; - for (StringList::const_iterator ci = values.begin(); - ci != values.end(); ++ci) { + for (const std::string& category : values) { if (token_cnt > 0 || prepend_comma) StringAppendF(out, ","); - StringAppendF(out, "%s%s", (included ? "" : "-"), ci->c_str()); + StringAppendF(out, "%s%s", (included ? "" : "-"), category.c_str()); ++token_cnt; } } @@ -721,35 +665,28 @@ std::string* out) const { bool prepend_comma = !out->empty(); int token_cnt = 0; - for (StringList::const_iterator ci = delays.begin(); - ci != delays.end(); ++ci) { + for (const std::string& category : delays) { if (token_cnt > 0 || prepend_comma) StringAppendF(out, ","); StringAppendF(out, "%s%s)", kSyntheticDelayCategoryFilterPrefix, - ci->c_str()); + category.c_str()); ++token_cnt; } } bool TraceConfig::IsCategoryEnabled(const char* category_name) const { - StringList::const_iterator ci; - // Check the disabled- filters and the disabled-* wildcard first so that a // "*" filter does not include the disabled. - for (ci = disabled_categories_.begin(); - ci != disabled_categories_.end(); - ++ci) { - if (base::MatchPattern(category_name, ci->c_str())) + for (const std::string& category : disabled_categories_) { + if (MatchPattern(category_name, category)) return true; } - if (base::MatchPattern(category_name, TRACE_DISABLED_BY_DEFAULT("*"))) + if (MatchPattern(category_name, TRACE_DISABLED_BY_DEFAULT("*"))) return false; - for (ci = included_categories_.begin(); - ci != included_categories_.end(); - ++ci) { - if (base::MatchPattern(category_name, ci->c_str())) + for (const std::string& category : included_categories_) { + if (MatchPattern(category_name, category)) return true; } @@ -757,10 +694,8 @@ } bool TraceConfig::IsEmptyOrContainsLeadingOrTrailingWhitespace( - const std::string& str) { - return str.empty() || - str.at(0) == ' ' || - str.at(str.length() - 1) == ' '; + StringPiece str) { + return str.empty() || str.front() == ' ' || str.back() == ' '; } bool TraceConfig::HasIncludedPatterns() const {
diff --git a/base/trace_event/trace_config.h b/base/trace_event/trace_config.h index c3a940e2..91d6f1f3 100644 --- a/base/trace_event/trace_config.h +++ b/base/trace_event/trace_config.h
@@ -13,6 +13,7 @@ #include "base/base_export.h" #include "base/gtest_prod_util.h" +#include "base/strings/string_piece.h" #include "base/trace_event/memory_dump_request_args.h" #include "base/values.h" @@ -39,7 +40,7 @@ class BASE_EXPORT TraceConfig { public: - typedef std::vector<std::string> StringList; + using StringList = std::vector<std::string>; // Specifies the memory dump config for tracing. // Used only when "memory-infra" category is enabled. @@ -124,11 +125,10 @@ // Example: TraceConfig("DELAY(gpu.PresentingFrame;16;alternating)", ""); // would make swap buffers take at least 16 ms every other time it // is called; and use default options. - TraceConfig(const std::string& category_filter_string, - const std::string& trace_options_string); + TraceConfig(StringPiece category_filter_string, + StringPiece trace_options_string); - TraceConfig(const std::string& category_filter_string, - TraceRecordMode record_mode); + TraceConfig(StringPiece category_filter_string, TraceRecordMode record_mode); // Create TraceConfig object from the trace config string. // @@ -158,7 +158,7 @@ // // Note: memory_dump_config can be specified only if // disabled-by-default-memory-infra category is enabled. - explicit TraceConfig(const std::string& config_string); + explicit TraceConfig(StringPiece config_string); // Functionally identical to the above, but takes a parsed dictionary as input // instead of its JSON serialization. @@ -233,25 +233,24 @@ void InitializeFromConfigDict(const DictionaryValue& dict); // Initialize from a config string. - void InitializeFromConfigString(const std::string& config_string); + void InitializeFromConfigString(StringPiece config_string); // Initialize from category filter and trace options strings - void InitializeFromStrings(const std::string& category_filter_string, - const std::string& trace_options_string); + void InitializeFromStrings(StringPiece category_filter_string, + StringPiece trace_options_string); - void SetCategoriesFromIncludedList(const base::ListValue& included_list); - void SetCategoriesFromExcludedList(const base::ListValue& excluded_list); - void SetSyntheticDelaysFromList(const base::ListValue& list); - void AddCategoryToDict(base::DictionaryValue& dict, + void SetCategoriesFromIncludedList(const ListValue& included_list); + void SetCategoriesFromExcludedList(const ListValue& excluded_list); + void SetSyntheticDelaysFromList(const ListValue& list); + void AddCategoryToDict(DictionaryValue* dict, const char* param, const StringList& categories) const; void SetMemoryDumpConfigFromConfigDict( - const base::DictionaryValue& memory_dump_config); + const DictionaryValue& memory_dump_config); void SetDefaultMemoryDumpConfig(); - // Convert TraceConfig to the dict representation of the TraceConfig. - void ToDict(base::DictionaryValue& dict) const; + std::unique_ptr<DictionaryValue> ToDict() const; std::string ToTraceOptionsString() const; @@ -267,8 +266,7 @@ // category is enabled from the tracing runtime's perspective. bool IsCategoryEnabled(const char* category_name) const; - static bool IsEmptyOrContainsLeadingOrTrailingWhitespace( - const std::string& str); + static bool IsEmptyOrContainsLeadingOrTrailingWhitespace(StringPiece str); bool HasIncludedPatterns() const;
diff --git a/blimp/client/BUILD.gn b/blimp/client/BUILD.gn index 1c5725bb..50fcb16 100644 --- a/blimp/client/BUILD.gn +++ b/blimp/client/BUILD.gn
@@ -423,7 +423,7 @@ ":blimp_java_resources", "//base:base_java", "//blimp/client/core:core_java", - "//blimp/client/core/public:public_java", + "//blimp/client/public:public_java", # TODO(dtrainor): Remove the ui_java target once no more Android Toast # notifications are used. @@ -462,7 +462,7 @@ "//base:base_java", "//base:base_java_test_support", "//blimp/client/core:core_java", - "//blimp/client/core/public:public_java", + "//blimp/client/public:public_java", google_play_services_library, ]
diff --git a/blimp/client/app/android/java/res/mipmap-hdpi/app_icon.png b/blimp/client/app/android/java/res/mipmap-hdpi/app_icon.png index 8b3efd3..e1924bf 100644 --- a/blimp/client/app/android/java/res/mipmap-hdpi/app_icon.png +++ b/blimp/client/app/android/java/res/mipmap-hdpi/app_icon.png Binary files differ
diff --git a/blimp/client/app/android/java/res/mipmap-mdpi/app_icon.png b/blimp/client/app/android/java/res/mipmap-mdpi/app_icon.png index b248545..32d78b5 100644 --- a/blimp/client/app/android/java/res/mipmap-mdpi/app_icon.png +++ b/blimp/client/app/android/java/res/mipmap-mdpi/app_icon.png Binary files differ
diff --git a/blimp/client/app/android/java/res/mipmap-xhdpi/app_icon.png b/blimp/client/app/android/java/res/mipmap-xhdpi/app_icon.png index 8040d0b4..91e027d 100644 --- a/blimp/client/app/android/java/res/mipmap-xhdpi/app_icon.png +++ b/blimp/client/app/android/java/res/mipmap-xhdpi/app_icon.png Binary files differ
diff --git a/blimp/client/app/android/java/res/mipmap-xxhdpi/app_icon.png b/blimp/client/app/android/java/res/mipmap-xxhdpi/app_icon.png index 3c723846..7aba520 100644 --- a/blimp/client/app/android/java/res/mipmap-xxhdpi/app_icon.png +++ b/blimp/client/app/android/java/res/mipmap-xxhdpi/app_icon.png Binary files differ
diff --git a/blimp/client/app/android/java/res/mipmap-xxxhdpi/app_icon.png b/blimp/client/app/android/java/res/mipmap-xxxhdpi/app_icon.png index 839b0a7..f8b22ff2 100644 --- a/blimp/client/app/android/java/res/mipmap-xxxhdpi/app_icon.png +++ b/blimp/client/app/android/java/res/mipmap-xxxhdpi/app_icon.png Binary files differ
diff --git a/blimp/client/app/android/javatests/src/org/chromium/blimp/core/BlimpContentsTest.java b/blimp/client/app/android/javatests/src/org/chromium/blimp/core/BlimpContentsTest.java index 0bd541b..f33981e 100644 --- a/blimp/client/app/android/javatests/src/org/chromium/blimp/core/BlimpContentsTest.java +++ b/blimp/client/app/android/javatests/src/org/chromium/blimp/core/BlimpContentsTest.java
@@ -8,9 +8,9 @@ import org.chromium.base.ThreadUtils; import org.chromium.blimp.BlimpNativeInstrumentationTestCase; -import org.chromium.blimp.core_public.BlimpContents; -import org.chromium.blimp.core_public.BlimpNavigationController; -import org.chromium.blimp.core_public.EmptyBlimpContentsObserver; +import org.chromium.blimp_public.BlimpContents; +import org.chromium.blimp_public.BlimpNavigationController; +import org.chromium.blimp_public.EmptyBlimpContentsObserver; import java.util.concurrent.atomic.AtomicReference;
diff --git a/blimp/client/core/BUILD.gn b/blimp/client/core/BUILD.gn index 54faf01..b98e4eb2 100644 --- a/blimp/client/core/BUILD.gn +++ b/blimp/client/core/BUILD.gn
@@ -20,7 +20,7 @@ deps = [ "//base", - "//blimp/client/core/public", + "//blimp/client/public", "//url", ] @@ -51,7 +51,7 @@ deps = [ "//base", "//blimp/client/core", - "//blimp/client/core/public", + "//blimp/client/public", "//testing/gtest", "//url", ] @@ -70,7 +70,7 @@ deps = [ "//base:base_java", - "//blimp/client/core/public:public_java", + "//blimp/client/public:public_java", ] }
diff --git a/blimp/client/core/android/blimp_contents_observer_proxy.h b/blimp/client/core/android/blimp_contents_observer_proxy.h index f68a01ff..06d2560 100644 --- a/blimp/client/core/android/blimp_contents_observer_proxy.h +++ b/blimp/client/core/android/blimp_contents_observer_proxy.h
@@ -10,7 +10,7 @@ #include "base/macros.h" #include "blimp/client/core/android/blimp_contents_impl_android.h" #include "blimp/client/core/android/blimp_navigation_controller_impl_android.h" -#include "blimp/client/core/public/blimp_contents_observer.h" +#include "blimp/client/public/blimp_contents_observer.h" namespace blimp { namespace client {
diff --git a/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsFactory.java b/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsFactory.java index df513402..07db1aed 100644 --- a/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsFactory.java +++ b/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsFactory.java
@@ -5,7 +5,7 @@ package org.chromium.blimp.core; import org.chromium.base.annotations.JNINamespace; -import org.chromium.blimp.core_public.BlimpContents; +import org.chromium.blimp_public.BlimpContents; /** * This factory creates BlimpContents objects and the associated native counterpart.
diff --git a/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsImpl.java b/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsImpl.java index 67327081..df2b298 100644 --- a/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsImpl.java +++ b/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsImpl.java
@@ -6,9 +6,9 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; -import org.chromium.blimp.core_public.BlimpContents; -import org.chromium.blimp.core_public.BlimpContentsObserver; -import org.chromium.blimp.core_public.BlimpNavigationController; +import org.chromium.blimp_public.BlimpContents; +import org.chromium.blimp_public.BlimpContentsObserver; +import org.chromium.blimp_public.BlimpNavigationController; /** * BlimpContentsImpl is a Java wrapper to allow communicating with the native BlimpContentsImpl
diff --git a/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsObserverProxy.java b/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsObserverProxy.java index 657c7bb..b000c080 100644 --- a/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsObserverProxy.java +++ b/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpContentsObserverProxy.java
@@ -7,7 +7,7 @@ import org.chromium.base.ObserverList; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; -import org.chromium.blimp.core_public.BlimpContentsObserver; +import org.chromium.blimp_public.BlimpContentsObserver; /** * Serves as a compound observer proxy for dispatching BlimpContentsObserver callbacks,
diff --git a/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpNavigationControllerImpl.java b/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpNavigationControllerImpl.java index a907ed95..7dc5264 100644 --- a/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpNavigationControllerImpl.java +++ b/blimp/client/core/android/java/src/org/chromium/blimp/core/BlimpNavigationControllerImpl.java
@@ -6,7 +6,7 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; -import org.chromium.blimp.core_public.BlimpNavigationController; +import org.chromium.blimp_public.BlimpNavigationController; /** * BlimpNavigationControllerImpl is a Java wrapper to allow communicating with the native
diff --git a/blimp/client/core/blimp_contents_impl.cc b/blimp/client/core/blimp_contents_impl.cc index d3c1635..3e93e924 100644 --- a/blimp/client/core/blimp_contents_impl.cc +++ b/blimp/client/core/blimp_contents_impl.cc
@@ -6,7 +6,7 @@ #include "base/memory/ptr_util.h" #include "base/supports_user_data.h" -#include "blimp/client/core/public/blimp_contents_observer.h" +#include "blimp/client/public/blimp_contents_observer.h" #if defined(OS_ANDROID) #include "blimp/client/core/android/blimp_contents_impl_android.h"
diff --git a/blimp/client/core/blimp_contents_impl.h b/blimp/client/core/blimp_contents_impl.h index 077796e..bbe1dd9 100644 --- a/blimp/client/core/blimp_contents_impl.h +++ b/blimp/client/core/blimp_contents_impl.h
@@ -10,7 +10,7 @@ #include "base/supports_user_data.h" #include "blimp/client/core/blimp_navigation_controller_delegate.h" #include "blimp/client/core/blimp_navigation_controller_impl.h" -#include "blimp/client/core/public/blimp_contents.h" +#include "blimp/client/public/blimp_contents.h" #include "url/gurl.h" #if defined(OS_ANDROID)
diff --git a/blimp/client/core/blimp_contents_impl_unittest.cc b/blimp/client/core/blimp_contents_impl_unittest.cc index 3d4a7c0..0c9f846 100644 --- a/blimp/client/core/blimp_contents_impl_unittest.cc +++ b/blimp/client/core/blimp_contents_impl_unittest.cc
@@ -6,7 +6,7 @@ #include "base/message_loop/message_loop.h" #include "blimp/client/core/blimp_contents_impl.h" -#include "blimp/client/core/public/blimp_contents_observer.h" +#include "blimp/client/public/blimp_contents_observer.h" #include "testing/gtest/include/gtest/gtest.h" namespace blimp {
diff --git a/blimp/client/core/blimp_navigation_controller_impl.h b/blimp/client/core/blimp_navigation_controller_impl.h index b62ed25a..90c42e06 100644 --- a/blimp/client/core/blimp_navigation_controller_impl.h +++ b/blimp/client/core/blimp_navigation_controller_impl.h
@@ -7,7 +7,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "blimp/client/core/public/blimp_navigation_controller.h" +#include "blimp/client/public/blimp_navigation_controller.h" #include "url/gurl.h" namespace blimp {
diff --git a/blimp/client/core/public/BUILD.gn b/blimp/client/core/public/BUILD.gn deleted file mode 100644 index 5e840d0..0000000 --- a/blimp/client/core/public/BUILD.gn +++ /dev/null
@@ -1,32 +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. - -if (is_android) { - import("//build/config/android/config.gni") - import("//build/config/android/rules.gni") -} - -source_set("public") { - sources = [ - "blimp_contents.h", - "blimp_contents_observer.h", - "blimp_navigation_controller.h", - ] - - deps = [ - "//base", - "//url", - ] -} - -if (is_android) { - android_library("public_java") { - java_files = [ - "android/java/src/org/chromium/blimp/core_public/BlimpContents.java", - "android/java/src/org/chromium/blimp/core_public/BlimpContentsObserver.java", - "android/java/src/org/chromium/blimp/core_public/BlimpNavigationController.java", - "android/java/src/org/chromium/blimp/core_public/EmptyBlimpContentsObserver.java", - ] - } -}
diff --git a/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpContents.java b/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpContents.java deleted file mode 100644 index 1760bfc..0000000 --- a/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpContents.java +++ /dev/null
@@ -1,37 +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. - -package org.chromium.blimp.core_public; - -/** - * BlimpContents is the Java representation of a native BlimpContents object. - * - * BlimpContents is the core class in //blimp/client/core. It renders web pages from an engine in a - * rectangular area. It enables callers to control the blimp engine through the use of the - * navigation controller. - */ -public interface BlimpContents { - /** - * Retrives the {@link BlimpNavigationController} that controls all navigation related - * to this BlimpContents. - */ - BlimpNavigationController getNavigationController(); - - /** - * Adds an observer to this BlimpContents. - */ - void addObserver(BlimpContentsObserver observer); - - /** - * Removes an observer from this BlimpContents. - */ - void removeObserver(BlimpContentsObserver observer); - - /** - * For BlimpContents that are owned by Java, i.e. created by the - * {@link org.chromium.blimp.core.BlimpContentsFactory}, this must be called before this - * BlimpContents is garbage collected. - */ - void destroy(); -}
diff --git a/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpContentsObserver.java b/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpContentsObserver.java deleted file mode 100644 index ee9fa5a..0000000 --- a/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpContentsObserver.java +++ /dev/null
@@ -1,19 +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. - -package org.chromium.blimp.core_public; - -/** - * BlimpContentsObserver is the Java representation of a native BlimpContentsObserver object. - * - * The BlimpContentsObserver is an observer API implemented by classes which are interested in - * various events related to {@link BlimpContents}. - */ -public interface BlimpContentsObserver { - /** - * Invoked when the URL of the BlimpContents is changes. - * @param url the new URL. - */ - void onUrlUpdated(String url); -}
diff --git a/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpNavigationController.java b/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpNavigationController.java deleted file mode 100644 index 2e60b97d..0000000 --- a/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/BlimpNavigationController.java +++ /dev/null
@@ -1,29 +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. - -package org.chromium.blimp.core_public; - -/** - * BlimpNavigationController is the Java representation of a native BlimpNavigationController - * object. - * - * The BlimpNavigationController maintains the back-forward list for a {@link BlimpContents} and - * manages all navigation within that list. - * - * Each BlimpNavigationController belongs to one {@link BlimpContents}, and each - * {@link BlimpContents} has exactly one BlimpNavigationController. - */ -public interface BlimpNavigationController { - - /** - * Calls to loadUrl informs the engine that it should start navigating to the provided |url|. - * @param url the URL to start navigation to. - */ - void loadUrl(String url); - - /** - * Retrieves the URL of the currently selected item in the navigation list. - */ - String getUrl(); -}
diff --git a/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/EmptyBlimpContentsObserver.java b/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/EmptyBlimpContentsObserver.java deleted file mode 100644 index 2f4097b2a..0000000 --- a/blimp/client/core/public/android/java/src/org/chromium/blimp/core_public/EmptyBlimpContentsObserver.java +++ /dev/null
@@ -1,15 +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. - -package org.chromium.blimp.core_public; - -/** - * EmptyBlimpContentsObserver is a helper class that has an empty implementation of all the - * methods in the {@link BlimpContentsObserver}. It is intented to be used by every class that - * does not need to implement all the observer-methods. - */ -public class EmptyBlimpContentsObserver implements BlimpContentsObserver { - @Override - public void onUrlUpdated(String url) {} -}
diff --git a/blimp/client/core/public/blimp_contents.h b/blimp/client/core/public/blimp_contents.h deleted file mode 100644 index 5da71d27..0000000 --- a/blimp/client/core/public/blimp_contents.h +++ /dev/null
@@ -1,43 +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 BLIMP_CLIENT_CORE_PUBLIC_BLIMP_CONTENTS_H_ -#define BLIMP_CLIENT_CORE_PUBLIC_BLIMP_CONTENTS_H_ - -#include "base/macros.h" -#include "url/gurl.h" - -namespace blimp { -namespace client { - -class BlimpContentsObserver; -class BlimpNavigationController; - -// BlimpContents is the core class in //blimp/client/core. It renders web pages -// from an engine in a rectangular area. -// It enables callers to control the blimp engine through the use of the -// navigation controller. -class BlimpContents { - public: - virtual ~BlimpContents() = default; - - // Retrives the navigation controller that controls all navigation related - // to this BlimpContents. - virtual BlimpNavigationController& GetNavigationController() = 0; - - // Enables adding and removing observers to this BlimpContents. - virtual void AddObserver(BlimpContentsObserver* observer) = 0; - virtual void RemoveObserver(BlimpContentsObserver* observer) = 0; - - protected: - BlimpContents() {} - - private: - DISALLOW_COPY_AND_ASSIGN(BlimpContents); -}; - -} // namespace client -} // namespace blimp - -#endif // BLIMP_CLIENT_CORE_PUBLIC_BLIMP_CONTENTS_H_
diff --git a/blimp/client/core/public/blimp_contents_observer.h b/blimp/client/core/public/blimp_contents_observer.h deleted file mode 100644 index bd3b86a..0000000 --- a/blimp/client/core/public/blimp_contents_observer.h +++ /dev/null
@@ -1,33 +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 BLIMP_CLIENT_CORE_PUBLIC_BLIMP_CONTENTS_OBSERVER_H_ -#define BLIMP_CLIENT_CORE_PUBLIC_BLIMP_CONTENTS_OBSERVER_H_ - -#include "base/macros.h" -#include "url/gurl.h" - -namespace blimp { -namespace client { - -// An observer API implemented by classes which are interested in various events -// related to BlimpContents. -class BlimpContentsObserver { - public: - virtual ~BlimpContentsObserver() = default; - - // Invoked when the URL of the BlimpContents is changes. - virtual void OnURLUpdated(const GURL& url) {} - - protected: - BlimpContentsObserver() {} - - private: - DISALLOW_COPY_AND_ASSIGN(BlimpContentsObserver); -}; - -} // namespace client -} // namespace blimp - -#endif // BLIMP_CLIENT_CORE_PUBLIC_BLIMP_CONTENTS_OBSERVER_H_
diff --git a/blimp/client/core/public/blimp_navigation_controller.h b/blimp/client/core/public/blimp_navigation_controller.h deleted file mode 100644 index fc79b068..0000000 --- a/blimp/client/core/public/blimp_navigation_controller.h +++ /dev/null
@@ -1,42 +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 BLIMP_CLIENT_CORE_PUBLIC_BLIMP_NAVIGATION_CONTROLLER_H_ -#define BLIMP_CLIENT_CORE_PUBLIC_BLIMP_NAVIGATION_CONTROLLER_H_ - -#include "base/macros.h" -#include "url/gurl.h" - -namespace blimp { -namespace client { - -class BlimpContentsObserver; - -// The BlimpNavigationController maintains the back-forward list for a -// BlimpContents and manages all navigation within that list. -// -// Each BlimpNavigationController belongs to one BlimpContents, and each -// BlimpContents has exactly one BlimpNavigationController. -class BlimpNavigationController { - public: - virtual ~BlimpNavigationController() = default; - - // Calls to LoadURL informs the engine that it should start navigating to the - // provided |url|. - virtual void LoadURL(const GURL& url) = 0; - - // Retrieves the URL of the currently selected item in the navigation list. - virtual const GURL& GetURL() = 0; - - protected: - BlimpNavigationController() {} - - private: - DISALLOW_COPY_AND_ASSIGN(BlimpNavigationController); -}; - -} // namespace client -} // namespace blimp - -#endif // BLIMP_CLIENT_CORE_PUBLIC_BLIMP_NAVIGATION_CONTROLLER_H_
diff --git a/blimp/client/feature/compositor/blimp_output_surface.cc b/blimp/client/feature/compositor/blimp_output_surface.cc index e7f905f..22e05b90 100644 --- a/blimp/client/feature/compositor/blimp_output_surface.cc +++ b/blimp/client/feature/compositor/blimp_output_surface.cc
@@ -23,7 +23,6 @@ void BlimpOutputSurface::SwapBuffers(cc::CompositorFrame frame) { // See cc::OutputSurface::SwapBuffers() comment for details. context_provider_->ContextSupport()->Swap(); - client_->DidSwapBuffers(); cc::OutputSurface::PostSwapBuffersComplete(); }
diff --git a/blimp/client/public/BUILD.gn b/blimp/client/public/BUILD.gn new file mode 100644 index 0000000..bd422f4a --- /dev/null +++ b/blimp/client/public/BUILD.gn
@@ -0,0 +1,32 @@ +# 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. + +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") +} + +source_set("public") { + sources = [ + "blimp_contents.h", + "blimp_contents_observer.h", + "blimp_navigation_controller.h", + ] + + deps = [ + "//base", + "//url", + ] +} + +if (is_android) { + android_library("public_java") { + java_files = [ + "android/java/src/org/chromium/blimp_public/BlimpContents.java", + "android/java/src/org/chromium/blimp_public/BlimpContentsObserver.java", + "android/java/src/org/chromium/blimp_public/BlimpNavigationController.java", + "android/java/src/org/chromium/blimp_public/EmptyBlimpContentsObserver.java", + ] + } +}
diff --git a/blimp/client/public/DEPS b/blimp/client/public/DEPS new file mode 100644 index 0000000..12c81a5 --- /dev/null +++ b/blimp/client/public/DEPS
@@ -0,0 +1,6 @@ +include_rules = [ + "+base", + "-blimp", + "-content", + "+url", +]
diff --git a/blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpContents.java b/blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpContents.java new file mode 100644 index 0000000..ae13f41 --- /dev/null +++ b/blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpContents.java
@@ -0,0 +1,37 @@ +// 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. + +package org.chromium.blimp_public; + +/** + * BlimpContents is the Java representation of a native BlimpContents object. + * + * BlimpContents is the core class in //blimp/client/core. It renders web pages from an engine in a + * rectangular area. It enables callers to control the blimp engine through the use of the + * navigation controller. + */ +public interface BlimpContents { + /** + * Retrives the {@link BlimpNavigationController} that controls all navigation related + * to this BlimpContents. + */ + BlimpNavigationController getNavigationController(); + + /** + * Adds an observer to this BlimpContents. + */ + void addObserver(BlimpContentsObserver observer); + + /** + * Removes an observer from this BlimpContents. + */ + void removeObserver(BlimpContentsObserver observer); + + /** + * For BlimpContents that are owned by Java, i.e. created by the + * {@link org.chromium.blimp.core.BlimpContentsFactory}, this must be called before this + * BlimpContents is garbage collected. + */ + void destroy(); +}
diff --git a/blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpContentsObserver.java b/blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpContentsObserver.java new file mode 100644 index 0000000..7d7a8581 --- /dev/null +++ b/blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpContentsObserver.java
@@ -0,0 +1,19 @@ +// 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. + +package org.chromium.blimp_public; + +/** + * BlimpContentsObserver is the Java representation of a native BlimpContentsObserver object. + * + * The BlimpContentsObserver is an observer API implemented by classes which are interested in + * various events related to {@link BlimpContents}. + */ +public interface BlimpContentsObserver { + /** + * Invoked when the URL of the BlimpContents is changes. + * @param url the new URL. + */ + void onUrlUpdated(String url); +}
diff --git a/blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpNavigationController.java b/blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpNavigationController.java new file mode 100644 index 0000000..efc4da2a --- /dev/null +++ b/blimp/client/public/android/java/src/org/chromium/blimp_public/BlimpNavigationController.java
@@ -0,0 +1,29 @@ +// 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. + +package org.chromium.blimp_public; + +/** + * BlimpNavigationController is the Java representation of a native BlimpNavigationController + * object. + * + * The BlimpNavigationController maintains the back-forward list for a {@link BlimpContents} and + * manages all navigation within that list. + * + * Each BlimpNavigationController belongs to one {@link BlimpContents}, and each + * {@link BlimpContents} has exactly one BlimpNavigationController. + */ +public interface BlimpNavigationController { + + /** + * Calls to loadUrl informs the engine that it should start navigating to the provided |url|. + * @param url the URL to start navigation to. + */ + void loadUrl(String url); + + /** + * Retrieves the URL of the currently selected item in the navigation list. + */ + String getUrl(); +}
diff --git a/blimp/client/public/android/java/src/org/chromium/blimp_public/EmptyBlimpContentsObserver.java b/blimp/client/public/android/java/src/org/chromium/blimp_public/EmptyBlimpContentsObserver.java new file mode 100644 index 0000000..8ff0500 --- /dev/null +++ b/blimp/client/public/android/java/src/org/chromium/blimp_public/EmptyBlimpContentsObserver.java
@@ -0,0 +1,15 @@ +// 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. + +package org.chromium.blimp_public; + +/** + * EmptyBlimpContentsObserver is a helper class that has an empty implementation of all the + * methods in the {@link BlimpContentsObserver}. It is intented to be used by every class that + * does not need to implement all the observer-methods. + */ +public class EmptyBlimpContentsObserver implements BlimpContentsObserver { + @Override + public void onUrlUpdated(String url) {} +}
diff --git a/blimp/client/public/blimp_contents.h b/blimp/client/public/blimp_contents.h new file mode 100644 index 0000000..239d3d93 --- /dev/null +++ b/blimp/client/public/blimp_contents.h
@@ -0,0 +1,43 @@ +// 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 BLIMP_CLIENT_PUBLIC_BLIMP_CONTENTS_H_ +#define BLIMP_CLIENT_PUBLIC_BLIMP_CONTENTS_H_ + +#include "base/macros.h" +#include "url/gurl.h" + +namespace blimp { +namespace client { + +class BlimpContentsObserver; +class BlimpNavigationController; + +// BlimpContents is the core class in //blimp/client/core. It renders web pages +// from an engine in a rectangular area. +// It enables callers to control the blimp engine through the use of the +// navigation controller. +class BlimpContents { + public: + virtual ~BlimpContents() = default; + + // Retrives the navigation controller that controls all navigation related + // to this BlimpContents. + virtual BlimpNavigationController& GetNavigationController() = 0; + + // Enables adding and removing observers to this BlimpContents. + virtual void AddObserver(BlimpContentsObserver* observer) = 0; + virtual void RemoveObserver(BlimpContentsObserver* observer) = 0; + + protected: + BlimpContents() {} + + private: + DISALLOW_COPY_AND_ASSIGN(BlimpContents); +}; + +} // namespace client +} // namespace blimp + +#endif // BLIMP_CLIENT_PUBLIC_BLIMP_CONTENTS_H_
diff --git a/blimp/client/public/blimp_contents_observer.h b/blimp/client/public/blimp_contents_observer.h new file mode 100644 index 0000000..c980833 --- /dev/null +++ b/blimp/client/public/blimp_contents_observer.h
@@ -0,0 +1,33 @@ +// 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 BLIMP_CLIENT_PUBLIC_BLIMP_CONTENTS_OBSERVER_H_ +#define BLIMP_CLIENT_PUBLIC_BLIMP_CONTENTS_OBSERVER_H_ + +#include "base/macros.h" +#include "url/gurl.h" + +namespace blimp { +namespace client { + +// An observer API implemented by classes which are interested in various events +// related to BlimpContents. +class BlimpContentsObserver { + public: + virtual ~BlimpContentsObserver() = default; + + // Invoked when the URL of the BlimpContents is changes. + virtual void OnURLUpdated(const GURL& url) {} + + protected: + BlimpContentsObserver() {} + + private: + DISALLOW_COPY_AND_ASSIGN(BlimpContentsObserver); +}; + +} // namespace client +} // namespace blimp + +#endif // BLIMP_CLIENT_PUBLIC_BLIMP_CONTENTS_OBSERVER_H_
diff --git a/blimp/client/public/blimp_navigation_controller.h b/blimp/client/public/blimp_navigation_controller.h new file mode 100644 index 0000000..87b30a0c --- /dev/null +++ b/blimp/client/public/blimp_navigation_controller.h
@@ -0,0 +1,42 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BLIMP_CLIENT_PUBLIC_BLIMP_NAVIGATION_CONTROLLER_H_ +#define BLIMP_CLIENT_PUBLIC_BLIMP_NAVIGATION_CONTROLLER_H_ + +#include "base/macros.h" +#include "url/gurl.h" + +namespace blimp { +namespace client { + +class BlimpContentsObserver; + +// The BlimpNavigationController maintains the back-forward list for a +// BlimpContents and manages all navigation within that list. +// +// Each BlimpNavigationController belongs to one BlimpContents, and each +// BlimpContents has exactly one BlimpNavigationController. +class BlimpNavigationController { + public: + virtual ~BlimpNavigationController() = default; + + // Calls to LoadURL informs the engine that it should start navigating to the + // provided |url|. + virtual void LoadURL(const GURL& url) = 0; + + // Retrieves the URL of the currently selected item in the navigation list. + virtual const GURL& GetURL() = 0; + + protected: + BlimpNavigationController() {} + + private: + DISALLOW_COPY_AND_ASSIGN(BlimpNavigationController); +}; + +} // namespace client +} // namespace blimp + +#endif // BLIMP_CLIENT_PUBLIC_BLIMP_NAVIGATION_CONTROLLER_H_
diff --git a/blimp/client/session/assignment_source_unittest.cc b/blimp/client/session/assignment_source_unittest.cc index e0695aa0..07deed72 100644 --- a/blimp/client/session/assignment_source_unittest.cc +++ b/blimp/client/session/assignment_source_unittest.cc
@@ -210,7 +210,7 @@ assignment.engine_endpoint = net::IPEndPoint(kTestIpAddress, kTestPort); assignment.cert = scoped_refptr<net::X509Certificate>(nullptr); - auto cmd_line = base::CommandLine::ForCurrentProcess(); + auto* cmd_line = base::CommandLine::ForCurrentProcess(); cmd_line->AppendSwitchASCII(switches::kEngineIP, kTestIpAddressString); cmd_line->AppendSwitchASCII(switches::kEnginePort, std::to_string(kTestPort)); @@ -234,7 +234,7 @@ assignment.engine_endpoint = net::IPEndPoint(kTestIpAddress, kTestPort); assignment.cert = cert_; - auto cmd_line = base::CommandLine::ForCurrentProcess(); + auto* cmd_line = base::CommandLine::ForCurrentProcess(); cmd_line->AppendSwitchASCII(switches::kEngineIP, kTestIpAddressString); cmd_line->AppendSwitchASCII(switches::kEnginePort,
diff --git a/blimp/engine/app/blimp_metrics_service_client.cc b/blimp/engine/app/blimp_metrics_service_client.cc index 019e54d3..6149b5a3 100644 --- a/blimp/engine/app/blimp_metrics_service_client.cc +++ b/blimp/engine/app/blimp_metrics_service_client.cc
@@ -118,8 +118,11 @@ } metrics::SystemProfileProto::Channel BlimpMetricsServiceClient::GetChannel() { - // Blimp engine does not have channel info yet. - return metrics::SystemProfileProto::CHANNEL_UNKNOWN; + // Blimp engine does not have channel info yet, however metrics data with + // CHANNEL_UNKNOWN is filtered in metrics visualization tools since the value + // typically implies a non-official build. + // Using CHANNEL_CANARY as a work around until channel is set here. + return metrics::SystemProfileProto::CHANNEL_CANARY; } std::string BlimpMetricsServiceClient::GetVersionString() {
diff --git a/blimp/engine/app/blimp_url_request_context_getter.cc b/blimp/engine/app/blimp_url_request_context_getter.cc index 42133f3c..523fa0f 100644 --- a/blimp/engine/app/blimp_url_request_context_getter.cc +++ b/blimp/engine/app/blimp_url_request_context_getter.cc
@@ -69,7 +69,7 @@ std::vector<std::unique_ptr<net::URLRequestInterceptor>> request_interceptors; - for (auto i : request_interceptors_) { + for (auto* i : request_interceptors_) { request_interceptors.push_back(base::WrapUnique(i)); } request_interceptors_.weak_clear();
diff --git a/blimp/engine/renderer/engine_image_serialization_processor.cc b/blimp/engine/renderer/engine_image_serialization_processor.cc index c79f2af0..8c5aed6 100644 --- a/blimp/engine/renderer/engine_image_serialization_processor.cc +++ b/blimp/engine/renderer/engine_image_serialization_processor.cc
@@ -165,7 +165,7 @@ picture.height = pixmap.height(); // Import picture from raw pixels. - auto pixel_chars = static_cast<const unsigned char*>(pixmap.addr()); + auto* pixel_chars = static_cast<const unsigned char*>(pixmap.addr()); CHECK(PlatformPictureImport(pixel_chars, &picture, pixmap.alphaType())); // Set up the writer parameters.
diff --git a/blimp/engine/testing/Dockerfile b/blimp/engine/testing/Dockerfile index 7115353..71c87fc 100644 --- a/blimp/engine/testing/Dockerfile +++ b/blimp/engine/testing/Dockerfile
@@ -1,2 +1,18 @@ -# Testing dockerfile stub -# TODO(jessicag): Fill in (crbug.com/616945). \ No newline at end of file +# This Dockerfile is used to build a filesystem environment containing +# binaries and required files for Blimp Engine test and tests for dependencies +# of Blimp Engine. It is built on the same base image that is used to run the +# Engine itself. +FROM base:latest + +RUN mkdir -p /out/test/ + +# The glob below expands to all files, but does not add directories +# recursively. +# Test binaries assume src directory is 2 levels down. While this behavior can +# be changed with flags, the directory structure is set up to minimize +# potential problems with initial integration. +ADD * /out/test/ + +RUN chown -R blimp_user /out/test/ + +USER blimp_user \ No newline at end of file
diff --git a/build/android/BUILD.gn b/build/android/BUILD.gn index 066dd194..e1d4e9b 100644 --- a/build/android/BUILD.gn +++ b/build/android/BUILD.gn
@@ -41,6 +41,19 @@ input_jar = android_sdk_jar output_jar = "$root_out_dir/lib.java/android.interface.jar" } + + _rebased_android_sdk_root = rebase_path(android_sdk_root, root_build_dir) + + # Record GN vars that are needed by generate_gradle.py. + # One statement per-line to make GN's formatter leave it alone. + CR = "$0x0A" + _json = "{$CR" + _json += " \"android_sdk_root\": \"$_rebased_android_sdk_root\",$CR" + _json += " \"android_sdk_root\": \"$_rebased_android_sdk_root\",$CR" + _json += " \"compile_sdk_version\": \"$android_sdk_version\",$CR" + _json += " \"build_tools_version\": \"$android_sdk_build_tools_version\"$CR" + _json += "}$CR" + write_file("$root_build_dir/gradle/config.json", _json) } # Copy to the lib.unstripped directory so that gdb can easily find it.
diff --git a/build/android/PRESUBMIT.py b/build/android/PRESUBMIT.py index aae0345..5fb2cc7 100644 --- a/build/android/PRESUBMIT.py +++ b/build/android/PRESUBMIT.py
@@ -21,7 +21,6 @@ build_pys = [ r'gyp/.*\.py$', r'gn/.*\.py', - r'incremental_install/.*\.py', ] output.extend(input_api.canned_checks.RunPylint( input_api, @@ -30,6 +29,7 @@ black_list=build_pys, extra_paths_list=[ J(), + J('gyp'), J('buildbot'), J('..', '..', 'third_party', 'catapult', 'devil') ]))
diff --git a/build/android/gradle/build.gradle.jinja b/build/android/gradle/build.gradle.jinja new file mode 100644 index 0000000..406e730 --- /dev/null +++ b/build/android/gradle/build.gradle.jinja
@@ -0,0 +1,98 @@ +{# 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. #} +// Generated by //build/android/generate_gradle.py +{% if template_type == 'root' %} + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath "com.android.tools.build:gradle:2.1.2" + } +} + +{% elif template_type == 'java_library' %} + +apply plugin: "java" + +sourceSets { + main { + java.srcDirs = {{ java_dirs }} + } +} + +sourceCompatibility = JavaVersion.VERSION_1_7 +targetCompatibility = JavaVersion.VERSION_1_7 + +{% else %} + +{% if template_type == 'android_library' %} +apply plugin: "com.android.library" +{% elif template_type == 'android_apk' %} +apply plugin: "com.android.application" +{% endif %} + +android { + compileSdkVersion {{ compile_sdk_version }} + buildToolsVersion "{{ build_tools_version }}" + publishNonDefault true + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_7 + targetCompatibility JavaVersion.VERSION_1_7 + } + + sourceSets { + main { + manifest.srcFile "{{ android_manifest }}" + java.srcDirs = [ +{% for path in java_dirs %} + "{{ path }}", +{% endfor %} + ] + resources.srcDirs = [] + aidl.srcDirs = [] + renderscript.srcDirs = [] + res.srcDirs = [] + assets.srcDirs = [] + } + } +} +{% endif %} +{% if template_type != 'root' %} + +dependencies { +{% for path in prebuilts %} + compile files("{{ path }}") +{% endfor %} +{% for proj in java_project_deps %} + compile project(":{{ proj }}") +{% endfor %} +{% for proj in android_project_deps %} + debugCompile project(path: ":{{ proj }}", configuration: "debug") + releaseCompile project(path: ":{{ proj }}", configuration: "release") +{% endfor %} +} + +afterEvaluate { + def tasksToDisable = tasks.findAll { + return (it.name.equals('generateDebugSources') // causes unwanted AndroidManifest.java + || it.name.equals('generateReleaseSources') + || it.name.endsWith('Assets') + || it.name.endsWith('BuildConfig') // causes unwanted BuildConfig.java +{% if not use_gradle_process_resources %} + || it.name.endsWith('Resources') + || it.name.endsWith('ResValues') +{% endif %} + || it.name.endsWith('Aidl') + || it.name.endsWith('Renderscript') + || it.name.endsWith('Shaders')) + } + tasksToDisable.each { Task task -> + task.enabled = false + } +} + +{% endif %}
diff --git a/build/android/gradle/generate_gradle.py b/build/android/gradle/generate_gradle.py new file mode 100755 index 0000000..90c98ef --- /dev/null +++ b/build/android/gradle/generate_gradle.py
@@ -0,0 +1,386 @@ +#!/usr/bin/env python +# 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. + +"""Generates an Android Studio project from a GN target.""" + +import argparse +import codecs +import logging +import os +import shutil +import subprocess +import sys +import zipfile + +_BUILD_ANDROID = os.path.join(os.path.dirname(__file__), os.pardir) +sys.path.append(_BUILD_ANDROID) +import devil_chromium +from devil.utils import run_tests_helper +from pylib import constants +from pylib.constants import host_paths + +sys.path.append(os.path.join(_BUILD_ANDROID, 'gyp')) +import jinja_template +from util import build_utils + + +_DEFAULT_ANDROID_MANIFEST_PATH = os.path.join( + host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'AndroidManifest.xml') +_JINJA_TEMPLATE_PATH = os.path.join( + os.path.dirname(__file__), 'build.gradle.jinja') + +_JAVA_SUBDIR = 'symlinked-java' +_SRCJARS_SUBDIR = 'extracted-srcjars' + + +def _RebasePath(path_or_list, new_cwd=None, old_cwd=None): + """Makes the given path(s) relative to new_cwd, or absolute if not specified. + + If new_cwd is not specified, absolute paths are returned. + If old_cwd is not specified, constants.GetOutDirectory() is assumed. + """ + if not isinstance(path_or_list, basestring): + return [_RebasePath(p, new_cwd, old_cwd) for p in path_or_list] + if old_cwd is None: + old_cwd = constants.GetOutDirectory() + old_cwd = os.path.abspath(old_cwd) + if new_cwd: + new_cwd = os.path.abspath(new_cwd) + return os.path.relpath(os.path.join(old_cwd, path_or_list), new_cwd) + return os.path.abspath(os.path.join(old_cwd, path_or_list)) + + +def _IsSubpathOf(child, parent): + """Returns whether |child| is a subpath of |parent|.""" + return not os.path.relpath(child, parent).startswith(os.pardir) + + +def _WriteFile(path, data): + """Writes |data| to |path|, constucting parent directories if necessary.""" + logging.info('Writing %s', path) + dirname = os.path.dirname(path) + if not os.path.exists(dirname): + os.makedirs(dirname) + with codecs.open(path, 'w', 'utf-8') as output_file: + output_file.write(data) + + +def _RunNinja(output_dir, ninja_targets): + cmd = ['ninja', '-C', output_dir, '-j50'] + cmd.extend(ninja_targets) + logging.info('Running: %r', cmd) + subprocess.check_call(cmd) + + +class _ProjectEntry(object): + """Helper class for various path transformations.""" + def __init__(self, gn_target): + assert gn_target.startswith('//'), gn_target + if ':' not in gn_target: + gn_target = '%s:%s' % (gn_target, os.path.basename(gn_target)) + self._gn_target = gn_target + self._build_config = None + + @classmethod + def FromBuildConfigPath(cls, path): + prefix = 'gen/' + suffix = '.build_config' + assert path.startswith(prefix) and path.endswith(suffix), path + subdir = path[len(prefix):-len(suffix)] + return cls('//%s:%s' % (os.path.split(subdir))) + + def __hash__(self): + return hash(self._gn_target) + + def __eq__(self, other): + return self._gn_target == other.GnTarget() + + def GnTarget(self): + return self._gn_target + + def NinjaTarget(self): + return self._gn_target[2:] + + def GnBuildConfigTarget(self): + return '%s__build_config' % self._gn_target + + def NinjaBuildConfigTarget(self): + return '%s__build_config' % self.NinjaTarget() + + def GradleSubdir(self): + """Returns the output subdirectory.""" + return self.NinjaTarget().replace(':', os.path.sep) + + def ProjectName(self): + """Returns the Gradle project name.""" + return self.GradleSubdir().replace(os.path.sep, '\\$') + + def BuildConfig(self): + """Reads and returns the project's .build_config JSON.""" + if not self._build_config: + path = os.path.join('gen', self.GradleSubdir() + '.build_config') + self._build_config = build_utils.ReadJson(_RebasePath(path)) + return self._build_config + + +def _ComputeJavaSourceDirs(java_files): + """Returns the list of source directories for the given files.""" + found_roots = set() + for path in java_files: + path_root = path + # Recognize these tokens as top-level. + while os.path.basename(path_root) not in ('javax', 'org', 'com', 'src'): + assert path_root, 'Failed to find source dir for ' + path + path_root = os.path.dirname(path_root) + # Assume that if we've hit "src", the we're at the root. + if os.path.basename(path_root) != 'src': + path_root = os.path.dirname(path_root) + found_roots.add(path_root) + return list(found_roots) + + +def _CreateSymlinkTree(entry_output_dir, symlink_dir, desired_files, + parent_dirs): + """Creates a directory tree of symlinks to the given files. + + The idea here is to replicate a directory tree while leaving out files within + it not listed by |desired_files|. + """ + assert _IsSubpathOf(symlink_dir, entry_output_dir) + if os.path.exists(symlink_dir): + shutil.rmtree(symlink_dir) + + for target_path in desired_files: + prefix = next(d for d in parent_dirs if target_path.startswith(d)) + subpath = os.path.relpath(target_path, prefix) + symlinked_path = os.path.join(symlink_dir, subpath) + symlinked_dir = os.path.dirname(symlinked_path) + if not os.path.exists(symlinked_dir): + os.makedirs(symlinked_dir) + relpath = os.path.relpath(target_path, symlinked_dir) + logging.debug('Creating symlink %s -> %s', symlinked_path, relpath) + os.symlink(relpath, symlinked_path) + + +def _CreateJavaSourceDir(entry_output_dir, java_sources_file): + """Computes and constructs when necessary the list of java source directories. + + 1. Computes the root java source directories from the list of files. + 2. Determines whether there are any .java files in them that are not included + in |java_sources_file|. + 3. If not, returns the list of java source directories. If so, constructs a + tree of symlinks within |entry_output_dir| of all files in + |java_sources_file|. + """ + java_dirs = [] + if java_sources_file: + with open(java_sources_file) as f: + java_files = _RebasePath([l.strip() for l in f]) + java_dirs = _ComputeJavaSourceDirs(java_files) + + found_java_files = build_utils.FindInDirectories(java_dirs, '*.java') + unwanted_java_files = set(found_java_files) - set(java_files) + missing_java_files = set(java_files) - set(found_java_files) + if unwanted_java_files: + logging.debug('Target requires .java symlinks: %s', entry_output_dir) + symlink_dir = os.path.join(entry_output_dir, _JAVA_SUBDIR) + _CreateSymlinkTree(entry_output_dir, symlink_dir, java_files, java_dirs) + java_dirs = [symlink_dir] + if missing_java_files: + logging.warning('Some java files were not found: %s', missing_java_files) + + return java_dirs + + +def _GenerateLocalProperties(sdk_dir): + """Returns the data for project.properties as a string.""" + return '\n'.join([ + '# Generated by //build/android/gradle/generate_gradle.py', + 'sdk.dir=%s' % sdk_dir, + '']) + + +def _GenerateGradleFile(build_config, config_json, java_dirs, relativize, + use_gradle_process_resources): + """Returns the data for a project's build.gradle.""" + deps_info = build_config['deps_info'] + gradle = build_config['gradle'] + + if deps_info['type'] == 'android_apk': + target_type = 'android_apk' + elif deps_info['type'] == 'java_library' and not deps_info['is_prebuilt']: + if deps_info['requires_android']: + target_type = 'android_library' + else: + target_type = 'java_library' + else: + return None + + variables = {} + variables['template_type'] = target_type + variables['use_gradle_process_resources'] = use_gradle_process_resources + variables['build_tools_version'] = config_json['build_tools_version'] + variables['compile_sdk_version'] = config_json['compile_sdk_version'] + android_manifest = gradle.get('android_manifest', + _DEFAULT_ANDROID_MANIFEST_PATH) + variables['android_manifest'] = relativize(android_manifest) + variables['java_dirs'] = relativize(java_dirs) + variables['prebuilts'] = relativize(gradle['dependent_prebuilt_jars']) + deps = [_ProjectEntry.FromBuildConfigPath(p) + for p in gradle['dependent_android_projects']] + + variables['android_project_deps'] = [d.ProjectName() for d in deps] + deps = [_ProjectEntry.FromBuildConfigPath(p) + for p in gradle['dependent_java_projects']] + variables['java_project_deps'] = [d.ProjectName() for d in deps] + + processor = jinja_template.JinjaProcessor(host_paths.DIR_SOURCE_ROOT) + return processor.Render(_JINJA_TEMPLATE_PATH, variables) + + +def _GenerateRootGradle(): + """Returns the data for the root project's build.gradle.""" + variables = {'template_type': 'root'} + processor = jinja_template.JinjaProcessor(host_paths.DIR_SOURCE_ROOT) + return processor.Render(_JINJA_TEMPLATE_PATH, variables) + + +def _GenerateSettingsGradle(project_entries): + """Returns the data for settings.gradle.""" + project_name = os.path.basename(os.path.dirname(host_paths.DIR_SOURCE_ROOT)) + lines = [] + lines.append('// Generated by //build/android/gradle/generate_gradle.py') + lines.append('rootProject.name = "%s"' % project_name) + lines.append('rootProject.projectDir = settingsDir') + lines.append('') + + for entry in project_entries: + # Example target: android_webview:android_webview_java__build_config + lines.append('include ":%s"' % entry.ProjectName()) + lines.append('project(":%s").projectDir = new File(settingsDir, "%s")' % + (entry.ProjectName(), entry.GradleSubdir())) + return '\n'.join(lines) + + +def _ExtractSrcjars(entry_output_dir, srcjar_tuples): + """Extracts all srcjars to the directory given by the tuples.""" + extracted_paths = set(s[1] for s in srcjar_tuples) + for extracted_path in extracted_paths: + assert _IsSubpathOf(extracted_path, entry_output_dir) + if os.path.exists(extracted_path): + shutil.rmtree(extracted_path) + + for srcjar_path, extracted_path in srcjar_tuples: + logging.info('Extracting %s to %s', srcjar_path, extracted_path) + with zipfile.ZipFile(srcjar_path) as z: + z.extractall(extracted_path) + + +def _FindAllProjectEntries(main_entry): + """Returns the list of all _ProjectEntry instances given the root project.""" + found = set() + to_scan = [main_entry] + while to_scan: + cur_entry = to_scan.pop() + if cur_entry in found: + continue + found.add(cur_entry) + build_config = cur_entry.BuildConfig() + sub_config_paths = build_config['deps_info']['deps_configs'] + to_scan.extend( + _ProjectEntry.FromBuildConfigPath(p) for p in sub_config_paths) + return list(found) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--output-directory', + help='Path to the root build directory.') + parser.add_argument('-v', + '--verbose', + dest='verbose_count', + default=0, + action='count', + help='Verbose level') + parser.add_argument('--target', + help='GN target to generate project for.', + default='//chrome/android:chrome_public_apk') + parser.add_argument('--project-dir', + help='Root of the output project.', + default=os.path.join('$CHROMIUM_OUTPUT_DIR', 'gradle')) + parser.add_argument('--use-gradle-process-resources', + action='store_true', + help='Have gradle generate R.java rather than ninja') + args = parser.parse_args() + if args.output_directory: + constants.SetOutputDirectory(args.output_directory) + constants.CheckOutputDirectory() + output_dir = constants.GetOutDirectory() + devil_chromium.Initialize(output_directory=output_dir) + run_tests_helper.SetLogLevel(args.verbose_count) + + gradle_output_dir = os.path.abspath( + args.project_dir.replace('$CHROMIUM_OUTPUT_DIR', output_dir)) + logging.warning('Creating project at: %s', gradle_output_dir) + + main_entry = _ProjectEntry(args.target) + logging.warning('Building .build_config files...') + _RunNinja(output_dir, [main_entry.NinjaBuildConfigTarget()]) + + all_entries = _FindAllProjectEntries(main_entry) + logging.info('Found %d dependent build_config targets.', len(all_entries)) + + config_json = build_utils.ReadJson( + os.path.join(output_dir, 'gradle', 'config.json')) + project_entries = [] + srcjar_tuples = [] + for entry in all_entries: + build_config = entry.BuildConfig() + if build_config['deps_info']['type'] not in ('android_apk', 'java_library'): + continue + + entry_output_dir = os.path.join(gradle_output_dir, entry.GradleSubdir()) + relativize = lambda x, d=entry_output_dir: _RebasePath(x, d) + + srcjars = _RebasePath(build_config['gradle'].get('bundled_srcjars', [])) + if not args.use_gradle_process_resources: + srcjars += _RebasePath(build_config['javac']['srcjars']) + + java_sources_file = build_config['gradle'].get('java_sources_file') + if java_sources_file: + java_sources_file = _RebasePath(java_sources_file) + + java_dirs = _CreateJavaSourceDir(entry_output_dir, java_sources_file) + if srcjars: + java_dirs.append(os.path.join(entry_output_dir, _SRCJARS_SUBDIR)) + + data = _GenerateGradleFile(build_config, config_json, java_dirs, relativize, + args.use_gradle_process_resources) + if data: + project_entries.append(entry) + srcjar_tuples.extend( + (s, os.path.join(entry_output_dir, _SRCJARS_SUBDIR)) for s in srcjars) + _WriteFile(os.path.join(entry_output_dir, 'build.gradle'), data) + + _WriteFile(os.path.join(gradle_output_dir, 'build.gradle'), + _GenerateRootGradle()) + + _WriteFile(os.path.join(gradle_output_dir, 'settings.gradle'), + _GenerateSettingsGradle(project_entries)) + + sdk_path = _RebasePath(config_json['android_sdk_root']) + _WriteFile(os.path.join(gradle_output_dir, 'local.properties'), + _GenerateLocalProperties(sdk_path)) + + if srcjar_tuples: + logging.warning('Building all .srcjar files...') + targets = _RebasePath([s[0] for s in srcjar_tuples], output_dir) + _RunNinja(output_dir, targets) + _ExtractSrcjars(gradle_output_dir, srcjar_tuples) + logging.warning('Project created successfully!') + + +if __name__ == '__main__': + main()
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py index 9f5e3e3..a58da3a 100755 --- a/build/android/gyp/write_build_config.py +++ b/build/android/gyp/write_build_config.py
@@ -236,6 +236,8 @@ # java library options parser.add_option('--jar-path', help='Path to target\'s jar output.') parser.add_option('--java-sources-file', help='Path to .sources file') + parser.add_option('--bundled-srcjars', + help='GYP-list of .srcjars that have been included in this java_library.') parser.add_option('--supports-android', action='store_true', help='Whether this library supports running on the Android platform.') parser.add_option('--requires-android', action='store_true', @@ -364,9 +366,20 @@ if options.type in ('java_binary', 'java_library', 'android_apk'): if options.java_sources_file: gradle['java_sources_file'] = options.java_sources_file + if options.bundled_srcjars: + gradle['bundled_srcjars'] = ( + build_utils.ParseGypList(options.bundled_srcjars)) + gradle['dependent_prebuilt_jars'] = deps.PrebuiltJarPaths() - gradle['dependent_projects'] = ( - [c['path'] for c in direct_library_deps if not c['is_prebuilt']]) + + gradle['dependent_android_projects'] = [] + gradle['dependent_java_projects'] = [] + for c in direct_library_deps: + if not c['is_prebuilt']: + if c['requires_android']: + gradle['dependent_android_projects'].append(c['path']) + else: + gradle['dependent_java_projects'].append(c['path']) if (options.type in ('java_binary', 'java_library') and
diff --git a/build/android/incremental_install/installer.py b/build/android/incremental_install/installer.py index 6c42911..2f4e994d48 100755 --- a/build/android/incremental_install/installer.py +++ b/build/android/incremental_install/installer.py
@@ -20,11 +20,10 @@ import devil_chromium from devil.android import apk_helper from devil.android import device_utils -from devil.android import device_errors from devil.android.sdk import version_codes from devil.utils import reraiser_thread +from devil.utils import run_tests_helper from pylib import constants -from pylib.utils import run_tests_helper from pylib.utils import time_profile prev_sys_path = list(sys.path)
diff --git a/build/android/pylib/base/test_instance_factory.py b/build/android/pylib/base/test_instance_factory.py index 523b4c5..5cc3723 100644 --- a/build/android/pylib/base/test_instance_factory.py +++ b/build/android/pylib/base/test_instance_factory.py
@@ -4,6 +4,7 @@ from pylib.gtest import gtest_test_instance from pylib.instrumentation import instrumentation_test_instance +from pylib.perf import perf_test_instance from pylib.uirobot import uirobot_test_instance from pylib.utils import isolator @@ -16,6 +17,8 @@ elif args.command == 'instrumentation': return instrumentation_test_instance.InstrumentationTestInstance( args, isolator.Isolator(), error_func) + elif args.command == 'perf': + return perf_test_instance.PerfTestInstance(args, error_func) elif args.command == 'uirobot': return uirobot_test_instance.UirobotTestInstance(args, error_func)
diff --git a/build/android/pylib/base/test_run_factory.py b/build/android/pylib/base/test_run_factory.py index 8db9bd63..46c8076 100644 --- a/build/android/pylib/base/test_run_factory.py +++ b/build/android/pylib/base/test_run_factory.py
@@ -7,6 +7,8 @@ from pylib.local.device import local_device_environment from pylib.local.device import local_device_gtest_run from pylib.local.device import local_device_instrumentation_test_run +from pylib.local.device import local_device_perf_test_run +from pylib.perf import perf_test_instance from pylib.uirobot import uirobot_test_instance try: @@ -21,7 +23,18 @@ remote_device_uirobot_test_run = None -def CreateTestRun(_args, env, test_instance, error_func): +def _CreatePerfTestRun(args, env, test_instance): + if args.print_step: + return local_device_perf_test_run.PrintStep( + env, test_instance) + elif args.output_json_list: + return local_device_perf_test_run.OutputJsonList( + env, test_instance) + return local_device_perf_test_run.LocalDevicePerfTestRun( + env, test_instance) + + +def CreateTestRun(args, env, test_instance, error_func): if isinstance(env, local_device_environment.LocalDeviceEnvironment): if isinstance(test_instance, gtest_test_instance.GtestTestInstance): return local_device_gtest_run.LocalDeviceGtestRun(env, test_instance) @@ -29,6 +42,9 @@ instrumentation_test_instance.InstrumentationTestInstance): return (local_device_instrumentation_test_run .LocalDeviceInstrumentationTestRun(env, test_instance)) + if isinstance(test_instance, + perf_test_instance.PerfTestInstance): + return _CreatePerfTestRun(args, env, test_instance) if (remote_device_environment and isinstance(env, remote_device_environment.RemoteDeviceEnvironment)):
diff --git a/build/android/pylib/device/OWNERS b/build/android/pylib/device/OWNERS deleted file mode 100644 index c35d7ace..0000000 --- a/build/android/pylib/device/OWNERS +++ /dev/null
@@ -1,2 +0,0 @@ -jbudorick@chromium.org -perezju@chromium.org
diff --git a/build/android/pylib/device/adb_wrapper.py b/build/android/pylib/device/adb_wrapper.py deleted file mode 100644 index f66619fe..0000000 --- a/build/android/pylib/device/adb_wrapper.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.sdk.adb_wrapper import *
diff --git a/build/android/pylib/device/battery_utils.py b/build/android/pylib/device/battery_utils.py deleted file mode 100644 index 95c5613e..0000000 --- a/build/android/pylib/device/battery_utils.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.battery_utils import *
diff --git a/build/android/pylib/device/decorators.py b/build/android/pylib/device/decorators.py deleted file mode 100644 index f8c2fdd..0000000 --- a/build/android/pylib/device/decorators.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.decorators import *
diff --git a/build/android/pylib/device/device_blacklist.py b/build/android/pylib/device/device_blacklist.py deleted file mode 100644 index fad1ca698..0000000 --- a/build/android/pylib/device/device_blacklist.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.device_blacklist import *
diff --git a/build/android/pylib/device/device_errors.py b/build/android/pylib/device/device_errors.py deleted file mode 100644 index cb09c3cf..0000000 --- a/build/android/pylib/device/device_errors.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.device_errors import *
diff --git a/build/android/pylib/device/device_list.py b/build/android/pylib/device/device_list.py deleted file mode 100644 index a730277..0000000 --- a/build/android/pylib/device/device_list.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.device_list import *
diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py deleted file mode 100644 index b8e8de24..0000000 --- a/build/android/pylib/device/device_utils.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.device_utils import *
diff --git a/build/android/pylib/device/intent.py b/build/android/pylib/device/intent.py deleted file mode 100644 index cb6fb68..0000000 --- a/build/android/pylib/device/intent.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.sdk.intent import *
diff --git a/build/android/pylib/device/logcat_monitor.py b/build/android/pylib/device/logcat_monitor.py deleted file mode 100644 index 0e492cb4..0000000 --- a/build/android/pylib/device/logcat_monitor.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.logcat_monitor import *
diff --git a/build/android/pylib/device/shared_prefs.py b/build/android/pylib/device/shared_prefs.py deleted file mode 100644 index 38db76a8..0000000 --- a/build/android/pylib/device/shared_prefs.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.sdk.shared_prefs import *
diff --git a/build/android/pylib/device_signal.py b/build/android/pylib/device_signal.py deleted file mode 100644 index ca57690..0000000 --- a/build/android/pylib/device_signal.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.device_signal import *
diff --git a/build/android/pylib/local/device/local_device_environment.py b/build/android/pylib/local/device/local_device_environment.py index 178e2f1..f8cd530 100644 --- a/build/android/pylib/local/device/local_device_environment.py +++ b/build/android/pylib/local/device/local_device_environment.py
@@ -90,6 +90,10 @@ monitor.Start() @property + def blacklist(self): + return self._blacklist + + @property def concurrent_adb(self): return self._concurrent_adb
diff --git a/build/android/pylib/local/device/local_device_perf_test_run.py b/build/android/pylib/local/device/local_device_perf_test_run.py new file mode 100644 index 0000000..d3bcd0f --- /dev/null +++ b/build/android/pylib/local/device/local_device_perf_test_run.py
@@ -0,0 +1,386 @@ +# 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 io +import json +import logging +import os +import pickle +import shutil +import tempfile +import time +import zipfile + +from devil.android import battery_utils +from devil.android import device_blacklist +from devil.android import device_errors +from devil.android import device_list +from devil.android import device_utils +from devil.android import forwarder +from devil.android.tools import device_recovery +from devil.android.tools import device_status +from devil.utils import cmd_helper +from devil.utils import parallelizer +from pylib import constants +from pylib.base import base_test_result +from pylib.constants import host_paths +from pylib.local.device import local_device_test_run + + +class TestShard(object): + def __init__( + self, env, test_instance, device, index, tests, retries=3, timeout=None): + logging.info('Create shard %s for device %s to run the following tests:', + index, device) + for t in tests: + logging.info(' %s', t) + self._battery = battery_utils.BatteryUtils(device) + self._device = device + self._env = env + self._index = index + self._output_dir = None + self._retries = retries + self._test_instance = test_instance + self._tests = tests + self._timeout = timeout + + @local_device_test_run.handle_shard_failures + def RunTestsOnShard(self): + results = base_test_result.TestRunResults() + for test in self._tests: + tries_left = self._retries + result_type = None + while (result_type != base_test_result.ResultType.PASS + and tries_left > 0): + try: + self._TestSetUp(test) + result_type = self._RunSingleTest(test) + except device_errors.CommandTimeoutError: + result_type = base_test_result.ResultType.TIMEOUT + except device_errors.CommandFailedError: + logging.exception('Exception when executing %s.', test) + result_type = base_test_result.ResultType.FAIL + finally: + self._TestTearDown() + if result_type != base_test_result.ResultType.PASS: + try: + device_recovery.RecoverDevice(self._device, self._env.blacklist) + except device_errors.CommandTimeoutError: + logging.exception( + 'Device failed to recover after failing %s.', test) + tries_left = tries_left - 1 + + results.AddResult(base_test_result.BaseTestResult(test, result_type)) + return results + + def _TestSetUp(self, test): + if not self._device.IsOnline(): + msg = 'Device %s is unresponsive.' % str(self._device) + raise device_errors.DeviceUnreachableError(msg) + + logging.info('Charge level: %s%%', + str(self._battery.GetBatteryInfo().get('level'))) + if self._test_instance.min_battery_level: + self._battery.ChargeDeviceToLevel(self._test_instance.min_battery_level) + + logging.info('temperature: %s (0.1 C)', + str(self._battery.GetBatteryInfo().get('temperature'))) + if self._test_instance.max_battery_temp: + self._battery.LetBatteryCoolToTemperature( + self._test_instance.max_battery_temp) + + if not self._device.IsScreenOn(): + self._device.SetScreen(True) + + if (self._test_instance.collect_chartjson_data + or self._tests[test].get('archive_output_dir')): + self._output_dir = tempfile.mkdtemp() + + def _RunSingleTest(self, test): + self._test_instance.WriteBuildBotJson(self._output_dir) + + timeout = self._tests[test].get('timeout', self._timeout) + cmd = self._CreateCmd(test) + cwd = os.path.abspath(host_paths.DIR_SOURCE_ROOT) + + logging.debug("Running %s with command '%s' on shard %d with timeout %d", + test, cmd, self._index, timeout) + + try: + start_time = time.time() + exit_code, output = cmd_helper.GetCmdStatusAndOutputWithTimeout( + cmd, timeout, cwd=cwd, shell=True) + end_time = time.time() + json_output = self._test_instance.ReadChartjsonOutput(self._output_dir) + if exit_code == 0: + result_type = base_test_result.ResultType.PASS + else: + result_type = base_test_result.ResultType.FAIL + except cmd_helper.TimeoutError as e: + end_time = time.time() + exit_code = -1 + output = e.output + json_output = '' + result_type = base_test_result.ResultType.TIMEOUT + + return self._ProcessTestResult(test, cmd, start_time, end_time, exit_code, + output, json_output, result_type) + + def _CreateCmd(self, test): + cmd = '%s --device %s' % (self._tests[test]['cmd'], str(self._device)) + if self._output_dir: + cmd = cmd + ' --output-dir=%s' % self._output_dir + if self._test_instance.dry_run: + cmd = 'echo %s' % cmd + return cmd + + def _ProcessTestResult(self, test, cmd, start_time, end_time, exit_code, + output, json_output, result_type): + if exit_code is None: + exit_code = -1 + logging.info('%s : exit_code=%d in %d secs on device %s', + test, exit_code, end_time - start_time, + str(self._device)) + + actual_exit_code = exit_code + if (self._test_instance.flaky_steps + and test in self._test_instance.flaky_steps): + exit_code = 0 + archive_bytes = (self._ArchiveOutputDir() + if self._tests[test].get('archive_output_dir') + else None) + persisted_result = { + 'name': test, + 'output': [output], + 'chartjson': json_output, + 'archive_bytes': archive_bytes, + 'exit_code': exit_code, + 'actual_exit_code': actual_exit_code, + 'result_type': result_type, + 'start_time': start_time, + 'end_time': end_time, + 'total_time': end_time - start_time, + 'device': str(self._device), + 'cmd': cmd, + } + self._SaveResult(persisted_result) + return result_type + + def _ArchiveOutputDir(self): + """Archive all files in the output dir, and return as compressed bytes.""" + with io.BytesIO() as archive: + with zipfile.ZipFile(archive, 'w', zipfile.ZIP_DEFLATED) as contents: + num_files = 0 + for absdir, _, files in os.walk(self._output_dir): + reldir = os.path.relpath(absdir, self._output_dir) + for filename in files: + src_path = os.path.join(absdir, filename) + # We use normpath to turn './file.txt' into just 'file.txt'. + dst_path = os.path.normpath(os.path.join(reldir, filename)) + contents.write(src_path, dst_path) + num_files += 1 + if num_files: + logging.info('%d files in the output dir were archived.', num_files) + else: + logging.warning('No files in the output dir. Archive is empty.') + return archive.getvalue() + + @staticmethod + def _SaveResult(result): + pickled = os.path.join(constants.PERF_OUTPUT_DIR, result['name']) + if os.path.exists(pickled): + with file(pickled, 'r') as f: + previous = pickle.loads(f.read()) + result['output'] = previous['output'] + result['output'] + with file(pickled, 'w') as f: + f.write(pickle.dumps(result)) + + def _TestTearDown(self): + if self._output_dir: + shutil.rmtree(self._output_dir, ignore_errors=True) + self._output_dir = None + try: + logging.info('Unmapping device ports for %s.', self._device) + forwarder.Forwarder.UnmapAllDevicePorts(self._device) + except Exception: # pylint: disable=broad-except + logging.exception('Exception when resetting ports.') + + +class LocalDevicePerfTestRun(local_device_test_run.LocalDeviceTestRun): + + _DEFAULT_TIMEOUT = 60 * 60 + _CONFIG_VERSION = 1 + + def __init__(self, env, test_instance): + super(LocalDevicePerfTestRun, self).__init__(env, test_instance) + self._devices = None + self._env = env + self._test_buckets = [] + self._test_instance = test_instance + self._timeout = None if test_instance.no_timeout else self._DEFAULT_TIMEOUT + + def SetUp(self): + self._devices = self._GetAllDevices(self._env.devices, + self._test_instance.known_devices_file) + + if os.path.exists(constants.PERF_OUTPUT_DIR): + shutil.rmtree(constants.PERF_OUTPUT_DIR) + os.makedirs(constants.PERF_OUTPUT_DIR) + + def TearDown(self): + pass + + def _GetStepsFromDict(self): + # From where this is called one of these two must be set. + if self._test_instance.single_step: + return { + 'version': self._CONFIG_VERSION, + 'steps': { + 'single_step': { + 'device_affinity': 0, + 'cmd': self._test_instance.single_step + }, + } + } + if self._test_instance.steps: + with file(self._test_instance.steps, 'r') as f: + steps = json.load(f) + if steps['version'] != self._CONFIG_VERSION: + raise TestDictVersionError( + 'Version is expected to be %d but was %d' % (self._CONFIG_VERSION, + steps['version'])) + return steps + raise PerfTestRunGetStepsError( + 'Neither single_step or steps set in test_instance.') + + def _SplitTestsByAffinity(self): + # This splits tests by their device affinity so that the same tests always + # run on the same devices. This is important for perf tests since different + # devices might yield slightly different performance results. + test_dict = self._GetStepsFromDict() + for test, test_config in test_dict['steps'].iteritems(): + try: + affinity = test_config['device_affinity'] + if len(self._test_buckets) < affinity + 1: + while len(self._test_buckets) != affinity + 1: + self._test_buckets.append({}) + self._test_buckets[affinity][test] = test_config + except KeyError: + logging.exception( + 'Test config for %s is bad.\n Config:%s', test, str(test_config)) + + @staticmethod + def _GetAllDevices(active_devices, devices_path): + try: + if devices_path: + devices = [device_utils.DeviceUtils(s) + for s in device_list.GetPersistentDeviceList(devices_path)] + if not devices and active_devices: + logging.warning('%s is empty. Falling back to active devices.', + devices_path) + devices = active_devices + else: + logging.warning('Known devices file path not being passed. For device ' + 'affinity to work properly, it must be passed.') + devices = active_devices + except IOError as e: + logging.error('Unable to find %s [%s]', devices_path, e) + devices = active_devices + return sorted(devices) + + #override + def RunTests(self): + # Affinitize the tests. + self._SplitTestsByAffinity() + if not self._test_buckets: + raise local_device_test_run.NoTestsError() + + blacklist = (device_blacklist.Blacklist(self._env.blacklist) + if self._env.blacklist + else None) + + def run_perf_tests(shard_id): + if device_status.IsBlacklisted(str(self._devices[shard_id]), blacklist): + logging.warning('Device %s is not active. Will not create shard %s.', + str(self._devices[shard_id]), shard_id) + return [] + s = TestShard(self._env, self._test_instance, self._devices[shard_id], + shard_id, self._test_buckets[shard_id], + retries=self._env.max_tries, timeout=self._timeout) + return s.RunTestsOnShard() + + device_indices = range(min(len(self._devices), len(self._test_buckets))) + shards = parallelizer.Parallelizer(device_indices).pMap(run_perf_tests) + return shards.pGet(self._timeout) + + # override + def TestPackage(self): + return 'perf' + + # override + def _CreateShards(self, _tests): + raise NotImplementedError + + # override + def _GetTests(self): + return self._test_buckets + + # override + def _RunTest(self, _device, _test): + raise NotImplementedError + + # override + def _ShouldShard(self): + return False + + +class OutputJsonList(LocalDevicePerfTestRun): + # override + def SetUp(self): + pass + + # override + def RunTests(self): + result_type = self._test_instance.OutputJsonList() + result = base_test_result.TestRunResults() + result.AddResult( + base_test_result.BaseTestResult('OutputJsonList', result_type)) + return [result] + + # override + def _CreateShards(self, _tests): + raise NotImplementedError + + # override + def _RunTest(self, _device, _test): + raise NotImplementedError + + +class PrintStep(LocalDevicePerfTestRun): + # override + def SetUp(self): + pass + + # override + def RunTests(self): + result_type = self._test_instance.PrintTestOutput() + result = base_test_result.TestRunResults() + result.AddResult( + base_test_result.BaseTestResult('PrintStep', result_type)) + return [result] + + # override + def _CreateShards(self, _tests): + raise NotImplementedError + + # override + def _RunTest(self, _device, _test): + raise NotImplementedError + + +class TestDictVersionError(Exception): + pass + +class PerfTestRunGetStepsError(Exception): + pass
diff --git a/build/android/pylib/local/device/local_device_test_run.py b/build/android/pylib/local/device/local_device_test_run.py index bcdb012..74e3d22 100644 --- a/build/android/pylib/local/device/local_device_test_run.py +++ b/build/android/pylib/local/device/local_device_test_run.py
@@ -222,3 +222,7 @@ def _ShouldShard(self): raise NotImplementedError + + +class NoTestsError(Exception): + """Error for when no tests are found."""
diff --git a/build/android/pylib/perf/cache_control.py b/build/android/pylib/perf/cache_control.py deleted file mode 100644 index 8b46575..0000000 --- a/build/android/pylib/perf/cache_control.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.perf.cache_control import *
diff --git a/build/android/pylib/perf/perf_control.py b/build/android/pylib/perf/perf_control.py deleted file mode 100644 index d95d7b7..0000000 --- a/build/android/pylib/perf/perf_control.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.perf.perf_control import *
diff --git a/build/android/pylib/perf/perf_test_instance.py b/build/android/pylib/perf/perf_test_instance.py new file mode 100644 index 0000000..17f3fd4 --- /dev/null +++ b/build/android/pylib/perf/perf_test_instance.py
@@ -0,0 +1,237 @@ +# 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 json +import logging +import os +import pickle +import re + +from devil import base_error +from devil.utils import cmd_helper +from pylib import constants +from pylib.base import base_test_result +from pylib.base import test_instance +from pylib.constants import host_paths + + +_GIT_CR_POS_RE = re.compile(r'^Cr-Commit-Position: refs/heads/master@{#(\d+)}$') + + +def _GetPersistedResult(test_name): + file_name = os.path.join(constants.PERF_OUTPUT_DIR, test_name) + if not os.path.exists(file_name): + logging.error('File not found %s', file_name) + return None + + with file(file_name, 'r') as f: + return pickle.loads(f.read()) + + +def _GetChromiumRevision(): + # pylint: disable=line-too-long + """Get the git hash and commit position of the chromium master branch. + + See: + https://chromium.googlesource.com/chromium/tools/build/+/387e3cf3/scripts/slave/runtest.py#211 + + Returns: + A dictionary with 'revision' and 'commit_pos' keys. + """ + # pylint: enable=line-too-long + status, output = cmd_helper.GetCmdStatusAndOutput( + ['git', 'log', '-n', '1', '--pretty=format:%H%n%B', 'HEAD'], + cwd=host_paths.DIR_SOURCE_ROOT) + revision = None + commit_pos = None + if not status: + lines = output.splitlines() + revision = lines[0] + for line in reversed(lines): + m = _GIT_CR_POS_RE.match(line.strip()) + if m: + commit_pos = int(m.group(1)) + break + return {'revision': revision, 'commit_pos': commit_pos} + + +class PerfTestInstance(test_instance.TestInstance): + def __init__(self, args, _): + super(PerfTestInstance, self).__init__() + + self._collect_chartjson_data = args.collect_chartjson_data + self._dry_run = args.dry_run + self._flaky_steps = args.flaky_steps + self._output_dir_archive_path = args.output_dir_archive_path + self._known_devices_file = args.known_devices_file + self._max_battery_temp = args.max_battery_temp + self._min_battery_level = args.min_battery_level + self._no_timeout = args.no_timeout + self._output_chartjson_data = args.output_chartjson_data + self._output_json_list = args.output_json_list + self._print_step = args.print_step + self._single_step = ( + ' '.join(args.single_step_command) if args.single_step else None) + self._steps = args.steps + self._test_filter = args.test_filter + self._write_buildbot_json = args.write_buildbot_json + + def SetUp(self): + pass + + def TearDown(self): + pass + + def OutputJsonList(self): + try: + with file(self._steps, 'r') as i: + all_steps = json.load(i) + + step_values = [] + for k, v in all_steps['steps'].iteritems(): + data = {'test': k, 'device_affinity': v['device_affinity']} + + persisted_result = _GetPersistedResult(k) + if persisted_result: + data['start_time'] = persisted_result['start_time'] + data['end_time'] = persisted_result['end_time'] + data['total_time'] = persisted_result['total_time'] + data['has_archive'] = persisted_result['archive_bytes'] is not None + step_values.append(data) + + with file(self._output_json_list, 'w') as o: + o.write(json.dumps(step_values)) + return base_test_result.ResultType.PASS + except KeyError: + logging.exception('Persistent results file missing key.') + return base_test_result.ResultType.FAIL + + def PrintTestOutput(self): + """Helper method to print the output of previously executed test_name. + + Test_name is passed from the command line as print_step + + Returns: + exit code generated by the test step. + """ + persisted_result = _GetPersistedResult(self._print_step) + if not persisted_result: + raise PersistentDataError('No data for test %s found.' % self._print_step) + logging.info('*' * 80) + logging.info('Output from:') + logging.info(persisted_result['cmd']) + logging.info('*' * 80) + + output_formatted = '' + persisted_outputs = persisted_result['output'] + for i in xrange(len(persisted_outputs)): + output_formatted += '\n\nOutput from run #%d:\n\n%s' % ( + i, persisted_outputs[i]) + print output_formatted + + if self._output_chartjson_data: + with file(self._output_chartjson_data, 'w') as f: + f.write(persisted_result['chartjson']) + + if self._output_dir_archive_path: + if persisted_result['archive_bytes'] is not None: + with file(self._output_dir_archive_path, 'wb') as f: + f.write(persisted_result['archive_bytes']) + else: + logging.error('The output dir was not archived.') + if persisted_result['exit_code'] == 0: + return base_test_result.ResultType.PASS + return base_test_result.ResultType.FAIL + + #override + def TestType(self): + return 'perf' + + @staticmethod + def ReadChartjsonOutput(output_dir): + if not output_dir: + return '' + json_output_path = os.path.join(output_dir, 'results-chart.json') + try: + with open(json_output_path) as f: + return f.read() + except IOError: + logging.exception('Exception when reading chartjson.') + logging.error('This usually means that telemetry did not run, so it could' + ' not generate the file. Please check the device running' + ' the test.') + return '' + + def WriteBuildBotJson(self, output_dir): + """Write metadata about the buildbot environment to the output dir.""" + if not output_dir or not self._write_buildbot_json: + return + data = { + 'chromium': _GetChromiumRevision(), + 'environment': dict(os.environ) + } + with open(os.path.join(output_dir, 'buildbot.json'), 'w') as f: + json.dump(data, f, sort_keys=True, separators=(',', ': ')) + + @property + def collect_chartjson_data(self): + return self._collect_chartjson_data + + @property + def dry_run(self): + return self._dry_run + + @property + def flaky_steps(self): + return self._flaky_steps + + @property + def known_devices_file(self): + return self._known_devices_file + + @property + def max_battery_temp(self): + return self._max_battery_temp + + @property + def min_battery_level(self): + return self._min_battery_level + + @property + def no_timeout(self): + return self._no_timeout + + @property + def output_chartjson_data(self): + return self._output_chartjson_data + + @property + def output_dir_archive_path(self): + return self._output_dir_archive_path + + @property + def output_json_list(self): + return self._output_json_list + + @property + def print_step(self): + return self._print_step + + @property + def single_step(self): + return self._single_step + + @property + def steps(self): + return self._steps + + @property + def test_filter(self): + return self._test_filter + + +class PersistentDataError(base_error.BaseError): + def __init__(self, message): + super(PersistentDataError, self).__init__(message) + self._is_infra_error = True
diff --git a/build/android/pylib/perf/surface_stats_collector.py b/build/android/pylib/perf/surface_stats_collector.py deleted file mode 100644 index 98b7fed..0000000 --- a/build/android/pylib/perf/surface_stats_collector.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.perf.surface_stats_collector import *
diff --git a/build/android/pylib/perf/thermal_throttle.py b/build/android/pylib/perf/thermal_throttle.py deleted file mode 100644 index 0473da88..0000000 --- a/build/android/pylib/perf/thermal_throttle.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.perf.thermal_throttle import *
diff --git a/build/android/pylib/sdk/__init__.py b/build/android/pylib/sdk/__init__.py deleted file mode 100644 index 50b23df..0000000 --- a/build/android/pylib/sdk/__init__.py +++ /dev/null
@@ -1,3 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file.
diff --git a/build/android/pylib/sdk/aapt.py b/build/android/pylib/sdk/aapt.py deleted file mode 100644 index 96fbf9c..0000000 --- a/build/android/pylib/sdk/aapt.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.sdk.aapt import *
diff --git a/build/android/pylib/sdk/dexdump.py b/build/android/pylib/sdk/dexdump.py deleted file mode 100644 index f7357f7..0000000 --- a/build/android/pylib/sdk/dexdump.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.sdk.dexdump import *
diff --git a/build/android/pylib/sdk/split_select.py b/build/android/pylib/sdk/split_select.py deleted file mode 100644 index 6adb106b..0000000 --- a/build/android/pylib/sdk/split_select.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.sdk.split_select import *
diff --git a/build/android/pylib/utils/apk_helper.py b/build/android/pylib/utils/apk_helper.py deleted file mode 100644 index dd458078..0000000 --- a/build/android/pylib/utils/apk_helper.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.apk_helper import *
diff --git a/build/android/pylib/utils/base_error.py b/build/android/pylib/utils/base_error.py deleted file mode 100644 index 263479a..0000000 --- a/build/android/pylib/utils/base_error.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.base_error import *
diff --git a/build/android/pylib/utils/device_temp_file.py b/build/android/pylib/utils/device_temp_file.py deleted file mode 100644 index ae1edc8..0000000 --- a/build/android/pylib/utils/device_temp_file.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.device_temp_file import *
diff --git a/build/android/pylib/utils/host_utils.py b/build/android/pylib/utils/host_utils.py deleted file mode 100644 index ba8c9d2..0000000 --- a/build/android/pylib/utils/host_utils.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.utils.host_utils import *
diff --git a/build/android/pylib/utils/md5sum.py b/build/android/pylib/utils/md5sum.py deleted file mode 100644 index a8fedcce..0000000 --- a/build/android/pylib/utils/md5sum.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.android.md5sum import *
diff --git a/build/android/pylib/utils/mock_calls.py b/build/android/pylib/utils/mock_calls.py deleted file mode 100644 index c65109d..0000000 --- a/build/android/pylib/utils/mock_calls.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.utils.mock_calls import *
diff --git a/build/android/pylib/utils/parallelizer.py b/build/android/pylib/utils/parallelizer.py deleted file mode 100644 index 49b18f02..0000000 --- a/build/android/pylib/utils/parallelizer.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.utils.parallelizer import *
diff --git a/build/android/pylib/utils/reraiser_thread.py b/build/android/pylib/utils/reraiser_thread.py deleted file mode 100644 index 828cd2b5..0000000 --- a/build/android/pylib/utils/reraiser_thread.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.utils.reraiser_thread import *
diff --git a/build/android/pylib/utils/run_tests_helper.py b/build/android/pylib/utils/run_tests_helper.py deleted file mode 100644 index 5c48668c..0000000 --- a/build/android/pylib/utils/run_tests_helper.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.utils.run_tests_helper import *
diff --git a/build/android/pylib/utils/timeout_retry.py b/build/android/pylib/utils/timeout_retry.py deleted file mode 100644 index e566f45..0000000 --- a/build/android/pylib/utils/timeout_retry.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.utils.timeout_retry import *
diff --git a/build/android/pylib/utils/watchdog_timer.py b/build/android/pylib/utils/watchdog_timer.py deleted file mode 100644 index 967794c..0000000 --- a/build/android/pylib/utils/watchdog_timer.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.utils.watchdog_timer import *
diff --git a/build/android/pylib/utils/zip_utils.py b/build/android/pylib/utils/zip_utils.py deleted file mode 100644 index 007b34b3..0000000 --- a/build/android/pylib/utils/zip_utils.py +++ /dev/null
@@ -1,8 +0,0 @@ -# Copyright 2015 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# pylint: disable=unused-wildcard-import -# pylint: disable=wildcard-import - -from devil.utils.zip_utils import *
diff --git a/build/android/test_runner.py b/build/android/test_runner.py index 46889f94..faec492 100755 --- a/build/android/test_runner.py +++ b/build/android/test_runner.py
@@ -562,9 +562,15 @@ '--output-chartjson-data', default='', help='Write out chartjson into the given file.') + # TODO(rnephew): Remove this when everything moves to new option in platform + # mode. group.add_argument( '--get-output-dir-archive', metavar='FILENAME', - help='Write the chached output directory archived by a step into the' + help='Write the cached output directory archived by a step into the' + ' given ZIP file.') + group.add_argument( + '--output-dir-archive-path', metavar='FILENAME', + help='Write the cached output directory archived by a step into the' ' given ZIP file.') group.add_argument( '--flaky-steps', @@ -585,12 +591,23 @@ '--max-battery-temp', type=int, help='Only start tests when the battery is at or below the given ' 'temperature (0.1 C)') - group.add_argument('single_step_command', nargs='*', action=SingleStepAction, - help='If --single-step is specified, the command to run.') - group.add_argument('--min-battery-level', type=int, - help='Only starts tests when the battery is charged above ' - 'given level.') + group.add_argument( + 'single_step_command', nargs='*', action=SingleStepAction, + help='If --single-step is specified, the command to run.') + group.add_argument( + '--min-battery-level', type=int, + help='Only starts tests when the battery is charged above ' + 'given level.') group.add_argument('--known-devices-file', help='Path to known device list.') + group.add_argument( + '--repeat', dest='repeat', type=int, default=0, + help='Number of times to repeat the specified set of tests.') + group.add_argument( + '--break-on-failure', '--break_on_failure', dest='break_on_failure', + action='store_true', help='Whether to break on failure.') + group.add_argument( + '--write-buildbot-json', action='store_true', + help='Whether to output buildbot json.') AddCommonOptions(parser) AddDeviceOptions(parser) @@ -776,6 +793,10 @@ return sorted(attached_devices) +# TODO(rnephew): Add perf when ready to switch to platform mode as default. +_DEFAULT_PLATFORM_MODE_TESTS = ['gtest', 'instrumentation'] + + def RunTestsCommand(args): # pylint: disable=too-many-return-statements """Checks test type and dispatches to the appropriate function. @@ -793,8 +814,7 @@ ProcessCommonOptions(args) logging.info('command: %s', ' '.join(sys.argv)) - - if args.enable_platform_mode or command in ('gtest', 'instrumentation'): + if args.enable_platform_mode or command in _DEFAULT_PLATFORM_MODE_TESTS: return RunTestsInPlatformMode(args) forwarder.Forwarder.RemoveHostLog() @@ -823,6 +843,7 @@ # TODO(jbudorick): Add support for more test types. 'gtest', 'instrumentation', + 'perf', 'uirobot', ]
diff --git a/build/android/test_runner.pydeps b/build/android/test_runner.pydeps index a1a7ed63..a751412 100644 --- a/build/android/test_runner.pydeps +++ b/build/android/test_runner.pydeps
@@ -46,6 +46,9 @@ ../../third_party/catapult/devil/devil/android/sdk/keyevent.py ../../third_party/catapult/devil/devil/android/sdk/split_select.py ../../third_party/catapult/devil/devil/android/sdk/version_codes.py +../../third_party/catapult/devil/devil/android/tools/__init__.py +../../third_party/catapult/devil/devil/android/tools/device_recovery.py +../../third_party/catapult/devil/devil/android/tools/device_status.py ../../third_party/catapult/devil/devil/android/valgrind_tools/__init__.py ../../third_party/catapult/devil/devil/android/valgrind_tools/base_tool.py ../../third_party/catapult/devil/devil/base_error.py @@ -58,8 +61,10 @@ ../../third_party/catapult/devil/devil/utils/host_utils.py ../../third_party/catapult/devil/devil/utils/lazy/__init__.py ../../third_party/catapult/devil/devil/utils/lazy/weak_constant.py +../../third_party/catapult/devil/devil/utils/lsusb.py ../../third_party/catapult/devil/devil/utils/parallelizer.py ../../third_party/catapult/devil/devil/utils/reraiser_thread.py +../../third_party/catapult/devil/devil/utils/reset_usb.py ../../third_party/catapult/devil/devil/utils/run_tests_helper.py ../../third_party/catapult/devil/devil/utils/signal_handler.py ../../third_party/catapult/devil/devil/utils/timeout_retry.py @@ -102,6 +107,7 @@ pylib/local/device/local_device_environment.py pylib/local/device/local_device_gtest_run.py pylib/local/device/local_device_instrumentation_test_run.py +pylib/local/device/local_device_perf_test_run.py pylib/local/device/local_device_test_run.py pylib/local/local_test_server_spawner.py pylib/monkey/__init__.py @@ -109,6 +115,7 @@ pylib/monkey/test_options.py pylib/monkey/test_runner.py pylib/perf/__init__.py +pylib/perf/perf_test_instance.py pylib/perf/setup.py pylib/perf/test_options.py pylib/perf/test_runner.py
diff --git a/build/common.gypi b/build/common.gypi index cdefdd1..0935433 100644 --- a/build/common.gypi +++ b/build/common.gypi
@@ -571,6 +571,9 @@ # SpellCheckerSession on Android. 'use_browser_spellchecker%': 0, + # Use Minikin hyphenation engine. + 'use_minikin_hyphenation%': 0, + # Webrtc compilation is enabled by default. Set to 0 to disable. 'enable_webrtc%': 1, @@ -698,6 +701,8 @@ # Control Flow Integrity for virtual calls and casts. # See http://clang.llvm.org/docs/ControlFlowIntegrity.html 'cfi_vptr%': 0, + # TODO(krasin): remove it. See https://crbug.com/626794. + 'cfi_cast%': 0, 'cfi_diag%': 0, 'cfi_blacklist%': '<(PRODUCT_DIR)/../../tools/cfi/blacklist.txt', @@ -826,6 +831,11 @@ 'use_browser_spellchecker%': 1, }], + # Android has hyphenation dictionaries for Minikin to use. + ['OS=="android"', { + 'use_minikin_hyphenation%': 1, + }], + # Enables proprietary codecs and demuxers; e.g. H264, AAC, MP3, and MP4. # We always build Google Chrome and Chromecast with proprietary codecs. ['branding=="Chrome" or chromecast==1', { @@ -966,17 +976,10 @@ }], ['chromeos==1', { - 'enable_basic_printing%': 0, + 'enable_basic_printing%': 1, 'enable_print_preview%': 1, }], - # Do not enable the Settings App on ChromeOS. - ['enable_app_list==1 and chromeos==0', { - 'enable_settings_app%': 1, - }, { - 'enable_settings_app%': 0, - }], - # Whether tests targets should be run, archived or just have the # dependencies verified. All the tests targets have the '_run' suffix, # e.g. base_unittests_run runs the target base_unittests. The test @@ -1226,6 +1229,7 @@ 'enable_print_preview%': '<(enable_print_preview)', 'enable_spellcheck%': '<(enable_spellcheck)', 'use_browser_spellchecker%': '<(use_browser_spellchecker)', + 'use_minikin_hyphenation%': '<(use_minikin_hyphenation)', 'cld2_table_size%': '<(cld2_table_size)', 'enable_captive_portal_detection%': '<(enable_captive_portal_detection)', 'disable_file_support%': '<(disable_file_support)', @@ -1242,7 +1246,6 @@ 'create_standalone_apk%': 1, 'enable_app_list%': '<(enable_app_list)', 'use_default_render_theme%': '<(use_default_render_theme)', - 'enable_settings_app%': '<(enable_settings_app)', 'google_api_key%': '<(google_api_key)', 'google_default_client_id%': '<(google_default_client_id)', 'google_default_client_secret%': '<(google_default_client_secret)', @@ -1259,6 +1262,7 @@ 'video_hole%': '<(video_hole)', 'v8_use_external_startup_data%': '<(v8_use_external_startup_data)', 'cfi_vptr%': '<(cfi_vptr)', + 'cfi_cast%': '<(cfi_cast)', 'cfi_diag%': '<(cfi_diag)', 'cfi_blacklist%': '<(cfi_blacklist)', 'mac_views_browser%': '<(mac_views_browser)', @@ -2017,7 +2021,7 @@ },{ 'msvs_large_module_debug_link_mode%': '2', # Yes }], - ['chrome_pgo_phase!=0 or target_arch=="x64"', { + ['chrome_pgo_phase!=0', { 'full_wpo_on_official%': 1, }], ], @@ -2163,9 +2167,6 @@ ['enable_app_list==1', { 'grit_defines': ['-D', 'enable_app_list'], }], - ['enable_settings_app==1', { - 'grit_defines': ['-D', 'enable_settings_app'], - }], ['use_concatenated_impulse_responses==1', { 'grit_defines': ['-D', 'use_concatenated_impulse_responses'], }], @@ -2941,15 +2942,15 @@ ['use_browser_spellchecker', { 'defines': ['USE_BROWSER_SPELLCHECKER=1'], }], + ['use_minikin_hyphenation', { + 'defines': ['USE_MINIKIN_HYPHENATION=1'], + }], ['enable_captive_portal_detection==1', { 'defines': ['ENABLE_CAPTIVE_PORTAL_DETECTION=1'], }], ['enable_app_list==1', { 'defines': ['ENABLE_APP_LIST=1'], }], - ['enable_settings_app==1', { - 'defines': ['ENABLE_SETTINGS_APP=1'], - }], ['disable_file_support==1', { 'defines': ['DISABLE_FILE_SUPPORT=1'], }], @@ -6212,8 +6213,6 @@ ['_toolset=="target"', { 'cflags': [ '-fsanitize=cfi-vcall', - '-fsanitize=cfi-derived-cast', - '-fsanitize=cfi-unrelated-cast', '-fsanitize-blacklist=<(cfi_blacklist)', ], 'ldflags': [ @@ -6224,8 +6223,6 @@ 'xcode_settings': { 'OTHER_CFLAGS': [ '-fsanitize=cfi-vcall', - '-fsanitize=cfi-derived-cast', - '-fsanitize=cfi-unrelated-cast', '-fsanitize-blacklist=<(cfi_blacklist)', ], }, @@ -6234,6 +6231,34 @@ 'xcode_settings': { 'OTHER_LDFLAGS': [ '-fsanitize=cfi-vcall', + ], + }, + }], + ], + }, + }], + ['cfi_vptr==1 and cfi_cast==1', { + 'target_defaults': { + 'target_conditions': [ + ['_toolset=="target"', { + 'cflags': [ + '-fsanitize=cfi-derived-cast', + '-fsanitize=cfi-unrelated-cast', + ], + 'ldflags': [ + '-fsanitize=cfi-derived-cast', + '-fsanitize=cfi-unrelated-cast', + ], + 'xcode_settings': { + 'OTHER_CFLAGS': [ + '-fsanitize=cfi-derived-cast', + '-fsanitize=cfi-unrelated-cast', + ], + }, + }], + ['_toolset=="target" and _type!="static_library"', { + 'xcode_settings': { + 'OTHER_LDFLAGS': [ '-fsanitize=cfi-derived-cast', '-fsanitize=cfi-unrelated-cast', ],
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn index c06f6ab..4934afa 100644 --- a/build/config/BUILD.gn +++ b/build/config/BUILD.gn
@@ -201,9 +201,6 @@ if (enable_app_list) { defines += [ "ENABLE_APP_LIST=1" ] } - if (enable_settings_app) { - defines += [ "ENABLE_SETTINGS_APP=1" ] - } if (enable_supervised_users) { defines += [ "ENABLE_SUPERVISED_USERS=1" ] }
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn index 4f3a223c..2036b345 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn
@@ -639,9 +639,14 @@ assert(invoker.static_component_type == "static_library" || invoker.static_component_type == "source_set") _component_mode = invoker.static_component_type - } else if (!defined(invoker.sources)) { + } else if (is_android || !defined(invoker.sources)) { # When there are no sources defined, use a source set to avoid creating # an empty static library (which generally don't work). + # + # TODO(brettw) remove the Android condition or comment why it needs to be + # kept after some analysis. Source sets vs. static libraries seem to be + # causing some performance differences. As part of the analysis for + # http://crbug.com/619593 we're testing source sets for components again. _component_mode = "source_set" } else { _component_mode = "static_library"
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 363a53a..22093c1 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -327,6 +327,11 @@ rebase_path(invoker.srcjar, root_build_dir), ] } + if (defined(invoker.bundled_srcjars)) { + _rebased_bundled_srcjars = + rebase_path(invoker.bundled_srcjars, root_build_dir) + args += [ "--bundled-srcjars=$_rebased_bundled_srcjars" ] + } } } @@ -2157,6 +2162,15 @@ if (_java_files != []) { java_sources_file = _java_sources_file } + + if (defined(invoker.srcjar_deps)) { + bundled_srcjars = [] + foreach(d, invoker.srcjar_deps) { + _dep_gen_dir = get_label_info(d, "target_gen_dir") + _dep_name = get_label_info(d, "name") + bundled_srcjars += [ "$_dep_gen_dir/$_dep_name.srcjar" ] + } + } } _accumulated_deps += [ ":$build_config_target_name" ] }
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni index dd89503..1090faf 100644 --- a/build/config/compiler/compiler.gni +++ b/build/config/compiler/compiler.gni
@@ -51,7 +51,7 @@ declare_args() { # Whether or not the official builds should be built with full WPO. Enabled by # default for the PGO and the x64 builds. - if (chrome_pgo_phase > 0 || target_cpu == "x64") { + if (chrome_pgo_phase > 0) { full_wpo_on_official = true } else { full_wpo_on_official = false
diff --git a/build/config/features.gni b/build/config/features.gni index f0dca909..d3bf763 100644 --- a/build/config/features.gni +++ b/build/config/features.gni
@@ -44,7 +44,7 @@ enable_webrtc = !is_ios # Enables the Media Router. - enable_media_router = !is_ios + enable_media_router = !is_ios && !is_chromecast # Enables proprietary codecs and demuxers; e.g. H264, AAC, MP3, and MP4. # We always build Google Chrome and Chromecast with proprietary codecs. @@ -81,7 +81,7 @@ # external API. if (is_android) { safe_browsing_mode = 2 - } else if (is_ios) { + } else if (is_ios || is_chromecast) { safe_browsing_mode = 0 } else { safe_browsing_mode = 1 @@ -110,7 +110,7 @@ use_gio = is_linux && !is_chromeos && !is_chromecast # Enable basic printing support and UI. - enable_basic_printing = !is_chromeos && !is_chromecast && !is_ios + enable_basic_printing = !is_chromecast && !is_ios # Enable printing with print preview. It does not imply # enable_basic_printing. It's possible to build Chrome with preview only. @@ -128,6 +128,9 @@ # Use the operating system's spellchecker rather than hunspell. use_browser_spellchecker = is_android || is_mac +# Use Minikin hyphenation engine. +use_minikin_hyphenation = is_android + # Enables the use of CDMs in pepper plugins. enable_pepper_cdms = enable_plugins && (is_linux || is_mac || is_win) && !is_chromecast @@ -155,8 +158,6 @@ enable_rlz_support = is_win || is_mac || is_ios || is_chromeos enable_rlz = is_chrome_branded && enable_rlz_support -enable_settings_app = enable_app_list && !is_chromeos - enable_service_discovery = enable_mdns || is_mac # Image loader extension is enabled on ChromeOS only.
diff --git a/build/config/ios/ios_sdk.gni b/build/config/ios/ios_sdk.gni index 31885e77..e3abd7b 100644 --- a/build/config/ios/ios_sdk.gni +++ b/build/config/ios/ios_sdk.gni
@@ -23,6 +23,43 @@ # ios_enable_code_signing_flag=<bool> flag to make the invocation clearer. ios_enable_code_signing = true ios_code_signing_identity = "" + + # If non-empty, this list must contain valid cpu architecture, and the final + # build will be a multi-architecture build (aka fat build) supporting the + # main $target_cpu architecture and all of $additional_target_cpus. + # + # For example to build an application that will run on both arm64 and armv7 + # devices, you would use the following in args.gn file when running "gn args": + # + # target_os = "ios" + # target_cpu = "arm64" + # additional_target_cpus = [ "arm" ] + # + # You can also pass the value via "--args" parameter for "gn gen" command by + # using the syntax --args='additional_target_cpus=["arm"] target_cpu="arm64"'. + additional_target_cpus = [] +} + +assert(custom_toolchain == "" || additional_target_cpus == [], + "cannot define both custom_toolchain and additional_target_cpus") + +# Initialize additional_toolchains from additional_target_cpus. Assert here +# that the list does not contains $target_cpu nor duplicates as this would +# cause weird errors during the build. +additional_toolchains = [] +if (additional_target_cpus != []) { + foreach(_additional_target_cpu, additional_target_cpus) { + assert(_additional_target_cpu != target_cpu, + "target_cpu must not be listed in additional_target_cpus") + + _toolchain = "//build/toolchain/mac:ios_clang_$_additional_target_cpu" + foreach(_additional_toolchain, additional_toolchains) { + assert(_toolchain != _additional_toolchain, + "additional_target_cpus must not contains duplicate values") + } + + additional_toolchains += [ _toolchain ] + } } if (ios_sdk_path == "") {
diff --git a/build/config/ios/rules.gni b/build/config/ios/rules.gni index 219b580b..aec0de5 100644 --- a/build/config/ios/rules.gni +++ b/build/config/ios/rules.gni
@@ -70,10 +70,6 @@ } } -# TODO(crbug.com/297668): refactor this template to extract common behaviour -# between OS X and iOS bundle generation, then create a generic "app" template -# that forward to "executable" on all platform except iOS/OS X. - # Template to build an application bundle for iOS. # # This should be used instead of "executable" built-in target type on iOS. @@ -122,155 +118,323 @@ _output_name = invoker.output_name } - _generate_info_plist = target_name + "_generate_info_plist" - _bundle_data_info_plist = target_name + "_bundle_data_info_plist" + # This template expands to multiple targets with some differences between + # the the different build configuration. + # + # For a thin build (i.e. when additional_target_cpus is an empty list), + # it compiles the final application binary with an "executable" target, + # performs variable expansions on the Info.plist, defines some "bundle_data" + # target to pack Info.plist and the executable into the .app bundle, and + # finally a "create_bundle" target that packs everything the bundle. If the + # bundle needs to be signed, then the binary is copied into the bundle by + # the "create_bundle" target and the intermediate "bundle_data" target is + # not generated. + # + # For a multi-architecture build (aka fat-build), the template expands to + # a simple "executable" target for non-default toolchain. This is because + # the real application bundle will contains a single binary that supports + # all the architectures and creating a separate .app bundle for every + # architecture would be a waste of time. + # + # The target for the default toolchain of a multi-architecture build will + # build the executable for current_cpu in a temporary location. The real + # fat binary will be created by "lipo" command from all those "executable" + # target (including those of the non-default toolchains). This additional + # target has the same role as the "executable" target of a thin build. + # + # The rest of the build, including the codesigning step, are the same for + # thin and fat builds. - ios_info_plist(_generate_info_plist) { - executable_name = _output_name - forward_variables_from(invoker, - [ - "extra_substitutions", - "info_plist", - "info_plist_target", - ]) + _is_fat_build = additional_toolchains != [] + if (_is_fat_build) { + _is_fat_build_main_target = current_toolchain == default_toolchain } - bundle_data(_bundle_data_info_plist) { - forward_variables_from(invoker, [ "testonly" ]) - visibility = [ ":$_target_name" ] - sources = get_target_outputs(":$_generate_info_plist") - outputs = [ - "{{bundle_root_dir}}/Info.plist", - ] - public_deps = [ - ":$_generate_info_plist", - ] - } + if (_is_fat_build && !_is_fat_build_main_target) { + # For the non-default toolchain of a fat-build, the template expands to a + # single "executable" target that creates "$root_out_dir/$_output_name". + executable(_target_name) { + forward_variables_from(invoker, + "*", + [ + "bundle_extension", + "entitlements_path", + "extra_substitutions", + "info_plist", + "info_plist_target", + "output_name", + "product_type", + ]) - _generate_executable = target_name + "_generate_executable" - if (!ios_enable_code_signing) { - _bundle_data_executable = target_name + "_bundle_data_executable" - } + if (defined(visibility)) { + visibility += [ ":*($default_toolchain)" ] + } - executable(_generate_executable) { - if (ios_enable_code_signing) { + output_name = _output_name + if (!defined(libs)) { + libs = [] + } + libs += [ "UIKit.framework" ] + if (!defined(ldflags)) { + ldflags = [] + } + ldflags += [ "-ObjC" ] + } + } else { + # This is either a thin build or the default toolchain of a fat-build. + # The template will expand in many different target ($target_name is the + # create_bundle target) used as input to the create_bundle target. + _generate_info_plist = target_name + "_generate_info_plist" + _bundle_data_info_plist = target_name + "_bundle_data_info_plist" + + ios_info_plist(_generate_info_plist) { + visibility = [ ":$_bundle_data_info_plist" ] + executable_name = _output_name + forward_variables_from(invoker, + [ + "extra_substitutions", + "info_plist", + "info_plist_target", + ]) + } + + bundle_data(_bundle_data_info_plist) { visibility = [ ":$_target_name" ] - } else { - visibility = [ ":$_bundle_data_executable" ] - } - forward_variables_from(invoker, - "*", - [ - "bundle_extension", - "data_deps", - "entitlements_path", - "info_plist", - "info_plist_target", - "output_name", - "product_type", - "visibility", - ]) - - output_name = rebase_path("$target_gen_dir/$_output_name", root_out_dir) - output_prefix_override = true - - if (!defined(libs)) { - libs = [] - } - libs += [ "UIKit.framework" ] - if (!defined(ldflags)) { - ldflags = [] - } - ldflags += [ "-ObjC" ] - } - - if (!ios_enable_code_signing) { - bundle_data(_bundle_data_executable) { forward_variables_from(invoker, [ "testonly" ]) - visibility = [ ":$_target_name" ] - sources = [ - "$target_gen_dir/$_output_name", - ] + sources = get_target_outputs(":$_generate_info_plist") outputs = [ - "{{bundle_executable_dir}}/$_output_name", + "{{bundle_root_dir}}/Info.plist", ] public_deps = [ - ":$_generate_executable", + ":$_generate_info_plist", ] } + + _link_executable = _target_name + "_link_executable" + _executable_path = "$target_out_dir/$_output_name" + + if (ios_enable_code_signing) { + _link_executable_visibility = [ ":$_target_name" ] + } else { + _bundle_data_executable = target_name + "_bundle_data_executable" + _link_executable_visibility = [ ":$_bundle_data_executable" ] + } + + # For a fat-build, the different "executable" outputs will be used to + # create the final binary using "lipo". As the corresponding target has + # the same role as the "executable" target in a thin build, copy the + # visibility and redefine some variables. + if (_is_fat_build) { + _lipo_executable = _target_name + "_lipo_executable" + _lipo_executable_visibility = _link_executable_visibility + + _link_executable_visibility = [] + _link_executable_visibility = [ ":$_lipo_executable" ] + + _arch_executable_path = "$target_out_dir/$current_cpu/$_output_name" + } + + executable(_link_executable) { + forward_variables_from(invoker, + "*", + [ + "bundle_extension", + "data_deps", + "entitlements_path", + "extra_substitutions", + "info_plist", + "info_plist_target", + "output_name", + "product_type", + "visibility", + ]) + + visibility = _link_executable_visibility + + output_prefix_override = true + if (_is_fat_build) { + output_name = rebase_path(_arch_executable_path, root_build_dir) + } else { + output_name = rebase_path(_executable_path, root_build_dir) + } + + if (!defined(libs)) { + libs = [] + } + libs += [ "UIKit.framework" ] + if (!defined(ldflags)) { + ldflags = [] + } + ldflags += [ "-ObjC" ] + } + + if (_is_fat_build) { + # Create the multi-architecture binary from all the single architecture + # binaries using "lipo". This target exists for the default toolchain + # of a fat-build only and depends on the expansion of "ios_app_bundle" + # for the other toolchains (i.e. a single "executable" target). + # + # This action only happens once per "ios_app_bundle" template (for the + # main toolchain). + action(_lipo_executable) { + forward_variables_from(invoker, [ "testonly" ]) + visibility = _lipo_executable_visibility + script = "//build/config/mac/xcrun.py" + outputs = [ + _executable_path, + ] + inputs = [ + _arch_executable_path, + ] + deps = [ + ":$_link_executable", + ] + foreach(_additional_toolchain, additional_toolchains) { + _additional_toolchain_target = "$_target_name($_additional_toolchain)" + deps += [ ":$_additional_toolchain_target" ] + inputs += [ get_label_info(_additional_toolchain_target, + "root_out_dir") + "/$_output_name" ] + } + args = [ + "lipo", + "-create", + "-output", + rebase_path(outputs[0], root_build_dir), + ] + rebase_path(inputs, root_build_dir) + } + } + + if (!ios_enable_code_signing) { + # If codesigning is enabled, the binary will be copied into the bundle + # by the codesigning script (as the binary is updated by the signature). + # Otherwise, this "bundle_data" declares the location of the binary in + # the .app bundle. + bundle_data(_bundle_data_executable) { + forward_variables_from(invoker, [ "testonly" ]) + visibility = [ ":$_target_name" ] + outputs = [ + "{{bundle_executable_dir}}/$_output_name", + ] + if (_is_fat_build) { + public_deps = [ + ":$_lipo_executable", + ] + } else { + public_deps = [ + ":$_link_executable", + ] + } + sources = [ + "$target_out_dir/$_output_name", + ] + } + } + + create_bundle(target_name) { + forward_variables_from(invoker, + [ + "data_deps", + "deps", + "public_deps", + "testonly", + "visibility", + ]) + + if (!defined(deps)) { + deps = [] + } + deps += [ ":$_bundle_data_info_plist" ] + if (ios_enable_code_signing) { + if (_is_fat_build) { + deps += [ ":$_lipo_executable" ] + } else { + deps += [ ":$_link_executable" ] + } + } else { + deps += [ ":$_bundle_data_executable" ] + } + + if (use_ios_simulator) { + if (!defined(data_deps)) { + data_deps = [] + } + data_deps += [ "//testing/iossim" ] + } + + if (defined(invoker.product_type)) { + product_type = invoker.product_type + } else { + product_type = "com.apple.product-type.application" + } + + if (defined(invoker.bundle_extension)) { + _bundle_extension = invoker.bundle_extension + } else { + _bundle_extension = ".app" + } + + bundle_root_dir = "$root_out_dir/$_output_name$_bundle_extension" + bundle_resources_dir = bundle_root_dir + bundle_executable_dir = bundle_root_dir + bundle_plugins_dir = "$bundle_root_dir/PlugIns" + + if (ios_enable_code_signing) { + _entitlements_path = "$ios_sdk_path/Entitlements.plist" + if (defined(invoker.entitlements_path)) { + _entitlements_path = invoker.entitlements_path + } + + code_signing_script = "//build/config/ios/codesign.py" + code_signing_sources = [ + _entitlements_path, + "$target_out_dir/$_output_name", + ] + code_signing_outputs = [ + "$bundle_root_dir/$_output_name", + "$bundle_root_dir/_CodeSignature/CodeResources", + "$bundle_root_dir/embedded.mobileprovision", + ] + code_signing_args = [ + "-i=" + ios_code_signing_identity, + "-b=" + rebase_path("$target_out_dir/$_output_name", root_build_dir), + "-e=" + rebase_path(_entitlements_path, root_build_dir), + rebase_path(bundle_root_dir, root_build_dir), + ] + } + } } - create_bundle(target_name) { - forward_variables_from(invoker, - [ - "data_deps", - "deps", - "public_deps", - "testonly", - "visibility", - ]) - - if (!defined(deps)) { - deps = [] - } - deps += [ ":$_bundle_data_info_plist" ] - if (ios_enable_code_signing) { - deps += [ ":$_generate_executable" ] - } else { - deps += [ ":$_bundle_data_executable" ] - } - - if (use_ios_simulator) { - if (!defined(data_deps)) { - data_deps = [] - } - data_deps += [ "//testing/iossim" ] - } - - if (defined(invoker.product_type)) { - product_type = invoker.product_type - } else { - product_type = "com.apple.product-type.application" - } - - if (defined(invoker.bundle_extension)) { - _bundle_extension = invoker.bundle_extension - } else { - _bundle_extension = ".app" - } - - bundle_root_dir = "$root_out_dir/$_output_name$_bundle_extension" - bundle_resources_dir = bundle_root_dir - bundle_executable_dir = bundle_root_dir - bundle_plugins_dir = "$bundle_root_dir/PlugIns" - - if (defined(invoker.entitlements_path)) { - _entitlements_path = invoker.entitlements_path - } else { - _entitlements_path = "$ios_sdk_path/Entitlements.plist" - } - - if (ios_enable_code_signing) { - code_signing_script = "//build/config/ios/codesign.py" - code_signing_sources = [ - _entitlements_path, - "$target_gen_dir/$_output_name", - ] - code_signing_outputs = [ - "$bundle_root_dir/$_output_name", - "$bundle_root_dir/_CodeSignature/CodeResources", - "$bundle_root_dir/embedded.mobileprovision", - ] - code_signing_args = [ - "-i=" + ios_code_signing_identity, - "-b=" + rebase_path("$target_gen_dir/$_output_name", root_build_dir), - "-e=" + rebase_path(_entitlements_path, root_build_dir), - rebase_path(bundle_root_dir, root_build_dir), - ] - } else { - assert(_entitlements_path != "", - "force usage of _entitlements_path to avoid unused variable error") - } + # TODO(crbug.com/395883): ensure those variables are marked as used to + # avoid errors while running "gn gen". + if (defined(invoker.entitlements_path)) { + assert(invoker.entitlements_path != "", + "mark invoker.entitlements_path as used") + } + if (defined(invoker.bundle_extension)) { + assert(invoker.bundle_extension != "", + "mark invoker.bundle_extension as used") + } + if (defined(invoker.bundle_extension)) { + assert(invoker.bundle_extension != "", + "mark invoker.bundle_extension as used") + } + if (defined(invoker.entitlements_path)) { + assert(invoker.entitlements_path != "", + "mark invoker.entitlements_path as used") + } + if (defined(invoker.extra_substitutions)) { + assert(invoker.extra_substitutions != [], + "mark invoker.extra_substitutions as used") + } + if (defined(invoker.info_plist)) { + assert(invoker.info_plist != "", "mark invoker.info_plist as used") + } + if (defined(invoker.info_plist_target)) { + assert(invoker.info_plist_target != "", + "mark invoker.info_plist_target as used") + } + if (defined(invoker.product_type)) { + assert(invoker.product_type != "", "mark product_type as used") } }
diff --git a/build/config/locales.gni b/build/config/locales.gni index 98c53c6..5886132 100644 --- a/build/config/locales.gni +++ b/build/config/locales.gni
@@ -9,19 +9,15 @@ if (is_ios) { ios_unsupported_locales = [ "am", - "bg", "bn", "et", - "fa", "fil", "gu", "kn", - "lt", "lv", "ml", "mr", "sl", - "sr", "sw", "ta", "te",
diff --git a/build/config/sanitizers/BUILD.gn b/build/config/sanitizers/BUILD.gn index 0b099f4..695dba0 100644 --- a/build/config/sanitizers/BUILD.gn +++ b/build/config/sanitizers/BUILD.gn
@@ -155,11 +155,13 @@ } if (is_cfi && !is_nacl) { - ldflags += [ - "-fsanitize=cfi-vcall", - "-fsanitize=cfi-derived-cast", - "-fsanitize=cfi-unrelated-cast", - ] + ldflags += [ "-fsanitize=cfi-vcall" ] + if (use_cfi_cast) { + ldflags += [ + "-fsanitize=cfi-derived-cast", + "-fsanitize=cfi-unrelated-cast", + ] + } if (use_cfi_diag) { ldflags += [ "-fno-sanitize-trap=cfi", @@ -206,6 +208,12 @@ cflags = [] if (is_asan) { cflags += [ "-fsanitize=address" ] + if (!asan_globals) { + cflags += [ + "-mllvm", + "-asan-globals=0", + ] + } if (is_win) { cflags += [ "-fsanitize-blacklist=" + rebase_path("//tools/memory/asan/blacklist_win.txt", @@ -216,23 +224,8 @@ [ "-fsanitize-blacklist=" + rebase_path("//tools/memory/asan/blacklist.txt", root_build_dir) ] } - if (is_android) { - # Android build relies on -Wl,--gc-sections removing unreachable code. - # ASan instrumentation for globals inhibits this and results in a - # library with unresolvable relocations. - # TODO(eugenis): find a way to reenable this. - cflags += [ - "-mllvm", - "-asan-globals=0", - ] - } else if (is_mac) { - # http://crbug.com/352073 - cflags += [ - "-mllvm", - "-asan-globals=0", - ] - # TODO(GYP): deal with mac_bundles. - } else if (is_win) { + + if (is_win) { assert(current_cpu == "x86", "WinASan is 32-bit only currently") if (is_component_build) { libs = [ @@ -255,11 +248,16 @@ rebase_path("//tools/cfi/blacklist.txt", root_build_dir) cflags += [ "-fsanitize=cfi-vcall", - "-fsanitize=cfi-derived-cast", - "-fsanitize=cfi-unrelated-cast", "-fsanitize-blacklist=$cfi_blacklist_path", ] + if (use_cfi_cast) { + cflags += [ + "-fsanitize=cfi-derived-cast", + "-fsanitize=cfi-unrelated-cast", + ] + } + if (use_cfi_diag) { cflags += [ "-fno-sanitize-trap=cfi",
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni index 32cecff..c58e72f66 100644 --- a/build/config/sanitizers/sanitizers.gni +++ b/build/config/sanitizers/sanitizers.gni
@@ -49,6 +49,11 @@ # TODO(pcc): Remove this flag if/when CFI is enabled in official builds. is_cfi = false + # Enable checks for bad casts: derived cast and unrelated cast. + # TODO(krasin): remove this, when we're ready to add these checks by default. + # https://crbug.com/626794 + use_cfi_cast = false + # By default, Control Flow Integrity will crash the program if it detects a # violation. Set this to true to print detailed diagnostics instead. use_cfi_diag = false @@ -78,7 +83,6 @@ # trace-pc # Default value when unset and use_sanitizer_coverage=true: # edge,indirect-calls,8bit-counters - sanitizer_coverage_flags = "" } @@ -96,6 +100,16 @@ # Enable -fsanitize-coverage. use_sanitizer_coverage = use_libfuzzer || use_afl || sanitizer_coverage_flags != "" + + # Detect overflow/underflow for global objects. + # + # Android build relies on -Wl,--gc-sections removing unreachable code. + # ASan instrumentation for globals inhibits this and results in a + # library with unresolvable relocations. + # TODO(eugenis): find a way to reenable this. + # + # Mac: http://crbug.com/352073 + asan_globals = !is_android && !is_mac } if (use_afl && sanitizer_coverage_flags == "") {
diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi index 8cf538d3..af9e26e 100644 --- a/build/gn_migration.gypi +++ b/build/gn_migration.gypi
@@ -55,6 +55,7 @@ '../content/content_shell_and_tests.gyp:content_unittests', '../crypto/crypto.gyp:crypto_unittests', '../device/device_tests.gyp:device_unittests', + '../gin/gin.gyp:gin_v8_snapshot_fingerprint', '../gpu/gpu.gyp:angle_unittests', '../gpu/gpu.gyp:gl_tests', '../gpu/gpu.gyp:gpu_perftests',
diff --git a/build/secondary/tools/swarming_client/isolate.pydeps b/build/secondary/tools/swarming_client/isolate.pydeps index d7a9189..fa7c47d 100644 --- a/build/secondary/tools/swarming_client/isolate.pydeps +++ b/build/secondary/tools/swarming_client/isolate.pydeps
@@ -1,6 +1,7 @@ # Generated by running: # build/print_python_deps.py --root tools/swarming_client --output build/secondary/tools/swarming_client/isolate.pydeps --whitelist tools/swarming_client/third_party tools/swarming_client/isolate.py auth.py +cipd.py isolate.py isolate_format.py isolated_format.py @@ -213,6 +214,7 @@ utils/__init__.py utils/file_path.py utils/fs.py +utils/large.py utils/logging_utils.py utils/lru.py utils/net.py
diff --git a/cc/PRESUBMIT.py b/cc/PRESUBMIT.py index c1f2ad20..56448098 100644 --- a/cc/PRESUBMIT.py +++ b/cc/PRESUBMIT.py
@@ -338,7 +338,7 @@ return [] bots = [ - 'tryserver.blink:linux_blink_rel', + 'master.tryserver.blink:linux_blink_rel', ] results = []
diff --git a/cc/base/rolling_time_delta_history.cc b/cc/base/rolling_time_delta_history.cc index e296c4b..a80ca21 100644 --- a/cc/base/rolling_time_delta_history.cc +++ b/cc/base/rolling_time_delta_history.cc
@@ -4,6 +4,7 @@ #include <stddef.h> +#include <algorithm> #include <cmath> #include "cc/base/rolling_time_delta_history.h" @@ -11,7 +12,9 @@ namespace cc { RollingTimeDeltaHistory::RollingTimeDeltaHistory(size_t max_size) - : max_size_(max_size) {} + : next_index_(0), max_size_(max_size) { + sample_vector_.reserve(max_size_); +} RollingTimeDeltaHistory::~RollingTimeDeltaHistory() {} @@ -19,47 +22,37 @@ if (max_size_ == 0) return; - if (sample_set_.size() == max_size_) { - sample_set_.erase(chronological_sample_deque_.front()); - chronological_sample_deque_.pop_front(); + if (sample_vector_.size() == max_size_) { + sample_vector_[next_index_++] = time; + if (next_index_ == max_size_) + next_index_ = 0; + } else { + sample_vector_.push_back(time); } - - TimeDeltaMultiset::iterator it = sample_set_.insert(time); - chronological_sample_deque_.push_back(it); } void RollingTimeDeltaHistory::Clear() { - chronological_sample_deque_.clear(); - sample_set_.clear(); + sample_vector_.clear(); + next_index_ = 0; } base::TimeDelta RollingTimeDeltaHistory::Percentile(double percent) const { - if (sample_set_.size() == 0) + if (sample_vector_.size() == 0) return base::TimeDelta(); double fraction = percent / 100.0; - if (fraction <= 0.0) - return *(sample_set_.begin()); + return *std::min_element(sample_vector_.begin(), sample_vector_.end()); if (fraction >= 1.0) - return *(sample_set_.rbegin()); + return *std::max_element(sample_vector_.begin(), sample_vector_.end()); size_t num_smaller_samples = - static_cast<size_t>(std::ceil(fraction * sample_set_.size())) - 1; + static_cast<size_t>(std::ceil(fraction * sample_vector_.size())) - 1; - if (num_smaller_samples > sample_set_.size() / 2) { - size_t num_larger_samples = sample_set_.size() - num_smaller_samples - 1; - TimeDeltaMultiset::const_reverse_iterator it = sample_set_.rbegin(); - for (size_t i = 0; i < num_larger_samples; i++) - it++; - return *it; - } - - TimeDeltaMultiset::const_iterator it = sample_set_.begin(); - for (size_t i = 0; i < num_smaller_samples; i++) - it++; - return *it; + std::vector<base::TimeDelta> v(sample_vector_.begin(), sample_vector_.end()); + std::nth_element(v.begin(), v.begin() + num_smaller_samples, v.end()); + return v[num_smaller_samples]; } } // namespace cc
diff --git a/cc/base/rolling_time_delta_history.h b/cc/base/rolling_time_delta_history.h index 61ed339..192c8e07 100644 --- a/cc/base/rolling_time_delta_history.h +++ b/cc/base/rolling_time_delta_history.h
@@ -7,8 +7,7 @@ #include <stddef.h> -#include <deque> -#include <set> +#include <vector> #include "base/macros.h" #include "base/time/time.h" @@ -33,10 +32,8 @@ base::TimeDelta Percentile(double percent) const; private: - typedef std::multiset<base::TimeDelta> TimeDeltaMultiset; - - TimeDeltaMultiset sample_set_; - std::deque<TimeDeltaMultiset::iterator> chronological_sample_deque_; + std::vector<base::TimeDelta> sample_vector_; + size_t next_index_; size_t max_size_; DISALLOW_COPY_AND_ASSIGN(RollingTimeDeltaHistory);
diff --git a/cc/ipc/cc_param_traits.cc b/cc/ipc/cc_param_traits.cc index 43864d3..26c804f 100644 --- a/cc/ipc/cc_param_traits.cc +++ b/cc/ipc/cc_param_traits.cc
@@ -570,13 +570,13 @@ void ParamTraits<cc::SurfaceId>::GetSize(base::PickleSizer* s, const param_type& p) { - GetParamSize(s, p.id_namespace()); + GetParamSize(s, p.client_id()); GetParamSize(s, p.local_id()); GetParamSize(s, p.nonce()); } void ParamTraits<cc::SurfaceId>::Write(base::Pickle* m, const param_type& p) { - WriteParam(m, p.id_namespace()); + WriteParam(m, p.client_id()); WriteParam(m, p.local_id()); WriteParam(m, p.nonce()); } @@ -584,8 +584,8 @@ bool ParamTraits<cc::SurfaceId>::Read(const base::Pickle* m, base::PickleIterator* iter, param_type* p) { - uint32_t id_namespace; - if (!ReadParam(m, iter, &id_namespace)) + uint32_t client_id; + if (!ReadParam(m, iter, &client_id)) return false; uint32_t local_id; @@ -596,13 +596,13 @@ if (!ReadParam(m, iter, &nonce)) return false; - *p = cc::SurfaceId(id_namespace, local_id, nonce); + *p = cc::SurfaceId(client_id, local_id, nonce); return true; } void ParamTraits<cc::SurfaceId>::Log(const param_type& p, std::string* l) { l->append("SurfaceId("); - LogParam(p.id_namespace(), l); + LogParam(p.client_id(), l); l->append(", "); LogParam(p.local_id(), l); l->append(", "); @@ -677,45 +677,18 @@ void ParamTraits<cc::CompositorFrameAck>::Write(base::Pickle* m, const param_type& p) { WriteParam(m, p.resources); - if (p.gl_frame_data) { - WriteParam(m, static_cast<int>(GL_FRAME)); - WriteParam(m, *p.gl_frame_data); - } else { - WriteParam(m, static_cast<int>(NO_FRAME)); - } } bool ParamTraits<cc::CompositorFrameAck>::Read(const base::Pickle* m, base::PickleIterator* iter, param_type* p) { - if (!ReadParam(m, iter, &p->resources)) - return false; - - int compositor_frame_type; - if (!ReadParam(m, iter, &compositor_frame_type)) - return false; - - switch (compositor_frame_type) { - case NO_FRAME: - break; - case GL_FRAME: - p->gl_frame_data.reset(new cc::GLFrameData()); - if (!ReadParam(m, iter, p->gl_frame_data.get())) - return false; - break; - default: - return false; - } - return true; + return ReadParam(m, iter, &p->resources); } void ParamTraits<cc::CompositorFrameAck>::Log(const param_type& p, std::string* l) { l->append("CompositorFrameAck("); LogParam(p.resources, l); - l->append(", "); - if (p.gl_frame_data) - LogParam(*p.gl_frame_data, l); l->append(")"); }
diff --git a/cc/ipc/cc_param_traits_macros.h b/cc/ipc/cc_param_traits_macros.h index 43431c6..655ea26 100644 --- a/cc/ipc/cc_param_traits_macros.h +++ b/cc/ipc/cc_param_traits_macros.h
@@ -47,7 +47,7 @@ IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(cc::SurfaceSequence) - IPC_STRUCT_TRAITS_MEMBER(id_namespace) + IPC_STRUCT_TRAITS_MEMBER(client_id) IPC_STRUCT_TRAITS_MEMBER(sequence) IPC_STRUCT_TRAITS_END()
diff --git a/cc/ipc/compositor_frame.typemap b/cc/ipc/compositor_frame.typemap index f6818b7..5b7b1e8 100644 --- a/cc/ipc/compositor_frame.typemap +++ b/cc/ipc/compositor_frame.typemap
@@ -12,4 +12,4 @@ "//cc", ] type_mappings = - [ "cc.mojom.CompositorFrame=cc::CompositorFrame[pass_by_value]" ] + [ "cc.mojom.CompositorFrame=cc::CompositorFrame[move_only]" ]
diff --git a/cc/ipc/struct_traits_unittest.cc b/cc/ipc/struct_traits_unittest.cc index f74f10ad..2748f6f1 100644 --- a/cc/ipc/struct_traits_unittest.cc +++ b/cc/ipc/struct_traits_unittest.cc
@@ -729,26 +729,26 @@ } TEST_F(StructTraitsTest, SurfaceId) { - const uint32_t id_namespace = 1337; + const uint32_t client_id = 1337; const uint32_t local_id = 0xfbadbeef; const uint64_t nonce = 0xdeadbeef; - SurfaceId input(id_namespace, local_id, nonce); + SurfaceId input(client_id, local_id, nonce); mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy(); SurfaceId output; proxy->EchoSurfaceId(input, &output); - EXPECT_EQ(id_namespace, output.id_namespace()); + EXPECT_EQ(client_id, output.client_id()); EXPECT_EQ(local_id, output.local_id()); EXPECT_EQ(nonce, output.nonce()); } TEST_F(StructTraitsTest, SurfaceSequence) { - const uint32_t id_namespace = 2016; + const uint32_t client_id = 2016; const uint32_t sequence = 0xfbadbeef; - SurfaceSequence input(id_namespace, sequence); + SurfaceSequence input(client_id, sequence); mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy(); SurfaceSequence output; proxy->EchoSurfaceSequence(input, &output); - EXPECT_EQ(id_namespace, output.id_namespace); + EXPECT_EQ(client_id, output.client_id); EXPECT_EQ(sequence, output.sequence); }
diff --git a/cc/ipc/surface_id.mojom b/cc/ipc/surface_id.mojom index f4f74272..0a0e5fa 100644 --- a/cc/ipc/surface_id.mojom +++ b/cc/ipc/surface_id.mojom
@@ -4,19 +4,19 @@ module cc.mojom; -// A surface ID is composed of three parts: a namespace, a local ID, and a +// A surface ID is composed of three parts: a client ID, a local ID, and a // nonce. The local part and nonce are allocated by the client using any scheme -// that avoids duplicates and makes IDs unguessable respectively. The namespace +// that avoids duplicates and makes IDs unguessable respectively. The client ID // is allocated by the service and will be different for each client. // -// The special id_namespace value 0 is equivalent to the namespace of the -// client. This can be used to create, destroy and submit frames to -// surfaces before learning the namespace and to reference other surfaces -// owned by the same client. The actual id namespace must be used to pass -// surface ids to other clients for them to reference. +// The special client_id value 0 is equivalent to the current client. +// This can be used to create, destroy and submit frames to surfaces before +// learning the client ID and to reference other surfaces owned by the same +// client. The actual client ID must be used to pass surface ids to other +// clients for them to reference. struct SurfaceId { // A service allocated ID identifying a client. - uint32 id_namespace; + uint32 client_id; // An identifier allocated by the client uniquely identifying a surface within // a client process.
diff --git a/cc/ipc/surface_id_struct_traits.h b/cc/ipc/surface_id_struct_traits.h index bafadf9cd..162b398 100644 --- a/cc/ipc/surface_id_struct_traits.h +++ b/cc/ipc/surface_id_struct_traits.h
@@ -14,16 +14,14 @@ // respectively. template <typename T> struct StructTraits<T, cc::SurfaceId> { - static uint32_t id_namespace(const cc::SurfaceId& id) { - return id.id_namespace(); - } + static uint32_t client_id(const cc::SurfaceId& id) { return id.client_id(); } static uint32_t local_id(const cc::SurfaceId& id) { return id.local_id(); } static uint64_t nonce(const cc::SurfaceId& id) { return id.nonce(); } static bool Read(typename T::DataView data, cc::SurfaceId* out) { - *out = cc::SurfaceId(data.id_namespace(), data.local_id(), data.nonce()); + *out = cc::SurfaceId(data.client_id(), data.local_id(), data.nonce()); return true; } };
diff --git a/cc/ipc/surface_sequence.mojom b/cc/ipc/surface_sequence.mojom index 631fe8d..d186077e 100644 --- a/cc/ipc/surface_sequence.mojom +++ b/cc/ipc/surface_sequence.mojom
@@ -7,9 +7,8 @@ // A per-surface-namespace sequence number that's used to coordinate // dependencies between frames. A sequence number may be satisfied once, and // may be depended on once. -// A surface sequence consists of an id namespace and a local sequence number. struct SurfaceSequence { - uint32 id_namespace; + uint32 client_id; uint32 sequence; };
diff --git a/cc/ipc/surface_sequence_struct_traits.h b/cc/ipc/surface_sequence_struct_traits.h index 2635b4df..db47458 100644 --- a/cc/ipc/surface_sequence_struct_traits.h +++ b/cc/ipc/surface_sequence_struct_traits.h
@@ -14,8 +14,8 @@ // .mojom-blink.h respectively. template <typename T> struct StructTraits<T, cc::SurfaceSequence> { - static uint32_t id_namespace(const cc::SurfaceSequence& id) { - return id.id_namespace; + static uint32_t client_id(const cc::SurfaceSequence& id) { + return id.client_id; } static uint32_t sequence(const cc::SurfaceSequence& id) { @@ -23,7 +23,7 @@ } static bool Read(typename T::DataView data, cc::SurfaceSequence* out) { - *out = cc::SurfaceSequence(data.id_namespace(), data.sequence()); + *out = cc::SurfaceSequence(data.client_id(), data.sequence()); return true; } };
diff --git a/cc/layers/picture_layer_unittest.cc b/cc/layers/picture_layer_unittest.cc index bb1405ed..0b14eb4 100644 --- a/cc/layers/picture_layer_unittest.cc +++ b/cc/layers/picture_layer_unittest.cc
@@ -448,7 +448,7 @@ EXPECT_TRUE(layer->IsSuitableForGpuRasterization()); // Veto gpu rasterization. - recording_source->SetUnsuitableForGpuRasterization(); + recording_source->SetForceUnsuitableForGpuRasterization(true); EXPECT_FALSE(recording_source->IsSuitableForGpuRasterization()); EXPECT_FALSE(layer->IsSuitableForGpuRasterization()); }
diff --git a/cc/layers/surface_layer.cc b/cc/layers/surface_layer.cc index 8f0e051..5dbc7a2f 100644 --- a/cc/layers/surface_layer.cc +++ b/cc/layers/surface_layer.cc
@@ -57,7 +57,7 @@ DCHECK(destroy_sequence_.is_null()); } -void SurfaceLayer::SetSurfaceId(SurfaceId surface_id, +void SurfaceLayer::SetSurfaceId(const SurfaceId& surface_id, float scale, const gfx::Size& size) { SatisfyDestroySequence();
diff --git a/cc/layers/surface_layer.h b/cc/layers/surface_layer.h index 1799a3a..06c84c1 100644 --- a/cc/layers/surface_layer.h +++ b/cc/layers/surface_layer.h
@@ -32,7 +32,9 @@ const SatisfyCallback& satisfy_callback, const RequireCallback& require_callback); - void SetSurfaceId(SurfaceId surface_id, float scale, const gfx::Size& size); + void SetSurfaceId(const SurfaceId& surface_id, + float scale, + const gfx::Size& size); // Layer overrides. std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
diff --git a/cc/layers/surface_layer_impl.cc b/cc/layers/surface_layer_impl.cc index c262d2e..a474d87d 100644 --- a/cc/layers/surface_layer_impl.cc +++ b/cc/layers/surface_layer_impl.cc
@@ -29,7 +29,7 @@ return SurfaceLayerImpl::Create(tree_impl, id()); } -void SurfaceLayerImpl::SetSurfaceId(SurfaceId surface_id) { +void SurfaceLayerImpl::SetSurfaceId(const SurfaceId& surface_id) { if (surface_id_ == surface_id) return;
diff --git a/cc/layers/surface_layer_impl.h b/cc/layers/surface_layer_impl.h index d67efd86..e5d4128 100644 --- a/cc/layers/surface_layer_impl.h +++ b/cc/layers/surface_layer_impl.h
@@ -23,10 +23,10 @@ } ~SurfaceLayerImpl() override; - void SetSurfaceId(SurfaceId surface_id); + void SetSurfaceId(const SurfaceId& surface_id); void SetSurfaceScale(float scale); void SetSurfaceSize(const gfx::Size& size); - SurfaceId surface_id() const { return surface_id_; } + const SurfaceId& surface_id() const { return surface_id_; } // LayerImpl overrides. std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
diff --git a/cc/layers/surface_layer_impl_unittest.cc b/cc/layers/surface_layer_impl_unittest.cc index e88f3e54..2223153 100644 --- a/cc/layers/surface_layer_impl_unittest.cc +++ b/cc/layers/surface_layer_impl_unittest.cc
@@ -12,6 +12,8 @@ namespace cc { namespace { +static constexpr uint32_t kArbitraryClientId = 0; + TEST(SurfaceLayerImplTest, Occlusion) { gfx::Size layer_size(1000, 1000); gfx::Size viewport_size(1000, 1000); @@ -22,7 +24,7 @@ impl.AddChildToRoot<SurfaceLayerImpl>(); surface_layer_impl->SetBounds(layer_size); surface_layer_impl->SetDrawsContent(true); - SurfaceId surface_id(0, 9, 0); + SurfaceId surface_id(kArbitraryClientId, 9, 0); surface_layer_impl->SetSurfaceId(surface_id); surface_layer_impl->SetSurfaceScale(1.f); surface_layer_impl->SetSurfaceSize(layer_size);
diff --git a/cc/layers/surface_layer_unittest.cc b/cc/layers/surface_layer_unittest.cc index 8ff9ad9..bc60299 100644 --- a/cc/layers/surface_layer_unittest.cc +++ b/cc/layers/surface_layer_unittest.cc
@@ -26,6 +26,8 @@ namespace cc { namespace { +static constexpr uint32_t kArbitraryClientId = 0; + class SurfaceLayerTest : public testing::Test { public: SurfaceLayerTest() @@ -73,8 +75,9 @@ scoped_refptr<SurfaceLayer> layer(SurfaceLayer::Create( base::Bind(&SatisfyCallback, &blank_change), base::Bind(&RequireCallback, &required_id, &required_seq))); - layer->SetSurfaceId(SurfaceId(0, 1, 0), 1.f, gfx::Size(1, 1)); - layer_tree_host_->set_surface_id_namespace(1); + layer->SetSurfaceId(SurfaceId(kArbitraryClientId, 1, 0), 1.f, + gfx::Size(1, 1)); + layer_tree_host_->set_surface_client_id(1); layer_tree_host_->SetRootLayer(layer); std::unique_ptr<FakeLayerTreeHost> layer_tree_host2 = @@ -82,8 +85,9 @@ scoped_refptr<SurfaceLayer> layer2(SurfaceLayer::Create( base::Bind(&SatisfyCallback, &blank_change), base::Bind(&RequireCallback, &required_id, &required_seq))); - layer2->SetSurfaceId(SurfaceId(0, 1, 0), 1.f, gfx::Size(1, 1)); - layer_tree_host2->set_surface_id_namespace(2); + layer2->SetSurfaceId(SurfaceId(kArbitraryClientId, 1, 0), 1.f, + gfx::Size(1, 1)); + layer_tree_host2->set_surface_client_id(2); layer_tree_host2->SetRootLayer(layer2); // Layers haven't been removed, so no sequence should be satisfied. @@ -101,7 +105,7 @@ // Set of sequences that need to be satisfied should include sequences from // both trees. - EXPECT_TRUE(required_id == SurfaceId(0, 1, 0)); + EXPECT_TRUE(required_id == SurfaceId(kArbitraryClientId, 1, 0)); EXPECT_EQ(2u, required_seq.size()); EXPECT_TRUE(required_seq.count(expected1)); EXPECT_TRUE(required_seq.count(expected2)); @@ -125,11 +129,12 @@ : commit_count_(0), sequence_was_satisfied_(false) {} void BeginTest() override { - layer_tree_host()->set_surface_id_namespace(1); + layer_tree_host()->set_surface_client_id(1); layer_ = SurfaceLayer::Create( base::Bind(&SatisfyCallback, &satisfied_sequence_), base::Bind(&RequireCallback, &required_id_, &required_set_)); - layer_->SetSurfaceId(SurfaceId(0, 1, 0), 1.f, gfx::Size(1, 1)); + layer_->SetSurfaceId(SurfaceId(kArbitraryClientId, 1, 0), 1.f, + gfx::Size(1, 1)); // Layer hasn't been added to tree so no SurfaceSequence generated yet. EXPECT_EQ(0u, required_set_.size()); @@ -138,7 +143,7 @@ // Should have SurfaceSequence from first tree. SurfaceSequence expected(1u, 1u); - EXPECT_TRUE(required_id_ == SurfaceId(0, 1, 0)); + EXPECT_TRUE(required_id_ == SurfaceId(kArbitraryClientId, 1, 0)); EXPECT_EQ(1u, required_set_.size()); EXPECT_TRUE(required_set_.count(expected)); @@ -191,8 +196,7 @@ } } - void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { - EXPECT_TRUE(result); + void SwapBuffersCompleteOnThread() override { std::vector<uint32_t>& satisfied = output_surface()->last_sent_frame()->metadata.satisfies_sequences; EXPECT_LE(satisfied.size(), 1u); @@ -208,7 +212,7 @@ } void AfterTest() override { - EXPECT_TRUE(required_id_ == SurfaceId(0, 1, 0)); + EXPECT_TRUE(required_id_ == SurfaceId(kArbitraryClientId, 1, 0)); EXPECT_EQ(1u, required_set_.size()); // Sequence should have been satisfied through Swap, not with the // callback. @@ -249,7 +253,7 @@ } void AfterTest() override { - EXPECT_TRUE(required_id_ == SurfaceId(0, 1, 0)); + EXPECT_TRUE(required_id_ == SurfaceId(kArbitraryClientId, 1, 0)); EXPECT_EQ(1u, required_set_.size()); // Sequence should have been satisfied with the callback. EXPECT_TRUE(satisfied_sequence_ == SurfaceSequence(1u, 1u));
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc index 3a13f3d..2a32a1c 100644 --- a/cc/layers/texture_layer_unittest.cc +++ b/cc/layers/texture_layer_unittest.cc
@@ -1066,9 +1066,6 @@ } void MailboxReleased(const gpu::SyncToken& sync_token, bool lost_resource) { - // Source frame number during callback is the same as the source frame - // on which it was released. - EXPECT_EQ(1, layer_tree_host()->source_frame_number()); EXPECT_TRUE(sync_token.HasData()); EndTest(); } @@ -1105,23 +1102,6 @@ } } - void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { - ASSERT_TRUE(result); - DelegatedFrameData* delegated_frame_data = - output_surface()->last_sent_frame()->delegated_frame_data.get(); - if (!delegated_frame_data) - return; - - // Return all resources immediately. - TransferableResourceArray resources_to_return = - output_surface()->resources_held_by_parent(); - - CompositorFrameAck ack; - for (size_t i = 0; i < resources_to_return.size(); ++i) - output_surface()->ReturnResource(resources_to_return[i].id, &ack); - host_impl->ReclaimResources(&ack); - } - void AfterTest() override {} private: @@ -1242,23 +1222,6 @@ } } - void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { - ASSERT_TRUE(result); - DelegatedFrameData* delegated_frame_data = - output_surface()->last_sent_frame()->delegated_frame_data.get(); - if (!delegated_frame_data) - return; - - // Return all resources immediately. - TransferableResourceArray resources_to_return = - output_surface()->resources_held_by_parent(); - - CompositorFrameAck ack; - for (size_t i = 0; i < resources_to_return.size(); ++i) - output_surface()->ReturnResource(resources_to_return[i].id, &ack); - host_impl->ReclaimResources(&ack); - } - void AfterTest() override {} private:
diff --git a/cc/output/compositor_frame_ack.h b/cc/output/compositor_frame_ack.h index 55ca7f1..e5fb241 100644 --- a/cc/output/compositor_frame_ack.h +++ b/cc/output/compositor_frame_ack.h
@@ -20,7 +20,6 @@ ~CompositorFrameAck(); ReturnedResourceArray resources; - std::unique_ptr<GLFrameData> gl_frame_data; private: DISALLOW_COPY_AND_ASSIGN(CompositorFrameAck);
diff --git a/cc/output/delegating_renderer_unittest.cc b/cc/output/delegating_renderer_unittest.cc index 7821382..a073033 100644 --- a/cc/output/delegating_renderer_unittest.cc +++ b/cc/output/delegating_renderer_unittest.cc
@@ -51,10 +51,10 @@ void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { EXPECT_EQ(0u, output_surface_->num_sent_frames()); + drawn_viewport_ = host_impl->DeviceViewport(); } - void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { - EXPECT_TRUE(result); + void SwapBuffersCompleteOnThread() override { EXPECT_EQ(1u, output_surface_->num_sent_frames()); const CompositorFrame* last_frame = output_surface_->last_sent_frame(); @@ -62,8 +62,8 @@ last_frame->delegated_frame_data.get(); ASSERT_TRUE(last_frame->delegated_frame_data); EXPECT_FALSE(last_frame->gl_frame_data); - EXPECT_EQ(host_impl->DeviceViewport().ToString(), - last_frame_data->render_pass_list.back()->output_rect.ToString()); + EXPECT_EQ(drawn_viewport_, + last_frame_data->render_pass_list.back()->output_rect); EXPECT_EQ(0.5f, last_frame->metadata.min_page_scale_factor); EXPECT_EQ(4.f, last_frame->metadata.max_page_scale_factor); @@ -72,6 +72,8 @@ EndTest(); } + + gfx::Rect drawn_viewport_; }; SINGLE_AND_MULTI_THREAD_DELEGATING_RENDERER_TEST_F(DelegatingRendererTestDraw); @@ -105,8 +107,7 @@ EXPECT_EQ(0u, output_surface_->num_sent_frames()); } - void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { - EXPECT_TRUE(result); + void SwapBuffersCompleteOnThread() override { EXPECT_EQ(1u, output_surface_->num_sent_frames()); const CompositorFrame* last_frame = output_surface_->last_sent_frame();
diff --git a/cc/output/output_surface.h b/cc/output/output_surface.h index b936006..5d10435 100644 --- a/cc/output/output_surface.h +++ b/cc/output/output_surface.h
@@ -143,8 +143,7 @@ // The implementation may destroy or steal the contents of the CompositorFrame // passed in (though it will not take ownership of the CompositorFrame // itself). For successful swaps, the implementation must call - // OutputSurfaceClient::DidSwapBuffers() and eventually - // DidSwapBuffersComplete(). + // DidSwapBuffersComplete() (via OnSwapBuffersComplete()) eventually. virtual void SwapBuffers(CompositorFrame frame) = 0; virtual void OnSwapBuffersComplete();
diff --git a/cc/output/output_surface_client.h b/cc/output/output_surface_client.h index 342a9a9..6fb4276 100644 --- a/cc/output/output_surface_client.h +++ b/cc/output/output_surface_client.h
@@ -34,7 +34,11 @@ virtual void SetBeginFrameSource(BeginFrameSource* source) = 0; virtual void SetNeedsRedrawRect(const gfx::Rect& damage_rect) = 0; - virtual void DidSwapBuffers() = 0; + // For LayerTreeHostImpl, this is more of a OnSwapBuffersAck from the display + // compositor that it received and will use the frame, unblocking it from + // producing more frames. + // For the display compositor this is literally a notification that the swap + // to the hardware is complete. virtual void DidSwapBuffersComplete() = 0; virtual void DidReceiveTextureInUseResponses( const gpu::TextureInUseResponses& responses) = 0;
diff --git a/cc/output/output_surface_unittest.cc b/cc/output/output_surface_unittest.cc index 4f0a1e1..d4fa9f7 100644 --- a/cc/output/output_surface_unittest.cc +++ b/cc/output/output_surface_unittest.cc
@@ -43,7 +43,6 @@ std::move(software_device)) {} void SwapBuffers(CompositorFrame frame) override { - client_->DidSwapBuffers(); client_->DidSwapBuffersComplete(); } uint32_t GetFramebufferCopyTextureFormat() override { @@ -51,8 +50,6 @@ return GL_RGB; } - void DidSwapBuffersForTesting() { client_->DidSwapBuffers(); } - void OnSwapBuffersCompleteForTesting() { client_->DidSwapBuffersComplete(); } protected:
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc index 3c7e16b..38ba3417 100644 --- a/cc/output/overlay_unittest.cc +++ b/cc/output/overlay_unittest.cc
@@ -156,7 +156,6 @@ return GL_RGB; } void SwapBuffers(CompositorFrame frame) override { - client_->DidSwapBuffers(); } void OnSwapBuffersComplete() override { client_->DidSwapBuffersComplete(); }
diff --git a/cc/output/renderer_unittest.cc b/cc/output/renderer_unittest.cc index bb958b01..b0ee437 100644 --- a/cc/output/renderer_unittest.cc +++ b/cc/output/renderer_unittest.cc
@@ -34,7 +34,6 @@ } void TestOutputSurface::SwapBuffers(CompositorFrame frame) { - client_->DidSwapBuffers(); client_->DidSwapBuffersComplete(); }
diff --git a/cc/proto/layer_tree_host.proto b/cc/proto/layer_tree_host.proto index 4d89190..71bbcf5 100644 --- a/cc/proto/layer_tree_host.proto +++ b/cc/proto/layer_tree_host.proto
@@ -60,7 +60,7 @@ optional int32 outer_viewport_scroll_layer_id = 29; optional LayerSelection selection = 30; optional PropertyTrees property_trees = 31; - optional uint32 surface_id_namespace = 32; + optional uint32 surface_client_id = 32; optional uint32 next_surface_sequence = 33; optional uint32 wheel_event_listener_properties = 34; optional bool have_scroll_event_handlers = 35;
diff --git a/cc/quads/surface_draw_quad.cc b/cc/quads/surface_draw_quad.cc index d1a2882..4ec7fa26 100644 --- a/cc/quads/surface_draw_quad.cc +++ b/cc/quads/surface_draw_quad.cc
@@ -16,7 +16,7 @@ void SurfaceDrawQuad::SetNew(const SharedQuadState* shared_quad_state, const gfx::Rect& rect, const gfx::Rect& visible_rect, - SurfaceId surface_id) { + const SurfaceId& surface_id) { gfx::Rect opaque_rect; bool needs_blending = false; DrawQuad::SetAll(shared_quad_state, DrawQuad::SURFACE_CONTENT, rect, @@ -29,7 +29,7 @@ const gfx::Rect& opaque_rect, const gfx::Rect& visible_rect, bool needs_blending, - SurfaceId surface_id) { + const SurfaceId& surface_id) { DrawQuad::SetAll(shared_quad_state, DrawQuad::SURFACE_CONTENT, rect, opaque_rect, visible_rect, needs_blending); this->surface_id = surface_id;
diff --git a/cc/quads/surface_draw_quad.h b/cc/quads/surface_draw_quad.h index 890f3bf..b0db76aa 100644 --- a/cc/quads/surface_draw_quad.h +++ b/cc/quads/surface_draw_quad.h
@@ -20,14 +20,14 @@ void SetNew(const SharedQuadState* shared_quad_state, const gfx::Rect& rect, const gfx::Rect& visible_rect, - SurfaceId surface_id); + const SurfaceId& surface_id); void SetAll(const SharedQuadState* shared_quad_state, const gfx::Rect& rect, const gfx::Rect& opaque_rect, const gfx::Rect& visible_rect, bool needs_blending, - SurfaceId surface_id); + const SurfaceId& surface_id); SurfaceId surface_id;
diff --git a/cc/raster/bitmap_raster_buffer_provider.cc b/cc/raster/bitmap_raster_buffer_provider.cc index 1bc2e04..7c811df1 100644 --- a/cc/raster/bitmap_raster_buffer_provider.cc +++ b/cc/raster/bitmap_raster_buffer_provider.cc
@@ -108,7 +108,7 @@ return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha)); } -bool BitmapRasterBufferProvider::IsPartialRasterSupported() const { +bool BitmapRasterBufferProvider::CanPartialRasterIntoProvidedResource() const { return true; }
diff --git a/cc/raster/bitmap_raster_buffer_provider.h b/cc/raster/bitmap_raster_buffer_provider.h index 182be515..ded16f5 100644 --- a/cc/raster/bitmap_raster_buffer_provider.h +++ b/cc/raster/bitmap_raster_buffer_provider.h
@@ -36,7 +36,7 @@ void OrderingBarrier() override; ResourceFormat GetResourceFormat(bool must_support_alpha) const override; bool IsResourceSwizzleRequired(bool must_support_alpha) const override; - bool IsPartialRasterSupported() const override; + bool CanPartialRasterIntoProvidedResource() const override; void Shutdown() override; protected:
diff --git a/cc/raster/gpu_raster_buffer_provider.cc b/cc/raster/gpu_raster_buffer_provider.cc index adeddbd..81ae9445 100644 --- a/cc/raster/gpu_raster_buffer_provider.cc +++ b/cc/raster/gpu_raster_buffer_provider.cc
@@ -194,7 +194,7 @@ return false; } -bool GpuRasterBufferProvider::IsPartialRasterSupported() const { +bool GpuRasterBufferProvider::CanPartialRasterIntoProvidedResource() const { return true; }
diff --git a/cc/raster/gpu_raster_buffer_provider.h b/cc/raster/gpu_raster_buffer_provider.h index dc4fb61d..0df055b2 100644 --- a/cc/raster/gpu_raster_buffer_provider.h +++ b/cc/raster/gpu_raster_buffer_provider.h
@@ -34,7 +34,7 @@ void OrderingBarrier() override; ResourceFormat GetResourceFormat(bool must_support_alpha) const override; bool IsResourceSwizzleRequired(bool must_support_alpha) const override; - bool IsPartialRasterSupported() const override; + bool CanPartialRasterIntoProvidedResource() const override; void Shutdown() override; void PlaybackOnWorkerThread(
diff --git a/cc/raster/one_copy_raster_buffer_provider.cc b/cc/raster/one_copy_raster_buffer_provider.cc index 44e3845..f0f6b0f 100644 --- a/cc/raster/one_copy_raster_buffer_provider.cc +++ b/cc/raster/one_copy_raster_buffer_provider.cc
@@ -153,8 +153,11 @@ return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha)); } -bool OneCopyRasterBufferProvider::IsPartialRasterSupported() const { - return true; +bool OneCopyRasterBufferProvider::CanPartialRasterIntoProvidedResource() const { + // While OneCopyRasterBufferProvider has an internal partial raster + // implementation, it cannot directly partial raster into the externally + // owned resource provided in AcquireBufferForRaster. + return false; } void OneCopyRasterBufferProvider::Shutdown() {
diff --git a/cc/raster/one_copy_raster_buffer_provider.h b/cc/raster/one_copy_raster_buffer_provider.h index 008a5bd4..159a044 100644 --- a/cc/raster/one_copy_raster_buffer_provider.h +++ b/cc/raster/one_copy_raster_buffer_provider.h
@@ -41,7 +41,7 @@ void OrderingBarrier() override; ResourceFormat GetResourceFormat(bool must_support_alpha) const override; bool IsResourceSwizzleRequired(bool must_support_alpha) const override; - bool IsPartialRasterSupported() const override; + bool CanPartialRasterIntoProvidedResource() const override; void Shutdown() override; // Playback raster source and copy result into |resource|.
diff --git a/cc/raster/raster_buffer_provider.h b/cc/raster/raster_buffer_provider.h index 616d123..fe6921d 100644 --- a/cc/raster/raster_buffer_provider.h +++ b/cc/raster/raster_buffer_provider.h
@@ -63,8 +63,8 @@ virtual bool IsResourceSwizzleRequired(bool must_support_alpha) const = 0; // Determine if the RasterBufferProvider can handle partial raster into - // resources. - virtual bool IsPartialRasterSupported() const = 0; + // the Resource provided in AcquireBufferForRaster. + virtual bool CanPartialRasterIntoProvidedResource() const = 0; // Shutdown for doing cleanup. virtual void Shutdown() = 0;
diff --git a/cc/raster/zero_copy_raster_buffer_provider.cc b/cc/raster/zero_copy_raster_buffer_provider.cc index e33bb43..ecb8c825 100644 --- a/cc/raster/zero_copy_raster_buffer_provider.cc +++ b/cc/raster/zero_copy_raster_buffer_provider.cc
@@ -116,7 +116,8 @@ return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha)); } -bool ZeroCopyRasterBufferProvider::IsPartialRasterSupported() const { +bool ZeroCopyRasterBufferProvider::CanPartialRasterIntoProvidedResource() + const { return false; }
diff --git a/cc/raster/zero_copy_raster_buffer_provider.h b/cc/raster/zero_copy_raster_buffer_provider.h index 67262c7..6abf129 100644 --- a/cc/raster/zero_copy_raster_buffer_provider.h +++ b/cc/raster/zero_copy_raster_buffer_provider.h
@@ -38,7 +38,7 @@ void OrderingBarrier() override; ResourceFormat GetResourceFormat(bool must_support_alpha) const override; bool IsResourceSwizzleRequired(bool must_support_alpha) const override; - bool IsPartialRasterSupported() const override; + bool CanPartialRasterIntoProvidedResource() const override; void Shutdown() override; protected:
diff --git a/cc/resources/resource_pool.cc b/cc/resources/resource_pool.cc index 0ec2400..469f790 100644 --- a/cc/resources/resource_pool.cc +++ b/cc/resources/resource_pool.cc
@@ -133,36 +133,85 @@ pool_resource->size(), pool_resource->format()); ++total_resource_count_; + // Clear the invalidated rect and content ID, as we are about to raster new + // content. These will be re-set when rasterization completes successfully. + pool_resource->set_invalidated_rect(gfx::Rect()); + pool_resource->set_content_id(0); + Resource* resource = pool_resource.get(); in_use_resources_[resource->id()] = std::move(pool_resource); in_use_memory_usage_bytes_ += ResourceUtil::UncheckedSizeInBytes<size_t>( resource->size(), resource->format()); + return resource; } -Resource* ResourcePool::TryAcquireResourceWithContentId(uint64_t content_id) { - DCHECK(content_id); +Resource* ResourcePool::TryAcquireResourceForPartialRaster( + uint64_t new_content_id, + const gfx::Rect& new_invalidated_rect, + uint64_t previous_content_id, + gfx::Rect* total_invalidated_rect) { + DCHECK(new_content_id); + DCHECK(previous_content_id); + *total_invalidated_rect = gfx::Rect(); - auto it = std::find_if( + // Try to find |previous_content_id| in |unused_resources_|. + auto found_unused = std::find_if( unused_resources_.begin(), unused_resources_.end(), - [content_id](const std::unique_ptr<PoolResource>& pool_resource) { - return pool_resource->content_id() == content_id; + [previous_content_id](const ResourceDeque::value_type& pool_resource) { + return pool_resource->content_id() == previous_content_id; }); - if (it == unused_resources_.end()) - return nullptr; + if (found_unused != unused_resources_.end()) { + PoolResource* found_resource = found_unused->get(); + DCHECK(resource_provider_->CanLockForWrite(found_resource->id())); - Resource* resource = it->get(); - DCHECK(resource_provider_->CanLockForWrite(resource->id())); + // Transfer resource to |in_use_resources_|. + in_use_resources_[found_resource->id()] = std::move(*found_unused); + unused_resources_.erase(found_unused); + in_use_memory_usage_bytes_ += ResourceUtil::UncheckedSizeInBytes<size_t>( + found_resource->size(), found_resource->format()); - // Transfer resource to |in_use_resources_|. - in_use_resources_[resource->id()] = std::move(*it); - unused_resources_.erase(it); - in_use_memory_usage_bytes_ += ResourceUtil::UncheckedSizeInBytes<size_t>( - resource->size(), resource->format()); - return resource; + *total_invalidated_rect = new_invalidated_rect; + if (!found_resource->invalidated_rect().IsEmpty()) + total_invalidated_rect->Union(found_resource->invalidated_rect()); + + // Clear the invalidated rect and content ID on the resource being retunred. + // These will be updated when raster completes successfully. + found_resource->set_invalidated_rect(gfx::Rect()); + found_resource->set_content_id(0); + + return found_resource; + } + + // Couldn't find an unused previous resource. If possible, update the + // invalidation on the in-use resource to allow for future partial raster. + // + // We could update all in-use resources (rather than just the first one we + // find), however the latency on resources being returned by the browser + // is typically one frame, so this extra searching would be largely wasted. + // + // Skipping any additional resources is not a correctness risk, as the + // un-updated resources will have their old content ID, and will not be found + // by future partial raster searches, which will use the new content ID. + auto found_in_use = std::find_if( + in_use_resources_.begin(), in_use_resources_.end(), + [previous_content_id](const InUseResourceMap::value_type& in_use_entry) { + return in_use_entry.second->content_id() == previous_content_id; + }); + if (found_in_use != in_use_resources_.end()) { + PoolResource* found_resource = found_in_use->second.get(); + gfx::Rect updated_invalidated_rect = new_invalidated_rect; + if (!found_resource->invalidated_rect().IsEmpty()) + updated_invalidated_rect.Union(found_resource->invalidated_rect()); + + found_resource->set_content_id(new_content_id); + found_resource->set_invalidated_rect(updated_invalidated_rect); + } + + return nullptr; } -void ResourcePool::ReleaseResource(Resource* resource, uint64_t content_id) { +void ResourcePool::ReleaseResource(Resource* resource) { // Ensure that the provided resource is valid. // TODO(ericrk): Remove this once we've investigated further. // crbug.com/598286. @@ -202,7 +251,6 @@ CHECK(it->second.get()); PoolResource* pool_resource = it->second.get(); - pool_resource->set_content_id(content_id); pool_resource->set_last_usage(base::TimeTicks::Now()); // Transfer resource to |busy_resources_|. @@ -216,6 +264,14 @@ ScheduleEvictExpiredResourcesIn(resource_expiration_delay_); } +void ResourcePool::OnContentReplaced(ResourceId resource_id, + uint64_t content_id) { + auto found = in_use_resources_.find(resource_id); + DCHECK(found != in_use_resources_.end()); + found->second->set_content_id(content_id); + found->second->set_invalidated_rect(gfx::Rect()); +} + void ResourcePool::SetResourceUsageLimits(size_t max_memory_usage_bytes, size_t max_resource_count) { max_memory_usage_bytes_ = max_memory_usage_bytes;
diff --git a/cc/resources/resource_pool.h b/cc/resources/resource_pool.h index 74262de..ab13fee 100644 --- a/cc/resources/resource_pool.h +++ b/cc/resources/resource_pool.h
@@ -42,8 +42,20 @@ ~ResourcePool() override; Resource* AcquireResource(const gfx::Size& size, ResourceFormat format); - Resource* TryAcquireResourceWithContentId(uint64_t content_id); - void ReleaseResource(Resource* resource, uint64_t content_id); + + // Tries to acquire the resource with |previous_content_id| for us in partial + // raster. If successful, this function will retun the invalidated rect which + // must be re-rastered in |total_invalidated_rect|. + Resource* TryAcquireResourceForPartialRaster( + uint64_t new_content_id, + const gfx::Rect& new_invalidated_rect, + uint64_t previous_content_id, + gfx::Rect* total_invalidated_rect); + + // Called when a resource's content has been fully replaced (and is completely + // valid). Updates the resource's content ID to its new value. + void OnContentReplaced(ResourceId resource_id, uint64_t content_id); + void ReleaseResource(Resource* resource); void SetResourceUsageLimits(size_t max_memory_usage_bytes, size_t max_resource_count); @@ -95,11 +107,17 @@ base::TimeTicks last_usage() const { return last_usage_; } void set_last_usage(base::TimeTicks time) { last_usage_ = time; } + gfx::Rect invalidated_rect() const { return invalidated_rect_; } + void set_invalidated_rect(const gfx::Rect& invalidated_rect) { + invalidated_rect_ = invalidated_rect; + } + private: explicit PoolResource(ResourceProvider* resource_provider) : ScopedResource(resource_provider), content_id_(0) {} uint64_t content_id_; base::TimeTicks last_usage_; + gfx::Rect invalidated_rect_; }; void DidFinishUsingResource(std::unique_ptr<PoolResource> resource); @@ -125,7 +143,8 @@ ResourceDeque unused_resources_; ResourceDeque busy_resources_; - std::map<ResourceId, std::unique_ptr<PoolResource>> in_use_resources_; + using InUseResourceMap = std::map<ResourceId, std::unique_ptr<PoolResource>>; + InUseResourceMap in_use_resources_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; bool evict_expired_resources_pending_;
diff --git a/cc/resources/resource_pool_unittest.cc b/cc/resources/resource_pool_unittest.cc index d9025c62..af14a60 100644 --- a/cc/resources/resource_pool_unittest.cc +++ b/cc/resources/resource_pool_unittest.cc
@@ -49,7 +49,7 @@ EXPECT_EQ(format, resource->format()); EXPECT_TRUE(resource_provider_->CanLockForWrite(resource->id())); - resource_pool_->ReleaseResource(resource, 0u); + resource_pool_->ReleaseResource(resource); } TEST_F(ResourcePoolTest, AccountingSingleResource) { @@ -70,7 +70,7 @@ EXPECT_EQ(1u, resource_pool_->resource_count()); EXPECT_EQ(0u, resource_pool_->GetBusyResourceCountForTesting()); - resource_pool_->ReleaseResource(resource, 0u); + resource_pool_->ReleaseResource(resource); EXPECT_EQ(resource_bytes, resource_pool_->GetTotalMemoryUsageForTesting()); EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting()); EXPECT_EQ(1u, resource_pool_->GetBusyResourceCountForTesting()); @@ -101,21 +101,21 @@ ResourceFormat format = RGBA_8888; Resource* resource = resource_pool_->AcquireResource(size, format); - resource_pool_->ReleaseResource(resource, 0u); + resource_pool_->ReleaseResource(resource); resource_pool_->CheckBusyResources(); EXPECT_EQ(1u, resource_provider_->num_resources()); // Same size/format should re-use resource. resource = resource_pool_->AcquireResource(size, format); EXPECT_EQ(1u, resource_provider_->num_resources()); - resource_pool_->ReleaseResource(resource, 0u); + resource_pool_->ReleaseResource(resource); resource_pool_->CheckBusyResources(); EXPECT_EQ(1u, resource_provider_->num_resources()); // Different size/format should alloate new resource. resource = resource_pool_->AcquireResource(gfx::Size(50, 50), LUMINANCE_8); EXPECT_EQ(2u, resource_provider_->num_resources()); - resource_pool_->ReleaseResource(resource, 0u); + resource_pool_->ReleaseResource(resource); resource_pool_->CheckBusyResources(); EXPECT_EQ(2u, resource_provider_->num_resources()); } @@ -133,7 +133,7 @@ EXPECT_EQ(1u, resource_provider_->num_resources()); resource_provider_->LoseResourceForTesting(resource->id()); - resource_pool_->ReleaseResource(resource, 0u); + resource_pool_->ReleaseResource(resource); resource_pool_->CheckBusyResources(); EXPECT_EQ(0u, resource_provider_->num_resources()); } @@ -157,7 +157,7 @@ EXPECT_EQ(40000u, resource_pool_->GetTotalMemoryUsageForTesting()); EXPECT_EQ(1u, resource_pool_->resource_count()); - resource_pool_->ReleaseResource(resource, 0u); + resource_pool_->ReleaseResource(resource); EXPECT_EQ(1u, resource_provider_->num_resources()); EXPECT_EQ(40000u, resource_pool_->GetTotalMemoryUsageForTesting()); EXPECT_EQ(0u, resource_pool_->memory_usage_bytes()); @@ -195,7 +195,7 @@ EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting()); EXPECT_EQ(1u, resource_pool_->resource_count()); - resource_pool_->ReleaseResource(resource, 0u); + resource_pool_->ReleaseResource(resource); EXPECT_EQ(1u, resource_provider_->num_resources()); EXPECT_EQ(40000u, resource_pool_->GetTotalMemoryUsageForTesting()); EXPECT_EQ(1u, resource_pool_->GetTotalResourceCountForTesting()); @@ -220,5 +220,70 @@ EXPECT_EQ(0u, resource_pool_->GetTotalMemoryUsageForTesting()); } +TEST_F(ResourcePoolTest, UpdateContentId) { + gfx::Size size(100, 100); + ResourceFormat format = RGBA_8888; + uint64_t content_id = 42; + uint64_t new_content_id = 43; + gfx::Rect new_invalidated_rect(20, 20, 10, 10); + + Resource* resource = resource_pool_->AcquireResource(size, format); + resource_pool_->OnContentReplaced(resource->id(), content_id); + resource_pool_->ReleaseResource(resource); + resource_pool_->CheckBusyResources(); + + // Ensure that we can retrieve the resource based on |content_id|. + gfx::Rect invalidated_rect; + Resource* reacquired_resource = + resource_pool_->TryAcquireResourceForPartialRaster( + new_content_id, new_invalidated_rect, content_id, &invalidated_rect); + EXPECT_EQ(resource, reacquired_resource); + EXPECT_EQ(new_invalidated_rect, invalidated_rect); + resource_pool_->ReleaseResource(reacquired_resource); +} + +TEST_F(ResourcePoolTest, UpdateContentIdAndInvalidatedRect) { + gfx::Size size(100, 100); + ResourceFormat format = RGBA_8888; + uint64_t content_ids[] = {42, 43, 44}; + gfx::Rect invalidated_rect(20, 20, 10, 10); + gfx::Rect second_invalidated_rect(25, 25, 10, 10); + gfx::Rect expected_total_invalidated_rect(20, 20, 15, 15); + + // Acquire a new resource with the first content id. + Resource* resource = resource_pool_->AcquireResource(size, format); + resource_pool_->OnContentReplaced(resource->id(), content_ids[0]); + + // Attempt to acquire this resource. It is in use, so its ID and invalidated + // rect should be updated, but a new resource will be returned. + gfx::Rect new_invalidated_rect; + Resource* reacquired_resource = + resource_pool_->TryAcquireResourceForPartialRaster( + content_ids[1], invalidated_rect, content_ids[0], + &new_invalidated_rect); + EXPECT_EQ(nullptr, reacquired_resource); + EXPECT_EQ(gfx::Rect(), new_invalidated_rect); + + // Release the original resource, returning it to the unused pool. + resource_pool_->ReleaseResource(resource); + resource_pool_->CheckBusyResources(); + + // Ensure that we cannot retrieve a resource based on the original content id. + reacquired_resource = resource_pool_->TryAcquireResourceForPartialRaster( + content_ids[1], invalidated_rect, content_ids[0], &new_invalidated_rect); + EXPECT_EQ(nullptr, reacquired_resource); + EXPECT_EQ(gfx::Rect(), new_invalidated_rect); + + // Ensure that we can retrieve the resource based on the second (updated) + // content ID and that it has the expected invalidated rect. + gfx::Rect total_invalidated_rect; + reacquired_resource = resource_pool_->TryAcquireResourceForPartialRaster( + content_ids[2], second_invalidated_rect, content_ids[1], + &total_invalidated_rect); + EXPECT_EQ(resource, reacquired_resource); + EXPECT_EQ(expected_total_invalidated_rect, total_invalidated_rect); + resource_pool_->ReleaseResource(reacquired_resource); +} + } // namespace } // namespace cc
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc index ee2ac86d..4fa133c 100644 --- a/cc/scheduler/scheduler.cc +++ b/cc/scheduler/scheduler.cc
@@ -80,9 +80,7 @@ base::TimeTicks Scheduler::Now() const { base::TimeTicks now = base::TimeTicks::Now(); TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.now"), - "Scheduler::Now", - "now", - now); + "Scheduler::Now", "now", now); return now; } @@ -314,8 +312,8 @@ if (should_defer_begin_frame) { begin_retro_frame_args_.push_back(adjusted_args); - TRACE_EVENT_INSTANT0( - "cc", "Scheduler::BeginFrame deferred", TRACE_EVENT_SCOPE_THREAD); + TRACE_EVENT_INSTANT0("cc", "Scheduler::BeginFrame deferred", + TRACE_EVENT_SCOPE_THREAD); // Queuing the frame counts as "using it", so we need to return true. } else { BeginImplFrameWithDeadline(adjusted_args); @@ -332,7 +330,7 @@ DCHECK(settings_.using_synchronous_renderer_compositor); DCHECK_EQ(state_machine_.begin_impl_frame_state(), SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); - DCHECK(!BeginImplFrameDeadlinePending()); + DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); state_machine_.SetResourcelessSoftwareDraw(resourceless_software_draw); state_machine_.OnBeginImplFrameDeadline(); @@ -379,8 +377,7 @@ } if (begin_retro_frame_args_.empty()) { - TRACE_EVENT_INSTANT0("cc", - "Scheduler::BeginRetroFrames all expired", + TRACE_EVENT_INSTANT0("cc", "Scheduler::BeginRetroFrames all expired", TRACE_EVENT_SCOPE_THREAD); } else { BeginFrameArgs front = begin_retro_frame_args_.front(); @@ -395,9 +392,7 @@ // BeginFrames in FIFO order. void Scheduler::PostBeginRetroFrameIfNeeded() { TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), - "Scheduler::PostBeginRetroFrameIfNeeded", - "state", - AsValue()); + "Scheduler::PostBeginRetroFrameIfNeeded", "state", AsValue()); if (!observing_begin_frame_source_) return; @@ -508,7 +503,7 @@ void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { DCHECK_EQ(state_machine_.begin_impl_frame_state(), SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); - DCHECK(!BeginImplFrameDeadlinePending()); + DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); DCHECK(state_machine_.HasInitializedOutputSurface()); begin_impl_frame_tracker_.Start(args); @@ -580,8 +575,9 @@ if (begin_impl_frame_deadline_mode_ == state_machine_.CurrentBeginImplFrameDeadlineMode() && - BeginImplFrameDeadlinePending()) + !begin_impl_frame_deadline_task_.IsCancelled()) { return; + } ScheduleBeginImplFrameDeadline(); } @@ -637,9 +633,8 @@ } void Scheduler::SetDeferCommits(bool defer_commits) { - TRACE_EVENT1("cc", "Scheduler::SetDeferCommits", - "defer_commits", - defer_commits); + TRACE_EVENT1("cc", "Scheduler::SetDeferCommits", "defer_commits", + defer_commits); state_machine_.SetDeferCommits(defer_commits); ProcessScheduledActions(); } @@ -656,11 +651,9 @@ do { action = state_machine_.NextAction(); TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), - "SchedulerStateMachine", - "state", - AsValue()); - base::AutoReset<SchedulerStateMachine::Action> - mark_inside_action(&inside_action_, action); + "SchedulerStateMachine", "state", AsValue()); + base::AutoReset<SchedulerStateMachine::Action> mark_inside_action( + &inside_action_, action); switch (action) { case SchedulerStateMachine::ACTION_NONE: break;
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h index 017307e..09bac9a0 100644 --- a/cc/scheduler/scheduler.h +++ b/cc/scheduler/scheduler.h
@@ -117,9 +117,6 @@ bool PrepareTilesPending() const { return state_machine_.PrepareTilesPending(); } - bool BeginImplFrameDeadlinePending() const { - return !begin_impl_frame_deadline_task_.IsCancelled(); - } bool ImplLatencyTakesPriority() const { return state_machine_.ImplLatencyTakesPriority(); }
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc index bf3b3f9..c16eb97 100644 --- a/cc/scheduler/scheduler_unittest.cc +++ b/cc/scheduler/scheduler_unittest.cc
@@ -32,13 +32,13 @@ } \ for (int i = expected_num_actions; i < client->num_actions_(); ++i) \ ADD_FAILURE() << "Unexpected action: " << client->Action(i) \ - << " with state:\n" << client->StateForAction(i); \ + << " with state:\n" \ + << client->StateForAction(i); \ } while (false) #define EXPECT_NO_ACTION(client) EXPECT_ACTION("", client, -1, 0) -#define EXPECT_SINGLE_ACTION(action, client) \ - EXPECT_ACTION(action, client, 0, 1) +#define EXPECT_SINGLE_ACTION(action, client) EXPECT_ACTION(action, client, 0, 1) #define EXPECT_SCOPED(statements) \ { \ @@ -56,7 +56,8 @@ public FakeExternalBeginFrameSource::Client { public: FakeSchedulerClient() - : automatic_swap_ack_(true), + : inside_begin_impl_frame_(false), + automatic_swap_ack_(true), scheduler_(nullptr) { Reset(); } @@ -90,9 +91,7 @@ return -1; } - bool HasAction(const char* action) const { - return ActionIndex(action) >= 0; - } + bool HasAction(const char* action) const { return ActionIndex(action) >= 0; } void SetWillBeginImplFrameRequestsOneBeginImplFrame(bool request) { will_begin_impl_frame_requests_one_begin_impl_frame_ = request; @@ -111,13 +110,18 @@ } // SchedulerClient implementation. void WillBeginImplFrame(const BeginFrameArgs& args) override { + EXPECT_FALSE(inside_begin_impl_frame_); + inside_begin_impl_frame_ = true; PushAction("WillBeginImplFrame"); if (will_begin_impl_frame_requests_one_begin_impl_frame_) scheduler_->SetNeedsOneBeginImplFrame(); if (will_begin_impl_frame_causes_redraw_) scheduler_->SetNeedsRedraw(); } - void DidFinishImplFrame() override {} + void DidFinishImplFrame() override { + EXPECT_TRUE(inside_begin_impl_frame_); + inside_begin_impl_frame_ = false; + } void ScheduledActionSendBeginMainFrame(const BeginFrameArgs& args) override { PushAction("ScheduledActionSendBeginMainFrame"); @@ -171,10 +175,11 @@ PushAction("SendBeginMainFrameNotExpectedSoon"); } - base::Callback<bool(void)> ImplFrameDeadlinePending(bool state) { - return base::Bind(&FakeSchedulerClient::ImplFrameDeadlinePendingCallback, - base::Unretained(this), - state); + bool IsInsideBeginImplFrame() const { return inside_begin_impl_frame_; } + + base::Callback<bool(void)> InsideBeginImplFrame(bool state) { + return base::Bind(&FakeSchedulerClient::InsideBeginImplFrameCallback, + base::Unretained(this), state); } void PushAction(const char* description) { @@ -191,10 +196,11 @@ } protected: - bool ImplFrameDeadlinePendingCallback(bool state) { - return scheduler_->BeginImplFrameDeadlinePending() == state; + bool InsideBeginImplFrameCallback(bool state) { + return inside_begin_impl_frame_ == state; } + bool inside_begin_impl_frame_; bool will_begin_impl_frame_causes_redraw_; bool will_begin_impl_frame_requests_one_begin_impl_frame_; bool draw_will_happen_; @@ -308,7 +314,7 @@ scheduler_->DidCreateAndInitializeOutputSurface(); scheduler_->SetNeedsBeginMainFrame(); EXPECT_TRUE(scheduler_->begin_frames_expected()); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); { @@ -328,11 +334,11 @@ scheduler_->OnDrawForOutputSurface(resourceless_software_draw); } else { // Run the posted deadline task. - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); + task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true)); } - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); } client_->Reset(); @@ -344,11 +350,11 @@ if (!scheduler_settings_.using_synchronous_renderer_compositor) { // Run the posted deadline task. - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); + task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true)); } - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); } EXPECT_FALSE(scheduler_->begin_frames_expected()); @@ -362,10 +368,10 @@ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "FakeSchedulerClient::AdvanceFrame"); // Consume any previous deadline first, if no deadline is currently - // pending, ImplFrameDeadlinePending will return false straight away and we + // pending, InsideBeginImplFrame will return false straight away and we // will run no tasks. - task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true)); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true)); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); // Send the next BeginFrame message if using an external source, otherwise // it will be already in the task queue. @@ -377,9 +383,9 @@ if (!scheduler_->settings().using_synchronous_renderer_compositor) { // Then run tasks until new deadline is scheduled. - EXPECT_TRUE(task_runner_->RunTasksWhile( - client_->ImplFrameDeadlinePending(false))); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE( + task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(false))); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); } } @@ -445,13 +451,13 @@ client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); // WillBeginImplFrame is responsible for sending BeginFrames to video. EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); client_->Reset(); @@ -459,8 +465,8 @@ EXPECT_NO_ACTION(client_); client_->Reset(); - task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true)); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true)); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_ACTION("RemoveObserver(this)", client_, 0, 2); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); EXPECT_FALSE(scheduler_->begin_frames_expected()); @@ -478,14 +484,14 @@ EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // If we don't swap on the deadline, we wait for the next BeginFrame. task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_NO_ACTION(client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); @@ -505,14 +511,14 @@ // BeginImplFrame should prepare the draw. EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // BeginImplFrame deadline should draw. task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); @@ -520,7 +526,7 @@ // to avoid excessive toggles. EXPECT_SCOPED(AdvanceFrame()); EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. @@ -553,7 +559,7 @@ EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); } TEST_F(SchedulerTest, DeferCommitWithRedraw) { @@ -579,7 +585,7 @@ client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); @@ -599,7 +605,7 @@ EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); @@ -614,18 +620,18 @@ scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); // Activate it. scheduler_->NotifyReadyToActivate(); EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); // Because we just swapped, the Scheduler should also request the next // BeginImplFrame from the OutputSurface. @@ -636,7 +642,7 @@ EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); // Finishing the commit before the deadline should post a new deadline task @@ -644,15 +650,15 @@ scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); scheduler_->NotifyReadyToActivate(); EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); @@ -950,7 +956,7 @@ client->Reset(); EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); // On the deadline, the actions should have occured in the right order. client->Reset(); @@ -962,7 +968,7 @@ client->ActionIndex("ScheduledActionPrepareTiles")); EXPECT_FALSE(scheduler_->RedrawPending()); EXPECT_FALSE(scheduler_->PrepareTilesPending()); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); // Request a draw. We don't need a PrepareTiles yet. client->Reset(); @@ -977,7 +983,7 @@ client->Reset(); EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); // Draw. The draw will trigger SetNeedsPrepareTiles, and // then the PrepareTiles action will be triggered after the Draw. @@ -991,18 +997,18 @@ client->ActionIndex("ScheduledActionPrepareTiles")); EXPECT_FALSE(scheduler_->RedrawPending()); EXPECT_FALSE(scheduler_->PrepareTilesPending()); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); // We need a BeginImplFrame where we don't swap to go idle. client->Reset(); EXPECT_SCOPED(AdvanceFrame()); EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_ACTION("RemoveObserver(this)", client_, 0, 2); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_EQ(0, client->num_draws()); // Now trigger a PrepareTiles outside of a draw. We will then need @@ -1018,13 +1024,13 @@ client->Reset(); EXPECT_SCOPED(AdvanceFrame()); EXPECT_SINGLE_ACTION("WillBeginImplFrame", client); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_EQ(0, client->num_draws()); EXPECT_FALSE(client->HasAction("ScheduledActionDrawAndSwapIfPossible")); EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles")); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); } // Test that PrepareTiles only happens once per frame. If an external caller @@ -1040,7 +1046,7 @@ client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->PrepareTilesPending()); scheduler_->WillPrepareTiles(); @@ -1054,7 +1060,7 @@ EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles")); EXPECT_FALSE(scheduler_->RedrawPending()); EXPECT_FALSE(scheduler_->PrepareTilesPending()); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); // Next frame without DidPrepareTiles should PrepareTiles with draw. scheduler_->SetNeedsPrepareTiles(); @@ -1062,7 +1068,7 @@ client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. @@ -1073,7 +1079,7 @@ client_->ActionIndex("ScheduledActionPrepareTiles")); EXPECT_FALSE(scheduler_->RedrawPending()); EXPECT_FALSE(scheduler_->PrepareTilesPending()); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); // If we get another DidPrepareTiles within the same frame, we should // not PrepareTiles on the next frame. @@ -1084,7 +1090,7 @@ client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->PrepareTilesPending()); @@ -1094,7 +1100,7 @@ EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible")); EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles")); EXPECT_FALSE(scheduler_->RedrawPending()); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); // If we get another DidPrepareTiles, we should not PrepareTiles on the next // frame. This verifies we don't alternate calling PrepareTiles once and @@ -1108,7 +1114,7 @@ client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->PrepareTilesPending()); @@ -1118,7 +1124,7 @@ EXPECT_TRUE(client_->HasAction("ScheduledActionDrawAndSwapIfPossible")); EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles")); EXPECT_FALSE(scheduler_->RedrawPending()); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); // Next frame without DidPrepareTiles should PrepareTiles with draw. scheduler_->SetNeedsPrepareTiles(); @@ -1126,7 +1132,7 @@ client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. @@ -1137,7 +1143,7 @@ client_->ActionIndex("ScheduledActionPrepareTiles")); EXPECT_FALSE(scheduler_->RedrawPending()); EXPECT_FALSE(scheduler_->PrepareTilesPending()); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); } TEST_F(SchedulerTest, PrepareTilesFunnelResetOnVisibilityChange) { @@ -1164,11 +1170,11 @@ client_->Reset(); AdvanceFrame(); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2); EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 1, 2); } @@ -1262,7 +1268,7 @@ // Scheduler loses output surface, and stops waiting for ready to draw signal. client_->Reset(); scheduler_->DidLoseOutputSurface(); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); @@ -1276,7 +1282,7 @@ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); EXPECT_SCOPED(AdvanceFrame()); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline()); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); @@ -1293,7 +1299,7 @@ EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline()); EXPECT_SCOPED(AdvanceFrame()); EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_EQ(expect_send_begin_main_frame, scheduler_->MainThreadMissedLastDeadline()); EXPECT_TRUE(client_->HasAction("WillBeginImplFrame")); @@ -1423,7 +1429,7 @@ EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline()); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline()); @@ -1439,7 +1445,7 @@ EXPECT_TRUE(client_->HasAction("WillBeginImplFrame")); EXPECT_TRUE(client_->HasAction("ScheduledActionSendBeginMainFrame")); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline()); } @@ -1460,7 +1466,7 @@ EXPECT_ACTION("WillBeginImplFrame", client_, 1, 3); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 3); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline()); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline()); @@ -1489,7 +1495,7 @@ EXPECT_TRUE(client_->HasAction("WillBeginImplFrame")); EXPECT_TRUE(client_->HasAction("ScheduledActionSendBeginMainFrame")); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline()); } @@ -1513,7 +1519,7 @@ scheduler_->NotifyReadyToCommit(); scheduler_->NotifyReadyToActivate(); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_ACTION("ScheduledActionCommit", client_, 0, 3); EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 3); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3); @@ -1530,7 +1536,7 @@ SendNextBeginFrame(); // Verify that we skip the BeginImplFrame EXPECT_NO_ACTION(client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); // Verify that we do not perform any actions after we are no longer @@ -1539,10 +1545,10 @@ if (swap_ack_before_deadline) { // It shouldn't matter if the swap ack comes back before the deadline... scheduler_->DidSwapBuffersComplete(); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); } else { // ... or after the deadline. - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); scheduler_->DidSwapBuffersComplete(); } EXPECT_NO_ACTION(client_); @@ -1559,7 +1565,7 @@ scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); scheduler_->NotifyReadyToActivate(); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_ACTION("ScheduledActionCommit", client_, 0, 3); EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 3); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3); @@ -1641,7 +1647,7 @@ client_->Reset(); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); // Verify we skip every other frame if the swap ack consistently @@ -1655,7 +1661,7 @@ SendNextBeginFrame(); // Verify that we skip the BeginImplFrame EXPECT_NO_ACTION(client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); // Verify that we do not perform any actions after we are no longer @@ -1673,9 +1679,9 @@ client_->Reset(); // Deadline should be immediate. - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); task_runner().RunUntilTime(now_src_->NowTicks()); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); } } @@ -1698,7 +1704,7 @@ scheduler_->NotifyReadyToCommit(); scheduler_->NotifyReadyToActivate(); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_ACTION("ScheduledActionCommit", client_, 0, 3); EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 3); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 2, 3); @@ -1713,7 +1719,7 @@ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); SendNextBeginFrame(); EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); client_->Reset(); @@ -1721,7 +1727,7 @@ scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); scheduler_->NotifyReadyToActivate(); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); // Verify that we don't skip the actions of the BeginImplFrame EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 0, 4); @@ -1801,7 +1807,7 @@ EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); EXPECT_SCOPED(AdvanceFrame()); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline()); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); @@ -1820,7 +1826,7 @@ EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline()); EXPECT_SCOPED(AdvanceFrame()); EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); scheduler_->NotifyReadyToActivate(); @@ -1838,7 +1844,7 @@ EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline()); EXPECT_SCOPED(AdvanceFrame()); EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); // Note: BeginMainFrame and swap are skipped here because of @@ -1862,7 +1868,7 @@ SendNextBeginFrame(); EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline()); scheduler_->DidSwapBuffersComplete(); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); @@ -1874,7 +1880,7 @@ EXPECT_TRUE(scheduler_->NeedsBeginMainFrame()); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); SendNextBeginFrame(); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); scheduler_->DidSwapBuffersComplete(); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); @@ -1891,7 +1897,7 @@ scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); scheduler_->NotifyReadyToActivate(); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); scheduler_->DidSwapBuffersComplete(); EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline()); @@ -1925,9 +1931,9 @@ scheduler_->SetNeedsRedraw(); EXPECT_SCOPED(AdvanceFrame()); EXPECT_TRUE(scheduler_->CommitPending()); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); scheduler_->NotifyReadyToActivate(); @@ -1947,9 +1953,9 @@ scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); scheduler_->NotifyReadyToActivate(); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 3); EXPECT_ACTION("ScheduledActionCommit", client_, 2, 3); @@ -1990,9 +1996,9 @@ scheduler_->SetNeedsRedraw(); EXPECT_SCOPED(AdvanceFrame()); EXPECT_TRUE(scheduler_->CommitPending()); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); scheduler_->DidSwapBuffersComplete(); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); @@ -2010,9 +2016,9 @@ scheduler_->SetNeedsRedraw(); EXPECT_SCOPED(AdvanceFrame()); EXPECT_TRUE(scheduler_->CommitPending()); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); scheduler_->DidSwapBuffersComplete(); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); @@ -2049,7 +2055,7 @@ fake_external_begin_frame_source()->TestOnBeginFrame(args); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); @@ -2062,7 +2068,7 @@ // If we don't swap on the deadline, we wait for the next BeginImplFrame. task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_NO_ACTION(client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); @@ -2082,14 +2088,14 @@ // BeginImplFrame should prepare the draw. task_runner().RunPendingTasks(); // Run posted BeginRetroFrame. EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); // BeginImplFrame deadline should draw. task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); @@ -2097,7 +2103,7 @@ // to avoid excessive toggles. task_runner().RunPendingTasks(); // Run posted BeginRetroFrame. EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. @@ -2118,7 +2124,7 @@ EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); @@ -2128,7 +2134,7 @@ // This BeginFrame is queued up as a retro frame. EXPECT_NO_ACTION(client_); // The previous deadline is still pending. - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); // This main frame activating should schedule the (previous) deadline to @@ -2140,8 +2146,8 @@ client_->Reset(); // The deadline task should trigger causing a draw. - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); // Keep animating. @@ -2154,14 +2160,14 @@ now_src()->Advance(retro_frame_args.deadline - now_src()->NowTicks()); // The retro frame hasn't expired yet. - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(false)); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); // This is an immediate deadline case. client_->Reset(); task_runner().RunPendingTasks(); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); } @@ -2177,7 +2183,7 @@ EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); @@ -2187,7 +2193,7 @@ // This BeginFrame is queued up as a retro frame. EXPECT_NO_ACTION(client_); // The previous deadline is still pending. - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); // This main frame activating should schedule the (previous) deadline to @@ -2199,8 +2205,8 @@ client_->Reset(); // The deadline task should trigger causing a draw. - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); // Keep animating. @@ -2236,10 +2242,10 @@ client_->Reset(); fake_external_begin_frame_source_->TestOnBeginFrame(missed_frame_args); EXPECT_TRUE( - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false))); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(false))); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); } TEST_F(SchedulerTest, MissedFrameExpiresOnTime) { @@ -2262,9 +2268,9 @@ client_->Reset(); fake_external_begin_frame_source_->TestOnBeginFrame(missed_frame_args); EXPECT_FALSE( - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(false))); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(false))); EXPECT_NO_ACTION(client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); } void SchedulerTest::BeginFramesNotFromClient( @@ -2286,13 +2292,13 @@ task_runner().RunPendingTasks(); // Run posted BeginFrame. EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); // If we don't swap on the deadline, we wait for the next BeginFrame. task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_NO_ACTION(client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); // NotifyReadyToCommit should trigger the commit. @@ -2309,20 +2315,20 @@ // BeginImplFrame should prepare the draw. task_runner().RunPendingTasks(); // Run posted BeginFrame. EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); // BeginImplFrame deadline should draw. - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); // The following BeginImplFrame deadline should SetNeedsBeginFrame(false) // to avoid excessive toggles. task_runner().RunPendingTasks(); // Run posted BeginFrame. EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); // Make sure SetNeedsBeginFrame isn't called on the client @@ -2380,7 +2386,7 @@ EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); // NotifyReadyToCommit should trigger the pending commit. @@ -2396,9 +2402,9 @@ // Swapping will put us into a swap throttled state. // Run posted deadline. - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); // While swap throttled, BeginFrames should trigger BeginImplFrames, @@ -2407,44 +2413,44 @@ scheduler_->SetNeedsRedraw(); EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame. EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); base::TimeTicks before_deadline, after_deadline; // The deadline is set to the regular deadline. before_deadline = now_src()->NowTicks(); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); after_deadline = now_src()->NowTicks(); // We can't do an equality comparison here because the scheduler uses a fudge // factor that's an internal implementation detail. EXPECT_GT(after_deadline, before_deadline); EXPECT_LT(after_deadline, before_deadline + BeginFrameArgs::DefaultInterval()); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); // Run posted BeginFrame. EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); // Take us out of a swap throttled state. scheduler_->DidSwapBuffersComplete(); EXPECT_SINGLE_ACTION("ScheduledActionSendBeginMainFrame", client_); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); // The deadline is set to the regular deadline. before_deadline = now_src()->NowTicks(); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); after_deadline = now_src()->NowTicks(); // We can't do an equality comparison here because the scheduler uses a fudge // factor that's an internal implementation detail. EXPECT_GT(after_deadline, before_deadline); EXPECT_LT(after_deadline, before_deadline + BeginFrameArgs::DefaultInterval()); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); } @@ -2498,7 +2504,7 @@ EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); scheduler_->DidLoseOutputSurface(); @@ -2512,7 +2518,7 @@ EXPECT_ACTION("ScheduledActionActivateSyncTree", client_, 1, 2); client_->Reset(); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); @@ -2531,7 +2537,7 @@ EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); scheduler_->DidLoseOutputSurface(); @@ -2540,20 +2546,20 @@ client_->Reset(); // Run posted deadline. - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); // OnBeginImplFrameDeadline didn't schedule output surface creation because // main frame is not yet completed. EXPECT_ACTION("RemoveObserver(this)", client_, 0, 2); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); // BeginImplFrame is not started. client_->Reset(); task_runner().RunUntilTime(now_src()->NowTicks() + base::TimeDelta::FromMilliseconds(10)); EXPECT_NO_ACTION(client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); @@ -2575,7 +2581,7 @@ EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); @@ -2589,7 +2595,7 @@ // RemoveObserver(this) is not called until the end of the frame. client_->Reset(); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); @@ -2606,7 +2612,7 @@ client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); scheduler_->DidLoseOutputSurface(); @@ -2614,7 +2620,7 @@ EXPECT_NO_ACTION(client_); client_->Reset(); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 0, 4); EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 1, 4); EXPECT_ACTION("RemoveObserver(this)", client_, 2, 4); @@ -2638,7 +2644,7 @@ fake_external_begin_frame_source()->TestOnBeginFrame(args); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); // Queue BeginFrames while we are still handling the previous BeginFrame. @@ -2651,7 +2657,7 @@ client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_NO_ACTION(client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); // NotifyReadyToCommit should trigger the commit. @@ -2698,7 +2704,7 @@ fake_external_begin_frame_source()->TestOnBeginFrame(args); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); // Queue BeginFrames while we are still handling the previous BeginFrame. @@ -2711,7 +2717,7 @@ client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_NO_ACTION(client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); // NotifyReadyToCommit should trigger the commit. @@ -2731,7 +2737,7 @@ client_->Reset(); task_runner().RunPendingTasks(); // Run posted BeginRetroFrame. EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); @@ -2742,11 +2748,11 @@ // BeginImplFrame deadline should abort drawing. client_->Reset(); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_FALSE(scheduler_->begin_frames_expected()); // No more BeginRetroFrame because BeginRetroFrame queue is cleared. @@ -2767,7 +2773,7 @@ AdvanceFrame(); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); // NotifyReadyToCommit should trigger the commit. @@ -2790,7 +2796,7 @@ EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 2); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); EXPECT_FALSE(scheduler_->begin_frames_expected()); @@ -2808,7 +2814,7 @@ EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); @@ -2820,7 +2826,7 @@ EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); client_->Reset(); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); // Idle time between BeginFrames. @@ -2843,13 +2849,13 @@ EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); scheduler_->SetVisible(false); @@ -2873,13 +2879,13 @@ EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); fake_external_begin_frame_source_->SetPaused(true); @@ -2901,7 +2907,7 @@ EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. @@ -2915,13 +2921,13 @@ // Unthrottled frame source will immediately begin a new frame. task_runner().RunPendingTasks(); // Run posted BeginFrame. EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); // If we don't swap on the deadline, we wait for the next BeginFrame. task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); } @@ -2943,7 +2949,7 @@ scheduler_->SetBeginFrameSource(unthrottled_frame_source_.get()); client_->Reset(); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); @@ -2956,7 +2962,7 @@ task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); } @@ -2973,12 +2979,12 @@ task_runner().RunPendingTasks(); // Run posted BeginFrame. EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); // Switch to a throttled frame source. @@ -2993,7 +2999,7 @@ EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_TRUE(scheduler_->begin_frames_expected()); client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. @@ -3017,34 +3023,34 @@ EXPECT_SINGLE_ACTION("RemoveObserver(this)", client_); client_->Reset(); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); task_runner().RunPendingTasks(); // Run posted deadline. EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); EXPECT_FALSE(scheduler_->begin_frames_expected()); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); // AdvanceFrame helper can't be used here because there's no deadline posted. scheduler_->SetNeedsRedraw(); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_NO_ACTION(client_); client_->Reset(); scheduler_->SetNeedsBeginMainFrame(); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_NO_ACTION(client_); client_->Reset(); // Switch back to the same source, make sure frames continue to be produced. scheduler_->SetBeginFrameSource(fake_external_begin_frame_source_.get()); EXPECT_SINGLE_ACTION("AddObserver(this)", client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); task_runner().RunPendingTasks(); @@ -3079,7 +3085,7 @@ // Scheduler loses output surface, and stops waiting for ready to draw signal. client_->Reset(); scheduler_->DidLoseOutputSurface(); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); task_runner().RunPendingTasks(); EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 3); EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); @@ -3132,7 +3138,7 @@ // and send a SendBeginMainFrameNotExpectedSoon. EXPECT_SCOPED(AdvanceFrame()); EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); task_runner().RunPendingTasks(); // Run posted deadline. @@ -3159,7 +3165,7 @@ AdvanceFrame(); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 1, 2); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); // Android onDraw. This doesn't consume the single begin frame request. @@ -3167,7 +3173,7 @@ bool resourceless_software_draw = false; scheduler_->OnDrawForOutputSurface(resourceless_software_draw); EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); // The animation inside of WillBeginImplFrame changes stuff on the screen, but @@ -3178,14 +3184,14 @@ AdvanceFrame(); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 1, 2); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); // Android onDraw. scheduler_->SetNeedsRedraw(); scheduler_->OnDrawForOutputSurface(resourceless_software_draw); EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); // Idle on next vsync, as the animation has completed. @@ -3193,7 +3199,7 @@ EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); } @@ -3207,7 +3213,7 @@ scheduler_->OnDrawForOutputSurface(resourceless_software_draw); EXPECT_ACTION("AddObserver(this)", client_, 0, 2); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 1, 2); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); // Idle on next vsync. @@ -3215,7 +3221,7 @@ EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); } @@ -3236,7 +3242,7 @@ // Next vsync, the first requested frame happens. EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); // We don't request another frame here. @@ -3245,12 +3251,12 @@ // the previous frame's begin impl frame step). EXPECT_SCOPED(AdvanceFrame()); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 1); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); client_->Reset(); // End that frame's deadline. - task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true)); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true)); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); // Scheduler shuts down the source now that no begin frame is requested. EXPECT_ACTION("RemoveObserver(this)", client_, 0, 2); @@ -3270,7 +3276,7 @@ AdvanceFrame(); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); @@ -3279,7 +3285,7 @@ // Next vsync. AdvanceFrame(); EXPECT_SINGLE_ACTION("WillBeginImplFrame", client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); scheduler_->NotifyReadyToCommit(); @@ -3294,7 +3300,7 @@ AdvanceFrame(); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 1, 2); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); // Android onDraw. @@ -3302,7 +3308,7 @@ bool resourceless_software_draw = false; scheduler_->OnDrawForOutputSurface(resourceless_software_draw); EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); // Idle on next vsync. @@ -3310,7 +3316,7 @@ EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); EXPECT_ACTION("RemoveObserver(this)", client_, 1, 3); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); } @@ -3327,7 +3333,7 @@ AdvanceFrame(); EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); @@ -3348,7 +3354,7 @@ EXPECT_ACTION("WillBeginImplFrame", client_, 0, 3); EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 3); EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 2, 3); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); @@ -3395,7 +3401,7 @@ scheduler_->OnDrawForOutputSurface(resourceless_software_draw); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2); EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 1, 2); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_FALSE(scheduler_->PrepareTilesPending()); client_->Reset(); @@ -3404,7 +3410,7 @@ scheduler_->OnDrawForOutputSurface(resourceless_software_draw); EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 2); EXPECT_ACTION("ScheduledActionPrepareTiles", client_, 1, 2); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_FALSE(scheduler_->PrepareTilesPending()); client_->Reset(); @@ -3439,7 +3445,7 @@ bool resourceless_software_draw = false; scheduler_->OnDrawForOutputSurface(resourceless_software_draw); EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_FALSE(scheduler_->PrepareTilesPending()); client_->Reset(); @@ -3467,7 +3473,7 @@ scheduler_->SetNeedsRedraw(); scheduler_->OnDrawForOutputSurface(resourceless_software_draw); EXPECT_SINGLE_ACTION("ScheduledActionDrawAndSwapIfPossible", client_); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_FALSE(scheduler_->PrepareTilesPending()); client_->Reset(); @@ -3489,7 +3495,7 @@ scheduler_->OnDrawForOutputSurface(resourceless_software_draw); // SynchronousCompositor has to draw regardless of visibility. EXPECT_ACTION("ScheduledActionDrawAndSwapIfPossible", client_, 0, 1); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); client_->Reset(); } @@ -3507,7 +3513,7 @@ scheduler_->NotifyBeginMainFrameStarted(base::TimeTicks()); scheduler_->NotifyReadyToCommit(); scheduler_->NotifyReadyToActivate(); - task_runner().RunTasksWhile(client_->ImplFrameDeadlinePending(true)); + task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true)); // Test changing the interval on the frame source external to the scheduler. synthetic_frame_source_->OnUpdateVSyncParameters(now_src_->NowTicks(), @@ -3570,13 +3576,13 @@ // Lose the output surface and trigger the deadline. client_->Reset(); scheduler_->DidLoseOutputSurface(); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_NO_ACTION(client_); // The scheduler should not trigger the output surface creation till the // commit is aborted. - task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true)); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true)); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_SINGLE_ACTION("SendBeginMainFrameNotExpectedSoon", client_); // Abort the commit. @@ -3601,13 +3607,13 @@ // Lose the output surface and trigger the deadline. client_->Reset(); scheduler_->DidLoseOutputSurface(); - EXPECT_TRUE(scheduler_->BeginImplFrameDeadlinePending()); + EXPECT_TRUE(client_->IsInsideBeginImplFrame()); EXPECT_NO_ACTION(client_); // The scheduler should trigger the output surface creation immediately after // the begin_impl_frame_state_ is cleared. - task_runner_->RunTasksWhile(client_->ImplFrameDeadlinePending(true)); - EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true)); + EXPECT_FALSE(client_->IsInsideBeginImplFrame()); EXPECT_ACTION("ScheduledActionBeginOutputSurfaceCreation", client_, 0, 2); EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 1, 2); }
diff --git a/cc/surfaces/display.cc b/cc/surfaces/display.cc index f45842d9..21be047 100644 --- a/cc/surfaces/display.cc +++ b/cc/surfaces/display.cc
@@ -92,8 +92,8 @@ DCHECK(ok); } -void Display::SetSurfaceId(SurfaceId id, float device_scale_factor) { - DCHECK_EQ(id.id_namespace(), compositor_surface_namespace_); +void Display::SetSurfaceId(const SurfaceId& id, float device_scale_factor) { + DCHECK_EQ(id.client_id(), compositor_surface_namespace_); if (current_surface_id_ == id && device_scale_factor_ == device_scale_factor) return; @@ -322,6 +322,8 @@ } benchmark_instrumentation::IssueDisplayRenderingStatsEvent(); renderer_->SwapBuffers(std::move(frame.metadata)); + if (scheduler_) + scheduler_->DidSwapBuffers(); } else { if (have_damage && !size_matches) aggregator_->SetFullDamageForSurface(current_surface_id_); @@ -329,18 +331,14 @@ stored_latency_info_.insert(stored_latency_info_.end(), frame.metadata.latency_info.begin(), frame.metadata.latency_info.end()); - DidSwapBuffers(); + if (scheduler_) + scheduler_->DidSwapBuffers(); DidSwapBuffersComplete(); } return true; } -void Display::DidSwapBuffers() { - if (scheduler_) - scheduler_->DidSwapBuffers(); -} - void Display::DidSwapBuffersComplete() { if (scheduler_) scheduler_->DidSwapBuffersComplete(); @@ -402,7 +400,7 @@ aggregator_->SetFullDamageForSurface(current_surface_id_); } -void Display::OnSurfaceDamaged(SurfaceId surface_id, bool* changed) { +void Display::OnSurfaceDamaged(const SurfaceId& surface_id, bool* changed) { if (aggregator_ && aggregator_->previous_contained_surfaces().count(surface_id)) { Surface* surface = surface_manager_->GetSurfaceForId(surface_id); @@ -426,7 +424,7 @@ UpdateRootSurfaceResourcesLocked(); } -SurfaceId Display::CurrentSurfaceId() { +const SurfaceId& Display::CurrentSurfaceId() { return current_surface_id_; }
diff --git a/cc/surfaces/display.h b/cc/surfaces/display.h index 9df93d41..c9afdea 100644 --- a/cc/surfaces/display.h +++ b/cc/surfaces/display.h
@@ -72,13 +72,13 @@ // device_scale_factor is used to communicate to the external window system // what scale this was rendered at. - void SetSurfaceId(SurfaceId id, float device_scale_factor); + void SetSurfaceId(const SurfaceId& id, float device_scale_factor); void Resize(const gfx::Size& new_size); void SetColorSpace(const gfx::ColorSpace& color_space); void SetExternalClip(const gfx::Rect& clip); void SetOutputIsSecure(bool secure); - SurfaceId CurrentSurfaceId(); + const SurfaceId& CurrentSurfaceId(); // DisplaySchedulerClient implementation. bool DrawAndSwap() override; @@ -88,7 +88,6 @@ base::TimeDelta interval) override; void SetBeginFrameSource(BeginFrameSource* source) override; void SetNeedsRedrawRect(const gfx::Rect& damage_rect) override; - void DidSwapBuffers() override; void DidSwapBuffersComplete() override; void DidReceiveTextureInUseResponses( const gpu::TextureInUseResponses& responses) override; @@ -108,7 +107,7 @@ void SetFullRootLayerDamage() override; // SurfaceDamageObserver implementation. - void OnSurfaceDamaged(SurfaceId surface, bool* changed) override; + void OnSurfaceDamaged(const SurfaceId& surface, bool* changed) override; void SetEnlargePassTextureAmountForTesting( const gfx::Size& enlarge_texture_amount) {
diff --git a/cc/surfaces/display_scheduler.cc b/cc/surfaces/display_scheduler.cc index 98f2a689..d26d1b6 100644 --- a/cc/surfaces/display_scheduler.cc +++ b/cc/surfaces/display_scheduler.cc
@@ -69,7 +69,7 @@ // Notification that there was a resize or the root surface changed and // that we should just draw immediately. -void DisplayScheduler::SetNewRootSurface(SurfaceId root_surface_id) { +void DisplayScheduler::SetNewRootSurface(const SurfaceId& root_surface_id) { TRACE_EVENT0("cc", "DisplayScheduler::SetNewRootSurface"); root_surface_id_ = root_surface_id; SurfaceDamaged(root_surface_id); @@ -78,7 +78,7 @@ // Indicates that there was damage to one of the surfaces. // Has some logic to wait for multiple active surfaces before // triggering the deadline. -void DisplayScheduler::SurfaceDamaged(SurfaceId surface_id) { +void DisplayScheduler::SurfaceDamaged(const SurfaceId& surface_id) { TRACE_EVENT1("cc", "DisplayScheduler::SurfaceDamaged", "surface_id", surface_id.ToString());
diff --git a/cc/surfaces/display_scheduler.h b/cc/surfaces/display_scheduler.h index aa3a9067..16d0868 100644 --- a/cc/surfaces/display_scheduler.h +++ b/cc/surfaces/display_scheduler.h
@@ -40,8 +40,8 @@ void SetRootSurfaceResourcesLocked(bool locked); void ForceImmediateSwapIfPossible(); virtual void DisplayResized(); - virtual void SetNewRootSurface(SurfaceId root_surface_id); - virtual void SurfaceDamaged(SurfaceId surface_id); + virtual void SetNewRootSurface(const SurfaceId& root_surface_id); + virtual void SurfaceDamaged(const SurfaceId& surface_id); virtual void DidSwapBuffers(); void DidSwapBuffersComplete();
diff --git a/cc/surfaces/display_unittest.cc b/cc/surfaces/display_unittest.cc index 0de4a9f..0778b6a2 100644 --- a/cc/surfaces/display_unittest.cc +++ b/cc/surfaces/display_unittest.cc
@@ -70,11 +70,11 @@ void DisplayResized() override { display_resized_ = true; } - void SetNewRootSurface(SurfaceId root_surface_id) override { + void SetNewRootSurface(const SurfaceId& root_surface_id) override { has_new_root_surface = true; } - void SurfaceDamaged(SurfaceId surface_id) override { + void SurfaceDamaged(const SurfaceId& surface_id) override { damaged = true; needs_draw_ = true; } @@ -97,9 +97,9 @@ public: DisplayTest() : factory_(&manager_, &surface_factory_client_), - id_allocator_(kArbitrarySurfaceNamespace), + id_allocator_(kArbitraryClientId), task_runner_(new base::NullTaskRunner) { - id_allocator_.RegisterSurfaceIdNamespace(&manager_); + id_allocator_.RegisterSurfaceClientId(&manager_); } void SetUpDisplay(const RendererSettings& settings, @@ -125,13 +125,14 @@ display_ = base::MakeUnique<Display>( &manager_, &shared_bitmap_manager_, nullptr /* gpu_memory_buffer_manager */, settings, - id_allocator_.id_namespace(), std::move(begin_frame_source), + id_allocator_.client_id(), std::move(begin_frame_source), std::move(output_surface), std::move(scheduler), base::MakeUnique<TextureMailboxDeleter>(task_runner_.get())); } protected: - void SubmitCompositorFrame(RenderPassList* pass_list, SurfaceId surface_id) { + void SubmitCompositorFrame(RenderPassList* pass_list, + const SurfaceId& surface_id) { std::unique_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); pass_list->swap(frame_data->render_pass_list); @@ -142,7 +143,7 @@ SurfaceFactory::DrawCallback()); } - static constexpr int kArbitrarySurfaceNamespace = 3; + static constexpr int kArbitraryClientId = 3; SurfaceManager manager_; FakeSurfaceFactoryClient surface_factory_client_;
diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc index 3755d9b8..fc1eb39 100644 --- a/cc/surfaces/surface.cc +++ b/cc/surfaces/surface.cc
@@ -22,7 +22,7 @@ // completely damaged the first time they're drawn from. static const int kFrameIndexStart = 2; -Surface::Surface(SurfaceId id, SurfaceFactory* factory) +Surface::Surface(const SurfaceId& id, SurfaceFactory* factory) : surface_id_(id), previous_frame_surface_id_(id), factory_(factory->AsWeakPtr()), @@ -89,7 +89,7 @@ // Notify the manager that sequences were satisfied either if some new // sequences were satisfied, or if the set of referenced surfaces changed // to force a GC to happen. - factory_->manager()->DidSatisfySequences(surface_id_.id_namespace(), + factory_->manager()->DidSatisfySequences(surface_id_.client_id(), &satisfies_sequences); } } @@ -165,13 +165,13 @@ void Surface::SatisfyDestructionDependencies( std::unordered_set<SurfaceSequence, SurfaceSequenceHash>* sequences, - std::unordered_set<uint32_t>* valid_id_namespaces) { + std::unordered_set<uint32_t>* valid_client_ids) { destruction_dependencies_.erase( std::remove_if(destruction_dependencies_.begin(), destruction_dependencies_.end(), - [sequences, valid_id_namespaces](SurfaceSequence seq) { + [sequences, valid_client_ids](SurfaceSequence seq) { return (!!sequences->erase(seq) || - !valid_id_namespaces->count(seq.id_namespace)); + !valid_client_ids->count(seq.client_id)); }), destruction_dependencies_.end()); }
diff --git a/cc/surfaces/surface.h b/cc/surfaces/surface.h index e91d0bf..d101f6d 100644 --- a/cc/surfaces/surface.h +++ b/cc/surfaces/surface.h
@@ -40,11 +40,11 @@ public: using DrawCallback = SurfaceFactory::DrawCallback; - Surface(SurfaceId id, SurfaceFactory* factory); + Surface(const SurfaceId& id, SurfaceFactory* factory); ~Surface(); - SurfaceId surface_id() const { return surface_id_; } - SurfaceId previous_frame_surface_id() const { + const SurfaceId& surface_id() const { return surface_id_; } + const SurfaceId& previous_frame_surface_id() const { return previous_frame_surface_id_; }
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc index 83e313dd..2e9aeef 100644 --- a/cc/surfaces/surface_aggregator.cc +++ b/cc/surfaces/surface_aggregator.cc
@@ -124,7 +124,7 @@ } RenderPassId SurfaceAggregator::RemapPassId(RenderPassId surface_local_pass_id, - SurfaceId surface_id) { + const SurfaceId& surface_id) { std::unique_ptr<RenderPassIdAllocator>& allocator = render_pass_allocator_map_[surface_id]; if (!allocator) @@ -160,7 +160,7 @@ if (previous_index == surface->frame_index()) return gfx::Rect(); } - SurfaceId previous_surface_id = surface->previous_frame_surface_id(); + const SurfaceId& previous_surface_id = surface->previous_frame_surface_id(); if (surface->surface_id() != previous_surface_id) { it = previous_contained_surfaces_.find(previous_surface_id); @@ -358,7 +358,7 @@ const gfx::Transform& target_transform, const ClipData& clip_rect, RenderPass* dest_pass, - SurfaceId surface_id) { + const SurfaceId& surface_id) { const SharedQuadState* last_copied_source_shared_quad_state = nullptr; const SharedQuadState* dest_shared_quad_state = nullptr; // If the current frame has copy requests then aggregate the entire @@ -543,7 +543,7 @@ // Walk the Surface tree from surface_id. Validate the resources of the current // surface and its descendants, check if there are any copy requests, and // return the combined damage rect. -gfx::Rect SurfaceAggregator::PrewalkTree(SurfaceId surface_id, +gfx::Rect SurfaceAggregator::PrewalkTree(const SurfaceId& surface_id, bool in_moved_pixel_pass, RenderPassId parent_pass, PrewalkResult* result) { @@ -765,7 +765,7 @@ } } -CompositorFrame SurfaceAggregator::Aggregate(SurfaceId surface_id) { +CompositorFrame SurfaceAggregator::Aggregate(const SurfaceId& surface_id) { Surface* surface = manager_->GetSurfaceForId(surface_id); DCHECK(surface); contained_surfaces_[surface_id] = surface->frame_index(); @@ -820,7 +820,7 @@ return frame; } -void SurfaceAggregator::ReleaseResources(SurfaceId surface_id) { +void SurfaceAggregator::ReleaseResources(const SurfaceId& surface_id) { SurfaceToResourceChildIdMap::iterator it = surface_id_to_resource_child_id_.find(surface_id); if (it != surface_id_to_resource_child_id_.end()) { @@ -829,7 +829,7 @@ } } -void SurfaceAggregator::SetFullDamageForSurface(SurfaceId surface_id) { +void SurfaceAggregator::SetFullDamageForSurface(const SurfaceId& surface_id) { auto it = previous_contained_surfaces_.find(surface_id); if (it == previous_contained_surfaces_.end()) return;
diff --git a/cc/surfaces/surface_aggregator.h b/cc/surfaces/surface_aggregator.h index 99e93308..a06ba877 100644 --- a/cc/surfaces/surface_aggregator.h +++ b/cc/surfaces/surface_aggregator.h
@@ -36,12 +36,12 @@ bool aggregate_only_damaged); ~SurfaceAggregator(); - CompositorFrame Aggregate(SurfaceId surface_id); - void ReleaseResources(SurfaceId surface_id); + CompositorFrame Aggregate(const SurfaceId& surface_id); + void ReleaseResources(const SurfaceId& surface_id); SurfaceIndexMap& previous_contained_surfaces() { return previous_contained_surfaces_; } - void SetFullDamageForSurface(SurfaceId surface_id); + void SetFullDamageForSurface(const SurfaceId& surface_id); void set_output_is_secure(bool secure) { output_is_secure_ = secure; } private: @@ -67,7 +67,7 @@ const gfx::Transform& target_transform); RenderPassId RemapPassId(RenderPassId surface_local_pass_id, - SurfaceId surface_id); + const SurfaceId& surface_id); void HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad, const gfx::Transform& target_transform, @@ -84,8 +84,8 @@ const gfx::Transform& target_transform, const ClipData& clip_rect, RenderPass* dest_pass, - SurfaceId surface_id); - gfx::Rect PrewalkTree(SurfaceId surface_id, + const SurfaceId& surface_id); + gfx::Rect PrewalkTree(const SurfaceId& surface_id, bool in_moved_pixel_pass, RenderPassId parent_pass, PrewalkResult* result);
diff --git a/cc/surfaces/surface_aggregator_perftest.cc b/cc/surfaces/surface_aggregator_perftest.cc index d903743..9295e02 100644 --- a/cc/surfaces/surface_aggregator_perftest.cc +++ b/cc/surfaces/surface_aggregator_perftest.cc
@@ -22,6 +22,8 @@ namespace cc { namespace { +static constexpr uint32_t kArbitraryClientId = 0; + class EmptySurfaceFactoryClient : public SurfaceFactoryClient { public: void ReturnResources(const ReturnedResourceArray& resources) override {} @@ -49,7 +51,7 @@ aggregator_.reset(new SurfaceAggregator(&manager_, resource_provider_.get(), optimize_damage)); for (int i = 1; i <= num_surfaces; i++) { - factory_.Create(SurfaceId(0, i, 0)); + factory_.Create(SurfaceId(kArbitraryClientId, i, 0)); std::unique_ptr<RenderPass> pass(RenderPass::Create()); std::unique_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); @@ -86,17 +88,18 @@ SurfaceDrawQuad* surface_quad = pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>(); surface_quad->SetNew(sqs, gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1), - SurfaceId(0, i - 1, 0)); + SurfaceId(kArbitraryClientId, i - 1, 0)); } frame_data->render_pass_list.push_back(std::move(pass)); CompositorFrame frame; frame.delegated_frame_data = std::move(frame_data); - factory_.SubmitCompositorFrame(SurfaceId(0, i, 0), std::move(frame), + factory_.SubmitCompositorFrame(SurfaceId(kArbitraryClientId, i, 0), + std::move(frame), SurfaceFactory::DrawCallback()); } - factory_.Create(SurfaceId(0, num_surfaces + 1, 0)); + factory_.Create(SurfaceId(kArbitraryClientId, num_surfaces + 1, 0)); timer_.Reset(); do { std::unique_ptr<RenderPass> pass(RenderPass::Create()); @@ -107,7 +110,7 @@ pass->CreateAndAppendDrawQuad<SurfaceDrawQuad>(); surface_quad->SetNew(sqs, gfx::Rect(0, 0, 100, 100), gfx::Rect(0, 0, 100, 100), - SurfaceId(0, num_surfaces, 0)); + SurfaceId(kArbitraryClientId, num_surfaces, 0)); if (full_damage) pass->damage_rect = gfx::Rect(0, 0, 100, 100); @@ -117,21 +120,21 @@ frame_data->render_pass_list.push_back(std::move(pass)); CompositorFrame frame; frame.delegated_frame_data = std::move(frame_data); - factory_.SubmitCompositorFrame(SurfaceId(0, num_surfaces + 1, 0), - std::move(frame), - SurfaceFactory::DrawCallback()); + factory_.SubmitCompositorFrame( + SurfaceId(kArbitraryClientId, num_surfaces + 1, 0), std::move(frame), + SurfaceFactory::DrawCallback()); - CompositorFrame aggregated = - aggregator_->Aggregate(SurfaceId(0, num_surfaces + 1, 0)); + CompositorFrame aggregated = aggregator_->Aggregate( + SurfaceId(kArbitraryClientId, num_surfaces + 1, 0)); timer_.NextLap(); } while (!timer_.HasTimeLimitExpired()); perf_test::PrintResult("aggregator_speed", "", name, timer_.LapsPerSecond(), "runs/s", true); - factory_.Destroy(SurfaceId(0, num_surfaces + 1, 0)); + factory_.Destroy(SurfaceId(kArbitraryClientId, num_surfaces + 1, 0)); for (int i = 1; i <= num_surfaces; i++) - factory_.Destroy(SurfaceId(0, i, 0)); + factory_.Destroy(SurfaceId(kArbitraryClientId, i, 0)); } protected:
diff --git a/cc/surfaces/surface_aggregator_unittest.cc b/cc/surfaces/surface_aggregator_unittest.cc index 7df08f5..804620a 100644 --- a/cc/surfaces/surface_aggregator_unittest.cc +++ b/cc/surfaces/surface_aggregator_unittest.cc
@@ -37,8 +37,10 @@ namespace cc { namespace { +static constexpr uint32_t kArbitraryClientId = 0; + SurfaceId InvalidSurfaceId() { - static SurfaceId invalid(0, 0xdeadbeef, 0); + static SurfaceId invalid(kArbitraryClientId, 0xdeadbeef, 0); return invalid; } @@ -79,7 +81,7 @@ }; TEST_F(SurfaceAggregatorTest, ValidSurfaceNoFrame) { - SurfaceId one_id(0, 7, 0); + SurfaceId one_id(kArbitraryClientId, 7, 0); factory_.Create(one_id); CompositorFrame frame = aggregator_.Aggregate(one_id); @@ -138,7 +140,8 @@ } } - void SubmitPassListAsFrame(SurfaceId surface_id, RenderPassList* pass_list) { + void SubmitPassListAsFrame(const SurfaceId& surface_id, + RenderPassList* pass_list) { std::unique_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); pass_list->swap(frame_data->render_pass_list); @@ -151,14 +154,14 @@ void SubmitCompositorFrame(test::Pass* passes, size_t pass_count, - SurfaceId surface_id) { + const SurfaceId& surface_id) { RenderPassList pass_list; AddPasses(&pass_list, gfx::Rect(SurfaceSize()), passes, pass_count); SubmitPassListAsFrame(surface_id, &pass_list); } void QueuePassAsFrame(std::unique_ptr<RenderPass> pass, - SurfaceId surface_id) { + const SurfaceId& surface_id) { std::unique_ptr<DelegatedFrameData> delegated_frame_data( new DelegatedFrameData); delegated_frame_data->render_pass_list.push_back(std::move(pass)); @@ -1917,7 +1920,7 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) { ResourceTrackingSurfaceFactoryClient client; SurfaceFactory factory(&manager_, &client); - SurfaceId surface_id(0, 7u, 0); + SurfaceId surface_id(kArbitraryClientId, 7u, 0); factory.Create(surface_id); ResourceId ids[] = {11, 12, 13}; @@ -1947,7 +1950,7 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TakeInvalidResources) { ResourceTrackingSurfaceFactoryClient client; SurfaceFactory factory(&manager_, &client); - SurfaceId surface_id(0, 7u, 0); + SurfaceId surface_id(kArbitraryClientId, 7u, 0); factory.Create(surface_id); std::unique_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); @@ -1981,10 +1984,10 @@ TEST_F(SurfaceAggregatorWithResourcesTest, TwoSurfaces) { ResourceTrackingSurfaceFactoryClient client; SurfaceFactory factory(&manager_, &client); - SurfaceId surface1_id(0, 7u, 0); + SurfaceId surface1_id(kArbitraryClientId, 7u, 0); factory.Create(surface1_id); - SurfaceId surface2_id(0, 8u, 0); + SurfaceId surface2_id(kArbitraryClientId, 8u, 0); factory.Create(surface2_id); ResourceId ids[] = {11, 12, 13}; @@ -2022,11 +2025,11 @@ TEST_F(SurfaceAggregatorWithResourcesTest, InvalidChildSurface) { ResourceTrackingSurfaceFactoryClient client; SurfaceFactory factory(&manager_, &client); - SurfaceId root_surface_id(0, 7u, 0); + SurfaceId root_surface_id(kArbitraryClientId, 7u, 0); factory.Create(root_surface_id); - SurfaceId middle_surface_id(0, 8u, 0); + SurfaceId middle_surface_id(kArbitraryClientId, 8u, 0); factory.Create(middle_surface_id); - SurfaceId child_surface_id(0, 9u, 0); + SurfaceId child_surface_id(kArbitraryClientId, 9u, 0); factory.Create(child_surface_id); ResourceId ids[] = {14, 15, 16}; @@ -2070,10 +2073,10 @@ TEST_F(SurfaceAggregatorWithResourcesTest, SecureOutputTexture) { ResourceTrackingSurfaceFactoryClient client; SurfaceFactory factory(&manager_, &client); - SurfaceId surface1_id(0, 7u, 0); + SurfaceId surface1_id(kArbitraryClientId, 7u, 0); factory.Create(surface1_id); - SurfaceId surface2_id(0, 8u, 0); + SurfaceId surface2_id(kArbitraryClientId, 8u, 0); factory.Create(surface2_id); ResourceId ids[] = {11, 12, 13};
diff --git a/cc/surfaces/surface_damage_observer.h b/cc/surfaces/surface_damage_observer.h index 62ee012..b266e6e 100644 --- a/cc/surfaces/surface_damage_observer.h +++ b/cc/surfaces/surface_damage_observer.h
@@ -5,15 +5,15 @@ #ifndef CC_SURFACES_SURFACE_DAMAGE_OBSERVER_H_ #define CC_SURFACES_SURFACE_DAMAGE_OBSERVER_H_ -#include "cc/surfaces/surface_id.h" - namespace cc { +class SurfaceId; + class SurfaceDamageObserver { public: // Runs when a Surface is damaged. *changed should be set to true if this // causes a Display to be damaged. - virtual void OnSurfaceDamaged(SurfaceId surface_id, bool* changed) = 0; + virtual void OnSurfaceDamaged(const SurfaceId& surface_id, bool* changed) = 0; }; } // namespace cc
diff --git a/cc/surfaces/surface_display_output_surface.cc b/cc/surfaces/surface_display_output_surface.cc index 6dc569c7..07ed3c03 100644 --- a/cc/surfaces/surface_display_output_surface.cc +++ b/cc/surfaces/surface_display_output_surface.cc
@@ -74,8 +74,6 @@ display_->SetSurfaceId(delegated_surface_id_, frame.metadata.device_scale_factor); - client_->DidSwapBuffers(); - factory_.SubmitCompositorFrame( delegated_surface_id_, std::move(frame), base::Bind(&SurfaceDisplayOutputSurface::SwapBuffersComplete, @@ -86,7 +84,7 @@ DCHECK(thread_checker_.CalledOnValidThread()); surface_manager_->RegisterSurfaceFactoryClient( - surface_id_allocator_->id_namespace(), this); + surface_id_allocator_->client_id(), this); if (!OutputSurface::BindToClient(client)) return false; @@ -115,7 +113,7 @@ // Unregister the SurfaceFactoryClient here instead of the dtor so that only // one client is alive for this namespace at any given time. surface_manager_->UnregisterSurfaceFactoryClient( - surface_id_allocator_->id_namespace()); + surface_id_allocator_->client_id()); if (!delegated_surface_id_.is_null()) factory_.Destroy(delegated_surface_id_);
diff --git a/cc/surfaces/surface_display_output_surface_unittest.cc b/cc/surfaces/surface_display_output_surface_unittest.cc index 27de2b9..598a982 100644 --- a/cc/surfaces/surface_display_output_surface_unittest.cc +++ b/cc/surfaces/surface_display_output_surface_unittest.cc
@@ -25,16 +25,18 @@ namespace cc { namespace { +static constexpr int kArbitraryClientId = 0; + class SurfaceDisplayOutputSurfaceTest : public testing::Test { public: SurfaceDisplayOutputSurfaceTest() : now_src_(new base::SimpleTestTickClock()), task_runner_(new OrderedSimpleTaskRunner(now_src_.get(), true)), - allocator_(0), + allocator_(kArbitraryClientId), display_size_(1920, 1080), display_rect_(display_size_), context_provider_(TestContextProvider::Create()) { - surface_manager_.RegisterSurfaceIdNamespace(allocator_.id_namespace()); + surface_manager_.RegisterSurfaceClientId(allocator_.client_id()); std::unique_ptr<FakeOutputSurface> display_output_surface = FakeOutputSurface::Create3d(); @@ -50,7 +52,7 @@ display_.reset(new Display( &surface_manager_, &bitmap_manager_, &gpu_memory_buffer_manager_, - RendererSettings(), allocator_.id_namespace(), + RendererSettings(), allocator_.client_id(), std::move(begin_frame_source), std::move(display_output_surface), std::move(scheduler), base::MakeUnique<TextureMailboxDeleter>(task_runner_.get())));
diff --git a/cc/surfaces/surface_factory.cc b/cc/surfaces/surface_factory.cc index 03517c4..345171a 100644 --- a/cc/surfaces/surface_factory.cc +++ b/cc/surfaces/surface_factory.cc
@@ -39,14 +39,14 @@ surface_map_.clear(); } -void SurfaceFactory::Create(SurfaceId surface_id) { +void SurfaceFactory::Create(const SurfaceId& surface_id) { std::unique_ptr<Surface> surface(new Surface(surface_id, this)); manager_->RegisterSurface(surface.get()); DCHECK(!surface_map_.count(surface_id)); surface_map_[surface_id] = std::move(surface); } -void SurfaceFactory::Destroy(SurfaceId surface_id) { +void SurfaceFactory::Destroy(const SurfaceId& surface_id) { OwningSurfaceMap::iterator it = surface_map_.find(surface_id); DCHECK(it != surface_map_.end()); DCHECK(it->second->factory().get() == this); @@ -56,8 +56,8 @@ manager_->Destroy(std::move(surface)); } -void SurfaceFactory::SetPreviousFrameSurface(SurfaceId new_id, - SurfaceId old_id) { +void SurfaceFactory::SetPreviousFrameSurface(const SurfaceId& new_id, + const SurfaceId& old_id) { OwningSurfaceMap::iterator it = surface_map_.find(new_id); DCHECK(it != surface_map_.end()); Surface* old_surface = manager_->GetSurfaceForId(old_id); @@ -66,7 +66,7 @@ } } -void SurfaceFactory::SubmitCompositorFrame(SurfaceId surface_id, +void SurfaceFactory::SubmitCompositorFrame(const SurfaceId& surface_id, CompositorFrame frame, const DrawCallback& callback) { TRACE_EVENT0("cc", "SurfaceFactory::SubmitCompositorFrame"); @@ -81,7 +81,7 @@ } void SurfaceFactory::RequestCopyOfSurface( - SurfaceId surface_id, + const SurfaceId& surface_id, std::unique_ptr<CopyOutputRequest> copy_request) { OwningSurfaceMap::iterator it = surface_map_.find(surface_id); if (it == surface_map_.end()) { @@ -93,7 +93,7 @@ manager_->SurfaceModified(surface_id); } -void SurfaceFactory::WillDrawSurface(SurfaceId id, +void SurfaceFactory::WillDrawSurface(const SurfaceId& id, const gfx::Rect& damage_rect) { client_->WillDrawSurface(id, damage_rect); }
diff --git a/cc/surfaces/surface_factory.h b/cc/surfaces/surface_factory.h index 1acf09f..52f44bbb 100644 --- a/cc/surfaces/surface_factory.h +++ b/cc/surfaces/surface_factory.h
@@ -45,25 +45,26 @@ SurfaceFactory(SurfaceManager* manager, SurfaceFactoryClient* client); ~SurfaceFactory(); - void Create(SurfaceId surface_id); - void Destroy(SurfaceId surface_id); + void Create(const SurfaceId& surface_id); + void Destroy(const SurfaceId& surface_id); void DestroyAll(); // Set that the current frame on new_id is to be treated as the successor to // the current frame on old_id for the purposes of calculating damage. - void SetPreviousFrameSurface(SurfaceId new_id, SurfaceId old_id); + void SetPreviousFrameSurface(const SurfaceId& new_id, + const SurfaceId& old_id); // A frame can only be submitted to a surface created by this factory, // although the frame may reference surfaces created by other factories. // The callback is called the first time this frame is used to draw, or if // the frame is discarded. - void SubmitCompositorFrame(SurfaceId surface_id, + void SubmitCompositorFrame(const SurfaceId& surface_id, CompositorFrame frame, const DrawCallback& callback); - void RequestCopyOfSurface(SurfaceId surface_id, + void RequestCopyOfSurface(const SurfaceId& surface_id, std::unique_ptr<CopyOutputRequest> copy_request); - void WillDrawSurface(SurfaceId id, const gfx::Rect& damage_rect); + void WillDrawSurface(const SurfaceId& id, const gfx::Rect& damage_rect); SurfaceFactoryClient* client() { return client_; }
diff --git a/cc/surfaces/surface_factory_unittest.cc b/cc/surfaces/surface_factory_unittest.cc index b4620465..b5cfa1c 100644 --- a/cc/surfaces/surface_factory_unittest.cc +++ b/cc/surfaces/surface_factory_unittest.cc
@@ -26,6 +26,8 @@ namespace cc { namespace { +static constexpr uint32_t kArbitraryClientId = 0; + class TestSurfaceFactoryClient : public SurfaceFactoryClient { public: TestSurfaceFactoryClient() : begin_frame_source_(nullptr) {} @@ -66,7 +68,7 @@ public: SurfaceFactoryTest() : factory_(new SurfaceFactory(&manager_, &client_)), - surface_id_(0, 3, 0), + surface_id_(kArbitraryClientId, 3, 0), frame_sync_token_(GenTestSyncToken(4)), consumer_sync_token_(GenTestSyncToken(5)) { manager_.AddObserver(this); @@ -74,7 +76,7 @@ } // SurfaceDamageObserver implementation. - void OnSurfaceDamaged(SurfaceId id, bool* changed) override { + void OnSurfaceDamaged(const SurfaceId& id, bool* changed) override { *changed = true; } @@ -419,7 +421,7 @@ } TEST_F(SurfaceFactoryTest, BlankNoIndexIncrement) { - SurfaceId surface_id(0, 6, 0); + SurfaceId surface_id(kArbitraryClientId, 6, 0); factory_->Create(surface_id); Surface* surface = manager_.GetSurfaceForId(surface_id); ASSERT_NE(nullptr, surface); @@ -437,7 +439,7 @@ uint32_t* execute_count, SurfaceDrawStatus* result, SurfaceDrawStatus drawn) { - SurfaceId new_id(0, 7, 0); + SurfaceId new_id(kArbitraryClientId, 7, 0); factory->Create(new_id); factory->Destroy(new_id); *execute_count += 1; @@ -445,7 +447,7 @@ } TEST_F(SurfaceFactoryTest, AddDuringDestroy) { - SurfaceId surface_id(0, 6, 0); + SurfaceId surface_id(kArbitraryClientId, 6, 0); factory_->Create(surface_id); CompositorFrame frame; frame.delegated_frame_data.reset(new DelegatedFrameData); @@ -471,7 +473,7 @@ // Tests doing a DestroyAll before shutting down the factory; TEST_F(SurfaceFactoryTest, DestroyAll) { - SurfaceId id(0, 7, 0); + SurfaceId id(kArbitraryClientId, 7, 0); factory_->Create(id); std::unique_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData); @@ -494,10 +496,10 @@ } TEST_F(SurfaceFactoryTest, DestroySequence) { - SurfaceId id2(0, 5, 0); + SurfaceId id2(kArbitraryClientId, 5, 0); factory_->Create(id2); - manager_.RegisterSurfaceIdNamespace(0); + manager_.RegisterSurfaceClientId(0); // Check that waiting before the sequence is satisfied works. manager_.GetSurfaceForId(id2) @@ -525,12 +527,12 @@ // Tests that Surface ID namespace invalidation correctly allows // Sequences to be ignored. -TEST_F(SurfaceFactoryTest, InvalidIdNamespace) { +TEST_F(SurfaceFactoryTest, InvalidClientId) { uint32_t id_namespace = 9u; SurfaceId id(id_namespace, 5, 0); factory_->Create(id); - manager_.RegisterSurfaceIdNamespace(id_namespace); + manager_.RegisterSurfaceClientId(id_namespace); manager_.GetSurfaceForId(id) ->AddDestructionDependency(SurfaceSequence(id_namespace, 4)); factory_->Destroy(id); @@ -538,7 +540,7 @@ // Verify the dependency has prevented the surface from getting destroyed. EXPECT_TRUE(manager_.GetSurfaceForId(id)); - manager_.InvalidateSurfaceIdNamespace(id_namespace); + manager_.InvalidateSurfaceClientId(id_namespace); // Verify that the invalidated namespace caused the unsatisfied sequence // to be ignored. @@ -546,10 +548,10 @@ } TEST_F(SurfaceFactoryTest, DestroyCycle) { - SurfaceId id2(0, 5, 0); + SurfaceId id2(kArbitraryClientId, 5, 0); factory_->Create(id2); - manager_.RegisterSurfaceIdNamespace(0); + manager_.RegisterSurfaceClientId(0); manager_.GetSurfaceForId(id2) ->AddDestructionDependency(SurfaceSequence(0, 4));
diff --git a/cc/surfaces/surface_hittest.cc b/cc/surfaces/surface_hittest.cc index b56f976b..20fb717c 100644 --- a/cc/surfaces/surface_hittest.cc +++ b/cc/surfaces/surface_hittest.cc
@@ -23,9 +23,10 @@ SurfaceHittest::~SurfaceHittest() {} -SurfaceId SurfaceHittest::GetTargetSurfaceAtPoint(SurfaceId root_surface_id, - const gfx::Point& point, - gfx::Transform* transform) { +SurfaceId SurfaceHittest::GetTargetSurfaceAtPoint( + const SurfaceId& root_surface_id, + const gfx::Point& point, + gfx::Transform* transform) { SurfaceId out_surface_id = root_surface_id; // Reset the output transform to identity. @@ -40,9 +41,10 @@ return out_surface_id; } -bool SurfaceHittest::GetTransformToTargetSurface(SurfaceId root_surface_id, - SurfaceId target_surface_id, - gfx::Transform* transform) { +bool SurfaceHittest::GetTransformToTargetSurface( + const SurfaceId& root_surface_id, + const SurfaceId& target_surface_id, + gfx::Transform* transform) { // Reset the output transform to identity. if (transform) *transform = gfx::Transform(); @@ -54,7 +56,7 @@ } bool SurfaceHittest::GetTargetSurfaceAtPointInternal( - SurfaceId surface_id, + const SurfaceId& surface_id, const RenderPassId& render_pass_id, const gfx::Point& point_in_root_target, std::set<const RenderPass*>* referenced_passes, @@ -148,8 +150,8 @@ } bool SurfaceHittest::GetTransformToTargetSurfaceInternal( - SurfaceId root_surface_id, - SurfaceId target_surface_id, + const SurfaceId& root_surface_id, + const SurfaceId& target_surface_id, const RenderPassId& render_pass_id, std::set<const RenderPass*>* referenced_passes, gfx::Transform* out_transform) { @@ -228,7 +230,7 @@ } const RenderPass* SurfaceHittest::GetRenderPassForSurfaceById( - SurfaceId surface_id, + const SurfaceId& surface_id, const RenderPassId& render_pass_id) { Surface* surface = manager_->GetSurfaceForId(surface_id); if (!surface)
diff --git a/cc/surfaces/surface_hittest.h b/cc/surfaces/surface_hittest.h index ce45a90f..14f08455 100644 --- a/cc/surfaces/surface_hittest.h +++ b/cc/surfaces/surface_hittest.h
@@ -33,20 +33,20 @@ // Returns the target surface that falls underneath the provided |point|. // Also returns the |transform| to convert the |point| to the target surface's // space. - SurfaceId GetTargetSurfaceAtPoint(SurfaceId root_surface_id, + SurfaceId GetTargetSurfaceAtPoint(const SurfaceId& root_surface_id, const gfx::Point& point, gfx::Transform* transform); // Returns whether the target surface falls inside the provide root surface. // Returns the |transform| to convert points from the root surface coordinate // space to the target surface coordinate space. - bool GetTransformToTargetSurface(SurfaceId root_surface_id, - SurfaceId target_surface_id, + bool GetTransformToTargetSurface(const SurfaceId& root_surface_id, + const SurfaceId& target_surface_id, gfx::Transform* transform); private: bool GetTargetSurfaceAtPointInternal( - SurfaceId surface_id, + const SurfaceId& surface_id, const RenderPassId& render_pass_id, const gfx::Point& point_in_root_target, std::set<const RenderPass*>* referenced_passes, @@ -54,14 +54,14 @@ gfx::Transform* out_transform); bool GetTransformToTargetSurfaceInternal( - SurfaceId root_surface_id, - SurfaceId target_surface_id, + const SurfaceId& root_surface_id, + const SurfaceId& target_surface_id, const RenderPassId& render_pass_id, std::set<const RenderPass*>* referenced_passes, gfx::Transform* out_transform); const RenderPass* GetRenderPassForSurfaceById( - SurfaceId surface_id, + const SurfaceId& surface_id, const RenderPassId& render_pass_id); bool PointInQuad(const DrawQuad* quad,
diff --git a/cc/surfaces/surface_id.h b/cc/surfaces/surface_id.h index c48e8129..48a434a 100644 --- a/cc/surfaces/surface_id.h +++ b/cc/surfaces/surface_id.h
@@ -18,58 +18,57 @@ class SurfaceId { public: - SurfaceId() : id_namespace_(0), local_id_(0), nonce_(0) {} + SurfaceId() : client_id_(0), local_id_(0), nonce_(0) {} SurfaceId(const SurfaceId& other) - : id_namespace_(other.id_namespace_), + : client_id_(other.client_id_), local_id_(other.local_id_), nonce_(other.nonce_) {} - // A SurfaceId consists of three components: namespace, local Id, and nonce. - // An |id_namespace| is a display compositor service allocated ID that + // A SurfaceId consists of three components: client Id, local Id, and nonce. + // A |client_id| is a display compositor service allocated ID that // uniquely identifies a client. // A |local_id| is a sequentially allocated ID generated by the display - // compositor client. + // compositor client that uniquely identifies a surface. // A |nonce| is a cryptographically secure random int that makes a SurfaceId // unguessable by other clients. - SurfaceId(uint32_t id_namespace, uint32_t local_id, uint64_t nonce) - : id_namespace_(id_namespace), local_id_(local_id), nonce_(nonce) {} + SurfaceId(uint32_t client_id, uint32_t local_id, uint64_t nonce) + : client_id_(client_id), local_id_(local_id), nonce_(nonce) {} bool is_null() const { - return id_namespace_ == 0 && nonce_ == 0 && local_id_ == 0; + return client_id_ == 0 && nonce_ == 0 && local_id_ == 0; } size_t hash() const { - size_t interim = base::HashInts(id_namespace_, local_id_); + size_t interim = base::HashInts(client_id_, local_id_); return base::HashInts(static_cast<uint64_t>(interim), nonce_); } - uint32_t id_namespace() const { return id_namespace_; } + uint32_t client_id() const { return client_id_; } uint32_t local_id() const { return local_id_; } uint64_t nonce() const { return nonce_; } std::string ToString() const { - return base::StringPrintf("%d:%d:%" PRIu64, id_namespace_, local_id_, - nonce_); + return base::StringPrintf("%d:%d:%" PRIu64, client_id_, local_id_, nonce_); } bool operator==(const SurfaceId& other) const { - return id_namespace_ == other.id_namespace_ && - local_id_ == other.local_id_ && nonce_ == other.nonce_; + return client_id_ == other.client_id_ && local_id_ == other.local_id_ && + nonce_ == other.nonce_; } bool operator!=(const SurfaceId& other) const { return !(*this == other); } bool operator<(const SurfaceId& other) const { - return std::tie(id_namespace_, local_id_, nonce_) < - std::tie(other.id_namespace_, other.local_id_, other.nonce_); + return std::tie(client_id_, local_id_, nonce_) < + std::tie(other.client_id_, other.local_id_, other.nonce_); } private: // See SurfaceIdAllocator::GenerateId. - uint32_t id_namespace_; + uint32_t client_id_; uint32_t local_id_; uint64_t nonce_; };
diff --git a/cc/surfaces/surface_id_allocator.cc b/cc/surfaces/surface_id_allocator.cc index 8b169a5..9151400f 100644 --- a/cc/surfaces/surface_id_allocator.cc +++ b/cc/surfaces/surface_id_allocator.cc
@@ -11,24 +11,23 @@ namespace cc { -SurfaceIdAllocator::SurfaceIdAllocator(uint32_t id_namespace) - : id_namespace_(id_namespace), next_id_(1u), manager_(nullptr) { -} +SurfaceIdAllocator::SurfaceIdAllocator(uint32_t client_id) + : client_id_(client_id), next_id_(1u), manager_(nullptr) {} -void SurfaceIdAllocator::RegisterSurfaceIdNamespace(SurfaceManager* manager) { +void SurfaceIdAllocator::RegisterSurfaceClientId(SurfaceManager* manager) { DCHECK(!manager_); manager_ = manager; - manager_->RegisterSurfaceIdNamespace(id_namespace_); + manager_->RegisterSurfaceClientId(client_id_); } SurfaceIdAllocator::~SurfaceIdAllocator() { if (manager_) - manager_->InvalidateSurfaceIdNamespace(id_namespace_); + manager_->InvalidateSurfaceClientId(client_id_); } SurfaceId SurfaceIdAllocator::GenerateId() { uint64_t nonce = base::RandUint64(); - SurfaceId id(id_namespace_, next_id_, nonce); + SurfaceId id(client_id_, next_id_, nonce); next_id_++; return id; }
diff --git a/cc/surfaces/surface_id_allocator.h b/cc/surfaces/surface_id_allocator.h index 3e1bbc7..c77f359 100644 --- a/cc/surfaces/surface_id_allocator.h +++ b/cc/surfaces/surface_id_allocator.h
@@ -20,7 +20,7 @@ // class in a mutex. class CC_SURFACES_EXPORT SurfaceIdAllocator { public: - explicit SurfaceIdAllocator(uint32_t id_namespace); + explicit SurfaceIdAllocator(uint32_t client_id); ~SurfaceIdAllocator(); SurfaceId GenerateId(); @@ -31,16 +31,16 @@ // automatically invalidated and any remaining sequences with that // namespace will be ignored. This method does not need to be called in // contexts where there is no SurfaceManager (e.g. a renderer process). - void RegisterSurfaceIdNamespace(SurfaceManager* manager); + void RegisterSurfaceClientId(SurfaceManager* manager); - uint32_t id_namespace() const { return id_namespace_; } + uint32_t client_id() const { return client_id_; } // SurfaceIdAllocator's owner can call this when it find out that // SurfaceManager is no longer alive during destruction. void DidDestroySurfaceManager() { manager_ = nullptr; } private: - const uint32_t id_namespace_; + const uint32_t client_id_; uint32_t next_id_; SurfaceManager* manager_;
diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc index 26c8440..e34bb63 100644 --- a/cc/surfaces/surface_manager.cc +++ b/cc/surfaces/surface_manager.cc
@@ -51,7 +51,7 @@ surface_map_[surface->surface_id()] = surface; } -void SurfaceManager::DeregisterSurface(SurfaceId surface_id) { +void SurfaceManager::DeregisterSurface(const SurfaceId& surface_id) { DCHECK(thread_checker_.CalledOnValidThread()); SurfaceMap::iterator it = surface_map_.find(surface_id); DCHECK(it != surface_map_.end()); @@ -65,25 +65,25 @@ GarbageCollectSurfaces(); } -void SurfaceManager::DidSatisfySequences(uint32_t id_namespace, +void SurfaceManager::DidSatisfySequences(uint32_t client_id, std::vector<uint32_t>* sequence) { DCHECK(thread_checker_.CalledOnValidThread()); for (std::vector<uint32_t>::iterator it = sequence->begin(); it != sequence->end(); ++it) { - satisfied_sequences_.insert(SurfaceSequence(id_namespace, *it)); + satisfied_sequences_.insert(SurfaceSequence(client_id, *it)); } sequence->clear(); GarbageCollectSurfaces(); } -void SurfaceManager::RegisterSurfaceIdNamespace(uint32_t id_namespace) { - bool inserted = valid_surface_id_namespaces_.insert(id_namespace).second; +void SurfaceManager::RegisterSurfaceClientId(uint32_t client_id) { + bool inserted = valid_surface_client_ids_.insert(client_id).second; DCHECK(inserted); } -void SurfaceManager::InvalidateSurfaceIdNamespace(uint32_t id_namespace) { - valid_surface_id_namespaces_.erase(id_namespace); +void SurfaceManager::InvalidateSurfaceClientId(uint32_t client_id) { + valid_surface_client_ids_.erase(client_id); GarbageCollectSurfaces(); } @@ -98,7 +98,7 @@ // their destruction dependencies satisfied. for (auto& map_entry : surface_map_) { map_entry.second->SatisfyDestructionDependencies( - &satisfied_sequences_, &valid_surface_id_namespaces_); + &satisfied_sequences_, &valid_surface_client_ids_); if (!map_entry.second->destroyed() || map_entry.second->GetDestructionDependencyCount()) { live_surfaces_set.insert(map_entry.first); @@ -112,7 +112,7 @@ Surface* surf = surface_map_[live_surfaces[i]]; DCHECK(surf); - for (SurfaceId id : surf->referenced_surfaces()) { + for (const SurfaceId& id : surf->referenced_surfaces()) { if (live_surfaces_set.count(id)) continue; @@ -143,16 +143,16 @@ } void SurfaceManager::RegisterSurfaceFactoryClient( - uint32_t id_namespace, + uint32_t client_id, SurfaceFactoryClient* client) { DCHECK(client); - DCHECK(!namespace_client_map_[id_namespace].client); - DCHECK_EQ(valid_surface_id_namespaces_.count(id_namespace), 1u); + DCHECK(!namespace_client_map_[client_id].client); + DCHECK_EQ(valid_surface_client_ids_.count(client_id), 1u); - auto iter = namespace_client_map_.find(id_namespace); + auto iter = namespace_client_map_.find(client_id); if (iter == namespace_client_map_.end()) { auto insert_result = namespace_client_map_.insert( - std::make_pair(id_namespace, ClientSourceMapping())); + std::make_pair(client_id, ClientSourceMapping())); DCHECK(insert_result.second); iter = insert_result.first; } @@ -163,11 +163,11 @@ client->SetBeginFrameSource(iter->second.source); } -void SurfaceManager::UnregisterSurfaceFactoryClient(uint32_t id_namespace) { - DCHECK_EQ(valid_surface_id_namespaces_.count(id_namespace), 1u); - DCHECK_EQ(namespace_client_map_.count(id_namespace), 1u); +void SurfaceManager::UnregisterSurfaceFactoryClient(uint32_t client_id) { + DCHECK_EQ(valid_surface_client_ids_.count(client_id), 1u); + DCHECK_EQ(namespace_client_map_.count(client_id), 1u); - auto iter = namespace_client_map_.find(id_namespace); + auto iter = namespace_client_map_.find(client_id); if (iter->second.source) iter->second.client->SetBeginFrameSource(nullptr); iter->second.client = nullptr; @@ -180,28 +180,28 @@ } void SurfaceManager::RegisterBeginFrameSource(BeginFrameSource* source, - uint32_t id_namespace) { + uint32_t client_id) { DCHECK(source); DCHECK_EQ(registered_sources_.count(source), 0u); - DCHECK_EQ(valid_surface_id_namespaces_.count(id_namespace), 1u); + DCHECK_EQ(valid_surface_client_ids_.count(client_id), 1u); - registered_sources_[source] = id_namespace; - RecursivelyAttachBeginFrameSource(id_namespace, source); + registered_sources_[source] = client_id; + RecursivelyAttachBeginFrameSource(client_id, source); } void SurfaceManager::UnregisterBeginFrameSource(BeginFrameSource* source) { DCHECK(source); DCHECK_EQ(registered_sources_.count(source), 1u); - uint32_t id_namespace = registered_sources_[source]; + uint32_t client_id = registered_sources_[source]; registered_sources_.erase(source); - if (namespace_client_map_.count(id_namespace) == 0u) + if (namespace_client_map_.count(client_id) == 0u) return; // TODO(enne): these walks could be done in one step. // Remove this begin frame source from its subtree. - RecursivelyDetachBeginFrameSource(id_namespace, source); + RecursivelyDetachBeginFrameSource(client_id, source); // Then flush every remaining registered source to fix any sources that // became null because of the previous step but that have an alternative. for (auto source_iter : registered_sources_) @@ -209,9 +209,9 @@ } void SurfaceManager::RecursivelyAttachBeginFrameSource( - uint32_t id_namespace, + uint32_t client_id, BeginFrameSource* source) { - ClientSourceMapping& mapping = namespace_client_map_[id_namespace]; + ClientSourceMapping& mapping = namespace_client_map_[client_id]; if (!mapping.source) { mapping.source = source; if (mapping.client) @@ -222,9 +222,9 @@ } void SurfaceManager::RecursivelyDetachBeginFrameSource( - uint32_t id_namespace, + uint32_t client_id, BeginFrameSource* source) { - auto iter = namespace_client_map_.find(id_namespace); + auto iter = namespace_client_map_.find(client_id); if (iter == namespace_client_map_.end()) return; if (iter->second.source == source) { @@ -263,8 +263,8 @@ void SurfaceManager::RegisterSurfaceNamespaceHierarchy( uint32_t parent_namespace, uint32_t child_namespace) { - DCHECK_EQ(valid_surface_id_namespaces_.count(parent_namespace), 1u); - DCHECK_EQ(valid_surface_id_namespaces_.count(child_namespace), 1u); + DCHECK_EQ(valid_surface_client_ids_.count(parent_namespace), 1u); + DCHECK_EQ(valid_surface_client_ids_.count(child_namespace), 1u); // If it's possible to reach the parent through the child's descendant chain, // then this will create an infinite loop. Might as well just crash here. @@ -331,7 +331,7 @@ RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first); } -Surface* SurfaceManager::GetSurfaceForId(SurfaceId surface_id) { +Surface* SurfaceManager::GetSurfaceForId(const SurfaceId& surface_id) { DCHECK(thread_checker_.CalledOnValidThread()); SurfaceMap::iterator it = surface_map_.find(surface_id); if (it == surface_map_.end()) @@ -339,7 +339,7 @@ return it->second; } -bool SurfaceManager::SurfaceModified(SurfaceId surface_id) { +bool SurfaceManager::SurfaceModified(const SurfaceId& surface_id) { CHECK(thread_checker_.CalledOnValidThread()); bool changed = false; FOR_EACH_OBSERVER(SurfaceDamageObserver, observer_list_,
diff --git a/cc/surfaces/surface_manager.h b/cc/surfaces/surface_manager.h index 24d82aa..6261fb36 100644 --- a/cc/surfaces/surface_manager.h +++ b/cc/surfaces/surface_manager.h
@@ -33,12 +33,12 @@ ~SurfaceManager(); void RegisterSurface(Surface* surface); - void DeregisterSurface(SurfaceId surface_id); + void DeregisterSurface(const SurfaceId& surface_id); // Destroy the Surface once a set of sequence numbers has been satisfied. void Destroy(std::unique_ptr<Surface> surface); - Surface* GetSurfaceForId(SurfaceId surface_id); + Surface* GetSurfaceForId(const SurfaceId& surface_id); void AddObserver(SurfaceDamageObserver* obs) { observer_list_.AddObserver(obs); @@ -48,18 +48,17 @@ observer_list_.RemoveObserver(obs); } - bool SurfaceModified(SurfaceId surface_id); + bool SurfaceModified(const SurfaceId& surface_id); // A frame for a surface satisfies a set of sequence numbers in a particular // id namespace. - void DidSatisfySequences(uint32_t id_namespace, - std::vector<uint32_t>* sequence); + void DidSatisfySequences(uint32_t client_id, std::vector<uint32_t>* sequence); - void RegisterSurfaceIdNamespace(uint32_t id_namespace); + void RegisterSurfaceClientId(uint32_t client_id); // Invalidate a namespace that might still have associated sequences, // possibly because a renderer process has crashed. - void InvalidateSurfaceIdNamespace(uint32_t id_namespace); + void InvalidateSurfaceClientId(uint32_t client_id); // SurfaceFactoryClient, hierarchy, and BeginFrameSource can be registered // and unregistered in any order with respect to each other. @@ -74,15 +73,14 @@ // Caller guarantees the client is alive between register/unregister. // Reregistering the same namespace when a previous client is active is not // valid. - void RegisterSurfaceFactoryClient(uint32_t id_namespace, + void RegisterSurfaceFactoryClient(uint32_t client_id, SurfaceFactoryClient* client); - void UnregisterSurfaceFactoryClient(uint32_t id_namespace); + void UnregisterSurfaceFactoryClient(uint32_t client_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, - uint32_t id_namespace); + void RegisterBeginFrameSource(BeginFrameSource* source, uint32_t client_id); void UnregisterBeginFrameSource(BeginFrameSource* source); // Register a relationship between two namespaces. This relationship means @@ -95,9 +93,9 @@ uint32_t child_namespace); private: - void RecursivelyAttachBeginFrameSource(uint32_t id_namespace, + void RecursivelyAttachBeginFrameSource(uint32_t client_id, BeginFrameSource* source); - void RecursivelyDetachBeginFrameSource(uint32_t id_namespace, + void RecursivelyDetachBeginFrameSource(uint32_t client_id, BeginFrameSource* source); // Returns true if |child namespace| is or has |search_namespace| as a child. bool ChildContains(uint32_t child_namespace, uint32_t search_namespace) const; @@ -121,7 +119,7 @@ // Set of valid surface ID namespaces. When a namespace is removed from // this set, any remaining sequences with that namespace are considered // satisfied. - std::unordered_set<uint32_t> valid_surface_id_namespaces_; + std::unordered_set<uint32_t> valid_surface_client_ids_; // Begin frame source routing. Both BeginFrameSource and SurfaceFactoryClient // pointers guaranteed alive by callers until unregistered.
diff --git a/cc/surfaces/surface_manager_unittest.cc b/cc/surfaces/surface_manager_unittest.cc index 05edb02..9c29094 100644 --- a/cc/surfaces/surface_manager_unittest.cc +++ b/cc/surfaces/surface_manager_unittest.cc
@@ -73,12 +73,12 @@ SurfaceManagerTest() { for (size_t i = 0; i < MAX_NAMESPACE; ++i) - manager_.RegisterSurfaceIdNamespace(i); + manager_.RegisterSurfaceClientId(i); } ~SurfaceManagerTest() override { for (size_t i = 0; i < MAX_NAMESPACE; ++i) - manager_.InvalidateSurfaceIdNamespace(i); + manager_.InvalidateSurfaceClientId(i); } protected:
diff --git a/cc/surfaces/surface_sequence.h b/cc/surfaces/surface_sequence.h index 9027ea13..fa0a8c8 100644 --- a/cc/surfaces/surface_sequence.h +++ b/cc/surfaces/surface_sequence.h
@@ -18,17 +18,17 @@ // dependencies between frames. A sequence number may be satisfied once, and // may be depended on once. struct SurfaceSequence { - SurfaceSequence() : id_namespace(0u), sequence(0u) {} - SurfaceSequence(uint32_t id_namespace, uint32_t sequence) - : id_namespace(id_namespace), sequence(sequence) {} - bool is_null() const { return id_namespace == 0u && sequence == 0u; } + SurfaceSequence() : client_id(0u), sequence(0u) {} + SurfaceSequence(uint32_t client_id, uint32_t sequence) + : client_id(client_id), sequence(sequence) {} + bool is_null() const { return client_id == 0u && sequence == 0u; } - uint32_t id_namespace; + uint32_t client_id; uint32_t sequence; }; inline bool operator==(const SurfaceSequence& a, const SurfaceSequence& b) { - return a.id_namespace == b.id_namespace && a.sequence == b.sequence; + return a.client_id == b.client_id && a.sequence == b.sequence; } inline bool operator!=(const SurfaceSequence& a, const SurfaceSequence& b) { @@ -36,13 +36,12 @@ } inline bool operator<(const SurfaceSequence& a, const SurfaceSequence& b) { - return std::tie(a.id_namespace, a.sequence) < - std::tie(b.id_namespace, b.sequence); + return std::tie(a.client_id, a.sequence) < std::tie(b.client_id, b.sequence); } struct SurfaceSequenceHash { size_t operator()(SurfaceSequence key) const { - return base::HashInts(key.id_namespace, key.sequence); + return base::HashInts(key.client_id, key.sequence); } };
diff --git a/cc/surfaces/surface_unittest.cc b/cc/surfaces/surface_unittest.cc index d4ac06e..0fe4f7d 100644 --- a/cc/surfaces/surface_unittest.cc +++ b/cc/surfaces/surface_unittest.cc
@@ -14,6 +14,8 @@ namespace cc { namespace { +static constexpr uint32_t kArbitraryClientId = 0; + class FakeSurfaceFactoryClient : public SurfaceFactoryClient { public: FakeSurfaceFactoryClient() : begin_frame_source_(nullptr) {} @@ -35,7 +37,7 @@ FakeSurfaceFactoryClient surface_factory_client; SurfaceFactory factory(&manager, &surface_factory_client); - SurfaceId surface_id(0, 6, 0); + SurfaceId surface_id(kArbitraryClientId, 6, 0); { factory.Create(surface_id); EXPECT_TRUE(manager.GetSurfaceForId(surface_id)); @@ -46,14 +48,14 @@ } TEST(SurfaceTest, SurfaceIds) { - uint32_t namespaces[] = {0u, 37u, ~0u}; + uint32_t client_ids[] = {0u, 37u, ~0u}; for (size_t i = 0; i < 3; ++i) { - uint32_t id_namespace = namespaces[i]; - SurfaceIdAllocator allocator(id_namespace); + uint32_t client_id = client_ids[i]; + SurfaceIdAllocator allocator(client_id); SurfaceId id1 = allocator.GenerateId(); - EXPECT_EQ(id1.id_namespace(), id_namespace); + EXPECT_EQ(id1.client_id(), client_id); SurfaceId id2 = allocator.GenerateId(); - EXPECT_EQ(id2.id_namespace(), id_namespace); + EXPECT_EQ(id2.client_id(), client_id); EXPECT_NE(id1.local_id(), id2.local_id()); EXPECT_NE(id1.nonce(), id2.nonce()); }
diff --git a/cc/surfaces/surfaces_pixeltest.cc b/cc/surfaces/surfaces_pixeltest.cc index ae2c9ba4..a52964c 100644 --- a/cc/surfaces/surfaces_pixeltest.cc +++ b/cc/surfaces/surfaces_pixeltest.cc
@@ -21,6 +21,8 @@ namespace cc { namespace { +static constexpr uint32_t kArbitraryClientId = 1u; + class EmptySurfaceFactoryClient : public SurfaceFactoryClient { public: void ReturnResources(const ReturnedResourceArray& resources) override {} @@ -29,7 +31,8 @@ class SurfacesPixelTest : public RendererPixelTest<GLRenderer> { public: - SurfacesPixelTest() : allocator_(1u), factory_(&manager_, &client_) {} + SurfacesPixelTest() + : allocator_(kArbitraryClientId), factory_(&manager_, &client_) {} protected: SurfaceManager manager_;
diff --git a/cc/test/fake_layer_tree_host_impl_client.h b/cc/test/fake_layer_tree_host_impl_client.h index 8fc8ab4..138ce01a 100644 --- a/cc/test/fake_layer_tree_host_impl_client.h +++ b/cc/test/fake_layer_tree_host_impl_client.h
@@ -19,7 +19,6 @@ base::TimeDelta interval) override {} void SetBeginFrameSource(BeginFrameSource* source) override {} void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override {} - void DidSwapBuffersOnImplThread() override {} void DidSwapBuffersCompleteOnImplThread() override {} void OnCanDrawStateChanged(bool can_draw) override {} void NotifyReadyToActivate() override {}
diff --git a/cc/test/fake_output_surface.cc b/cc/test/fake_output_surface.cc index f8a9b7cb..fb16c08 100644 --- a/cc/test/fake_output_surface.cc +++ b/cc/test/fake_output_surface.cc
@@ -42,9 +42,11 @@ capabilities_.delegated_rendering = delegated_rendering; } -FakeOutputSurface::~FakeOutputSurface() {} +FakeOutputSurface::~FakeOutputSurface() = default; void FakeOutputSurface::SwapBuffers(CompositorFrame frame) { + ReturnResourcesHeldByParent(); + std::unique_ptr<CompositorFrame> frame_copy(new CompositorFrame); *frame_copy = std::move(frame); if (frame_copy->delegated_frame_data || !context_provider()) { @@ -64,7 +66,6 @@ ++num_sent_frames_; } PostSwapBuffersComplete(); - client_->DidSwapBuffers(); } void FakeOutputSurface::BindFramebuffer() { @@ -96,25 +97,17 @@ } } +void FakeOutputSurface::DetachFromClient() { + ReturnResourcesHeldByParent(); + OutputSurface::DetachFromClient(); +} + void FakeOutputSurface::SetTreeActivationCallback( const base::Closure& callback) { DCHECK(client_); client_->SetTreeActivationCallback(callback); } -void FakeOutputSurface::ReturnResource(unsigned id, CompositorFrameAck* ack) { - TransferableResourceArray::iterator it; - for (it = resources_held_by_parent_.begin(); - it != resources_held_by_parent_.end(); - ++it) { - if (it->id == id) - break; - } - DCHECK(it != resources_held_by_parent_.end()); - ack->resources.push_back(it->ToReturnedResource()); - resources_held_by_parent_.erase(it); -} - bool FakeOutputSurface::HasExternalStencilTest() const { return has_external_stencil_test_; } @@ -133,4 +126,17 @@ memory_policy_to_set_at_bind_.swap(memory_policy_to_set_at_bind); } +void FakeOutputSurface::ReturnResourcesHeldByParent() { + // Check |delegated_frame_data| because we shouldn't reclaim resources + // for the Display which does not swap delegated frames. + if (last_sent_frame_ && last_sent_frame_->delegated_frame_data) { + // Return the last frame's resources immediately. + CompositorFrameAck ack; + for (const auto& resource : resources_held_by_parent_) + ack.resources.push_back(resource.ToReturnedResource()); + resources_held_by_parent_.clear(); + client_->ReclaimResources(&ack); + } +} + } // namespace cc
diff --git a/cc/test/fake_output_surface.h b/cc/test/fake_output_surface.h index 8fcc04a..ca6676de 100644 --- a/cc/test/fake_output_surface.h +++ b/cc/test/fake_output_surface.h
@@ -109,6 +109,7 @@ OutputSurfaceClient* client() { return client_; } bool BindToClient(OutputSurfaceClient* client) override; + void DetachFromClient() override; void set_framebuffer(GLint framebuffer, GLenum format) { framebuffer_ = framebuffer; @@ -123,8 +124,6 @@ return resources_held_by_parent_; } - void ReturnResource(unsigned id, CompositorFrameAck* ack); - bool HasExternalStencilTest() const override; bool SurfaceIsSuspendForRecycle() const override; @@ -149,6 +148,8 @@ return last_swap_rect_; } + void ReturnResourcesHeldByParent(); + protected: FakeOutputSurface(scoped_refptr<ContextProvider> context_provider, scoped_refptr<ContextProvider> worker_context_provider,
diff --git a/cc/test/fake_output_surface_client.cc b/cc/test/fake_output_surface_client.cc index 075db20..f50beaa 100644 --- a/cc/test/fake_output_surface_client.cc +++ b/cc/test/fake_output_surface_client.cc
@@ -7,7 +7,7 @@ namespace cc { -void FakeOutputSurfaceClient::DidSwapBuffers() { +void FakeOutputSurfaceClient::DidSwapBuffersComplete() { swap_count_++; }
diff --git a/cc/test/fake_output_surface_client.h b/cc/test/fake_output_surface_client.h index 8b41ac1..a2ee038 100644 --- a/cc/test/fake_output_surface_client.h +++ b/cc/test/fake_output_surface_client.h
@@ -23,8 +23,7 @@ base::TimeDelta interval) override {} void SetBeginFrameSource(BeginFrameSource* source) override {} void SetNeedsRedrawRect(const gfx::Rect& damage_rect) override {} - void DidSwapBuffers() override; - void DidSwapBuffersComplete() override {} + void DidSwapBuffersComplete() override; void DidReceiveTextureInUseResponses( const gpu::TextureInUseResponses& responses) override {} void ReclaimResources(const CompositorFrameAck* ack) override {}
diff --git a/cc/test/fake_raster_buffer_provider.cc b/cc/test/fake_raster_buffer_provider.cc index 9c24db2..20c91fa 100644 --- a/cc/test/fake_raster_buffer_provider.cc +++ b/cc/test/fake_raster_buffer_provider.cc
@@ -33,7 +33,8 @@ return ResourceFormatRequiresSwizzle(GetResourceFormat(must_support_alpha)); } -bool FakeRasterBufferProviderImpl::IsPartialRasterSupported() const { +bool FakeRasterBufferProviderImpl::CanPartialRasterIntoProvidedResource() + const { return true; }
diff --git a/cc/test/fake_raster_buffer_provider.h b/cc/test/fake_raster_buffer_provider.h index 37738a55..cb0c634 100644 --- a/cc/test/fake_raster_buffer_provider.h +++ b/cc/test/fake_raster_buffer_provider.h
@@ -24,7 +24,7 @@ void OrderingBarrier() override; ResourceFormat GetResourceFormat(bool must_support_alpha) const override; bool IsResourceSwizzleRequired(bool must_support_alpha) const override; - bool IsPartialRasterSupported() const override; + bool CanPartialRasterIntoProvidedResource() const override; void Shutdown() override; };
diff --git a/cc/test/fake_recording_source.h b/cc/test/fake_recording_source.h index 20f9538..159a3fb 100644 --- a/cc/test/fake_recording_source.h +++ b/cc/test/fake_recording_source.h
@@ -119,8 +119,8 @@ client_.set_bounds(size_); } - void SetUnsuitableForGpuRasterization() { - force_unsuitable_for_gpu_rasterization_ = true; + void SetForceUnsuitableForGpuRasterization(bool flag) { + force_unsuitable_for_gpu_rasterization_ = flag; } void SetPlaybackAllowedEvent(base::WaitableEvent* event) {
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc index 5666e12..c72d1f2 100644 --- a/cc/test/layer_tree_test.cc +++ b/cc/test/layer_tree_test.cc
@@ -242,15 +242,9 @@ test_hooks_->DrawLayersOnThread(this); } - bool SwapBuffers(const LayerTreeHostImpl::FrameData& frame) override { - bool result = LayerTreeHostImpl::SwapBuffers(frame); - test_hooks_->SwapBuffersOnThread(this, result); - return result; - } - void DidSwapBuffersComplete() override { LayerTreeHostImpl::DidSwapBuffersComplete(); - test_hooks_->SwapBuffersCompleteOnThread(this); + test_hooks_->SwapBuffersCompleteOnThread(); } void ReclaimResources(const CompositorFrameAck* ack) override {
diff --git a/cc/test/pixel_test_delegating_output_surface.cc b/cc/test/pixel_test_delegating_output_surface.cc index cc63498..6c40eced 100644 --- a/cc/test/pixel_test_delegating_output_surface.cc +++ b/cc/test/pixel_test_delegating_output_surface.cc
@@ -21,7 +21,7 @@ #include "cc/test/pixel_test_software_output_device.h" #include "cc/test/test_in_process_context_provider.h" -static constexpr uint32_t kCompositorSurfaceNamespace = 1; +static constexpr uint32_t kCompositorClientId = 1; namespace cc { @@ -46,14 +46,13 @@ renderer_settings_(renderer_settings), display_context_provider_(std::move(display_context_provider)), surface_manager_(new SurfaceManager), - surface_id_allocator_( - new SurfaceIdAllocator(kCompositorSurfaceNamespace)), + surface_id_allocator_(new SurfaceIdAllocator(kCompositorClientId)), surface_factory_(new SurfaceFactory(surface_manager_.get(), this)), weak_ptrs_(this) { capabilities_.delegated_rendering = true; capabilities_.can_force_reclaim_resources = allow_force_reclaim_resources_; - surface_id_allocator_->RegisterSurfaceIdNamespace(surface_manager_.get()); + surface_id_allocator_->RegisterSurfaceClientId(surface_manager_.get()); } PixelTestDelegatingOutputSurface::~PixelTestDelegatingOutputSurface() {} @@ -64,7 +63,7 @@ return false; surface_manager_->RegisterSurfaceFactoryClient( - surface_id_allocator_->id_namespace(), this); + surface_id_allocator_->client_id(), this); // The PixelTestOutputSurface is owned by the Display. std::unique_ptr<PixelTestOutputSurface> output_surface; @@ -98,7 +97,7 @@ display_.reset(new Display( surface_manager_.get(), shared_bitmap_manager_, gpu_memory_buffer_manager_, renderer_settings_, - surface_id_allocator_->id_namespace(), std::move(begin_frame_source), + surface_id_allocator_->client_id(), std::move(begin_frame_source), std::move(output_surface), std::move(scheduler), base::MakeUnique<TextureMailboxDeleter>(task_runner))); display_->SetEnlargePassTextureAmountForTesting(enlarge_pass_texture_amount_); @@ -111,7 +110,7 @@ if (!delegated_surface_id_.is_null()) surface_factory_->Destroy(delegated_surface_id_); surface_manager_->UnregisterSurfaceFactoryClient( - surface_id_allocator_->id_namespace()); + surface_id_allocator_->client_id()); display_ = nullptr; surface_factory_ = nullptr; @@ -122,8 +121,6 @@ } void PixelTestDelegatingOutputSurface::SwapBuffers(CompositorFrame frame) { - client_->DidSwapBuffers(); - if (delegated_surface_id_.is_null()) { delegated_surface_id_ = surface_id_allocator_->GenerateId(); surface_factory_->Create(delegated_surface_id_);
diff --git a/cc/test/pixel_test_output_surface.cc b/cc/test/pixel_test_output_surface.cc index e892c51f..31e3041b8 100644 --- a/cc/test/pixel_test_output_surface.cc +++ b/cc/test/pixel_test_output_surface.cc
@@ -54,7 +54,6 @@ void PixelTestOutputSurface::SwapBuffers(CompositorFrame frame) { PostSwapBuffersComplete(); - client_->DidSwapBuffers(); } uint32_t PixelTestOutputSurface::GetFramebufferCopyTextureFormat() {
diff --git a/cc/test/test_hooks.h b/cc/test/test_hooks.h index 299729a..89807e46 100644 --- a/cc/test/test_hooks.h +++ b/cc/test/test_hooks.h
@@ -46,8 +46,11 @@ LayerTreeHostImpl::FrameData* frame_data, DrawResult draw_result); virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) {} - virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) {} - virtual void SwapBuffersCompleteOnThread(LayerTreeHostImpl* host_impl) {} + // Note that this is called asynchronously from the LayerTreeHostImpl + // performing its draw, so you should record state you want to use here + // in DrawLayersOnThread() instead. For that reason this method does not + // receive a LayerTreeHostImpl pointer. + virtual void SwapBuffersCompleteOnThread() {} virtual void NotifyReadyToActivateOnThread(LayerTreeHostImpl* host_impl) {} virtual void NotifyReadyToDrawOnThread(LayerTreeHostImpl* host_impl) {} virtual void NotifyAllTileTasksCompleted(LayerTreeHostImpl* host_impl) {}
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc index 950f8f0..7323c21 100644 --- a/cc/tiles/tile_manager.cc +++ b/cc/tiles/tile_manager.cc
@@ -50,6 +50,7 @@ scoped_refptr<RasterSource> raster_source, const RasterSource::PlaybackSettings& playback_settings, TileResolution tile_resolution, + gfx::Rect invalidated_rect, uint64_t source_prepare_tiles_id, std::unique_ptr<RasterBuffer> raster_buffer, TileTask::Vector* dependencies, @@ -60,7 +61,7 @@ resource_(resource), raster_source_(std::move(raster_source)), content_rect_(tile->content_rect()), - invalid_content_rect_(tile->invalidated_content_rect()), + invalid_content_rect_(invalidated_rect), contents_scale_(tile->contents_scale()), playback_settings_(playback_settings), tile_resolution_(tile_resolution), @@ -745,7 +746,7 @@ void TileManager::FreeResourcesForTile(Tile* tile) { TileDrawInfo& draw_info = tile->draw_info(); if (draw_info.resource_) { - resource_pool_->ReleaseResource(draw_info.resource_, tile->id()); + resource_pool_->ReleaseResource(draw_info.resource_); draw_info.resource_ = nullptr; } } @@ -932,12 +933,13 @@ // Get the resource. uint64_t resource_content_id = 0; Resource* resource = nullptr; + gfx::Rect invalidated_rect = tile->invalidated_content_rect(); if (UsePartialRaster() && tile->invalidated_id()) { - // TODO(danakj): For resources that are in use, we should still grab them - // and copy from them instead of rastering everything. crbug.com/492754 - resource = - resource_pool_->TryAcquireResourceWithContentId(tile->invalidated_id()); + resource = resource_pool_->TryAcquireResourceForPartialRaster( + tile->id(), tile->invalidated_content_rect(), tile->invalidated_id(), + &invalidated_rect); } + if (resource) { resource_content_id = tile->invalidated_id(); DCHECK_EQ(DetermineResourceFormat(tile), resource->format()); @@ -977,15 +979,15 @@ else it = images.erase(it); } - bool supports_concurrent_execution = !use_gpu_rasterization_; std::unique_ptr<RasterBuffer> raster_buffer = raster_buffer_provider_->AcquireBufferForRaster( resource, resource_content_id, tile->invalidated_id()); return make_scoped_refptr(new RasterTaskImpl( this, tile, resource, prioritized_tile.raster_source(), playback_settings, - prioritized_tile.priority().resolution, prepare_tiles_count_, - std::move(raster_buffer), &decode_tasks, supports_concurrent_execution)); + prioritized_tile.priority().resolution, invalidated_rect, + prepare_tiles_count_, std::move(raster_buffer), &decode_tasks, + supports_concurrent_execution)); } void TileManager::OnRasterTaskCompleted( @@ -1011,14 +1013,11 @@ if (was_canceled) { ++flush_stats_.canceled_count; - // TODO(ericrk): If more partial raster work is done in the future, it may - // be worth returning the resource to the pool with its previous ID (not - // currently tracked). crrev.com/1370333002/#ps40001 has a possible method - // of achieving this. - resource_pool_->ReleaseResource(resource, 0 /* content_id */); + resource_pool_->ReleaseResource(resource); return; } + resource_pool_->OnContentReplaced(resource->id(), tile->id()); ++flush_stats_.completed_count; draw_info.set_use_resource(); @@ -1247,7 +1246,7 @@ bool TileManager::UsePartialRaster() const { return use_partial_raster_ && - raster_buffer_provider_->IsPartialRasterSupported(); + raster_buffer_provider_->CanPartialRasterIntoProvidedResource(); } // Utility function that can be used to create a "Task set finished" task that
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc index ab6fafb..10d35efc 100644 --- a/cc/tiles/tile_manager_unittest.cc +++ b/cc/tiles/tile_manager_unittest.cc
@@ -1331,7 +1331,7 @@ host_impl()->tile_manager()->CheckIfMoreTilesNeedToBePreparedForTesting(); EXPECT_FALSE(host_impl()->is_likely_to_require_a_draw()); - host_impl()->resource_pool()->ReleaseResource(resource, 0); + host_impl()->resource_pool()->ReleaseResource(resource); } TEST_F(TileManagerTilePriorityQueueTest, DefaultMemoryPolicy) { @@ -1783,8 +1783,11 @@ // Make sure that the tile we invalidated above was not returned to the pool // with its invalidated resource ID. host_impl()->resource_pool()->CheckBusyResources(); - EXPECT_FALSE(host_impl()->resource_pool()->TryAcquireResourceWithContentId( - kInvalidatedId)); + gfx::Rect total_invalidated_rect; + EXPECT_FALSE(host_impl()->resource_pool()->TryAcquireResourceForPartialRaster( + kInvalidatedId + 1, gfx::Rect(), kInvalidatedId, + &total_invalidated_rect)); + EXPECT_EQ(gfx::Rect(), total_invalidated_rect); // Free our host_impl_ before the tile_task_manager we passed it, as it // will use that class in clean up. @@ -1836,9 +1839,10 @@ &raster_buffer_provider); // Ensure there's a resource with our |kInvalidatedId| in the resource pool. - host_impl->resource_pool()->ReleaseResource( - host_impl->resource_pool()->AcquireResource(kTileSize, RGBA_8888), - kInvalidatedId); + auto* resource = + host_impl->resource_pool()->AcquireResource(kTileSize, RGBA_8888); + host_impl->resource_pool()->OnContentReplaced(resource->id(), kInvalidatedId); + host_impl->resource_pool()->ReleaseResource(resource); host_impl->resource_pool()->CheckBusyResources(); scoped_refptr<FakeRasterSource> pending_raster_source =
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index a9d4e06..cd02535 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -250,7 +250,7 @@ gpu_memory_buffer_manager_(params->gpu_memory_buffer_manager), task_graph_runner_(params->task_graph_runner), image_serialization_processor_(params->image_serialization_processor), - surface_id_namespace_(0u), + surface_client_id_(0u), next_surface_sequence_(1u) { DCHECK(task_graph_runner_); @@ -1050,10 +1050,21 @@ base::AutoReset<bool> painting(&in_paint_layer_contents_, true); bool did_paint_content = false; + bool content_is_suitable_for_gpu = true; for (const auto& layer : update_layer_list) { did_paint_content |= layer->Update(); - content_is_suitable_for_gpu_rasterization_ &= - layer->IsSuitableForGpuRasterization(); + content_is_suitable_for_gpu &= layer->IsSuitableForGpuRasterization(); + } + + if (content_is_suitable_for_gpu) { + ++num_consecutive_frames_suitable_for_gpu_; + if (num_consecutive_frames_suitable_for_gpu_ >= + kNumFramesToConsiderBeforeGpuRasterization) { + content_is_suitable_for_gpu_rasterization_ = true; + } + } else { + num_consecutive_frames_suitable_for_gpu_ = 0; + content_is_suitable_for_gpu_rasterization_ = false; } return did_paint_content; } @@ -1296,12 +1307,12 @@ swap_promise->OnCommit(); } -void LayerTreeHost::set_surface_id_namespace(uint32_t id_namespace) { - surface_id_namespace_ = id_namespace; +void LayerTreeHost::set_surface_client_id(uint32_t client_id) { + surface_client_id_ = client_id; } SurfaceSequence LayerTreeHost::CreateSurfaceSequence() { - return SurfaceSequence(surface_id_namespace_, next_surface_sequence_++); + return SurfaceSequence(surface_client_id_, next_surface_sequence_++); } void LayerTreeHost::SetLayerTreeMutator( @@ -1587,7 +1598,7 @@ property_trees_.ToProtobuf(proto->mutable_property_trees()); - proto->set_surface_id_namespace(surface_id_namespace_); + proto->set_surface_client_id(surface_client_id_); proto->set_next_surface_sequence(next_surface_sequence_); TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( @@ -1689,7 +1700,7 @@ layer->set_property_tree_sequence_number(seq_num); }); - surface_id_namespace_ = proto.surface_id_namespace(); + surface_client_id_ = proto.surface_client_id(); next_surface_sequence_ = proto.next_surface_sequence(); }
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h index cf52e948..5628309 100644 --- a/cc/trees/layer_tree_host.h +++ b/cc/trees/layer_tree_host.h
@@ -339,7 +339,7 @@ size_t num_queued_swap_promises() const { return swap_promise_list_.size(); } - void set_surface_id_namespace(uint32_t id_namespace); + void set_surface_client_id(uint32_t client_id); SurfaceSequence CreateSurfaceSequence(); PropertyTrees* property_trees() { return &property_trees_; } @@ -474,6 +474,10 @@ private: friend class LayerTreeHostSerializationTest; + // This is the number of consecutive frames in which we want the content to be + // suitable for GPU rasterization before re-enabling it. + enum { kNumFramesToConsiderBeforeGpuRasterization = 60 }; + void InitializeProxy( std::unique_ptr<Proxy> proxy, std::unique_ptr<BeginFrameSource> external_begin_frame_source); @@ -598,8 +602,9 @@ // Set of layers that need to push properties. std::unordered_set<Layer*> layers_that_should_push_properties_; - uint32_t surface_id_namespace_; + uint32_t surface_client_id_; uint32_t next_surface_sequence_; + uint32_t num_consecutive_frames_suitable_for_gpu_ = 0; DISALLOW_COPY_AND_ASSIGN(LayerTreeHost); };
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index dd3c629..cc98d5d 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -1476,10 +1476,6 @@ client_->SetNeedsRedrawRectOnImplThread(damage_rect); } -void LayerTreeHostImpl::DidSwapBuffers() { - client_->DidSwapBuffersOnImplThread(); -} - void LayerTreeHostImpl::DidSwapBuffersComplete() { client_->DidSwapBuffersCompleteOnImplThread(); }
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 04b306c..7bc3a8a 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h
@@ -102,7 +102,6 @@ base::TimeDelta interval) = 0; virtual void SetBeginFrameSource(BeginFrameSource* source) = 0; virtual void SetEstimatedParentDrawTime(base::TimeDelta draw_time) = 0; - virtual void DidSwapBuffersOnImplThread() = 0; virtual void DidSwapBuffersCompleteOnImplThread() = 0; virtual void OnCanDrawStateChanged(bool can_draw) = 0; virtual void NotifyReadyToActivate() = 0; @@ -367,7 +366,6 @@ const gfx::Rect& viewport_rect, const gfx::Transform& transform) override; void DidLoseOutputSurface() override; - void DidSwapBuffers() override; void DidSwapBuffersComplete() override; void DidReceiveTextureInUseResponses( const gpu::TextureInUseResponses& responses) override; @@ -426,7 +424,7 @@ } const RendererCapabilitiesImpl& GetRendererCapabilities() const; - virtual bool SwapBuffers(const FrameData& frame); + bool SwapBuffers(const FrameData& frame); virtual void WillBeginImplFrame(const BeginFrameArgs& args); virtual void DidFinishImplFrame(); void DidModifyTilePriorities();
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index b3807cf..77e6f79 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -133,7 +133,6 @@ base::TimeDelta interval) override {} void SetBeginFrameSource(BeginFrameSource* source) override {} void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override {} - void DidSwapBuffersOnImplThread() override {} void DidSwapBuffersCompleteOnImplThread() override {} void OnCanDrawStateChanged(bool can_draw) override { on_can_draw_state_changed_called_ = true;
diff --git a/cc/trees/layer_tree_host_pixeltest_filters.cc b/cc/trees/layer_tree_host_pixeltest_filters.cc index 92abb20a..27f8e2c 100644 --- a/cc/trees/layer_tree_host_pixeltest_filters.cc +++ b/cc/trees/layer_tree_host_pixeltest_filters.cc
@@ -438,7 +438,7 @@ // Allow some fuzziness so that this doesn't fail when Skia makes minor // changes to blur or rectangle rendering. - float percentage_pixels_large_error = 3.1f; + float percentage_pixels_large_error = 4.f; float percentage_pixels_small_error = 0.0f; float average_error_allowed_in_bad_pixels = 2.f; int large_error_allowed = 2;
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 3e298044..93a0f3f 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -130,7 +130,6 @@ IMPL_COMMIT_COMPLETE, IMPL_ACTIVATE, IMPL_DRAW, - IMPL_SWAP, IMPL_END, }; @@ -171,11 +170,6 @@ void DrawLayersOnThread(LayerTreeHostImpl* impl) override { EXPECT_TRUE(CheckStep(IMPL_DRAW, &impl_)); - } - - void SwapBuffersCompleteOnThread(LayerTreeHostImpl* impl) override { - EXPECT_TRUE(CheckStep(IMPL_SWAP, &impl_)); - EndTest(); } @@ -2802,7 +2796,7 @@ return draw_result; } - void SwapBuffersCompleteOnThread(LayerTreeHostImpl* host_impl) override { + void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { swap_count_++; switch (swap_count_) { case 1: @@ -4286,7 +4280,7 @@ } } - void SwapBuffersOnThread(LayerTreeHostImpl* impl, bool result) override { + void DrawLayersOnThread(LayerTreeHostImpl* impl) override { switch (impl->active_tree()->source_frame_number()) { case 1: EXPECT_EQ(first_output_surface_memory_limit_, @@ -4391,9 +4385,7 @@ } } - void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { - EndTest(); - } + void SwapBuffersCompleteOnThread() override { EndTest(); } void AfterTest() override { // The pending swap promise should activate and swap. @@ -4465,7 +4457,7 @@ } } - void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { + void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { int frame = host_impl->active_tree()->source_frame_number(); if (frame == 2) { EndTest(); @@ -4585,9 +4577,8 @@ : base::Closure()); } - void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { - EXPECT_TRUE(result); - if (host_impl->active_tree()->source_frame_number() >= 1) { + void SwapBuffersCompleteOnThread() override { + if (num_swaps_++ >= 1) { // The commit changes layers so it should cause a swap. base::AutoLock lock(swap_promise_result_.lock); EXPECT_TRUE(swap_promise_result_.did_swap_called); @@ -4600,6 +4591,7 @@ void AfterTest() override {} private: + int num_swaps_ = 0; scoped_refptr<Layer> layer_; TestSwapPromiseResult swap_promise_result_; }; @@ -4968,7 +4960,7 @@ EXPECT_TRUE(layer_tree_host()->has_gpu_rasterization_trigger()); // Content-based veto is relevant as well. - recording_source_->SetUnsuitableForGpuRasterization(); + recording_source_->SetForceUnsuitableForGpuRasterization(true); // Veto will take effect when layers are updated. // The results will be verified after commit is completed below. @@ -5005,6 +4997,90 @@ MULTI_THREAD_TEST_F(LayerTreeHostTestGpuRasterizationEnabled); +class LayerTreeHostTestGpuRasterizationReenabled : public LayerTreeHostTest { + protected: + void InitializeSettings(LayerTreeSettings* settings) override { + EXPECT_FALSE(settings->gpu_rasterization_enabled); + settings->gpu_rasterization_enabled = true; + settings->wait_for_beginframe_interval = false; + settings->renderer_settings.disable_display_vsync = true; + } + + void SetupTree() override { + LayerTreeHostTest::SetupTree(); + + std::unique_ptr<FakeRecordingSource> recording_source( + new FakeRecordingSource); + recording_source_ = recording_source.get(); + + scoped_refptr<FakePictureLayer> layer = + FakePictureLayer::CreateWithRecordingSource( + &layer_client_, std::move(recording_source)); + layer_ = layer.get(); + layer->SetBounds(gfx::Size(10, 10)); + layer->SetIsDrawable(true); + layer_tree_host()->root_layer()->AddChild(layer); + layer_client_.set_bounds(layer_->bounds()); + } + + void BeginTest() override { + // Verify default value. + EXPECT_FALSE(layer_tree_host()->has_gpu_rasterization_trigger()); + + // Gpu rasterization trigger is relevant. + layer_tree_host()->SetHasGpuRasterizationTrigger(true); + EXPECT_TRUE(layer_tree_host()->has_gpu_rasterization_trigger()); + + // Content-based veto is relevant as well. + recording_source_->SetForceUnsuitableForGpuRasterization(true); + + // Veto will take effect when layers are updated. + // The results will be verified after commit is completed below. + // Since we are manually marking the source as unsuitable, + // make sure that the layer gets a chance to update. + layer_->SetNeedsDisplay(); + PostSetNeedsCommitToMainThread(); + } + + void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override { + SCOPED_TRACE(base::StringPrintf("commit %d", num_commits_)); + if (expected_gpu_enabled_) { + EXPECT_TRUE(host_impl->use_gpu_rasterization()); + } else { + EXPECT_FALSE(host_impl->use_gpu_rasterization()); + } + + ++num_commits_; + switch (num_commits_) { + case 1: + recording_source_->SetForceUnsuitableForGpuRasterization(false); + break; + case 30: + recording_source_->SetForceUnsuitableForGpuRasterization(true); + break; + case 31: + recording_source_->SetForceUnsuitableForGpuRasterization(false); + break; + case 90: + expected_gpu_enabled_ = true; + break; + } + PostSetNeedsCommitToMainThread(); + if (num_commits_ > 100) + EndTest(); + } + + void AfterTest() override {} + + FakeContentLayerClient layer_client_; + FakePictureLayer* layer_; + FakeRecordingSource* recording_source_; + int num_commits_ = 0; + bool expected_gpu_enabled_ = false; +}; + +MULTI_THREAD_TEST_F(LayerTreeHostTestGpuRasterizationReenabled); + class LayerTreeHostTestGpuRasterizationForced : public LayerTreeHostTest { protected: void InitializeSettings(LayerTreeSettings* settings) override { @@ -5039,7 +5115,7 @@ EXPECT_TRUE(layer_tree_host()->has_gpu_rasterization_trigger()); // Content-based veto is irrelevant as well. - recording_source_->SetUnsuitableForGpuRasterization(); + recording_source_->SetForceUnsuitableForGpuRasterization(true); // Veto will take effect when layers are updated. // The results will be verified after commit is completed below. @@ -6685,12 +6761,15 @@ PostSetNeedsCommitToMainThread(); } - void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { + void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { + EXPECT_EQ(2.0f, host_impl->active_tree()->painted_device_scale_factor()); + EXPECT_EQ(1.0f, host_impl->active_tree()->device_scale_factor()); + } + + void SwapBuffersCompleteOnThread() override { EXPECT_EQ( 2.0f, output_surface()->last_sent_frame()->metadata.device_scale_factor); - EXPECT_EQ(2.0f, host_impl->active_tree()->painted_device_scale_factor()); - EXPECT_EQ(1.0f, host_impl->active_tree()->device_scale_factor()); EndTest(); }
diff --git a/cc/trees/layer_tree_host_unittest_animation.cc b/cc/trees/layer_tree_host_unittest_animation.cc index 4d660a5..c0f6309 100644 --- a/cc/trees/layer_tree_host_unittest_animation.cc +++ b/cc/trees/layer_tree_host_unittest_animation.cc
@@ -1338,11 +1338,21 @@ } } - void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { + void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { // After both animations have started, verify that they have valid // start times. if (host_impl->active_tree()->source_frame_number() < 2) return; + + // Animation state is updated after drawing. + ImplThreadTaskRunner()->PostTask( + FROM_HERE, + base::Bind(&LayerTreeHostAnimationTestAddAnimationAfterAnimating:: + CheckAnimations, + base::Unretained(this), host_impl)); + } + + void CheckAnimations(LayerTreeHostImpl* host_impl) { AnimationHost::ElementToAnimationsMap element_animations_copy = host_impl->animation_host()->active_element_animations_for_testing(); EXPECT_EQ(2u, element_animations_copy.size());
diff --git a/cc/trees/layer_tree_host_unittest_copyrequest.cc b/cc/trees/layer_tree_host_unittest_copyrequest.cc index e27498a3..3ae9e6ff 100644 --- a/cc/trees/layer_tree_host_unittest_copyrequest.cc +++ b/cc/trees/layer_tree_host_unittest_copyrequest.cc
@@ -774,8 +774,8 @@ EndTest(); } - void SwapBuffersOnThread(LayerTreeHostImpl* impl, bool result) override { - switch (impl->active_tree()->source_frame_number()) { + void SwapBuffersCompleteOnThread() override { + switch (num_swaps_++) { case 0: // The layers have been drawn, so their textures have been allocated. EXPECT_FALSE(result_); @@ -829,6 +829,7 @@ scoped_refptr<TestContextProvider> first_context_provider_; scoped_refptr<TestContextProvider> second_context_provider_; + int num_swaps_ = 0; size_t num_textures_without_readback_ = 0; size_t num_textures_after_loss_ = 0; FakeContentLayerClient client_; @@ -864,8 +865,6 @@ } void BeginTest() override { - num_textures_without_readback_ = 0; - num_textures_with_readback_ = 0; waited_sync_token_after_readback_.Clear(); PostSetNeedsCommitToMainThread(); } @@ -882,8 +881,8 @@ } } - void SwapBuffersOnThread(LayerTreeHostImpl* impl, bool result) override { - switch (impl->active_tree()->source_frame_number()) { + void SwapBuffersCompleteOnThread() override { + switch (num_swaps_++) { case 0: // The layers have been drawn, so their textures have been allocated. num_textures_without_readback_ = @@ -907,8 +906,9 @@ virtual void DoEndTest() { EndTest(); } scoped_refptr<TestContextProvider> context_provider_; - size_t num_textures_without_readback_; - size_t num_textures_with_readback_; + int num_swaps_ = 0; + size_t num_textures_without_readback_ = 0; + size_t num_textures_with_readback_ = 0; gpu::SyncToken waited_sync_token_after_readback_; FakeContentLayerClient client_; scoped_refptr<FakePictureLayer> root_; @@ -931,19 +931,20 @@ EXPECT_TRUE(result->HasTexture()); TextureMailbox mailbox; - std::unique_ptr<SingleReleaseCallback> release; - result->TakeTexture(&mailbox, &release); - EXPECT_TRUE(release); - - release->Run(gpu::SyncToken(), false); + result->TakeTexture(&mailbox, &release_); + EXPECT_TRUE(release_); } void AfterTest() override { + release_->Run(gpu::SyncToken(), false); + // No sync point was needed. EXPECT_FALSE(waited_sync_token_after_readback_.HasData()); // Except the copy to have made another texture. EXPECT_EQ(num_textures_without_readback_ + 1, num_textures_with_readback_); } + + std::unique_ptr<SingleReleaseCallback> release_; }; SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
diff --git a/cc/trees/layer_tree_host_unittest_damage.cc b/cc/trees/layer_tree_host_unittest_damage.cc index 246f910..405d837 100644 --- a/cc/trees/layer_tree_host_unittest_damage.cc +++ b/cc/trees/layer_tree_host_unittest_damage.cc
@@ -149,9 +149,6 @@ class LayerTreeHostDamageTestNoDamageDoesNotSwap : public LayerTreeHostDamageTest { void BeginTest() override { - expect_swap_and_succeed_ = 0; - did_swaps_ = 0; - did_swap_and_succeed_ = 0; PostSetNeedsCommitToMainThread(); } @@ -178,29 +175,31 @@ switch (source_frame) { case 0: // The first frame has damage, so we should draw and swap. - ++expect_swap_and_succeed_; + EXPECT_FALSE(frame_data->has_no_damage); + ++expect_swap_; break; case 1: // The second frame has no damage, so we should not draw and swap. + EXPECT_TRUE(frame_data->has_no_damage); break; case 2: // The third frame has damage again, so we should draw and swap. - ++expect_swap_and_succeed_; + EXPECT_FALSE(frame_data->has_no_damage); + ++expect_swap_; break; case 3: // The fourth frame has no visible damage, so we should not draw and // swap. + EXPECT_TRUE(frame_data->has_no_damage); EndTest(); break; } return draw_result; } - void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { - ++did_swaps_; - if (result) - ++did_swap_and_succeed_; - EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_); + void SwapBuffersCompleteOnThread() override { + ++did_swap_; + EXPECT_EQ(expect_swap_, did_swap_); } void DidCommit() override { @@ -223,16 +222,14 @@ } void AfterTest() override { - EXPECT_EQ(4, did_swaps_); - EXPECT_EQ(2, expect_swap_and_succeed_); - EXPECT_EQ(expect_swap_and_succeed_, did_swap_and_succeed_); + EXPECT_EQ(2, expect_swap_); + EXPECT_EQ(expect_swap_, did_swap_); } FakeContentLayerClient client_; scoped_refptr<FakePictureLayer> content_; - int expect_swap_and_succeed_; - int did_swaps_; - int did_swap_and_succeed_; + int expect_swap_ = 0; + int did_swap_ = 0; }; SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestNoDamageDoesNotSwap); @@ -376,7 +373,7 @@ class LayerTreeHostDamageTestScrollbarDoesDamage : public LayerTreeHostScrollbarDamageTest { void BeginTest() override { - did_swaps_ = 0; + num_draws_ = 0; PostSetNeedsCommitToMainThread(); } @@ -389,7 +386,7 @@ gfx::Rect root_damage = root_surface->damage_tracker()->current_damage_rect(); root_damage.Intersect(root_surface->content_rect()); - switch (did_swaps_) { + switch (num_draws_) { case 0: // The first frame has damage, so we should draw and swap. break; @@ -410,12 +407,11 @@ return draw_result; } - void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { - ++did_swaps_; - EXPECT_TRUE(result); + void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { + ++num_draws_; LayerImpl* scroll_layer = host_impl->active_tree()->LayerById(content_layer_->id()); - switch (did_swaps_) { + switch (num_draws_) { case 1: // Test that modifying the position of the content layer (not // scrolling) won't damage the scrollbar. @@ -440,20 +436,20 @@ } void ModifyContentLayerPosition() { - EXPECT_EQ(1, did_swaps_); + EXPECT_EQ(1, num_draws_); content_layer_->SetPosition(gfx::PointF(10.f, 10.f)); } void ResizeScrollLayer() { - EXPECT_EQ(3, did_swaps_); + EXPECT_EQ(3, num_draws_); Layer* root = layer_tree_host()->root_layer(); content_layer_->SetBounds( gfx::Size(root->bounds().width() + 60, root->bounds().height() + 100)); } - void AfterTest() override { EXPECT_EQ(4, did_swaps_); } + void AfterTest() override { EXPECT_EQ(4, num_draws_); } - int did_swaps_; + int num_draws_; }; MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarDoesDamage); @@ -461,7 +457,7 @@ class LayerTreeHostDamageTestScrollbarCommitDoesNoDamage : public LayerTreeHostScrollbarDamageTest { void BeginTest() override { - did_swaps_ = 0; + num_draws_ = 0; PostSetNeedsCommitToMainThread(); } @@ -475,7 +471,7 @@ root_surface->damage_tracker()->current_damage_rect(); root_damage.Intersect(root_surface->content_rect()); int frame = host_impl->active_tree()->source_frame_number(); - switch (did_swaps_) { + switch (num_draws_) { case 0: // The first frame has damage, so we should draw and swap. EXPECT_EQ(0, frame); @@ -497,12 +493,11 @@ return draw_result; } - void SwapBuffersOnThread(LayerTreeHostImpl* host_impl, bool result) override { - ++did_swaps_; - EXPECT_TRUE(result); + void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { + ++num_draws_; LayerImpl* scroll_layer = host_impl->active_tree()->LayerById(content_layer_->id()); - switch (did_swaps_) { + switch (num_draws_) { case 1: // Scroll on the thread. This should damage the scrollbar for the // next draw on the thread. @@ -523,9 +518,9 @@ } } - void AfterTest() override { EXPECT_EQ(3, did_swaps_); } + void AfterTest() override { EXPECT_EQ(3, num_draws_); } - int did_swaps_; + int num_draws_; }; MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarCommitDoesNoDamage);
diff --git a/cc/trees/layer_tree_host_unittest_serialization.cc b/cc/trees/layer_tree_host_unittest_serialization.cc index 59bc7016..becf0f3 100644 --- a/cc/trees/layer_tree_host_unittest_serialization.cc +++ b/cc/trees/layer_tree_host_unittest_serialization.cc
@@ -206,8 +206,8 @@ layer_tree_host_dst_->selection_); EXPECT_EQ(layer_tree_host_src_->property_trees_, layer_tree_host_dst_->property_trees_); - EXPECT_EQ(layer_tree_host_src_->surface_id_namespace_, - layer_tree_host_dst_->surface_id_namespace_); + EXPECT_EQ(layer_tree_host_src_->surface_client_id_, + layer_tree_host_dst_->surface_client_id_); EXPECT_EQ(layer_tree_host_src_->next_surface_sequence_, layer_tree_host_dst_->next_surface_sequence_); @@ -293,8 +293,8 @@ layer_tree_host_src_->property_trees_.sequence_number = layer_tree_host_src_->property_trees_.sequence_number * 3 + 1; - layer_tree_host_src_->surface_id_namespace_ = - layer_tree_host_src_->surface_id_namespace_ * 3 + 1; + layer_tree_host_src_->surface_client_id_ = + layer_tree_host_src_->surface_client_id_ * 3 + 1; layer_tree_host_src_->next_surface_sequence_ = layer_tree_host_src_->next_surface_sequence_ * 3 + 1;
diff --git a/cc/trees/proxy_impl.cc b/cc/trees/proxy_impl.cc index f69296deb..cf0dd57 100644 --- a/cc/trees/proxy_impl.cc +++ b/cc/trees/proxy_impl.cc
@@ -331,11 +331,6 @@ scheduler_->SetEstimatedParentDrawTime(draw_time); } -void ProxyImpl::DidSwapBuffersOnImplThread() { - DCHECK(IsImplThread()); - scheduler_->DidSwapBuffers(); -} - void ProxyImpl::DidSwapBuffersCompleteOnImplThread() { TRACE_EVENT0("cc,benchmark", "ProxyImpl::DidSwapBuffersCompleteOnImplThread"); DCHECK(IsImplThread()); @@ -660,8 +655,10 @@ bool start_ready_animations = draw_frame; layer_tree_host_impl_->UpdateAnimationState(start_ready_animations); - if (draw_frame) - layer_tree_host_impl_->SwapBuffers(frame); + if (draw_frame) { + if (layer_tree_host_impl_->SwapBuffers(frame)) + scheduler_->DidSwapBuffers(); + } // Tell the main thread that the the newly-commited frame was drawn. if (next_frame_is_newly_committed_frame_) {
diff --git a/cc/trees/proxy_impl.h b/cc/trees/proxy_impl.h index a996a1f..de61a75a 100644 --- a/cc/trees/proxy_impl.h +++ b/cc/trees/proxy_impl.h
@@ -85,7 +85,6 @@ base::TimeDelta interval) override; void SetBeginFrameSource(BeginFrameSource* source) override; void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override; - void DidSwapBuffersOnImplThread() override; void DidSwapBuffersCompleteOnImplThread() override; void OnCanDrawStateChanged(bool can_draw) override; void NotifyReadyToActivate() override;
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc index 37baa50f..0e1dee6 100644 --- a/cc/trees/single_thread_proxy.cc +++ b/cc/trees/single_thread_proxy.cc
@@ -512,13 +512,6 @@ scheduler_on_impl_thread_->SetEstimatedParentDrawTime(draw_time); } -void SingleThreadProxy::DidSwapBuffersOnImplThread() { - TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersOnImplThread"); - if (scheduler_on_impl_thread_) - scheduler_on_impl_thread_->DidSwapBuffers(); - client_->DidPostSwapBuffers(); -} - void SingleThreadProxy::DidSwapBuffersCompleteOnImplThread() { TRACE_EVENT0("cc,benchmark", "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread"); @@ -696,7 +689,11 @@ tracked_objects::ScopedTracker tracking_profile8( FROM_HERE_WITH_EXPLICIT_FUNCTION( "461509 SingleThreadProxy::DoComposite8")); - layer_tree_host_impl_->SwapBuffers(*frame); + if (layer_tree_host_impl_->SwapBuffers(*frame)) { + if (scheduler_on_impl_thread_) + scheduler_on_impl_thread_->DidSwapBuffers(); + client_->DidPostSwapBuffers(); + } } // TODO(robliao): Remove ScopedTracker below once https://crbug.com/461509 is // fixed.
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h index c24714b..46d7db7b 100644 --- a/cc/trees/single_thread_proxy.h +++ b/cc/trees/single_thread_proxy.h
@@ -83,7 +83,6 @@ base::TimeDelta interval) override; void SetBeginFrameSource(BeginFrameSource* source) override; void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override; - void DidSwapBuffersOnImplThread() override; void DidSwapBuffersCompleteOnImplThread() override; void OnCanDrawStateChanged(bool can_draw) override; void NotifyReadyToActivate() override;
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 1c26c3f..cc77145e 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -56,6 +56,32 @@ } } +# This target exists above chrome and it's main components in the dependency +# tree as a central place to put assert_no_deps annotations. Since this depends +# on Chrome and the main DLLs it uses, it will transitively assert that those +# targets also have no deps on disallowed things. +group("assert_no_deps") { + deps = [] + + if (is_android) { + deps += [ "//chrome/android:chrome_public_apk" ] + } else { + deps += [ ":chrome" ] + } + + if (is_win) { + deps += [ + ":chrome_dll", + ":main_dll", + ] + } + + # This should not pull in installer strings. This is will bloat the binary + # for no reason and is easy to mess up. See the comment at the top of + # //chrome/installer/util/BUILD.gn. + assert_no_deps = [ "//chrome/installer/util:strings" ] +} + if (!is_android && !is_mac) { group("chrome") { public_deps = [ @@ -1094,7 +1120,7 @@ } else { group("chrome_dump_syms") { } - group("chrome_symbol_archive") { + group("chrome_dsym_archive") { } } }
diff --git a/chrome/VERSION b/chrome/VERSION index d86c754..b08692a 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=54 MINOR=0 -BUILD=2795 +BUILD=2797 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 75e6228e..31efb82 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -561,6 +561,7 @@ deps = [ ":chrome_test_java", + "//chrome/android/webapk/libs/runtime_library:runtime_library_javatests", "//chrome/android/webapk/shell_apk:shell_apk_javatests", ] additional_apks = [
diff --git a/chrome/android/java/proguard.flags b/chrome/android/java/proguard.flags index 627ae0d..59ce6b7 100644 --- a/chrome/android/java/proguard.flags +++ b/chrome/android/java/proguard.flags
@@ -9,12 +9,6 @@ *; } -# Keep all the primitive and String constants for for the following two packages. --keepclassmembers class com.google.android.apps.chrome.**,org.chromium.** { - !private static final % *; - !private static final java.lang.String *; -} - # Fragments are loaded using reflection via Fragment.instantiate(Context,String) # This can be improved upon - see crbug.com/622023. -keep public class com.google.android.apps.chrome** extends android.app.Fragment
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java index 8d95ad3..1c9be71 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -1310,7 +1310,7 @@ mReaderModeManager); if (controlContainer != null - && DeviceClassManager.enableToolbarSwipe(FeatureUtilities.isDocumentMode(this))) { + && DeviceClassManager.enableToolbarSwipe()) { controlContainer.setSwipeHandler( getCompositorViewHolder().getLayoutManager().getTopSwipeHandler()); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java index ffe3e02d..1715d7e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
@@ -206,6 +206,10 @@ @Override public void onCreate() { UmaUtils.recordMainEntryPointTime(); + initCommandLine(); + TraceEvent.maybeEnableEarlyTracing(); + TraceEvent.begin("ChromeApplication.onCreate"); + super.onCreate(); ContextUtils.initApplicationContext(this); @@ -244,6 +248,7 @@ // in the SyncController constructor. UniqueIdentificationGeneratorFactory.registerGenerator(SyncController.GENERATOR_ID, new UuidBasedUniqueIdentificationGenerator(this, SESSIONS_UUID_PREF_KEY), false); + TraceEvent.end("ChromeApplication.onCreate"); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeSwitches.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeSwitches.java index 56c5902c..77736ca 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeSwitches.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeSwitches.java
@@ -19,10 +19,6 @@ /** Whether fullscreen support is disabled (auto hiding controls, etc...). */ public static final String DISABLE_FULLSCREEN = "disable-fullscreen"; - /** Enable toolbar swipe to change tabs in document mode */ - public static final String ENABLE_TOOLBAR_SWIPE_IN_DOCUMENT_MODE = - "enable-toolbar-swipe-in-document-mode"; - /** Whether instant is disabled. */ public static final String DISABLE_INSTANT = "disable-instant"; @@ -219,12 +215,6 @@ public static final String ENABLE_APP_LINK = "enable-app-link"; /** - * Enable tab switcher in document mode (merged tabs and apps option). - */ - public static final String ENABLE_TAB_SWITCHER_IN_DOCUMENT_MODE = - "enable-tab-switcher-in-document-mode"; - - /** * Set the partner-defined homepage URL, for testing. */ public static final String PARTNER_HOMEPAGE_FOR_TESTING = "partner-homepage-for-testing";
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 bdbc679..e82a148 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -1232,10 +1232,12 @@ getToolbarManager().finishAnimations(); } if (TextUtils.equals(externalAppId, getPackageName())) { - // If the intent was launched by chrome, open the new tab in the current model. + // If the intent was launched by chrome, open the new tab in the appropriate model. // Using FROM_LINK ensures the tab is parented to the current tab, which allows // the back button to close these tabs and restore selection to the previous tab. - return getCurrentTabCreator().launchUrl(url, TabLaunchType.FROM_LINK, intent, + boolean isIncognito = IntentUtils.safeGetBooleanExtra(intent, + IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, false); + return getTabCreator(isIncognito).launchUrl(url, TabLaunchType.FROM_LINK, intent, mIntentHandlingTimeMs); } else { return getTabCreator(false).launchUrlFromExternalApp(url, referer, headers,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/TabState.java b/chrome/android/java/src/org/chromium/chrome/browser/TabState.java index 8852253..1615093 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/TabState.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/TabState.java
@@ -286,54 +286,61 @@ /** * Writes the TabState to disk. This method may be called on either the UI or background thread. - * @param output Stream to write the tab's state to. + * @param file File to write the tab's state to. * @param state State object obtained from from {@link Tab#getState()}. * @param encrypted Whether or not the TabState should be encrypted. */ - public static void saveState(FileOutputStream output, TabState state, boolean encrypted) - throws IOException { + public static void saveState(File file, TabState state, boolean encrypted) { if (state == null || state.contentsState == null) { return; } - DataOutputStream stream; - if (encrypted) { - Cipher cipher = CipherFactory.getInstance().getCipher(Cipher.ENCRYPT_MODE); - if (cipher != null) { - stream = new DataOutputStream(new CipherOutputStream(output, cipher)); - } else { - // If cipher is null, getRandomBytes failed, which means encryption is meaningless. - // Therefore, do not save anything. This will cause users to lose Incognito state in - // certain cases. That is annoying, but is better than failing to provide the - // guarantee of Incognito Mode. - return; - } - } else { - stream = new DataOutputStream(output); - } + // Create the byte array from contentsState before opening the FileOutputStream, in case + // contentsState.buffer is an instance of MappedByteBuffer that is mapped to + // the tab state file. + state.contentsState.buffer().rewind(); + byte[] contentsStateBytes = new byte[state.contentsState.buffer().remaining()]; + state.contentsState.buffer().get(contentsStateBytes); + DataOutputStream dataOutputStream = null; + FileOutputStream fileOutputStream = null; try { + fileOutputStream = new FileOutputStream(file); + if (encrypted) { - stream.writeLong(KEY_CHECKER); - } - stream.writeLong(state.timestampMillis); - state.contentsState.buffer().rewind(); - stream.writeInt(state.contentsState.buffer().remaining()); - if (encrypted) { - byte[] bytes = new byte[state.contentsState.buffer().remaining()]; - state.contentsState.buffer().get(bytes); - stream.write(bytes); + Cipher cipher = CipherFactory.getInstance().getCipher(Cipher.ENCRYPT_MODE); + if (cipher != null) { + dataOutputStream = new DataOutputStream(new CipherOutputStream( + fileOutputStream, cipher)); + } else { + // If cipher is null, getRandomBytes failed, which means encryption is + // meaningless. Therefore, do not save anything. This will cause users + // to lose Incognito state in certain cases. That is annoying, but is + // better than failing to provide the guarantee of Incognito Mode. + return; + } } else { - output.getChannel().write(state.contentsState.buffer()); + dataOutputStream = new DataOutputStream(fileOutputStream); } - stream.writeInt(state.parentId); - stream.writeUTF(state.openerAppId != null ? state.openerAppId : ""); - stream.writeInt(state.contentsState.version()); - stream.writeLong(state.syncId); - stream.writeBoolean(state.shouldPreserve); - stream.writeInt(state.themeColor); + if (encrypted) { + dataOutputStream.writeLong(KEY_CHECKER); + } + dataOutputStream.writeLong(state.timestampMillis); + dataOutputStream.writeInt(contentsStateBytes.length); + dataOutputStream.write(contentsStateBytes); + dataOutputStream.writeInt(state.parentId); + dataOutputStream.writeUTF(state.openerAppId != null ? state.openerAppId : ""); + dataOutputStream.writeInt(state.contentsState.version()); + dataOutputStream.writeLong(state.syncId); + dataOutputStream.writeBoolean(state.shouldPreserve); + dataOutputStream.writeInt(state.themeColor); + } catch (FileNotFoundException e) { + Log.w(TAG, "FileNotFoundException while attempting to save TabState."); + } catch (IOException e) { + Log.w(TAG, "IOException while attempting to save TabState."); } finally { - StreamUtil.closeQuietly(stream); + StreamUtil.closeQuietly(dataOutputStream); + StreamUtil.closeQuietly(fileOutputStream); } } @@ -467,4 +474,4 @@ private static native void nativeFreeWebContentsStateBuffer(ByteBuffer buffer); private static native void nativeCreateHistoricalTab(ByteBuffer state, int savedStateVersion); -} +} \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java b/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java index 19f4531..b3e0dea 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java
@@ -12,44 +12,50 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.chrome.browser.ShortcutHelper; -import org.chromium.chrome.browser.tab.EmptyTabObserver; -import org.chromium.chrome.browser.tab.Tab; import org.chromium.content_public.browser.WebContents; /** * Manages an AppBannerInfoBar for a Tab. * - * The AppBannerManager manages a single AppBannerInfoBar, creating a new one when it detects that - * the current webpage is requesting a banner to be built. The actual observation of the WebContents - * (which triggers the automatic creation and removal of banners, among other things) is done by the - * native-side AppBannerManager. - * - * This Java-side class owns its native-side counterpart, which is basically used to grab resources - * from the network. + * The AppBannerManager is responsible for fetching details about native apps to display in the + * banner. The actual observation of the WebContents (which triggers the automatic creation and + * removal of banners, among other things) is done by the native-side AppBannerManagerAndroid. */ @JNINamespace("banners") -public class AppBannerManager extends EmptyTabObserver { +public class AppBannerManager { private static final String TAG = "AppBannerManager"; /** Retrieves information about a given package. */ private static AppDetailsDelegate sAppDetailsDelegate; - /** Whether the banners are enabled. */ - private static Boolean sIsEnabled; + /** Whether add to home screen is permitted by the system. */ + private static Boolean sIsSupported; + + /** Whether the tab to which this manager is attached to is permitted to show banners. */ + private boolean mIsEnabledForTab; /** Pointer to the native side AppBannerManager. */ private long mNativePointer; /** - * Checks if app banners are enabled. - * @return True if banners are enabled, false otherwise. + * Checks if the add to home screen intent is supported. + * @return true if add to home screen is supported, false otherwise. */ - public static boolean isEnabled() { - if (sIsEnabled == null) { + public static boolean isSupported() { + if (sIsSupported == null) { Context context = ContextUtils.getApplicationContext(); - sIsEnabled = ShortcutHelper.isAddToHomeIntentSupported(context); + sIsSupported = ShortcutHelper.isAddToHomeIntentSupported(context); } - return sIsEnabled; + return sIsSupported; + } + + /** + * Checks if app banners are enabled for the tab which this manager is attached to. + * @return true if app banners can be shown for this tab, false otherwise. + */ + @CalledByNative + private boolean isEnabledForTab() { + return isSupported() && mIsEnabledForTab; } /** @@ -62,41 +68,25 @@ } /** - * Constructs an AppBannerManager for the given tab. - * @param tab Tab that the AppBannerManager will be attached to. + * Constructs an AppBannerManager. + * @param nativePointer the native-side object that owns this AppBannerManager. */ - public AppBannerManager(Tab tab, Context context) { - mNativePointer = nativeInit(); - updatePointers(tab); + private AppBannerManager(long nativePointer) { + mNativePointer = nativePointer; + mIsEnabledForTab = isSupported(); } - @Override - public void onWebContentsSwapped(Tab tab, boolean didStartLoad, - boolean didFinishLoad) { - updatePointers(tab); + @CalledByNative + private static AppBannerManager create(long nativePointer) { + return new AppBannerManager(nativePointer); } - @Override - public void onContentChanged(Tab tab) { - updatePointers(tab); - } - - /** - * Destroys the native AppBannerManager. - */ - public void destroy() { - nativeDestroy(mNativePointer); + @CalledByNative + private void destroy() { mNativePointer = 0; } /** - * Updates which WebContents the native AppBannerManager is monitoring. - */ - private void updatePointers(Tab tab) { - nativeReplaceWebContents(mNativePointer, tab.getWebContents()); - } - - /** * Grabs package information for the banner asynchronously. * @param url URL for the page that is triggering the banner. * @param packageName Name of the package that is being advertised. @@ -133,15 +123,15 @@ }; } - /** Requests the app banner. This method is called from the DevTools. */ - public void requestAppBanner() { - nativeRequestAppBanner(mNativePointer); + /** Enables or disables app banners. */ + public void setIsEnabledForTab(boolean state) { + mIsEnabledForTab = state; } - /** Enables or disables the app banners for testing. */ + /** Overrides whether the system supports add to home screen. Used in testing. */ @VisibleForTesting - static void setIsEnabledForTesting(boolean state) { - sIsEnabled = state; + public static void setIsSupported(boolean state) { + sIsSupported = state; } /** Sets a constant (in days) that gets added to the time when the current time is requested. */ @@ -162,19 +152,21 @@ nativeSetEngagementWeights(directEngagement, indirectEngagement); } - /** Returns whether a AppBannerDataFetcher is actively retrieving data. */ + /** Returns whether an AppBannerDataFetcher is actively retrieving data. */ @VisibleForTesting public boolean isFetcherActiveForTesting() { return nativeIsFetcherActive(mNativePointer); } - private native long nativeInit(); - private native void nativeDestroy(long nativeAppBannerManagerAndroid); - private native void nativeReplaceWebContents(long nativeAppBannerManagerAndroid, + /** Returns the AppBannerManager object. This is owned by the C++ banner manager. */ + public static AppBannerManager getAppBannerManagerForWebContents(WebContents webContents) { + return nativeGetJavaBannerManagerForWebContents(webContents); + } + + private static native AppBannerManager nativeGetJavaBannerManagerForWebContents( WebContents webContents); private native boolean nativeOnAppDetailsRetrieved(long nativeAppBannerManagerAndroid, AppData data, String title, String packageName, String imageUrl); - private native void nativeRequestAppBanner(long nativeAppBannerManagerAndroid); // Testing methods. private static native void nativeSetTimeDeltaForTesting(int days);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java index b34157c0..5dd539b4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java
@@ -297,8 +297,9 @@ } /** - * Set the visibility of the base page text selection controls. - * TODO(mdjones): This should be replaced be focusing the panel's ContentViewCore. + * Set the visibility of the base page text selection controls. This will also attempt to + * remove focus from the base page to clear any open controls. + * TODO(mdjones): This should be replaced with focusing the panel's ContentViewCore. * @param visible If the text controls are visible. */ protected void setBasePageTextControlsVisibility(boolean visible) { @@ -308,10 +309,16 @@ if (baseContentView == null) return; // If the panel does not have focus or isn't open, return. - if (isPanelOpened() && mDidClearTextControls && visible) return; - if (!isPanelOpened() && !mDidClearTextControls && !visible) return; + if (isPanelOpened() && mDidClearTextControls && !visible) return; + if (!isPanelOpened() && !mDidClearTextControls && visible) return; mDidClearTextControls = !visible; + + if (!visible) { + baseContentView.preserveSelectionOnNextLossOfFocus(); + baseContentView.getContainerView().clearFocus(); + } + baseContentView.updateTextSelectionUI(visible); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java index b70b652..2dc7f406 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
@@ -37,7 +37,6 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver; import org.chromium.chrome.browser.tabmodel.TabModelUtils; -import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.chrome.browser.widget.OverviewListLayout; import org.chromium.ui.base.LocalizationUtils; import org.chromium.ui.resources.dynamics.DynamicResourceLoader; @@ -687,8 +686,7 @@ public boolean isSwipeEnabled(ScrollDirection direction) { FullscreenManager manager = mHost.getFullscreenManager(); if (getActiveLayout() != mStaticLayout - || !DeviceClassManager.enableToolbarSwipe( - FeatureUtilities.isDocumentMode(mHost.getContext())) + || !DeviceClassManager.enableToolbarSwipe() || (manager != null && manager.getPersistentFullscreenMode())) { return false; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerDocument.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerDocument.java index ac0a093..6794f2b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerDocument.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerDocument.java
@@ -396,8 +396,7 @@ FullscreenManager manager = mHost.getFullscreenManager(); if (getActiveLayout() != mStaticLayout || !FeatureUtilities.isDocumentModeEligible(mHost.getContext()) - || !DeviceClassManager.enableToolbarSwipe( - FeatureUtilities.isDocumentMode(mHost.getContext())) + || !DeviceClassManager.enableToolbarSwipe() || (manager != null && manager.getPersistentFullscreenMode())) { return false; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java index 74367d9..7a3c79d2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ContextualSearchSceneLayer.java
@@ -11,7 +11,7 @@ import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanel; import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPeekPromoControl; import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPromoControl; -import org.chromium.content.browser.ContentViewCore; +import org.chromium.content_public.browser.WebContents; import org.chromium.ui.resources.ResourceManager; /** @@ -106,6 +106,9 @@ float progressBarOpacity = panel.getProgressBarOpacity(); int progressBarCompletion = panel.getProgressBarCompletion(); + WebContents panelWebContents = panel.getContentViewCore() != null + ? panel.getContentViewCore().getWebContents() : null; + nativeUpdateContextualSearchLayer(mNativePtr, R.drawable.contextual_search_bar_background, searchContextViewId, @@ -124,7 +127,7 @@ mDpToPx, panel.getBasePageBrightness(), panel.getBasePageY() * mDpToPx, - panel.getContentViewCore(), + panelWebContents, searchPromoVisible, searchPromoHeightPx, searchPromoOpacity, @@ -218,7 +221,7 @@ float dpToPx, float basePageBrightness, float basePageYOffset, - ContentViewCore contentViewCore, + WebContents webContents, boolean searchPromoVisible, float searchPromoHeight, float searchPromoOpacity,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ReaderModeSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ReaderModeSceneLayer.java index 2b08a78..bec766f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ReaderModeSceneLayer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/ReaderModeSceneLayer.java
@@ -7,7 +7,7 @@ import org.chromium.base.annotations.JNINamespace; import org.chromium.chrome.R; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel; -import org.chromium.content.browser.ContentViewCore; +import org.chromium.content_public.browser.WebContents; import org.chromium.ui.resources.ResourceManager; /** @@ -57,11 +57,14 @@ mIsInitialized = true; } + WebContents panelWebContents = panel.getContentViewCore() != null + ? panel.getContentViewCore().getWebContents() : null; + nativeUpdate(mNativePtr, mDpToPx, panel.getBasePageBrightness(), panel.getBasePageY() * mDpToPx, - panel.getContentViewCore(), + panelWebContents, panel.getOffsetX() * mDpToPx, panel.getOffsetY() * mDpToPx, panel.getWidth() * mDpToPx, @@ -127,7 +130,7 @@ float dpToPx, float basePageBrightness, float basePageYOffset, - ContentViewCore contentViewCore, + WebContents webContents, float panelX, float panelY, float panelWidth,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslateController.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslateController.java index df0f0f75..307d1beb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslateController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslateController.java
@@ -20,6 +20,7 @@ * Controls how Translation One-box triggering is handled for the {@link ContextualSearchManager}. */ public class ContextualSearchTranslateController { + private static final int LOCALE_MIN_LENGTH = 2; private final ChromeActivity mActivity; private final ContextualSearchPolicy mPolicy; @@ -108,8 +109,8 @@ // Add the accept languages to the end, since they are a weaker hint than // the proficient languages. List<String> acceptLanguages = getAcceptLanguages(); - for (int i = 0; i < acceptLanguages.size(); i++) { - uniqueLanguages.add(trimLocaleToLanguage(acceptLanguages.get(i))); + for (String accept : acceptLanguages) { + if (isValidLocale(accept)) uniqueLanguages.add(trimLocaleToLanguage(accept)); } return new ArrayList<String>(uniqueLanguages); } @@ -138,7 +139,7 @@ Context context = mActivity.getApplicationContext(); if (context != null) { for (String locale : UiUtils.getIMELocales(context)) { - uniqueLanguages.add(trimLocaleToLanguage(locale)); + if (isValidLocale(locale)) uniqueLanguages.add(trimLocaleToLanguage(locale)); } } } @@ -153,21 +154,32 @@ List<String> result = new ArrayList<String>(); if (!ContextualSearchFieldTrial.isAcceptLanguagesForTranslationDisabled()) { String acceptLanguages = getNativeAcceptLanguages(); - for (String language : acceptLanguages.split(",")) { - result.add(language); + if (!TextUtils.isEmpty(acceptLanguages)) { + for (String language : acceptLanguages.split(",")) { + result.add(language); + } } } return result; } /** + * @return Whether the given locale appears to be valid. + */ + private boolean isValidLocale(String locale) { + return !TextUtils.isEmpty(locale) && locale.length() >= LOCALE_MIN_LENGTH; + } + + /** + * Converts a given locale to a language code. + * @param locale The locale string, which must have a length of at least 2. * @return The given locale as a language code. */ private String trimLocaleToLanguage(String locale) { // TODO(donnd): use getScript or getLanguageTag (both API 21), or some other standard way to // strip the country, instead of hard-coding the two character language code. // TODO(donnd): Shouldn't getLanguage() do this? - String trimmedLocale = locale.substring(0, 2); + String trimmedLocale = locale.substring(0, LOCALE_MIN_LENGTH); return new Locale(trimmedLocale).getLanguage(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslateInterface.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslateInterface.java index ae96b5f..43126352 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslateInterface.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTranslateInterface.java
@@ -15,7 +15,7 @@ public String getAcceptLanguages(); /** - * @return The Translate Service's target language string. + * @return The Translate Service's target language string, non-empty. */ public String getTranslateServiceTargetLanguage(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java index 0d4c76cd..0ab18c1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java
@@ -13,7 +13,6 @@ import org.chromium.base.Log; import org.chromium.base.VisibleForTesting; -import org.chromium.chrome.browser.banners.AppBannerManager; import org.chromium.chrome.browser.contextmenu.ChromeContextMenuPopulator; import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator; import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl; @@ -196,7 +195,7 @@ } @Override - public AppBannerManager createAppBannerManager(Tab tab) { - return null; + public boolean canShowAppBanners(Tab tab) { + return false; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/device/DeviceClassManager.java b/chrome/android/java/src/org/chromium/chrome/browser/device/DeviceClassManager.java index 6ff03bc9..46d59d4a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/device/DeviceClassManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/device/DeviceClassManager.java
@@ -28,7 +28,6 @@ private boolean mEnableAnimations; private boolean mEnablePrerendering; private boolean mEnableToolbarSwipe; - private boolean mEnableToolbarSwipeInDocumentMode; private boolean mDisableDomainReliability; private final boolean mEnableFullscreen; @@ -74,8 +73,6 @@ .hasSwitch(ChromeSwitches.ENABLE_ACCESSIBILITY_TAB_SWITCHER); mEnableFullscreen = !commandLine.hasSwitch(ChromeSwitches.DISABLE_FULLSCREEN); - mEnableToolbarSwipeInDocumentMode = - commandLine.hasSwitch(ChromeSwitches.ENABLE_TOOLBAR_SWIPE_IN_DOCUMENT_MODE); // Related features. if (mEnableAccessibilityLayout) { @@ -127,12 +124,10 @@ } /** - * @param isDocumentMode Whether or not chrome is in document mode. * @return Whether or not we can use the toolbar swipe. */ - public static boolean enableToolbarSwipe(boolean isDocumentMode) { - return getInstance().mEnableToolbarSwipe - && !(isDocumentMode && !getInstance().mEnableToolbarSwipeInDocumentMode); + public static boolean enableToolbarSwipe() { + return getInstance().mEnableToolbarSwipe; } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java index 411b08e..5c9a665 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java
@@ -116,16 +116,22 @@ public void onCreate(Bundle savedInstanceState) { // Third-party code adds disk access to Activity.onCreate. http://crbug.com/619824 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); + TraceEvent.begin("ChromeLauncherActivity"); + TraceEvent.begin("ChromeLauncherActivity.onCreate"); try { - super.onCreate(savedInstanceState); + doOnCreate(savedInstanceState); } finally { StrictMode.setThreadPolicy(oldPolicy); + TraceEvent.end("ChromeLauncherActivity.onCreate"); } + } + + private final void doOnCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); // This Activity is only transient. It launches another activity and // terminates itself. However, some of the work is performed outside of // {@link Activity#onCreate()}. To capture this, the TraceEvent starts // in onCreate(), and ends in onPause(). - TraceEvent.begin("ChromeLauncherActivity"); // Needs to be called as early as possible, to accurately capture the // time at which the intent was received. IntentHandler.addTimestampToIntent(getIntent()); @@ -231,8 +237,8 @@ } @Override - public void onPause() { - super.onPause(); + public void onDestroy() { + super.onDestroy(); TraceEvent.end("ChromeLauncherActivity"); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java index 30b6da5..729f2d2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java
@@ -201,6 +201,12 @@ */ @Override protected final void onCreate(Bundle savedInstanceState) { + TraceEvent.begin("AsyncInitializationActivity.onCreate()"); + onCreateInternal(savedInstanceState); + TraceEvent.end("AsyncInitializationActivity.onCreate()"); + } + + private final void onCreateInternal(Bundle savedInstanceState) { if (DocumentModeAssassin.getInstance().isMigrationNecessary()) { super.onCreate(null);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/MostVisitedItem.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/MostVisitedItem.java index 2cb6ca9..0207bc2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/MostVisitedItem.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/MostVisitedItem.java
@@ -53,6 +53,7 @@ private boolean mOfflineAvailable; private int mIndex; private int mTileType; + private int mSource; private View mView; /** @@ -66,9 +67,10 @@ * visited item. Empty otherwise. * @param offlineAvailable Whether there is an offline copy of the URL available. * @param index The index of this item in the list of most visited items. + * @param source The {@link MostVisitedSource} that generated this item. */ public MostVisitedItem(MostVisitedItemManager manager, String title, String url, - String whitelistIconPath, boolean offlineAvailable, int index) { + String whitelistIconPath, boolean offlineAvailable, int index, int source) { mManager = manager; mTitle = title; mUrl = url; @@ -76,6 +78,7 @@ mOfflineAvailable = offlineAvailable; mIndex = index; mTileType = MostVisitedTileType.NONE; + mSource = source; } /** @@ -154,6 +157,14 @@ mTileType = type; } + /** + * @return The source of this item. Used for metrics tracking. Valid values are listed in + * {@link MostVisitedSource}. + */ + public int getSource() { + return mSource; + } + @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { mManager.onCreateContextMenu(menu, this);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java index 7055300b..ba6e1ce9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -236,7 +236,8 @@ item.getUrl(), NewTabPageUma.RAPPOR_ACTION_VISITED_SUGGESTED_TILE); RecordHistogram.recordMediumTimesHistogram("NewTabPage.MostVisitedTime", System.nanoTime() - mLastShownTimeNs, TimeUnit.NANOSECONDS); - mMostVisitedSites.recordOpenedMostVisitedItem(item.getIndex(), item.getTileType()); + mMostVisitedSites.recordOpenedMostVisitedItem( + item.getIndex(), item.getTileType(), item.getSource()); } @Override @@ -502,10 +503,14 @@ if (!mTab.isHidden()) recordNTPShown(); int tileTypes[] = new int[items.length]; + int sources[] = new int[items.length]; + for (int i = 0; i < items.length; i++) { tileTypes[i] = items[i].getTileType(); + sources[i] = items[i].getSource(); } - mMostVisitedSites.recordTileTypeMetrics(tileTypes); + + mMostVisitedSites.recordTileTypeMetrics(tileTypes, sources); if (isNtpOfflinePagesEnabled()) { final int maxNumTiles = 12;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java index 4ddbb0c9..f4c7b76b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -815,8 +815,8 @@ // MostVisitedURLsObserver implementation @Override - public void onMostVisitedURLsAvailable( - final String[] titles, final String[] urls, final String[] whitelistIconPaths) { + public void onMostVisitedURLsAvailable(final String[] titles, final String[] urls, + final String[] whitelistIconPaths, final int[] sources) { Set<String> urlSet = new HashSet<>(Arrays.asList(urls)); // TODO(https://crbug.com/607573): We should show offline-available content in a nonblocking @@ -825,13 +825,13 @@ mManager.getUrlsAvailableOffline(urlSet, new Callback<Set<String>>() { @Override public void onResult(Set<String> offlineUrls) { - onOfflineUrlsAvailable(titles, urls, whitelistIconPaths, offlineUrls); + onOfflineUrlsAvailable(titles, urls, whitelistIconPaths, offlineUrls, sources); } }); } private void onOfflineUrlsAvailable(final String[] titles, final String[] urls, - final String[] whitelistIconPaths, final Set<String> offlineUrls) { + final String[] whitelistIconPaths, final Set<String> offlineUrls, final int[] sources) { mMostVisitedLayout.removeAllViews(); MostVisitedItem[] oldItems = mMostVisitedItems; @@ -846,6 +846,8 @@ final String url = urls[i]; final String title = titles[i]; final String whitelistIconPath = whitelistIconPaths[i]; + final int source = sources[i]; + boolean offlineAvailable = offlineUrls.contains(url); // Look for an existing item to reuse. @@ -865,8 +867,8 @@ // If nothing can be reused, create a new item. if (item == null) { - item = new MostVisitedItem( - mManager, title, url, whitelistIconPath, offlineAvailable, i); + item = new MostVisitedItem(mManager, title, url, whitelistIconPath, + offlineAvailable, i, source); View view = mMostVisitedDesign.createMostVisitedItemView(inflater, item, isInitialLoad); item.initView(view);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java index 3432348..4f00122 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
@@ -152,7 +152,7 @@ public boolean showMenuButtonInOmnibox() { // When we show tab switching button, we prefer to show menu right to the tab switcher // button. - return !FeatureUtilities.isTabSwitchingEnabled(getContext()); + return FeatureUtilities.isDocumentMode(getContext()); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillAddress.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillAddress.java index 599ce7b3..5e390249 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillAddress.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillAddress.java
@@ -32,7 +32,6 @@ @Nullable private static Pattern sRegionCodePattern; private AutofillProfile mProfile; - private boolean mIsComplete; @Nullable private Pattern mLanguageScriptCodePattern; /** @@ -46,11 +45,6 @@ mIsComplete = isComplete; } - /** @return Whether the data is complete and can be sent to the merchant as-is. */ - public boolean isComplete() { - return mIsComplete; - } - /** @return The autofill profile where this address data lives. */ public AutofillProfile getProfile() { return mProfile;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillContact.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillContact.java index 6c6c220f3..05447b4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillContact.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AutofillContact.java
@@ -16,7 +16,6 @@ */ public class AutofillContact extends PaymentOption { private final AutofillProfile mProfile; - private boolean mIsComplete; @Nullable private String mPayerPhone; @Nullable private String mPayerEmail; @@ -47,11 +46,6 @@ return mPayerPhone; } - /** @return Whether the data is complete and can be sent to the merchant as-is. */ - public boolean isComplete() { - return mIsComplete; - } - /** @return The autofill profile where this contact data lives. */ public AutofillProfile getProfile() { return mProfile;
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 360ab4a..efedc92 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
@@ -15,6 +15,7 @@ import org.chromium.chrome.browser.autofill.PersonalDataManager; import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; import org.chromium.chrome.browser.favicon.FaviconHelper; +import org.chromium.chrome.browser.payments.ui.Completable; import org.chromium.chrome.browser.payments.ui.LineItem; import org.chromium.chrome.browser.payments.ui.PaymentInformation; import org.chromium.chrome.browser.payments.ui.PaymentOption; @@ -45,6 +46,8 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -75,6 +78,8 @@ private static final String TAG = "cr_PaymentRequest"; + private static final int SUGGESTIONS_LIMIT = 4; + private static PaymentRequestServiceObserverForTest sObserverForTest; private final Handler mHandler = new Handler(); @@ -208,6 +213,20 @@ if (!parseAndValidateDetailsOrDisconnectFromClient(details)) return; + // Create a comparator to sort the suggestions by completeness. + Comparator<Completable> completenessComparator = new Comparator<Completable>() { + @Override + public int compare(Completable a, Completable b) { + if (a.isComplete() == b.isComplete()) { + return 0; + } else if (a.isComplete()) { + return -1; + } else { + return 1; + } + } + }; + // If the merchant requests shipping and does not provide a selected shipping option, then // the merchant needs the shipping address to calculate the shipping price and availability. boolean requestShipping = options != null && options.requestShipping; @@ -225,7 +244,6 @@ if (requestShipping) { mAddressEditor = new AddressEditor(); List<AutofillAddress> addresses = new ArrayList<>(); - int firstCompleteAddressIndex = SectionInformation.NO_SELECTION; for (int i = 0; i < profiles.size(); i++) { AutofillProfile profile = profiles.get(i); @@ -233,13 +251,22 @@ boolean isComplete = mAddressEditor.isProfileComplete(profile); addresses.add(new AutofillAddress(profile, isComplete)); - if (isComplete && firstCompleteAddressIndex == SectionInformation.NO_SELECTION - && !mMerchantNeedsShippingAddress) { - firstCompleteAddressIndex = i; - } } - // The shipping address section automatically selects the first complete entry. + // Suggest complete addresses first. + Collections.sort(addresses, completenessComparator); + + // Limit the number of suggestions. + addresses = addresses.subList(0, Math.min(addresses.size(), SUGGESTIONS_LIMIT)); + + // Automatically select the first address if one is complete and if the merchant does + // not require a shipping address to calculate shipping costs. + int firstCompleteAddressIndex = SectionInformation.NO_SELECTION; + if (!mMerchantNeedsShippingAddress && !addresses.isEmpty() + && addresses.get(0).isComplete()) { + firstCompleteAddressIndex = 0; + } + mShippingAddressesSection = new SectionInformation(PaymentRequestUI.TYPE_SHIPPING_ADDRESSES, firstCompleteAddressIndex, addresses); @@ -249,7 +276,6 @@ Set<String> uniqueContactInfos = new HashSet<>(); mContactEditor = new ContactEditor(requestPayerPhone, requestPayerEmail); List<AutofillContact> contacts = new ArrayList<>(); - int firstCompleteContactIndex = SectionInformation.NO_SELECTION; for (int i = 0; i < profiles.size(); i++) { AutofillProfile profile = profiles.get(i); @@ -270,15 +296,22 @@ boolean isComplete = mContactEditor.isContactInformationComplete(phone, email); contacts.add(new AutofillContact(profile, phone, email, isComplete)); - if (isComplete - && firstCompleteContactIndex == SectionInformation.NO_SELECTION) { - firstCompleteContactIndex = i; - } } } } - // The contact section automatically selects the first complete entry. + // Suggest complete contact infos first. + Collections.sort(contacts, completenessComparator); + + // Limit the number of suggestions. + contacts = contacts.subList(0, Math.min(contacts.size(), SUGGESTIONS_LIMIT)); + + // Automatically select the first address if it is complete. + int firstCompleteContactIndex = SectionInformation.NO_SELECTION; + if (!contacts.isEmpty() && contacts.get(0).isComplete()) { + firstCompleteContactIndex = 0; + } + mContactSection = new SectionInformation( PaymentRequestUI.TYPE_CONTACT_DETAILS, firstCompleteContactIndex, contacts); } @@ -692,13 +725,14 @@ } @Override - public void onPayClicked(PaymentOption selectedShippingAddress, + public boolean onPayClicked(PaymentOption selectedShippingAddress, PaymentOption selectedShippingOption, PaymentOption selectedPaymentMethod) { assert selectedPaymentMethod instanceof PaymentInstrument; PaymentInstrument instrument = (PaymentInstrument) selectedPaymentMethod; mPaymentAppRunning = true; instrument.getDetails(mMerchantName, mOrigin, mRawTotal, mRawLineItems, mMethodData.get(instrument.getMethodName()), this); + return !(instrument instanceof AutofillPaymentInstrument); } @Override @@ -816,6 +850,7 @@ } } + mUI.showProcessingMessage(); mClient.onPaymentResponse(response); } @@ -824,8 +859,8 @@ */ @Override public void onInstrumentDetailsError() { - disconnectFromClientWithDebugMessage("Failed to retrieve payment instrument details"); - closeUI(false); + mUI.onPayButtonProcessingCancelled(); + mPaymentAppRunning = false; } private void disconnectFromClientWithDebugMessage(String debugMessage) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/Completable.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/Completable.java new file mode 100644 index 0000000..4804314 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/Completable.java
@@ -0,0 +1,14 @@ +// 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. + +package org.chromium.chrome.browser.payments.ui; + +/** + * The interface for types that may be complete, i.e., can be sent to the merchant as-is, without + * being edited by the user first. + */ +public interface Completable { + /** @return Whether the data is complete and can be sent to the merchant as-is */ + boolean isComplete(); +} \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentOption.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentOption.java index 638df3a..c57bded 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentOption.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentOption.java
@@ -10,10 +10,11 @@ * An option that the user can select, e.g., a shipping option, a shipping address, or a payment * method. */ -public class PaymentOption { +public class PaymentOption implements Completable { /** The placeholder value that indicates the absence of an icon for this option. */ public static final int NO_ICON = 0; + protected boolean mIsComplete; private final String mId; private final int mIcon; @Nullable private String mLabel; @@ -35,6 +36,11 @@ mIcon = icon; } + @Override + public boolean isComplete() { + return mIsComplete; + } + /** * The non-human readable identifier for this option. For example, "standard_shipping" or the * GUID of an autofill card.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java index 4c506ba..11a09177 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java
@@ -25,10 +25,12 @@ import android.widget.TextView; import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.base.VisibleForTesting; import org.chromium.chrome.R; import org.chromium.chrome.browser.widget.TintedDrawable; import java.util.ArrayList; +import java.util.List; import javax.annotation.Nullable; @@ -524,6 +526,8 @@ private static final int INVALID_OPTION_INDEX = -1; + private final List<TextView> mLabelsForTest = new ArrayList<>(); + /** * Displays a row representing either a selectable option or some flavor text. * @@ -577,7 +581,7 @@ } /** Set the button identifier for the option. */ - public void setId(int id) { + public void setButtonId(int id) { mButton.setId(id); } @@ -864,6 +868,7 @@ private void updateOptionList(SectionInformation information, PaymentOption selectedItem) { mOptionLayout.removeAllViews(); mOptionRows.clear(); + mLabelsForTest.clear(); // Show any additional text requested by the layout. if (!TextUtils.isEmpty(mDelegate.getAdditionalText(this))) { @@ -884,13 +889,18 @@ if (firstOptionIndex == INVALID_OPTION_INDEX) firstOptionIndex = currentRow; PaymentOption item = information.getItem(i); - mOptionRows.add(new OptionRow(mOptionLayout, currentRow, - OptionRow.OPTION_ROW_TYPE_OPTION, item, item == selectedItem)); + OptionRow currentOptionRow = new OptionRow(mOptionLayout, currentRow, + OptionRow.OPTION_ROW_TYPE_OPTION, item, item == selectedItem); + mOptionRows.add(currentOptionRow); + + // For testing, keep the labels in a list for easy access. + mLabelsForTest.add(currentOptionRow.mLabel); } + // TODO(crbug.com/627186): Find another way to give access to this resource in tests. // For testing. if (firstOptionIndex != INVALID_OPTION_INDEX) { - mOptionRows.get(firstOptionIndex).setId(R.id.payments_first_radio_button); + mOptionRows.get(firstOptionIndex).setButtonId(R.id.payments_first_radio_button); } // If the user is allowed to add new options, show the button for it. @@ -898,7 +908,7 @@ OptionRow addRow = new OptionRow(mOptionLayout, mOptionLayout.getChildCount(), OptionRow.OPTION_ROW_TYPE_ADD, null, false); addRow.setLabel(information.getAddStringId()); - addRow.setId(R.id.payments_add_option_button); + addRow.setButtonId(R.id.payments_add_option_button); mOptionRows.add(addRow); } } @@ -907,6 +917,21 @@ if (TextUtils.isEmpty(item.getSublabel())) return item.getLabel(); return new StringBuilder(item.getLabel()).append("\n").append(item.getSublabel()); } + + /** + * Returns the label at the specified |labelIndex|. Returns null if there is no label at + * that index. + */ + @VisibleForTesting + public TextView getOptionLabelsForTest(int labelIndex) { + return mLabelsForTest.get(labelIndex); + } + + /** Returns the number of option labels. */ + @VisibleForTesting + public int getNumberOfOptionLabelsForTest() { + return mLabelsForTest.size(); + } } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java index 35bf3cd..6d5606a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
@@ -137,10 +137,10 @@ @DataType int optionType, Callback<PaymentInformation> checkedCallback); /** - * Called when the user clicks on the “Pay” button. At this point, the UI is disabled and is - * showing a spinner. + * Called when the user clicks on the “Pay” button. If this method returns true, the UI is + * disabled and is showing a spinner. Otherwise, the UI is hidden. */ - void onPayClicked(PaymentOption selectedShippingAddress, + boolean onPayClicked(PaymentOption selectedShippingAddress, PaymentOption selectedShippingOption, PaymentOption selectedPaymentMethod); /** @@ -248,6 +248,7 @@ private boolean mIsProcessingPayClicked; private boolean mIsClientClosing; private boolean mIsClientCheckingSelection; + private boolean mIsShowingSpinner; private ShoppingCart mShoppingCart; private SectionInformation mPaymentMethodSectionInformation; @@ -674,26 +675,68 @@ } private void processPayButton() { + assert !mIsShowingSpinner; mIsProcessingPayClicked = true; - mRequestView.removeView(mPaymentContainer); - mRequestView.removeView(mButtonBar); - mRequestView.addView(mSpinnyLayout); - - // Turn the bottom sheet back into a collapsed bottom sheet showing only the spinner. - // TODO(dfalcantara): Animate this: https://crbug.com/621955 - FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mRequestView.getLayoutParams(); - params.width = LayoutParams.MATCH_PARENT; - params.height = LayoutParams.WRAP_CONTENT; - params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; - mRequestView.requestLayout(); - - mClient.onPayClicked( + boolean shouldShowSpinner = mClient.onPayClicked( mShippingAddressSectionInformation == null ? null : mShippingAddressSectionInformation.getSelectedItem(), mShippingOptionsSectionInformation == null ? null : mShippingOptionsSectionInformation.getSelectedItem(), mPaymentMethodSectionInformation.getSelectedItem()); + + if (shouldShowSpinner) { + changeSpinnerVisibility(true); + } else { + mDialog.hide(); + } + } + + /** + * Called when user cancelled out of the UI that was shown after they clicked [PAY] button. + */ + public void onPayButtonProcessingCancelled() { + assert mIsProcessingPayClicked; + mIsProcessingPayClicked = false; + changeSpinnerVisibility(false); + mDialog.show(); + updatePayButtonEnabled(); + } + + /** + * Called when the user has sent the payment information to the website, which is now processing + * the payment. + */ + public void showProcessingMessage() { + assert mIsProcessingPayClicked; + changeSpinnerVisibility(true); + mDialog.show(); + } + + private void changeSpinnerVisibility(boolean showSpinner) { + if (mIsShowingSpinner == showSpinner) return; + mIsShowingSpinner = showSpinner; + + if (showSpinner) { + mRequestView.removeView(mPaymentContainer); + mRequestView.removeView(mButtonBar); + mRequestView.addView(mSpinnyLayout); + + // Turn the bottom sheet back into a collapsed bottom sheet showing only the spinner. + // TODO(dfalcantara): Animate this: https://crbug.com/621955 + FrameLayout.LayoutParams params = + (FrameLayout.LayoutParams) mRequestView.getLayoutParams(); + params.width = LayoutParams.MATCH_PARENT; + params.height = LayoutParams.WRAP_CONTENT; + params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; + mRequestView.requestLayout(); + } else { + mRequestView.removeView(mSpinnyLayout); + mRequestView.addView(mPaymentContainer); + mRequestView.addView(mButtonBar); + + if (mIsShowingEditDialog) expand(mSelectedSection); + } } private void updatePayButtonEnabled() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/profiles/MostVisitedSites.java b/chrome/android/java/src/org/chromium/chrome/browser/profiles/MostVisitedSites.java index c60da0ae..8683509 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/profiles/MostVisitedSites.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/profiles/MostVisitedSites.java
@@ -27,8 +27,8 @@ * visited URLs). */ @CalledByNative("MostVisitedURLsObserver") - public void onMostVisitedURLsAvailable( - String[] titles, String[] urls, String[] whitelistIconPaths); + public void onMostVisitedURLsAvailable(String[] titles, String[] urls, + String[] whitelistIconPaths, int[] sources); /** * This is called when the list of popular URLs is initially available or updated. @@ -72,11 +72,11 @@ public void setMostVisitedURLsObserver(final MostVisitedURLsObserver observer, int numSites) { MostVisitedURLsObserver wrappedObserver = new MostVisitedURLsObserver() { @Override - public void onMostVisitedURLsAvailable( - String[] titles, String[] urls, String[] whitelistIconPaths) { + public void onMostVisitedURLsAvailable(String[] titles, String[] urls, + String[] whitelistIconPaths, int[] sources) { // Don't notify observer if we've already been destroyed. if (mNativeMostVisitedSitesBridge != 0) { - observer.onMostVisitedURLsAvailable(titles, urls, whitelistIconPaths); + observer.onMostVisitedURLsAvailable(titles, urls, whitelistIconPaths, sources); } } @Override @@ -111,8 +111,8 @@ * @param tileTypes An array of values from MostVisitedTileType indicating the type of each * tile that's currently showing. */ - public void recordTileTypeMetrics(int[] tileTypes) { - nativeRecordTileTypeMetrics(mNativeMostVisitedSitesBridge, tileTypes); + public void recordTileTypeMetrics(int[] tileTypes, int[] sources) { + nativeRecordTileTypeMetrics(mNativeMostVisitedSitesBridge, tileTypes, sources); } /** @@ -120,8 +120,8 @@ * @param index The index of the item that was opened. * @param tileType The visual type of the item. Valid values are listed in MostVisitedTileType. */ - public void recordOpenedMostVisitedItem(int index, int tileType) { - nativeRecordOpenedMostVisitedItem(mNativeMostVisitedSitesBridge, index, tileType); + public void recordOpenedMostVisitedItem(int index, int tileType, int source) { + nativeRecordOpenedMostVisitedItem(mNativeMostVisitedSitesBridge, index, tileType, source); } private native long nativeInit(Profile profile); @@ -131,9 +131,8 @@ private native void nativeAddOrRemoveBlacklistedUrl( long nativeMostVisitedSitesBridge, String url, boolean addUrl); - private native void nativeRecordTileTypeMetrics( - long nativeMostVisitedSitesBridge, int[] tileTypes); + private native void nativeRecordTileTypeMetrics(long nativeMostVisitedSitesBridge, + int[] tileTypes, int[] sources); private native void nativeRecordOpenedMostVisitedItem( - long nativeMostVisitedSitesBridge, int index, int tileType); - + long nativeMostVisitedSitesBridge, int index, int tileType, int source); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachine.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachine.java index 7a05387..248f4ea 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachine.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachine.java
@@ -65,7 +65,7 @@ private final String mOldAccountName; private final String mNewAccountName; private final boolean mCurrentlyManaged; - private final Promise<Boolean> mNewAccountManaged = new Promise<Boolean>(); + private final Promise<Boolean> mNewAccountManaged = new Promise<>(); private final FragmentManager mFragmentManager; private final Context mContext; private final ImportSyncType mImportSyncType; @@ -78,6 +78,9 @@ public static void run(String oldAccountName, String newAccountName, ImportSyncType importSyncType, FragmentManager fragmentManager, Context context, ConfirmImportSyncDataDialog.Listener callback) { + // Includes implicit not-null assertion. + assert !newAccountName.equals("") : "New account name must be provided."; + ConfirmSyncDataStateMachine stateMachine = new ConfirmSyncDataStateMachine(oldAccountName, newAccountName, importSyncType, fragmentManager, context, callback); stateMachine.progress(); @@ -110,7 +113,7 @@ case BEFORE_OLD_ACCOUNT_DIALOG: mState = BEFORE_NEW_ACCOUNT_DIALOG; - if (TextUtils.isEmpty(mOldAccountName) || mOldAccountName == mNewAccountName) { + if (TextUtils.isEmpty(mOldAccountName) || mNewAccountName.equals(mOldAccountName)) { // If there is no old account or the user is just logging back into whatever // they were previously logged in as, progress past the old account checks. progress();
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 b168c93..414dcbecd 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
@@ -180,9 +180,6 @@ /** InfoBar container to show InfoBars for this tab. */ private InfoBarContainer mInfoBarContainer; - /** Manages app banners shown for this tab. */ - private AppBannerManager mAppBannerManager; - /** Controls overscroll pull-to-refresh behavior for this tab. */ private SwipeRefreshHandler mSwipeRefreshHandler; @@ -1435,11 +1432,6 @@ RevenueStats.getInstance().tabCreated(this); - if (AppBannerManager.isEnabled()) { - mAppBannerManager = mDelegateFactory.createAppBannerManager(this); - if (mAppBannerManager != null) addObserver(mAppBannerManager); - } - mTopControlsVisibilityDelegate = mDelegateFactory.createTopControlsVisibilityDelegate(this); @@ -1471,6 +1463,8 @@ if (!creatingWebContents && webContents.isLoadingToDifferentDocument()) { didStartPageLoad(webContents.getUrl(), false); } + + getAppBannerManager().setIsEnabledForTab(mDelegateFactory.canShowAppBanners(this)); } finally { if (mTimestampMillis == INVALID_TIMESTAMP) { mTimestampMillis = System.currentTimeMillis(); @@ -1561,7 +1555,7 @@ mWebContentsDelegate, mDelegateFactory.createContextMenuPopulator(this)); mTopControlsVisibilityDelegate = mDelegateFactory.createTopControlsVisibilityDelegate(this); setInterceptNavigationDelegate(mDelegateFactory.createInterceptNavigationDelegate(this)); - mAppBannerManager = mDelegateFactory.createAppBannerManager(this); + getAppBannerManager().setIsEnabledForTab(mDelegateFactory.canShowAppBanners(this)); // Reload the NativePage (if any), since the old NativePage has a reference to the old // activity. @@ -2031,13 +2025,6 @@ mInfoBarContainer = null; } - // Destroy the AppBannerManager after the InfoBarContainer because it monitors for infobar - // removals. - if (mAppBannerManager != null) { - mAppBannerManager.destroy(); - mAppBannerManager = null; - } - mPreviousFullscreenTopControlsOffsetY = Float.NaN; mPreviousFullscreenContentOffsetY = Float.NaN; @@ -2528,13 +2515,6 @@ } } - /** Requests the app banner. This method is called from the DevTools. */ - protected boolean requestAppBanner() { - if (mAppBannerManager == null) return false; - mAppBannerManager.requestAppBanner(); - return true; - } - @CalledByNative private void clearNativePtr() { assert mNativeTabAndroid != 0; @@ -3003,9 +2983,8 @@ /** * @return the AppBannerManager. */ - @VisibleForTesting - public AppBannerManager getAppBannerManagerForTesting() { - return mAppBannerManager; + public AppBannerManager getAppBannerManager() { + return AppBannerManager.getAppBannerManagerForWebContents(getWebContents()); } @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabDelegateFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabDelegateFactory.java index ac731f2..25850127 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabDelegateFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabDelegateFactory.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.tab; -import org.chromium.chrome.browser.banners.AppBannerManager; import org.chromium.chrome.browser.contextmenu.ChromeContextMenuPopulator; import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator; import org.chromium.components.navigation_interception.InterceptNavigationDelegate; @@ -43,12 +42,12 @@ } /** - * Creates the {@link AppBannerManager} the tab will be initialized with. + * Return true if app banners are to be permitted in this tab. * @param tab The associated {@link Tab}. - * @return {@link AppBannerManager} to be used for the given tab. May be null. + * @return true if app banners are permitted, and false otherwise. */ - public AppBannerManager createAppBannerManager(Tab tab) { - return new AppBannerManager(tab, tab.getApplicationContext()); + public boolean canShowAppBanners(Tab tab) { + return true; } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java index d485bfd..1193612 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java
@@ -343,11 +343,6 @@ return success; } - @CalledByNative - private boolean requestAppBanner() { - return mTab.requestAppBanner(); - } - @Override public void activateContents() { boolean activityIsDestroyed = false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java index 9a8bf23..7172413 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
@@ -341,20 +341,14 @@ for (Tab tab : mTabsToSave) { int id = tab.getId(); boolean incognito = tab.isIncognito(); - FileOutputStream stream = null; try { TabState state = tab.getState(); if (state != null) { - stream = openTabStateOutputStream(id, incognito); - TabState.saveState(stream, state, incognito); + TabState.saveState(getTabStateFile(id, incognito), state, incognito); } - } catch (IOException e) { - Log.w(TAG, "Error while saving tabs state; will attempt to continue...", e); } catch (OutOfMemoryError e) { Log.w(TAG, "Out of memory error while attempting to save tab state. Erasing."); deleteTabState(id, incognito); - } finally { - StreamUtil.closeQuietly(stream); } } mTabsToSave.clear();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersister.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersister.java index 08c8a0a6..28bfe9fb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersister.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersister.java
@@ -6,13 +6,9 @@ import android.util.Log; -import org.chromium.base.StreamUtil; import org.chromium.chrome.browser.TabState; import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; /** * Interacts with the file system to persist Tab and TabModel data. @@ -43,20 +39,12 @@ public boolean saveTabState(int tabId, boolean encrypted, TabState state) { if (state == null) return false; - FileOutputStream stream = null; try { - stream = openTabStateOutputStream(tabId, encrypted); - TabState.saveState(stream, state, encrypted); + TabState.saveState(getTabStateFile(tabId, encrypted), state, encrypted); return true; - } catch (FileNotFoundException exception) { - Log.w(TAG, "FileNotFoundException while attempt to TabState."); - } catch (IOException exception) { - Log.w(TAG, "IO Exception while attempting to save tab state."); } catch (OutOfMemoryError e) { Log.w(TAG, "Out of memory error while attempting to save tab state. Erasing."); deleteTabState(tabId, encrypted); - } finally { - StreamUtil.closeQuietly(stream); } return false; @@ -70,9 +58,4 @@ public void deleteTabState(int id, boolean encrypted) { TabState.deleteTabState(getStateDirectory(), id, encrypted); } - - protected FileOutputStream openTabStateOutputStream(int id, boolean encrypted) - throws IOException { - return new FileOutputStream(getTabStateFile(id, encrypted)); - } } \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index 5249c4c1..bba0848b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -65,7 +65,6 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; import org.chromium.chrome.browser.toolbar.ActionModeController.ActionBarDelegate; -import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.chrome.browser.widget.findinpage.FindToolbarManager; import org.chromium.chrome.browser.widget.findinpage.FindToolbarObserver; import org.chromium.content_public.browser.LoadUrlParams; @@ -752,12 +751,6 @@ mNativeLibraryReady = true; mToolbar.onNativeLibraryReady(); - if (FeatureUtilities.isTabSwitchingEnabledInDocumentMode(mToolbar.getContext())) { - // We want to give a similar look and feel as Android's overview mode button - // by not updating tab count and keep the button as a rounded square. - mShouldUpdateTabCount = false; - } - final TemplateUrlService templateUrlService = TemplateUrlService.getInstance(); TemplateUrlService.LoadListener mTemplateServiceLoadListener = new TemplateUrlService.LoadListener() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java index 535de6534..c4ce6e7f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
@@ -322,12 +322,9 @@ ApiCompatibilityUtils.setMarginEnd( (MarginLayoutParams) mMenuButtonWrapper.getLayoutParams(), getResources().getDimensionPixelSize(R.dimen.document_toolbar_menu_offset)); - } - - if (FeatureUtilities.isTabSwitchingEnabled(getContext())) { - inflateTabSwitchingResources(); - } else { hideTabSwitchingResources(); + } else { + inflateTabSwitchingResources(); } setWillNotDraw(false); @@ -417,15 +414,7 @@ super.onNativeLibraryReady(); getLocationBar().onNativeLibraryReady(); - if (FeatureUtilities.isTabSwitchingEnabledInDocumentMode(getContext())) { - // We might have hidden some buttons at onFinishInflate() because it was called - // before native library is ready and chrome switch can be correctly read. - // Now recover those buttons. Since we want to show toolbar even before native - // library is ready, and as tab switching is experimental, this is unavoidable. - unhideTabSwitchingResources(); - inflateTabSwitchingResources(); - enableTabSwitchingResources(); - } else if (FeatureUtilities.isDocumentMode(getContext())) { + if (FeatureUtilities.isDocumentMode(getContext())) { removeTabSwitchingResources(); } else { // non-document mode enableTabSwitchingResources();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java index ac6b2e44..dc0b7db 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
@@ -157,30 +157,6 @@ nativeSetIsInMultiWindowMode(isInMultiWindowMode); } - /** - * Check whether tab switching is enabled for the current context. - * Note that this may return false if native library is not yet ready. - * @param context The context - * @return Whether tab switching is enabled for the current context. - */ - public static boolean isTabSwitchingEnabled(Context context) { - return !isDocumentMode(context) || isTabSwitchingEnabledInDocumentModeInternal(); - } - - /** - * Check whether tab switching is enabled in document mode. - * Note that this may return false if native library is not yet ready. - * @return Whether tab switching is enabled in document mode. - */ - public static boolean isTabSwitchingEnabledInDocumentMode(Context context) { - return isDocumentMode(context) && isTabSwitchingEnabledInDocumentModeInternal(); - } - - private static boolean isTabSwitchingEnabledInDocumentModeInternal() { - return CommandLine.getInstance().hasSwitch( - ChromeSwitches.ENABLE_TAB_SWITCHER_IN_DOCUMENT_MODE); - } - private static boolean isHerbDisallowed(Context context) { return isDocumentMode(context) || ChromeVersionInfo.isStableBuild() || ChromeVersionInfo.isBetaBuild() || DeviceFormFactor.isTablet(context);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java index 28547bfb..b369549 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivity.java
@@ -10,7 +10,6 @@ import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.chrome.browser.ChromeApplication; import org.chromium.chrome.browser.ShortcutHelper; -import org.chromium.chrome.browser.banners.AppBannerManager; import org.chromium.chrome.browser.externalnav.ExternalNavigationParams; import org.chromium.chrome.browser.tab.InterceptNavigationDelegateImpl; import org.chromium.chrome.browser.tab.Tab; @@ -103,11 +102,11 @@ } @Override - public AppBannerManager createAppBannerManager(Tab tab) { + public boolean canShowAppBanners(Tab tab) { // Do not show app banners for WebAPKs regardless of the current page URL. // A WebAPK can display a page outside of its WebAPK scope if a page within the // WebAPK scope navigates via JavaScript while the WebAPK is in the background. - return null; + return false; } }; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java index 926cedf4..b4d4733 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -24,7 +24,6 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApplicationStatus; import org.chromium.base.Log; -import org.chromium.base.StreamUtil; import org.chromium.base.VisibleForTesting; import org.chromium.base.metrics.RecordHistogram; import org.chromium.blink_public.platform.WebDisplayMode; @@ -46,9 +45,6 @@ import org.chromium.ui.base.PageTransition; import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; import java.util.concurrent.TimeUnit; /** @@ -176,22 +172,15 @@ String tabFileName = TabState.getTabStateFilename(getActivityTab().getId(), false); File tabFile = new File(activityDirectory, tabFileName); - FileOutputStream foutput = null; // Temporarily allowing disk access while fixing. TODO: http://crbug.com/525781 StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); StrictMode.allowThreadDiskWrites(); try { long time = SystemClock.elapsedRealtime(); - foutput = new FileOutputStream(tabFile); - TabState.saveState(foutput, getActivityTab().getState(), false); + TabState.saveState(tabFile, getActivityTab().getState(), false); RecordHistogram.recordTimesHistogram("Android.StrictMode.WebappSaveState", SystemClock.elapsedRealtime() - time, TimeUnit.MILLISECONDS); - } catch (FileNotFoundException exception) { - Log.e(TAG, "Failed to save out tab state.", exception); - } catch (IOException exception) { - Log.e(TAG, "Failed to save out tab state.", exception); } finally { - StreamUtil.closeQuietly(foutput); StrictMode.setThreadPolicy(oldPolicy); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelWrapper.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelWrapper.java index 0cdc291..2c966fce 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelWrapper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelWrapper.java
@@ -62,6 +62,12 @@ mTabModelSelector.commitAllTabClosures(); mTabModelSelector.selectModel(mIncognito); setStateBasedOnModel(); + + int stackAnnouncementId = mIncognito + ? R.string.accessibility_tab_switcher_incognito_stack_selected + : R.string.accessibility_tab_switcher_standard_stack_selected; + AccessibilityTabModelWrapper.this.announceForAccessibility( + getResources().getString(stackAnnouncementId)); } } }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 87dc7e4..29660543 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -30,7 +30,7 @@ * Action bar items - 32 characters --> -<grit current_release="1" latest_public_release="0"> +<grit current_release="1" latest_public_release="0" output_all_resource_defines="false"> <outputs> <output filename="values-am/android_chrome_strings.xml" lang="am" type="android" /> <output filename="values-ar/android_chrome_strings.xml" lang="ar" type="android" /> @@ -881,15 +881,15 @@ <message name="IDS_DATA_REDUCTION_ENABLED_TOAST" desc="Toast message displayed after the user enables Data Saver from the promo" > Data Saver is on. Manage it in Settings. </message> - <message name="IDS_DATA_REDUCTION_PROMO_INFOBAR_TITLE" desc="Text to be displayed in the data reduction promo infobar title"> + <message name="IDS_DATA_REDUCTION_PROMO_INFOBAR_TITLE" desc="Text to be displayed in the data reduction promo infobar title"> Save up to 60% of your data - </message> - <message name="IDS_DATA_REDUCTION_PROMO_INFOBAR_TEXT" desc="Text to be displayed in the data reduction promo infobar"> + </message> + <message name="IDS_DATA_REDUCTION_PROMO_INFOBAR_TEXT" desc="Text to be displayed in the data reduction promo infobar"> Google servers will optimize the pages you visit, except for HTTPS and Incognito. </message> - <message name="IDS_DATA_REDUCTION_PROMO_INFOBAR_BUTTON" desc="Text to be displayed in the data reduction promo infobar confirm button"> + <message name="IDS_DATA_REDUCTION_PROMO_INFOBAR_BUTTON" desc="Text to be displayed in the data reduction promo infobar confirm button"> Turn on Data Saver - </message> + </message> <!-- About Chrome preferences --> <message name="IDS_PREFS_ABOUT_CHROME" desc="Title for the About Chrome page. [CHAR-LIMIT=32]"> @@ -1302,6 +1302,12 @@ <message name="IDS_ACCESSIBILITY_TAB_SWITCHER_INCOGNITO_STACK" desc="Content description for the incognito stack selection 'button'."> Incognito tabs </message> + <message name="IDS_ACCESSIBILITY_TAB_SWITCHER_STANDARD_STACK_SELECTED" desc="Announcement when the standard tab stack is selected."> + Switched to standard tabs + </message> + <message name="IDS_ACCESSIBILITY_TAB_SWITCHER_INCOGNITO_STACK_SELECTED" desc="Announcement when the incognito tab stack is selected."> + Switched to incognito tabs + </message> <message name="IDS_ACCESSIBILITY_TAB_SWITCHER_UNDO_TAB_CLOSED" desc="Content description for the undo tab closed 'button."> Reopen closed tab </message>
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index eb85ea3..f6fdc37 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -597,6 +597,7 @@ "java/src/org/chromium/chrome/browser/payments/PaymentInstrument.java", "java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java", "java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java", + "java/src/org/chromium/chrome/browser/payments/ui/Completable.java", "java/src/org/chromium/chrome/browser/payments/ui/EditorDialogToolbar.java", "java/src/org/chromium/chrome/browser/payments/ui/EditorDropdownField.java", "java/src/org/chromium/chrome/browser/payments/ui/EditorFieldModel.java", @@ -1167,8 +1168,11 @@ "javatests/src/org/chromium/chrome/browser/policy/CombinedPolicyProviderTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestAbortTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestContactDetailsTest.java", + "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMultipleContactDetailsTest.java", + "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingMultipleAddressesTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingSingleAddressTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestEmailTest.java", + "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFreeShippingTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteContactDetailsTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestIncompleteEmailTest.java", @@ -1302,6 +1306,7 @@ "junit/src/org/chromium/chrome/browser/payments/CurrencyStringFormatterTest.java", "junit/src/org/chromium/chrome/browser/snackbar/SnackbarCollectionUnitTest.java", "junit/src/org/chromium/chrome/browser/superviseduser/SupervisedUserContentProviderUnitTest.java", + "junit/src/org/chromium/chrome/browser/tabstate/TabStateUnitTest.java", "junit/src/org/chromium/chrome/browser/util/NonThreadSafeTest.java", "junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java", "junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java",
diff --git a/chrome/android/javatests/AndroidManifest.xml b/chrome/android/javatests/AndroidManifest.xml index f073bef..25a3a1bf 100644 --- a/chrome/android/javatests/AndroidManifest.xml +++ b/chrome/android/javatests/AndroidManifest.xml
@@ -59,6 +59,10 @@ </action> </intent-filter> </receiver> + + <service android:name="org.chromium.chrome.test.webapk.TestWebApkServiceImplWrapper" + android:exported="true"> + </service> </application> <instrumentation android:name="org.chromium.chrome.test.ChromeInstrumentationTestRunner"
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTestHelper.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTestHelper.java index 173fb56..7259a8e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTestHelper.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillTestHelper.java
@@ -151,7 +151,8 @@ } /** - * Sets the use |count| and use |date| of the test profile associated with the |guid|. + * Sets the use |count| and use |date| of the test profile associated with the |guid|. This + * update is not saved to disk. * @param guid The GUID of the profile to modify. * @param count The use count to assign to the profile. It should be non-negative. * @param date The use date to assign to the profile. It represents an absolute point in @@ -159,7 +160,7 @@ * epoch. For more details see the comment header in time.h. It should always be a * positive number. */ - void setProfileUseStatsForTesting(final String guid, final int count, final long date) + public void setProfileUseStatsForTesting(final String guid, final int count, final long date) throws InterruptedException { ThreadUtils.runOnUiThreadBlocking(new Runnable() { @Override @@ -167,11 +168,11 @@ PersonalDataManager.getInstance().setProfileUseStatsForTesting(guid, count, date); } }); - waitForDataChanged(); } /** - * Sets the use |count| and use |date| of the test credit card associated with the |guid|. + * Sets the use |count| and use |date| of the test credit card associated with the |guid|. This + * update is not saved to disk. * @param guid The GUID of the credit card to modify. * @param count The use count to assign to the credit card. It should be non-negative. * @param date The use date to assign to the credit card. It represents an absolute point in @@ -188,7 +189,6 @@ guid, count, date); } }); - waitForDataChanged(); } private void registerDataObserver() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java index 5fd2cca..16bd77d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -172,7 +172,7 @@ @Override protected void setUp() throws Exception { mPackageManager = new TestPackageManager(); - AppBannerManager.setIsEnabledForTesting(true); + AppBannerManager.setIsSupported(true); AppBannerInfoBarDelegateAndroid.setPackageManagerForTesting(mPackageManager); ShortcutHelper.setDelegateForTests(new ShortcutHelper.Delegate() { @Override @@ -223,8 +223,7 @@ CriteriaHelper.pollUiThread(new Criteria() { @Override public boolean isSatisfied() { - AppBannerManager manager = - getActivity().getActivityTab().getAppBannerManagerForTesting(); + AppBannerManager manager = getActivity().getActivityTab().getAppBannerManager(); return mDetailsDelegate.mNumRetrieved == numExpected && !manager.isFetcherActiveForTesting(); } @@ -313,8 +312,7 @@ CriteriaHelper.pollUiThread(new Criteria() { @Override public boolean isSatisfied() { - AppBannerManager manager = - getActivity().getActivityTab().getAppBannerManagerForTesting(); + AppBannerManager manager = getActivity().getActivityTab().getAppBannerManager(); return !manager.isFetcherActiveForTesting(); } }); @@ -326,8 +324,7 @@ CriteriaHelper.pollUiThread(new Criteria() { @Override public boolean isSatisfied() { - AppBannerManager manager = - getActivity().getActivityTab().getAppBannerManagerForTesting(); + AppBannerManager manager = getActivity().getActivityTab().getAppBannerManager(); return !manager.isFetcherActiveForTesting(); } }); @@ -486,8 +483,7 @@ CriteriaHelper.pollUiThread(new Criteria() { @Override public boolean isSatisfied() { - AppBannerManager manager = - getActivity().getActivityTab().getAppBannerManagerForTesting(); + AppBannerManager manager = getActivity().getActivityTab().getAppBannerManager(); return !manager.isFetcherActiveForTesting(); } }); @@ -504,8 +500,7 @@ CriteriaHelper.pollUiThread(new Criteria() { @Override public boolean isSatisfied() { - AppBannerManager manager = - getActivity().getActivityTab().getAppBannerManagerForTesting(); + AppBannerManager manager = getActivity().getActivityTab().getAppBannerManager(); return !manager.isFetcherActiveForTesting(); } });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/FakeMostVisitedSites.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/FakeMostVisitedSites.java index 617f727..3b238bc 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/FakeMostVisitedSites.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/FakeMostVisitedSites.java
@@ -19,6 +19,7 @@ private final String[] mMostVisitedTitles; private final String[] mMostVisitedUrls; private final String[] mMostVisitedWhitelistIconPaths; + private final int[] mMostVisitedSources; private final List<String> mBlacklistedUrls = new ArrayList<String>(); @@ -28,12 +29,13 @@ * @param mostVisitedUrls The URLs of the fixed list of most visited sites. */ public FakeMostVisitedSites(Profile p, String[] mostVisitedTitles, String[] mostVisitedUrls, - String[] mostVisitedWhitelistIconPaths) { + String[] mostVisitedWhitelistIconPaths, int[] mostVisitedSources) { super(p); assert mostVisitedTitles.length == mostVisitedUrls.length; mMostVisitedTitles = mostVisitedTitles.clone(); mMostVisitedUrls = mostVisitedUrls.clone(); mMostVisitedWhitelistIconPaths = mostVisitedWhitelistIconPaths.clone(); + mMostVisitedSources = mostVisitedSources.clone(); } @Override @@ -42,7 +44,8 @@ @Override public void run() { observer.onMostVisitedURLsAvailable(mMostVisitedTitles.clone(), - mMostVisitedUrls.clone(), mMostVisitedWhitelistIconPaths.clone()); + mMostVisitedUrls.clone(), mMostVisitedWhitelistIconPaths.clone(), + mMostVisitedSources.clone()); } }); } @@ -65,12 +68,12 @@ } @Override - public void recordTileTypeMetrics(int[] tileTypes) { + public void recordTileTypeMetrics(int[] tileTypes, int[] sources) { // Metrics are stubbed out. } @Override - public void recordOpenedMostVisitedItem(int index, int tileType) { + public void recordOpenedMostVisitedItem(int index, int tileType, int source) { // Metrics are stubbed out. } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java index 3a94395..c9efca6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -50,6 +50,7 @@ private static final String[] FAKE_MOST_VISITED_TITLES = new String[] { "Simple" }; private static final String[] FAKE_MOST_VISITED_WHITELIST_ICON_PATHS = new String[] { "" }; + private static final int[] FAKE_MOST_VISITED_SOURCES = new int[] {MostVisitedSource.TOP_SITES}; private Tab mTab; private NewTabPage mNtp; @@ -86,7 +87,8 @@ // native code. mFakeMostVisitedSites = new FakeMostVisitedSites(mTab.getProfile(), FAKE_MOST_VISITED_TITLES, - mFakeMostVisitedUrls, FAKE_MOST_VISITED_WHITELIST_ICON_PATHS); + mFakeMostVisitedUrls, FAKE_MOST_VISITED_WHITELIST_ICON_PATHS, + FAKE_MOST_VISITED_SOURCES); } }); } catch (Throwable t) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingMultipleAddressesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingMultipleAddressesTest.java new file mode 100644 index 0000000..12f84b7 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestDynamicShippingMultipleAddressesTest.java
@@ -0,0 +1,91 @@ +// 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. + +package org.chromium.chrome.browser.payments; + +import android.test.suitebuilder.annotation.MediumTest; + +import org.chromium.chrome.R; +import org.chromium.chrome.browser.autofill.AutofillTestHelper; +import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; +import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +/** + * A payment integration test for a merchant that requires shipping address to calculate shipping + * and user that has 5 addresses stored in autofill settings. + */ +public class PaymentRequestDynamicShippingMultipleAddressesTest extends PaymentRequestTestBase { + public PaymentRequestDynamicShippingMultipleAddressesTest() { + // This merchant requests the shipping address first before providing any shipping options. + super("payment_request_dynamic_shipping_test.html"); + } + + @Override + public void onMainActivityStarted() + throws InterruptedException, ExecutionException, TimeoutException { + AutofillTestHelper helper = new AutofillTestHelper(); + // Create an incomplete (no phone) profile with the highest frecency score. + String guid1 = helper.setProfile( + new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, + "Bart Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "", + "90210", "", "US", "", "bart@simpson.com", "")); + + // Create an incomplete (no phone) profile with a the second highest frecency score. + String guid2 = helper.setProfile( + new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, + "Homer Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "", + "90210", "", "US", "", "homer@simpson.com", "")); + + // Create a complete profile with a middle frecency score. + String guid3 = helper.setProfile( + new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, + "Lisa Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "", + "90210", "", "US", "555 123-4567", "lisa@simpson.com", "")); + + // Create a complete profile with the second lowest frecency score. + String guid4 = helper.setProfile( + new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, + "Maggie Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "", + "90210", "", "US", "555 123-4567", "maggie@simpson.com", "")); + + // Create an incomplete profile with the lowest frecency score. + String guid5 = helper.setProfile( + new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, + "Marge Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "", + "90210", "", "US", "", "marge@simpson.com", "")); + + // Create a credit card associated witht the fourth profile. + helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe", + "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa, + guid4)); + + // Set the use stats so that profile1 has the highest frecency score, profile2 the second + // highest, profile 3 the second lowest and profile4 the lowest. + helper.setProfileUseStatsForTesting(guid1, 20, 5000); + helper.setProfileUseStatsForTesting(guid2, 15, 5000); + helper.setProfileUseStatsForTesting(guid3, 10, 5000); + helper.setProfileUseStatsForTesting(guid4, 5, 5000); + helper.setProfileUseStatsForTesting(guid5, 1, 1); + } + + /** + * Make sure the address suggestions are in the correct order and that only the top 4 + * suggestions are shown. They should be ordered by frecency and complete addresses should be + * suggested first. + */ + @MediumTest + public void testShippingAddressSuggestionOrdering() + throws InterruptedException, ExecutionException, TimeoutException { + triggerUIAndWait(mReadyForInput); + clickInShippingSummaryAndWait(R.id.payments_section, mReadyForInput); + assertEquals(4, getNumberOfShippingAddressSuggestions()); + assertTrue(getShippingAddressSuggestionLabel(0).contains("Lisa Simpson")); + assertTrue(getShippingAddressSuggestionLabel(1).contains("Maggie Simpson")); + assertTrue(getShippingAddressSuggestionLabel(2).contains("Bart Simpson")); + assertTrue(getShippingAddressSuggestionLabel(3).contains("Homer Simpson")); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java new file mode 100644 index 0000000..2b0a25c --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestFailCompleteTest.java
@@ -0,0 +1,47 @@ +// 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. + +package org.chromium.chrome.browser.payments; + +import android.content.DialogInterface; +import android.test.suitebuilder.annotation.MediumTest; + +import org.chromium.chrome.R; +import org.chromium.chrome.browser.autofill.AutofillTestHelper; +import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; +import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +/** + * A payment integration test for a merchant that always fails to complete the transaction. + */ +public class PaymentRequestFailCompleteTest extends PaymentRequestTestBase { + public PaymentRequestFailCompleteTest() { + super("payment_request_fail_complete_test.html"); + } + + @Override + public void onMainActivityStarted() + throws InterruptedException, ExecutionException, TimeoutException { + AutofillTestHelper helper = new AutofillTestHelper(); + String billingAddressId = helper.setProfile(new AutofillProfile("", "https://example.com", + true, "Jon Doe", "Google", "340 Main St", "CA", "Los Angeles", "", "90291", "", + "US", "310-310-6000", "jon.doe@gmail.com", "en-US")); + helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe", + "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa, + billingAddressId)); + } + + @MediumTest + public void testPay() throws InterruptedException, ExecutionException, TimeoutException { + triggerUIAndWait(mReadyToPay); + clickAndWait(R.id.button_primary, mReadyForUnmaskInput); + setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask); + clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mResultReady); + clickAndWait(R.id.ok_button, mDismissed); + expectResultContains(new String[] {"Transaction failed"}); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMultipleContactDetailsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMultipleContactDetailsTest.java new file mode 100644 index 0000000..366c9b6 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestMultipleContactDetailsTest.java
@@ -0,0 +1,91 @@ +// 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. + +package org.chromium.chrome.browser.payments; + +import android.test.suitebuilder.annotation.MediumTest; + +import org.chromium.chrome.R; +import org.chromium.chrome.browser.autofill.AutofillTestHelper; +import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; +import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +/** + * A payment integration test for a merchant that requests contact details and a user that has + * 5 contact detail options. + */ +public class PaymentRequestMultipleContactDetailsTest extends PaymentRequestTestBase { + public PaymentRequestMultipleContactDetailsTest() { + // The merchant requests both a phone number and an email address. + super("payment_request_contact_details_test.html"); + } + + @Override + public void onMainActivityStarted() + throws InterruptedException, ExecutionException, TimeoutException { + AutofillTestHelper helper = new AutofillTestHelper(); + // Create an incomplete (no phone) profile with the highest frecency score. + String guid1 = helper.setProfile( + new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, + "Bart Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "", + "90210", "", "US", "", "bart@simpson.com", "")); + + // Create an incomplete (no phone) profile with a the second highest frecency score. + String guid2 = helper.setProfile( + new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, + "Homer Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "", + "90210", "", "US", "", "homer@simpson.com", "")); + + // Create a complete profile with a middle frecency score. + String guid3 = helper.setProfile( + new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, + "Lisa Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "", + "90210", "", "US", "555 123-4567", "lisa@simpson.com", "")); + + // Create a complete profile with the second lowest frecency score. + String guid4 = helper.setProfile( + new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, + "Maggie Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "", + "90210", "", "US", "555 123-4567", "maggie@simpson.com", "")); + + // Create an incomplete profile with the lowest frecency score. + String guid5 = helper.setProfile( + new AutofillProfile("" /* guid */, "https://www.example.com" /* origin */, + "Marge Simpson", "Acme Inc.", "123 Main", "California", "Los Angeles", "", + "90210", "", "US", "", "marge@simpson.com", "")); + + // Create a credit card associated with the fourth profile. + helper.setCreditCard(new CreditCard("", "https://example.com", true, true, "Jon Doe", + "4111111111111111", "1111", "12", "2050", "visa", R.drawable.pr_visa, + guid4)); + + // Set the use stats so that profile1 has the highest frecency score, profile2 the second + // highest, profile 3 the third lowest, profile4 the second lowest and profile 5 the lowest. + helper.setProfileUseStatsForTesting(guid1, 20, 5000); + helper.setProfileUseStatsForTesting(guid2, 15, 5000); + helper.setProfileUseStatsForTesting(guid3, 10, 5000); + helper.setProfileUseStatsForTesting(guid4, 5, 5000); + helper.setProfileUseStatsForTesting(guid5, 1, 1); + } + + /** + * Make sure the contact details suggestions are in the correct order and that only the top 4 + * are shown. They should be ordered by frecency and complete contact details should be + * suggested first. + */ + @MediumTest + public void testContactDetailsSuggestionOrdering() + throws InterruptedException, ExecutionException, TimeoutException { + triggerUIAndWait(mReadyToPay); + clickInContactInfoAndWait(R.id.payments_section, mReadyForInput); + assertEquals(4, getNumberOfContactDetailSuggestions()); + assertEquals("555 123-4567\nlisa@simpson.com", getContactDetailsSuggestionLabel(0)); + assertEquals("555 123-4567\nmaggie@simpson.com", getContactDetailsSuggestionLabel(1)); + assertEquals("bart@simpson.com", getContactDetailsSuggestionLabel(2)); + assertEquals("homer@simpson.com", getContactDetailsSuggestionLabel(3)); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java index c7646003..b35c0e7f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestNoShippingTest.java
@@ -62,19 +62,22 @@ } @MediumTest - public void testPayAndCancelDialog() throws InterruptedException, ExecutionException, - TimeoutException { + public void testPay() throws InterruptedException, ExecutionException, TimeoutException { triggerUIAndWait(mReadyToPay); clickAndWait(R.id.button_primary, mReadyForUnmaskInput); - clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_NEGATIVE, mResultReady); - clickAndWait(R.id.ok_button, mDismissed); - expectResultContains(new String[] {"Request cancelled"}); + setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask); + clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed); + expectResultContains(new String[] {"Jon Doe", "4111111111111111", "12", "2050", "visa", + "123"}); } @MediumTest - public void testPay() throws InterruptedException, ExecutionException, TimeoutException { + public void testCancelUnmaskAndRetry() + throws InterruptedException, ExecutionException, TimeoutException { triggerUIAndWait(mReadyToPay); clickAndWait(R.id.button_primary, mReadyForUnmaskInput); + clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_NEGATIVE, mReadyToPay); + clickAndWait(R.id.button_primary, mReadyForUnmaskInput); setTextInCardUnmaskDialogAndWait(R.id.card_unmask_input, "123", mReadyToUnmask); clickCardUnmaskButtonAndWait(DialogInterface.BUTTON_POSITIVE, mDismissed); expectResultContains(new String[] {"Jon Doe", "4111111111111111", "12", "2050", "visa",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java index c4cc7355..2444005c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestBase.java
@@ -18,6 +18,7 @@ import org.chromium.chrome.browser.autofill.CardUnmaskPrompt.CardUnmaskObserverForTest; import org.chromium.chrome.browser.payments.PaymentRequestImpl.PaymentRequestServiceObserverForTest; import org.chromium.chrome.browser.payments.ui.EditorTextField; +import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.OptionSection; import org.chromium.chrome.browser.payments.ui.PaymentRequestUI; import org.chromium.chrome.browser.payments.ui.PaymentRequestUI.PaymentRequestObserverForTest; import org.chromium.chrome.test.ChromeActivityTestCaseBase; @@ -205,6 +206,66 @@ }); } + /** + * Returns the label corresponding to the contact detail suggestion at the specified + * |suggestionIndex|. + */ + protected String getContactDetailsSuggestionLabel(final int suggestionIndex) + throws ExecutionException { + assert (suggestionIndex < getNumberOfContactDetailSuggestions()); + + return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() { + @Override + public String call() { + return ((OptionSection) mUI.getContactDetailsSectionForTest()) + .getOptionLabelsForTest(suggestionIndex).getText().toString(); + } + }); + } + + /** + * Returns the the number of contact detail suggestions, + */ + protected int getNumberOfContactDetailSuggestions() throws ExecutionException { + return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() { + @Override + public Integer call() { + return ((OptionSection) mUI.getContactDetailsSectionForTest()) + .getNumberOfOptionLabelsForTest(); + } + }); + } + + /** + * Returns the label corresponding to the shipping address suggestion at the specified + * |suggestionIndex|. + */ + protected String getShippingAddressSuggestionLabel(final int suggestionIndex) + throws ExecutionException { + assert (suggestionIndex < getNumberOfShippingAddressSuggestions()); + + return ThreadUtils.runOnUiThreadBlocking(new Callable<String>() { + @Override + public String call() { + return ((OptionSection) mUI.getShippingAddressSectionForTest()) + .getOptionLabelsForTest(suggestionIndex).getText().toString(); + } + }); + } + + /** + * Returns the the number of shipping address suggestions, + */ + protected int getNumberOfShippingAddressSuggestions() throws ExecutionException { + return ThreadUtils.runOnUiThreadBlocking(new Callable<Integer>() { + @Override + public Integer call() { + return ((OptionSection) mUI.getShippingAddressSectionForTest()) + .getNumberOfOptionLabelsForTest(); + } + }); + } + /** Selects the spinner value in the editor UI. */ protected void setSpinnerSelectionInEditor(final int selection, CallbackHelper helper) throws InterruptedException, TimeoutException {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabstate/TabStateUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabstate/TabStateUnitTest.java new file mode 100644 index 0000000..062fa28 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabstate/TabStateUnitTest.java
@@ -0,0 +1,107 @@ +// 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. + +package org.chromium.chrome.browser.tabstate; + +import static org.junit.Assert.assertEquals; + +import org.chromium.base.StreamUtil; +import org.chromium.chrome.browser.TabState; +import org.chromium.testing.local.LocalRobolectricTestRunner; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; + +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.channels.FileChannel; + +/** + * Unit tests for TabState. + */ +@RunWith(LocalRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class TabStateUnitTest { + + private static final byte[] CONTENTS_STATE_BYTES = new byte[] {1, 2, 3}; + private static final long TIMESTAMP = 10L; + private static final long SYNC_ID = 3; + private static final int PARENT_ID = 1; + private static final int VERSION = 2; + private static final int THEME_COLOR = 4; + private static final boolean SHOULD_PRESERVE = true; + private static final String OPENER_APP_ID = "test"; + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Test + public void testSaveTabStateWithMemoryMappedContentsState() throws IOException { + File file = createTestTabStateFile(); + TabState state = createTabStateWithMappedByteBuffer(file); + TabState.saveState(file, state, false); + + validateTestTabState(TabState.restoreTabState(file, false)); + } + + private TabState createTabStateWithMappedByteBuffer(File file) throws IOException { + TabState state = new TabState(); + FileInputStream fileInputStream = null; + + try { + fileInputStream = new FileInputStream(file); + state.contentsState = new TabState.WebContentsState(fileInputStream.getChannel().map( + FileChannel.MapMode.READ_ONLY, fileInputStream.getChannel().position(), + file.length())); + state.contentsState.setVersion(VERSION); + state.timestampMillis = TIMESTAMP; + state.parentId = PARENT_ID; + state.syncId = SYNC_ID; + state.themeColor = THEME_COLOR; + state.shouldPreserve = SHOULD_PRESERVE; + state.openerAppId = OPENER_APP_ID; + } finally { + StreamUtil.closeQuietly(fileInputStream); + } + return state; + } + + private void validateTestTabState(TabState state) { + assertEquals(TIMESTAMP, state.timestampMillis); + assertEquals(PARENT_ID, state.parentId); + assertEquals(OPENER_APP_ID, state.openerAppId); + assertEquals(VERSION, state.contentsState.version()); + assertEquals(SYNC_ID, state.syncId); + assertEquals(SHOULD_PRESERVE, state.shouldPreserve); + assertEquals(THEME_COLOR, state.getThemeColor()); + assertEquals(CONTENTS_STATE_BYTES.length, state.contentsState.buffer().remaining()); + + byte[] bytesFromFile = new byte[CONTENTS_STATE_BYTES.length]; + state.contentsState.buffer().get(bytesFromFile); + + for (int i = 0; i < CONTENTS_STATE_BYTES.length; i++) { + assertEquals(bytesFromFile[i], CONTENTS_STATE_BYTES[i]); + } + } + + private File createTestTabStateFile() throws IOException { + File file = temporaryFolder.newFile("tabStateByteBufferTestFile"); + FileOutputStream fileOutputStream = null; + DataOutputStream dataOutputStream = null; + try { + fileOutputStream = new FileOutputStream(file); + dataOutputStream = new DataOutputStream(fileOutputStream); + dataOutputStream.write(CONTENTS_STATE_BYTES); + } finally { + StreamUtil.closeQuietly(fileOutputStream); + StreamUtil.closeQuietly(dataOutputStream); + } + return file; + } +}
diff --git a/chrome/android/webapk/DEPS b/chrome/android/webapk/DEPS index 1a81e27..b870bb1c 100644 --- a/chrome/android/webapk/DEPS +++ b/chrome/android/webapk/DEPS
@@ -3,5 +3,6 @@ include_rules = [ "-base", "-chrome", + "-content", "-testing", ]
diff --git a/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkUtils.java b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkUtils.java index abb3a92..f1a05bc 100644 --- a/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkUtils.java +++ b/chrome/android/webapk/libs/common/src/org/chromium/webapk/lib/common/WebApkUtils.java
@@ -60,6 +60,27 @@ } /** + * Returns the uid for the host browser that was specified when building the WebAPK. + * @param context A context. + * @return The application uid. Returns -1 on an error. + */ + public static int getHostBrowserUid(Context context) { + String hostPackageName = getHostBrowserPackageName(context); + if (hostPackageName == null) { + return -1; + } + try { + PackageManager packageManager = context.getPackageManager(); + ApplicationInfo appInfo = packageManager.getApplicationInfo( + hostPackageName, PackageManager.GET_META_DATA); + return appInfo.uid; + } catch (NameNotFoundException e) { + e.printStackTrace(); + } + return -1; + } + + /** * Returns name of "Runtime Dex" asset in Chrome APK based on version. * @param version * @return Dex asset name.
diff --git a/chrome/android/webapk/libs/runtime_library/BUILD.gn b/chrome/android/webapk/libs/runtime_library/BUILD.gn index 705ebb0..b24cd068 100644 --- a/chrome/android/webapk/libs/runtime_library/BUILD.gn +++ b/chrome/android/webapk/libs/runtime_library/BUILD.gn
@@ -22,7 +22,8 @@ } android_library("runtime_library_java") { - dex_path = "$target_gen_dir/$runtime_library_dex_asset_name" + # The dx tool expects files ending in .dex.jar + dex_path = "$target_gen_dir/$runtime_library_dex_asset_name.jar" java_files = [ "src/org/chromium/webapk/lib/runtime_library/HostBrowserLauncher.java", "src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java", @@ -37,9 +38,10 @@ write_file("$target_gen_dir/webapk_dex_version.txt", runtime_library_version) sources = [ - "$target_gen_dir/$runtime_library_dex_asset_name", "$target_gen_dir/webapk_dex_version.txt", ] + renaming_sources = [ "$target_gen_dir/$runtime_library_dex_asset_name.jar" ] + renaming_destinations = [ "$runtime_library_dex_asset_name" ] disable_compression = true deps = [ @@ -47,10 +49,13 @@ ] } -junit_binary("webapk_runtime_library_junit_tests") { - java_files = [ "junit/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImplTest.java" ] +android_library("runtime_library_javatests") { + testonly = true + java_files = [ "javatests/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImplTest.java" ] deps = [ ":runtime_library_java", - "//base:base_junit_test_support", + "//base:base_java_test_support", + "//chrome/test/android:chrome_java_test_support", + "//content/public/test/android:content_java_test_support", ] }
diff --git a/chrome/android/webapk/libs/runtime_library/javatests/DEPS b/chrome/android/webapk/libs/runtime_library/javatests/DEPS new file mode 100644 index 0000000..7528863 --- /dev/null +++ b/chrome/android/webapk/libs/runtime_library/javatests/DEPS
@@ -0,0 +1,4 @@ +include_rules = [ + "+chrome/test", + "+content/public/test", +]
diff --git a/chrome/android/webapk/libs/runtime_library/javatests/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImplTest.java b/chrome/android/webapk/libs/runtime_library/javatests/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImplTest.java new file mode 100644 index 0000000..110a931e --- /dev/null +++ b/chrome/android/webapk/libs/runtime_library/javatests/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImplTest.java
@@ -0,0 +1,133 @@ +// 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. + +package org.chromium.webapk.lib.runtime_library; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.os.IBinder; +import android.test.InstrumentationTestCase; +import android.test.suitebuilder.annotation.SmallTest; + +import org.chromium.chrome.test.webapk.TestWebApkServiceImplWrapper; +import org.chromium.content.browser.test.util.CallbackHelper; + +/** + * Instrumentation tests for {@link org.chromium.webapk.WebApkServiceImpl}. + */ +public class WebApkServiceImplTest extends InstrumentationTestCase { + + private static final int SMALL_ICON_ID = 1229; + + private Context mContext; + private Context mTargetContext; + + /** + * The target app's uid. + */ + private int mTargetUid; + + /** + * CallbackHelper which blocks till the service is connected. + */ + private static class ServiceConnectionWaiter + extends CallbackHelper implements ServiceConnection { + private IWebApkApi mApi; + + public IWebApkApi api() { + return mApi; + } + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + mApi = IWebApkApi.Stub.asInterface(service); + notifyCalled(); + } + + @Override + public void onServiceDisconnected(ComponentName name) {} + } + + @Override + public void setUp() { + mContext = getInstrumentation().getContext(); + mTargetContext = getInstrumentation().getTargetContext(); + mTargetUid = getUid(mTargetContext); + } + + /** + * Test that an application which is not allowed to use the WebAPK service actually cannot. + */ + @SmallTest + public void testApiFailsIfNoPermission() throws Exception { + IWebApkApi api = bindService(mContext, mTargetUid + 1, SMALL_ICON_ID); + try { + // Check that the api either throws an exception or returns a default small icon id. + int actualSmallIconId = api.getSmallIconId(); + assertTrue(actualSmallIconId != SMALL_ICON_ID); + } catch (Exception e) { + } + } + + /** + * Test that an application which is allowed to use the WebAPK service actually can. + */ + @SmallTest + public void testApiWorksIfHasPermission() throws Exception { + IWebApkApi api = bindService(mContext, mTargetUid, SMALL_ICON_ID); + try { + // Check that the api returns the real small icon id. + int actualSmallIconId = api.getSmallIconId(); + assertEquals(SMALL_ICON_ID, actualSmallIconId); + } catch (Exception e) { + e.printStackTrace(); + fail("Should not have thrown an exception when permission is granted."); + } + } + + /** + * Returns the uid for {@link context}. + */ + private static int getUid(Context context) { + PackageManager packageManager = context.getPackageManager(); + ApplicationInfo appInfo; + try { + appInfo = packageManager.getApplicationInfo( + context.getPackageName(), PackageManager.GET_META_DATA); + return appInfo.uid; + } catch (Exception e) { + fail(); + } + return -1; + } + + /** + * Binds to the WebAPK service and blocks till the service is connected. + * @param context The context for the application containing the WebAPK service to bind to. + * @param authorizedUid The uid of the only application allowed to use the WebAPK service's + * methods. + * @param smallIconId The real small icon id. + * @return IWebApkApi to use to communicate with the service. + */ + private static IWebApkApi bindService(Context context, int authorizedUid, int smallIconId) + throws Exception { + Intent intent = new Intent(); + intent.setComponent(new ComponentName( + context.getPackageName(), TestWebApkServiceImplWrapper.class.getName())); + intent.putExtra(WebApkServiceImpl.KEY_SMALL_ICON_ID, smallIconId); + intent.putExtra(WebApkServiceImpl.KEY_HOST_BROWSER_UID, authorizedUid); + + ServiceConnectionWaiter waiter = new ServiceConnectionWaiter(); + context.bindService(intent, waiter, Context.BIND_AUTO_CREATE); + waiter.waitForCallback(0); + + IWebApkApi api = waiter.api(); + assertNotNull(api); + return api; + } +}
diff --git a/chrome/android/webapk/libs/runtime_library/junit/DEPS b/chrome/android/webapk/libs/runtime_library/junit/DEPS deleted file mode 100644 index 6c53bc2..0000000 --- a/chrome/android/webapk/libs/runtime_library/junit/DEPS +++ /dev/null
@@ -1,3 +0,0 @@ -include_rules = [ - "+testing", -]
diff --git a/chrome/android/webapk/libs/runtime_library/junit/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImplTest.java b/chrome/android/webapk/libs/runtime_library/junit/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImplTest.java deleted file mode 100644 index f3aceae..0000000 --- a/chrome/android/webapk/libs/runtime_library/junit/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImplTest.java +++ /dev/null
@@ -1,98 +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. - -package org.chromium.webapk.lib.runtime_library; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import android.content.pm.PackageManager; -import android.os.Bundle; -import android.os.RemoteException; - -import org.chromium.testing.local.LocalRobolectricTestRunner; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.Robolectric; -import org.robolectric.annotation.Config; - -/** - * Unit tests for {@link org.chromium.webapk.WebApkServiceImpl}. - */ -@RunWith(LocalRobolectricTestRunner.class) -@Config(manifest = Config.NONE) -public class WebApkServiceImplTest { - - private static final String ALLOWED_PACKAGE = "com.allowed.package"; - private static final int ALLOWED_UID = 0; - - private PackageManager mPackageManager; - - @Before - public void setUp() { - mPackageManager = mock(PackageManager.class); - when(mPackageManager.getPackagesForUid(ALLOWED_UID)).thenReturn( - new String[] { ALLOWED_PACKAGE }); - } - - @Test - public void testAllowedCaller() { - WebApkServiceImpl service = - new WebApkServiceImpl(Robolectric.application, createBundle(ALLOWED_PACKAGE)); - assertTrue(service.checkHasAccess(ALLOWED_UID, mPackageManager)); - } - - @Test - public void testProhibitedCaller() { - WebApkServiceImpl service = - new WebApkServiceImpl(Robolectric.application, createBundle(ALLOWED_PACKAGE)); - assertFalse(service.checkHasAccess(ALLOWED_UID + 1, mPackageManager)); - } - - @Test - public void testOnTransactThrowsIfNoPermission() { - WebApkServiceImpl service = new WebApkServiceImpl( - Robolectric.application, createBundle(ALLOWED_PACKAGE)) { - @Override - boolean checkHasAccess(int uid, PackageManager packageManager) { - return false; - } - }; - try { - service.onTransact(0, null, null, 0); - Assert.fail("Should have thrown an exception for no access."); - } catch (RemoteException e) { - } - } - - @Test - public void testOnTransactRunsIfHasPermission() { - WebApkServiceImpl service = new WebApkServiceImpl( - Robolectric.application, createBundle(ALLOWED_PACKAGE)) { - @Override - boolean checkHasAccess(int uid, PackageManager packageManager) { - return true; - } - }; - try { - service.onTransact(0, null, null, 0); - } catch (RemoteException e) { - e.printStackTrace(); - Assert.fail("Should not have thrown an exception when permission is granted."); - } - } - - /** - * Creates Bundle to pass to WebApkServiceImpl constructor. - */ - private static Bundle createBundle(String expectedHostBrowser) { - Bundle bundle = new Bundle(); - bundle.putString(WebApkServiceImpl.KEY_HOST_BROWSER_PACKAGE, expectedHostBrowser); - return bundle; - } -}
diff --git a/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java b/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java index 0d18623..5fccbdc7 100644 --- a/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java +++ b/chrome/android/webapk/libs/runtime_library/src/org/chromium/webapk/lib/runtime_library/WebApkServiceImpl.java
@@ -7,16 +7,10 @@ import android.app.Notification; import android.app.NotificationManager; import android.content.Context; -import android.content.pm.PackageManager; import android.os.Binder; import android.os.Bundle; import android.os.Parcel; import android.os.RemoteException; -import android.util.Log; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; /** * Implements services offered by the WebAPK to Chrome. @@ -24,7 +18,7 @@ public class WebApkServiceImpl extends IWebApkApi.Stub { public static final String KEY_SMALL_ICON_ID = "small_icon_id"; - public static final String KEY_HOST_BROWSER_PACKAGE = "host_browser_package"; + public static final String KEY_HOST_BROWSER_UID = "host_browser_uid"; private static final String TAG = "WebApkServiceImpl"; @@ -36,15 +30,10 @@ private final int mSmallIconId; /** - * Package name of only process allowed to call the service's methods. If a process with a - * different package name calls the service, the service throws a RemoteException. + * Uid of only application allowed to call the service's methods. If an application with a + * different uid calls the service, the service throws a RemoteException. */ - private final String mHostPackage; - - /** - * Uids of processes which are allowed to call the service. - */ - private final Set<Integer> mAuthorizedUids = new HashSet<>(); + private final int mHostUid; /** * Creates an instance of WebApkServiceImpl. @@ -54,38 +43,16 @@ public WebApkServiceImpl(Context context, Bundle bundle) { mContext = context; mSmallIconId = bundle.getInt(KEY_SMALL_ICON_ID); - mHostPackage = bundle.getString(KEY_HOST_BROWSER_PACKAGE); - assert mHostPackage != null; - } - - boolean checkHasAccess(int uid, PackageManager packageManager) { - String[] callingPackageNames = packageManager.getPackagesForUid(uid); - Log.d(TAG, "Verifying bind request from: " + Arrays.toString(callingPackageNames) + " " - + mHostPackage); - if (callingPackageNames == null) { - return false; - } - - for (String packageName : callingPackageNames) { - if (packageName.equals(mHostPackage)) { - return true; - } - } - - Log.e(TAG, "Unauthorized request from uid: " + uid); - return false; + mHostUid = bundle.getInt(KEY_HOST_BROWSER_UID); + assert mHostUid >= 0; } @Override public boolean onTransact(int arg0, Parcel arg1, Parcel arg2, int arg3) throws RemoteException { int callingUid = Binder.getCallingUid(); - if (!mAuthorizedUids.contains(callingUid)) { - if (checkHasAccess(callingUid, mContext.getPackageManager())) { - mAuthorizedUids.add(callingUid); - } else { - throw new RemoteException("Unauthorized caller " + callingUid - + " does not match expected host=" + mHostPackage); - } + if (mHostUid != callingUid) { + throw new RemoteException("Unauthorized caller " + callingUid + + " does not match expected host=" + mHostUid); } return super.onTransact(arg0, arg1, arg2, arg3); }
diff --git a/chrome/android/webapk/shell_apk/javatests/DEPS b/chrome/android/webapk/shell_apk/javatests/DEPS index 86da7fe..1890e75 100644 --- a/chrome/android/webapk/shell_apk/javatests/DEPS +++ b/chrome/android/webapk/shell_apk/javatests/DEPS
@@ -2,4 +2,5 @@ "+base", "+chrome/android/webapk/libs/client", "+chrome/android/webapk/libs/common", + "+content/public/test", ]
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkServiceFactory.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkServiceFactory.java index 575a076..7b49621 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkServiceFactory.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkServiceFactory.java
@@ -34,9 +34,9 @@ private static final String KEY_SMALL_ICON_ID = "small_icon_id"; /** - * Key for passing package name of only process allowed to call the service's methods. + * Key for passing uid of only application allowed to call the service's methods. */ - private static final String KEY_HOST_BROWSER_PACKAGE = "host_browser_package"; + private static final String KEY_HOST_BROWSER_UID = "host_browser_uid"; @Override public IBinder onBind(Intent intent) { @@ -52,10 +52,10 @@ webApkClassLoader.loadClass(WEBAPK_SERVICE_IMPL_CLASS_NAME); Constructor<?> webApkServiceImplConstructor = webApkServiceImplClass.getConstructor(Context.class, Bundle.class); - String hostPackageName = WebApkUtils.getHostBrowserPackageName(this); + int hostBrowserUid = WebApkUtils.getHostBrowserUid(this); Bundle bundle = new Bundle(); bundle.putInt(KEY_SMALL_ICON_ID, R.drawable.app_icon); - bundle.putString(KEY_HOST_BROWSER_PACKAGE, hostPackageName); + bundle.putInt(KEY_HOST_BROWSER_UID, hostBrowserUid); return (IBinder) webApkServiceImplConstructor.newInstance(new Object[] {this, bundle}); } catch (Exception e) { Log.w(TAG, "Unable to create WebApkServiceImpl.");
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn index 5caffce..9dc9cd7 100644 --- a/chrome/app/BUILD.gn +++ b/chrome/app/BUILD.gn
@@ -312,7 +312,7 @@ ] } -source_set("test_support") { +static_library("test_support") { testonly = true visibility = [ "//chrome/test:test_support" ]
diff --git a/chrome/app/bookmarks_strings.grdp b/chrome/app/bookmarks_strings.grdp index 2cbc54f..28f325e 100644 --- a/chrome/app/bookmarks_strings.grdp +++ b/chrome/app/bookmarks_strings.grdp
@@ -150,12 +150,12 @@ <!-- Begin of Bookmarks Bubble strings. --> <if expr="not use_titlecase"> <message name="IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARKED" desc="Title of the bubble after bookmarking a page."> - Bookmark added! + Bookmark added </message> </if> <if expr="use_titlecase"> <message name="IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARKED" desc="In Title Case: Title of the bubble after bookmarking a page."> - Bookmark Added! + Bookmark Added </message> </if> <message name="IDS_BOOKMARK_BUBBLE_PAGE_BOOKMARK" desc="Title of the bubble when re-clicking on a bookmark">
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd index eadfe62..71c53f77 100644 --- a/chrome/app/chromium_strings.grd +++ b/chrome/app/chromium_strings.grd
@@ -3,7 +3,7 @@ If you update this file, be sure also to update google_chrome_strings.grd. --> <grit base_dir="." latest_public_release="0" current_release="1" - source_lang_id="en" enc_check="möl"> + output_all_resource_defines="false" source_lang_id="en" enc_check="möl"> <outputs> <output filename="grit/chromium_strings.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index b3c9b5e4..1adc70c 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -8,7 +8,7 @@ --> <grit base_dir="." latest_public_release="0" current_release="1" - source_lang_id="en" enc_check="möl"> + output_all_resource_defines="false" source_lang_id="en" enc_check="möl"> <outputs> <output filename="grit/generated_resources.h" type="rc_header"> <emit emit_type='prepend'></emit> @@ -4965,19 +4965,6 @@ Keep changes </message> - <!-- chrome://settings-frame/options_settings_app.html for the App Launcher Settings App --> - <if expr="enable_settings_app"> - <message name="IDS_SETTINGS_APP_LAUNCHER_PRODUCT_NAME" desc="Product name to use when referring to applications running in the App Launcher inside the non-browser Settings App"> - App Launcher - </message> - <message name="IDS_SETTINGS_APP_PROFILES_SWITCH_BUTTON_LABEL" desc="The label that appears on the profile switch user button in the Settings App to allow a user to switch the app launcher profile to the current selection."> - Switch user - </message> - <message name="IDS_SETTINGS_APP_SYNC_OVERVIEW" desc="The message that appears in the non-browser Settings App when sync has not been set up by the user."> - Sign in with your Google Account to allow apps to synchronize settings and provide other customized services. - </message> - </if> - <!-- Material Design version of chrome://policy --> <message name="IDS_FLAGS_ENABLE_MATERIAL_DESIGN_POLICY_PAGE_NAME" desc="Name for the flag to enable the material design policy page."> Enable Material Design policy page @@ -6406,12 +6393,6 @@ <message name="IDS_FLAGS_CENTERED_APP_LIST_DESCRIPTION" desc="Description of the flag to center the app launcher and make it wide instead of tall."> Positions the App Launcher in the center of the screen with a landscape aspect. </message> - <message name="IDS_FLAGS_NEW_APP_LIST_MIXER_NAME" desc="Name of the flag to enable the new mixing algorithm in the app launcher."> - New App Launcher mixer algorithm - </message> - <message name="IDS_FLAGS_NEW_APP_LIST_MIXER_DESCRIPTION" desc="Description of the flag to enable the new mixing algorithm in the app launcher."> - This enables a new search result selecting and ranking algorithm in the App Launcher. - </message> </if> <if expr="chromeos"> <message name="IDS_FLAGS_FIRST_RUN_UI_TRANSITIONS_NAME" desc="Name of the flag to enable animated transitions for the first-run tutorial."> @@ -14863,19 +14844,31 @@ <if expr="not is_android and not is_ios"> <!-- Device Chooser Prompt --> - <message name="IDS_DEVICE_CHOOSER_PROMPT" desc="The label that is used to introduce chooser details to the user in a popup."> + <message name="IDS_BLUETOOTH_DEVICE_CHOOSER_PROMPT_ORIGIN" desc="The label that is used to introduce Bluetooth chooser details to the user in a popup when it is from a website."> + <ph name="Origin">$1<ex>www.google.com</ex></ph> wants to pair with: + </message> + <message name="IDS_BLUETOOTH_DEVICE_CHOOSER_PROMPT_EXTENSION_NAME" desc="The label that is used to introduce Bluetooth chooser details to the user in a popup when it is from a Chrome extension."> + "<ph name="CHROME_EXTENSION_NAME">$1<ex>Chrome extension name</ex></ph>" wants to pair with: + </message> + <message name="IDS_USB_DEVICE_CHOOSER_PROMPT_ORIGIN" desc="The label that is used to introduce USB chooser details to the user in a popup when it is from a website."> <ph name="Origin">$1<ex>www.google.com</ex></ph> wants to connect to: </message> + <message name="IDS_USB_DEVICE_CHOOSER_PROMPT_EXTENSION_NAME" desc="The label that is used to introduce USB chooser details to the user in a popup when it is from a Chrome extension."> + "<ph name="CHROME_EXTENSION_NAME">$1<ex>Chrome extension name</ex></ph>" wants to connect to: + </message> <message name="IDS_DEVICE_CHOOSER_NO_DEVICES_FOUND_PROMPT" desc="The label that is used to inform the user that no devices were found in the chooser popup."> No devices found. </message> <message name="IDS_DEVICE_CHOOSER_DEVICE_NAME_WITH_ID" desc="To distinguish devices with the same name, the device chooser shows the device name with id."> <ph name="DEVICE_NAME">$1<ex>device name</ex></ph> (<ph name="DEVICE_ID">$2<ex>device id</ex></ph>) </message> - <message name="IDS_DEVICE_CHOOSER_CONNECT_BUTTON_TEXT" desc="The text that is shown on the connect button in the chooser popup."> + <message name="IDS_BLUETOOTH_DEVICE_CHOOSER_PAIR_BUTTON_TEXT" desc="Label on the button that closes the Bluetooth chooser popup and pairs the selected device."> + Pair + </message> + <message name="IDS_USB_DEVICE_CHOOSER_CONNECT_BUTTON_TEXT" desc="Label on the button that closes the USB chooser popup and connects the selected device."> Connect </message> - <message name="IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT" desc="The text that is shown on the cancel button in the chooser popup."> + <message name="IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT" desc="Label on the button that closes the chooser popup without selecting an option."> Cancel </message> <message name="IDS_DEVICE_CHOOSER_FOOTNOTE_TEXT" desc="This text is shown at the bottom of the chooser popup with a link to part of its text.">
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd index 5a11db3..a21bfaa 100644 --- a/chrome/app/google_chrome_strings.grd +++ b/chrome/app/google_chrome_strings.grd
@@ -5,7 +5,7 @@ chromium_strings.grd. --> <grit base_dir="." latest_public_release="0" current_release="1" - source_lang_id="en" enc_check="möl"> + output_all_resource_defines="false" source_lang_id="en" enc_check="möl"> <outputs> <output filename="grit/google_chrome_strings.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/app/resources/locale_settings.grd b/chrome/app/resources/locale_settings.grd index b8264ad..d9cc66b74 100644 --- a/chrome/app/resources/locale_settings.grd +++ b/chrome/app/resources/locale_settings.grd
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/locale_settings.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/app/resources/locale_settings_chromiumos.grd b/chrome/app/resources/locale_settings_chromiumos.grd index 4fd0bd28..16270a5 100644 --- a/chrome/app/resources/locale_settings_chromiumos.grd +++ b/chrome/app/resources/locale_settings_chromiumos.grd
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/platform_locale_settings.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/app/resources/locale_settings_google_chromeos.grd b/chrome/app/resources/locale_settings_google_chromeos.grd index 8acea82..8153ec7 100644 --- a/chrome/app/resources/locale_settings_google_chromeos.grd +++ b/chrome/app/resources/locale_settings_google_chromeos.grd
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/platform_locale_settings.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/app/resources/locale_settings_linux.grd b/chrome/app/resources/locale_settings_linux.grd index 77a261b9..495c925 100644 --- a/chrome/app/resources/locale_settings_linux.grd +++ b/chrome/app/resources/locale_settings_linux.grd
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/platform_locale_settings.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/app/resources/locale_settings_mac.grd b/chrome/app/resources/locale_settings_mac.grd index 39f6d769..91d4b78 100644 --- a/chrome/app/resources/locale_settings_mac.grd +++ b/chrome/app/resources/locale_settings_mac.grd
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/platform_locale_settings.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/app/resources/locale_settings_win.grd b/chrome/app/resources/locale_settings_win.grd index 219c9dde..a4bcf1d 100644 --- a/chrome/app/resources/locale_settings_win.grd +++ b/chrome/app/resources/locale_settings_win.grd
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/platform_locale_settings.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/app/settings_chromium_strings.grd b/chrome/app/settings_chromium_strings.grd index df8a8f5..671f182c 100644 --- a/chrome/app/settings_chromium_strings.grd +++ b/chrome/app/settings_chromium_strings.grd
@@ -7,7 +7,7 @@ strings will begin to be translated. --> <grit base_dir="." latest_public_release="0" current_release="1" - source_lang_id="en" enc_check="möl"> + output_all_resource_defines="false" source_lang_id="en" enc_check="möl"> <outputs> <output filename="grit/settings_chromium_strings.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/app/settings_google_chrome_strings.grd b/chrome/app/settings_google_chrome_strings.grd index 68c71e2..44e0013 100644 --- a/chrome/app/settings_google_chrome_strings.grd +++ b/chrome/app/settings_google_chrome_strings.grd
@@ -7,7 +7,7 @@ strings will begin to be translated. --> <grit base_dir="." latest_public_release="0" current_release="1" - source_lang_id="en" enc_check="möl"> + output_all_resource_defines="false" source_lang_id="en" enc_check="möl"> <outputs> <output filename="grit/settings_google_chrome_strings.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/app/settings_strings.grd b/chrome/app/settings_strings.grd index 47fb06d..3ec4ed48 100644 --- a/chrome/app/settings_strings.grd +++ b/chrome/app/settings_strings.grd
@@ -7,13 +7,12 @@ strings will begin to be translated. --> <grit base_dir="." latest_public_release="0" current_release="1" - source_lang_id="en" enc_check="möl"> + output_all_resource_defines="false" source_lang_id="en" enc_check="möl"> <outputs> <output filename="grit/settings_strings.h" type="rc_header"> <emit emit_type='prepend'></emit> </output> <output filename="settings_strings.pak" type="data_package"/> - </outputs> <release seq="1" allow_pseudo="false">
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 6e5d76a5..e8f62914 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -3,6 +3,15 @@ <grit-part> <!-- About Page --> <if expr="chromeos"> + <message name="IDS_SETTINGS_ABOUT_PAGE_DETAILED_BUILD_INFO" desc="Label describing the section that shows detailed information about the current Chrome build."> + Detailed build information + </message> + <message name="IDS_SETTINGS_ABOUT_PAGE_ARC_VERSION" desc="Label for ARC version"> + ARC Version + </message> + <message name="IDS_SETTINGS_ABOUT_PAGE_CHANNEL" desc="The channel label under Detailed build info."> + Channel + </message> <message name="IDS_SETTINGS_ABOUT_PAGE_CHECK_FOR_UPDATES" desc="The button label to check for updates and apply (download and install) if found"> Check for updates </message> @@ -18,6 +27,12 @@ <message name="IDS_SETTINGS_ABOUT_PAGE_CURRENT_CHANNEL" desc="The message about current channel."> Currently on <ph name="CHANNEL_NAME">$1<ex>stable</ex></ph> </message> + <message name="IDS_SETTINGS_ABOUT_PAGE_FIRMWARE" desc="Label used for Chrome OS BIOS firmware version."> + Firmware + </message> + <message name="IDS_SETTINGS_ABOUT_PAGE_PLATFORM" desc="Label for Platform"> + Platform + </message> <message name="IDS_SETTINGS_ABOUT_PAGE_RELAUNCH" desc="The label for the relaunch button that relaunches the browser once update is complete"> Restart </message> @@ -213,7 +228,7 @@ <!-- Passwords and Autofill Page --> <message name="IDS_SETTINGS_OVERFLOW_MENU" desc="Alt text for the overflow button on a list item. Triggers a context menu when clicked."> - Menu + Menu </message> <message name="IDS_SETTINGS_PASSWORDS_AND_AUTOFILL_PAGE_TITLE" desc="Name of the settings page which allows managing passwords and autofill settings."> Passwords and forms @@ -227,6 +242,21 @@ <message name="IDS_SETTINGS_AUTOFILL_ADDRESSES_HEADING" desc="Title for the list of addresses that chrome has saved for use in filling in forms."> Addresses </message> + <message name="IDS_SETTINGS_AUTOFILL_ADDRESSES_ADD_TITLE" desc="This is the title for the 'Add address' dialog. This dialog allows a user to create a new address."> + Add address + </message> + <message name="IDS_SETTINGS_AUTOFILL_ADDRESSES_EDIT_TITLE" desc="This is the title for the 'Edit address' dialog. This dialog allows a user to edit an address that is already saved."> + Edit address + </message> + <message name="IDS_SETTINGS_AUTOFILL_ADDRESSES_COUNTRY" desc="This is the label for the dropdown that lets a user select the country their address is in. Will be shown when editing or adding an address to use in autofill."> + Country / Region + </message> + <message name="IDS_SETTINGS_AUTOFILL_ADDRESSES_PHONE" desc="This is the label for the field that lets a user modify the phone number that will be used when auto-filling forms on the web."> + Phone + </message> + <message name="IDS_SETTINGS_AUTOFILL_ADDRESSES_EMAIL" desc="This is the label for the field that lets a user modify the email address that will be used when auto-filling forms on the web."> + Email + </message> <message name="IDS_SETTINGS_AUTOFILL_ADD_ADDRESS_BUTTON" desc="Label for a button that allows a user to enter a new address that can be used to fill in forms."> Add address </message> @@ -243,16 +273,16 @@ Enable Autofill to fill out forms in a single click </message> <message name="IDS_SETTINGS_ADDRESS_EDIT" desc="Label for a context menu item that shows a dialog with edit options for the selected address." meaning="Edit selected address."> - Edit + Edit </message> <message name="IDS_SETTINGS_ADDRESS_REMOVE" desc="Label for a context menu item that removes the selected address." meaning="Remove selected address."> - Remove + Remove </message> <message name="IDS_SETTINGS_CREDIT_CARD_EDIT" desc="Label for a context menu item that shows a dialog with edit options for the selected credit card." meaning="Edit selected credit card."> - Edit + Edit </message> <message name="IDS_SETTINGS_CREDIT_CARD_REMOVE" desc="Label for a context menu item that removes the selected credit card." meaning="Remove selected credit card."> - Remove + Remove </message> <message name="IDS_SETTINGS_CREDIT_CARD_CLEAR" desc="Label for a context menu item clears the locally cached credit card that is also saved on Google Payments. Clicking this will NOT remove the credit card from Google Payments."> Clear copy @@ -294,10 +324,10 @@ Delete this item </message> <message name="IDS_SETTINGS_PASSWORD_EDIT" desc="Label for a context menu item that shows a dialog with edit options for the selected password." meaning="Edit selected password."> - Edit + Edit </message> <message name="IDS_SETTINGS_PASSWORD_REMOVE" desc="Label for a context menu item that removes the selected password." meaning="Remove selected password."> - Remove + Remove </message> <message name="IDS_SETTINGS_PASSWORDS_EDIT_TITLE" desc="Title for the 'Edit saved password' dialog. This dialog lets a user see a saved password and copy the username."> Edit saved password @@ -985,6 +1015,9 @@ <message name="IDS_SETTINGS_SITE_SETTINGS_COOKIES" desc="Label for the cookies site settings."> Cookies </message> + <message name="IDS_SETTINGS_SITE_SETTINGS_HANDLERS" desc="Label for the protocol handlers (e.g. mailto) in site settings."> + Handlers + </message> <message name="IDS_SETTINGS_SITE_SETTINGS_LOCATION" desc="Label for the location site settings."> Location </message> @@ -1069,6 +1102,15 @@ <message name="IDS_SETTINGS_SITE_SETTINGS_BACKGROUND_SYNC_BLOCKED" desc="The block label for background sync in site settings."> Do not allow recently closed sites to finish sending and receiving data </message> + <message name="IDS_SETTINGS_SITE_SETTINGS_HANDLERS_ASK" desc="The allow label for protocol handlers in site settings."> + Allow sites to ask to become default handlers for protocols + </message> + <message name="IDS_SETTINGS_SITE_SETTINGS_HANDLERS_ASK_RECOMMENDED" desc="The allow label for protocol handlers in site settings (with the 'recommended' suffix)."> + Allow sites to ask to become default handlers for protocols (recommended) + </message> + <message name="IDS_SETTINGS_SITE_SETTINGS_HANDLERS_BLOCKED" desc="The block label for protocol handlers in site settings."> + Do not allow any site to handle protocols + </message> <message name="IDS_SETTINGS_SITE_SETTINGS_KEYGEN_ALLOW" desc="The allow label for keygen in site settings."> Allow all sites to use key generation in forms </message> @@ -1168,6 +1210,15 @@ <message name="IDS_SETTINGS_SITE_SETTINGS_THIRD_PARTY_COOKIE_SUBLABEL" desc="A sub-label below the Block 3rd-party cookie checkbox."> Prevent third-party websites from saving and reading cookie data. </message> + <message name="IDS_SETTINGS_SITE_SETTINGS_HANDLER_IS_DEFAULT" desc="A label showing that a certain handler for a given protocol is the default."> + Default + </message> + <message name="IDS_SETTINGS_SITE_SETTINGS_HANDLER_SET_DEFAULT" desc="A label for the action of making a certain handler the default for a given protocol."> + Set as default + </message> + <message name="IDS_SETTINGS_SITE_SETTINGS_REMOVE" desc="A label for the action of removing (deleting) a certain handler."> + Remove + </message> <!-- Sync / People Page --> <message name="IDS_SETTINGS_PEOPLE" desc="Name of the settings page which manages Chrome's signed-in Google profile.">
diff --git a/chrome/app/theme/default_100_percent/settings_app_icon_128.png b/chrome/app/theme/default_100_percent/settings_app_icon_128.png deleted file mode 100644 index 6d2ed790..0000000 --- a/chrome/app/theme/default_100_percent/settings_app_icon_128.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/settings_app_icon_16.png b/chrome/app/theme/default_100_percent/settings_app_icon_16.png deleted file mode 100644 index 120c73c..0000000 --- a/chrome/app/theme/default_100_percent/settings_app_icon_16.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/settings_app_icon_32.png b/chrome/app/theme/default_100_percent/settings_app_icon_32.png deleted file mode 100644 index ba61c5a..0000000 --- a/chrome/app/theme/default_100_percent/settings_app_icon_32.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_100_percent/settings_app_icon_48.png b/chrome/app/theme/default_100_percent/settings_app_icon_48.png deleted file mode 100644 index 38faff2..0000000 --- a/chrome/app/theme/default_100_percent/settings_app_icon_48.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_200_percent/settings_app_icon_128.png b/chrome/app/theme/default_200_percent/settings_app_icon_128.png deleted file mode 100644 index be4f20d4..0000000 --- a/chrome/app/theme/default_200_percent/settings_app_icon_128.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_200_percent/settings_app_icon_16.png b/chrome/app/theme/default_200_percent/settings_app_icon_16.png deleted file mode 100644 index ba61c5a..0000000 --- a/chrome/app/theme/default_200_percent/settings_app_icon_16.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_200_percent/settings_app_icon_32.png b/chrome/app/theme/default_200_percent/settings_app_icon_32.png deleted file mode 100644 index 8fa1f803..0000000 --- a/chrome/app/theme/default_200_percent/settings_app_icon_32.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/default_200_percent/settings_app_icon_48.png b/chrome/app/theme/default_200_percent/settings_app_icon_48.png deleted file mode 100644 index f5bb3c1a..0000000 --- a/chrome/app/theme/default_200_percent/settings_app_icon_48.png +++ /dev/null Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd index f21c2dd8..9460b5d 100644 --- a/chrome/app/theme/theme_resources.grd +++ b/chrome/app/theme/theme_resources.grd
@@ -759,12 +759,6 @@ <if expr="chromeos"> <structure type="chrome_scaled_image" name="IDR_SECONDARY_USER_SETTINGS" file="cros/secondary_user_settings.png" /> </if> - <if expr="enable_settings_app"> - <structure type="chrome_scaled_image" name="IDR_SETTINGS_APP_ICON_128" file="settings_app_icon_128.png" /> - <structure type="chrome_scaled_image" name="IDR_SETTINGS_APP_ICON_16" file="settings_app_icon_16.png" /> - <structure type="chrome_scaled_image" name="IDR_SETTINGS_APP_ICON_32" file="settings_app_icon_32.png" /> - <structure type="chrome_scaled_image" name="IDR_SETTINGS_APP_ICON_48" file="settings_app_icon_48.png" /> - </if> <structure type="chrome_scaled_image" name="IDR_SETTINGS_FAVICON" file="common/favicon_settings.png" /> <structure type="chrome_scaled_image" name="IDR_STAR" file="common/star.png" /> <structure type="chrome_scaled_image" name="IDR_STAR_LIT" file="common/star_lit.png" />
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 76d4fabf..61d2c53 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -834,7 +834,6 @@ "//chrome/chrome_watcher:client", "//chrome/common:metrics_constants_util_win", "//chrome/common:version_header", - "//chrome/installer/util:strings", "//chrome_elf", "//chrome_elf:constants", "//chrome_elf:dll_hash", @@ -991,7 +990,7 @@ } if (is_win) { - source_set("chrome_process_finder") { + static_library("chrome_process_finder") { sources = [ "win/chrome_process_finder.cc", "win/chrome_process_finder.h", @@ -1325,7 +1324,7 @@ } # In GYP this is part of test_support_ui. -source_set("test_support_ui") { +static_library("test_support_ui") { testonly = true # Always include this via the main test support UI target. @@ -1352,7 +1351,7 @@ } if (enable_rlz_support) { - source_set("rlz") { + static_library("rlz") { sources = rebase_path(gypi_values.chrome_browser_rlz_sources, ".", "//chrome") deps = [ @@ -1368,7 +1367,7 @@ if (enable_pepper_cdms) { # These constants are separated so that test binaries can use them without # linking all of the test support. - source_set("pepper_cdm_test_constants") { + static_library("pepper_cdm_test_constants") { testonly = true visibility = [ "//chrome/*" ] sources = [
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 62686c60..499a307c 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -513,7 +513,6 @@ #endif // defined(OS_ANDROID) #if defined(OS_ANDROID) -const FeatureEntry::FeatureParam kNTPSnippetsFeatureVariationDefault[] = {}; const FeatureEntry::FeatureParam kNTPSnippetsFeatureVariationOnlyPersonal[] = { {"fetching_personalization", "personal"}, {"fetching_host_restrict", "off"}, @@ -529,10 +528,7 @@ {"fetching_host_restrict", "on"}, }; -// TODO(jkrcal) allow for nullptr instead of the empty array. const FeatureEntry::FeatureVariation kNTPSnippetsFeatureVariations[] = { - {"", kNTPSnippetsFeatureVariationDefault, - 0}, {"only personalized", kNTPSnippetsFeatureVariationOnlyPersonal, arraysize(kNTPSnippetsFeatureVariationOnlyPersonal)}, {"only from most visited sites", @@ -1330,11 +1326,6 @@ {"enable-centered-app-list", IDS_FLAGS_CENTERED_APP_LIST_NAME, IDS_FLAGS_CENTERED_APP_LIST_DESCRIPTION, kOsWin | kOsLinux | kOsCrOS, SINGLE_VALUE_TYPE(app_list::switches::kEnableCenteredAppList)}, - {"enable-new-app-list-mixer", IDS_FLAGS_NEW_APP_LIST_MIXER_NAME, - IDS_FLAGS_NEW_APP_LIST_MIXER_DESCRIPTION, - kOsWin | kOsLinux | kOsCrOS | kOsMac, - ENABLE_DISABLE_VALUE_TYPE(app_list::switches::kEnableNewAppListMixer, - app_list::switches::kDisableNewAppListMixer)}, #endif {"disable-threaded-scrolling", IDS_FLAGS_THREADED_SCROLLING_NAME, IDS_FLAGS_THREADED_SCROLLING_DESCRIPTION, kOsAll, @@ -1725,10 +1716,6 @@ {"tab-management-experiment-type", IDS_FLAGS_HERB_PROTOTYPE_CHOICES_NAME, IDS_FLAGS_HERB_PROTOTYPE_CHOICES_DESCRIPTION, kOsAndroid, MULTI_VALUE_TYPE(kHerbPrototypeChoices)}, - {"enable-tab-switcher-in-document-mode", - IDS_FLAGS_TAB_SWITCHER_IN_DOCUMENT_MODE_NAME, - IDS_FLAGS_TAB_SWITCHER_IN_DOCUMENT_MODE_DESCRIPTION, kOsAndroid, - SINGLE_VALUE_TYPE(switches::kEnableTabSwitcherInDocumentMode)}, {"app-link", IDS_FLAGS_ENABLE_APP_LINK_NAME, IDS_FLAGS_ENABLE_APP_LINK_DESCRIPTION, kOsAndroid, ENABLE_DISABLE_VALUE_TYPE(switches::kEnableAppLink, @@ -2021,14 +2008,6 @@ channel != version_info::Channel::UNKNOWN) { return true; } - // enable-tab-switcher-in-document-mode is only available for Chromium - // builds and the Canary channel. - if (!strcmp("enable-tab-switcher-in-document-mode", - entry.internal_name) && - channel != version_info::Channel::CANARY && - channel != version_info::Channel::UNKNOWN) { - return true; - } #endif // data-reduction-proxy-lo-fi and enable-data-reduction-proxy-lo-fi-preview
diff --git a/chrome/browser/android/banners/app_banner_manager_android.cc b/chrome/browser/android/banners/app_banner_manager_android.cc index 5556b54..5c8c44d 100644 --- a/chrome/browser/android/banners/app_banner_manager_android.cc +++ b/chrome/browser/android/banners/app_banner_manager_android.cc
@@ -19,6 +19,8 @@ using base::android::ConvertUTF8ToJavaString; using base::android::ConvertUTF16ToJavaString; +DEFINE_WEB_CONTENTS_USER_DATA_KEY(banners::AppBannerManagerAndroid); + namespace { const char kPlayPlatform[] = "play"; @@ -31,27 +33,65 @@ namespace banners { AppBannerManagerAndroid::AppBannerManagerAndroid( - JNIEnv* env, - jobject obj) - : AppBannerManager(nullptr), - weak_java_banner_view_manager_(env, obj) { + content::WebContents* web_contents) + : AppBannerManager(web_contents) { + CreateJavaBannerManager(); } AppBannerManagerAndroid::~AppBannerManagerAndroid() { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_AppBannerManager_destroy(env, java_banner_manager_.obj()); + java_banner_manager_.Reset(); } -void AppBannerManagerAndroid::Destroy(JNIEnv* env, - const JavaParamRef<jobject>& obj) { - delete this; +const base::android::ScopedJavaGlobalRef<jobject>& +AppBannerManagerAndroid::GetJavaBannerManager() const { + return java_banner_manager_; } -void AppBannerManagerAndroid::ReplaceWebContents( +bool AppBannerManagerAndroid::IsFetcherActive( + JNIEnv* env, + const JavaParamRef<jobject>& obj) { + return AppBannerManager::IsFetcherActive(); +} + +bool AppBannerManagerAndroid::OnAppDetailsRetrieved( JNIEnv* env, const JavaParamRef<jobject>& obj, - const JavaParamRef<jobject>& jweb_contents) { - content::WebContents* web_contents = - content::WebContents::FromJavaWebContents(jweb_contents); - AppBannerManager::ReplaceWebContents(web_contents); + const JavaParamRef<jobject>& japp_data, + const JavaParamRef<jstring>& japp_title, + const JavaParamRef<jstring>& japp_package, + const JavaParamRef<jstring>& jicon_url) { + AppBannerDataFetcherAndroid* android_fetcher = + static_cast<AppBannerDataFetcherAndroid*>(data_fetcher().get()); + if (!CheckFetcherMatchesContents(android_fetcher->is_debug_mode())) + return false; + + GURL image_url = GURL(ConvertJavaStringToUTF8(env, jicon_url)); + + return android_fetcher->ContinueFetching( + ConvertJavaStringToUTF16(env, japp_title), + ConvertJavaStringToUTF8(env, japp_package), japp_data, image_url); +} + +void AppBannerManagerAndroid::RequestAppBanner(const GURL& validated_url, + bool is_debug_mode) { + JNIEnv* env = base::android::AttachCurrentThread(); + if (!Java_AppBannerManager_isEnabledForTab(env, java_banner_manager_.obj())) + return; + + AppBannerManager::RequestAppBanner(validated_url, is_debug_mode); +} + +AppBannerDataFetcher* AppBannerManagerAndroid::CreateAppBannerDataFetcher( + base::WeakPtr<Delegate> weak_delegate, + bool is_debug_mode) { + return new AppBannerDataFetcherAndroid( + web_contents(), weak_delegate, + ShortcutHelper::GetIdealHomescreenIconSizeInDp(), + ShortcutHelper::GetMinimumHomescreenIconSizeInDp(), + ShortcutHelper::GetIdealSplashImageSizeInDp(), + ShortcutHelper::GetMinimumSplashImageSizeInDp(), is_debug_mode); } bool AppBannerManagerAndroid::HandleNonWebApp(const std::string& platform, @@ -65,8 +105,7 @@ // Send the info to the Java side to get info about the app. JNIEnv* env = base::android::AttachCurrentThread(); - ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env); - if (jobj.is_null()) + if (java_banner_manager_.is_null()) return false; std::string id_from_app_url = ExtractQueryValueForName(url, kIdName); @@ -93,12 +132,32 @@ ScopedJavaLocalRef<jstring> jreferrer( ConvertUTF8ToJavaString(env, referrer)); Java_AppBannerManager_fetchAppDetails( - env, jobj.obj(), jurl.obj(), + env, java_banner_manager_.obj(), jurl.obj(), jpackage.obj(), jreferrer.obj(), ShortcutHelper::GetIdealHomescreenIconSizeInDp()); return true; } +void AppBannerManagerAndroid::CreateJavaBannerManager() { + JNIEnv* env = base::android::AttachCurrentThread(); + java_banner_manager_.Reset( + Java_AppBannerManager_create(env, reinterpret_cast<intptr_t>(this))); +} + +bool AppBannerManagerAndroid::CheckFetcherMatchesContents(bool is_debug_mode) { + if (!web_contents()) + return false; + + if (!data_fetcher() || + data_fetcher()->validated_url() != web_contents()->GetURL()) { + banners::OutputDeveloperNotShownMessage( + web_contents(), banners::kUserNavigatedBeforeBannerShown, + is_debug_mode); + return false; + } + return true; +} + bool AppBannerManagerAndroid::CheckPlatformAndId(const std::string& platform, const std::string& id, bool is_debug_mode) { @@ -116,20 +175,6 @@ return true; } -bool AppBannerManagerAndroid::CheckFetcherMatchesContents(bool is_debug_mode) { - if (!web_contents()) - return false; - - if (!data_fetcher() || - data_fetcher()->validated_url() != web_contents()->GetURL()) { - banners::OutputDeveloperNotShownMessage( - web_contents(), banners::kUserNavigatedBeforeBannerShown, - is_debug_mode); - return false; - } - return true; -} - std::string AppBannerManagerAndroid::ExtractQueryValueForName( const GURL& url, const std::string& name) { @@ -146,72 +191,31 @@ return ""; } -AppBannerDataFetcher* AppBannerManagerAndroid::CreateAppBannerDataFetcher( - base::WeakPtr<Delegate> weak_delegate, - bool is_debug_mode) { - return new AppBannerDataFetcherAndroid( - web_contents(), weak_delegate, - ShortcutHelper::GetIdealHomescreenIconSizeInDp(), - ShortcutHelper::GetMinimumHomescreenIconSizeInDp(), - ShortcutHelper::GetIdealSplashImageSizeInDp(), - ShortcutHelper::GetMinimumSplashImageSizeInDp(), is_debug_mode); -} - -bool AppBannerManagerAndroid::OnAppDetailsRetrieved( - JNIEnv* env, - const JavaParamRef<jobject>& obj, - const JavaParamRef<jobject>& japp_data, - const JavaParamRef<jstring>& japp_title, - const JavaParamRef<jstring>& japp_package, - const JavaParamRef<jstring>& jicon_url) { - AppBannerDataFetcherAndroid* android_fetcher = - static_cast<AppBannerDataFetcherAndroid*>(data_fetcher().get()); - if (!CheckFetcherMatchesContents(android_fetcher->is_debug_mode())) - return false; - - GURL image_url = GURL(ConvertJavaStringToUTF8(env, jicon_url)); - - return android_fetcher->ContinueFetching( - ConvertJavaStringToUTF16(env, japp_title), - ConvertJavaStringToUTF8(env, japp_package), japp_data, image_url); -} - -bool AppBannerManagerAndroid::IsFetcherActive( - JNIEnv* env, - const JavaParamRef<jobject>& obj) { - return AppBannerManager::IsFetcherActive(); -} - -void AppBannerManagerAndroid::RequestAppBanner( - JNIEnv* env, - const JavaParamRef<jobject>& obj) { - // Set debug mode to true as this method is only called from DevTools. - AppBannerManager::RequestAppBanner(web_contents()->GetLastCommittedURL(), - true /* is_debug_mode */); -} - // static bool AppBannerManagerAndroid::Register(JNIEnv* env) { return RegisterNativesImpl(env); } -jlong Init(JNIEnv* env, - const JavaParamRef<jobject>& obj) { - AppBannerManagerAndroid* manager = new AppBannerManagerAndroid(env, obj); - return reinterpret_cast<intptr_t>(manager); +// static +ScopedJavaLocalRef<jobject> GetJavaBannerManagerForWebContents( + JNIEnv* env, + const JavaParamRef<jclass>& clazz, + const JavaParamRef<jobject>& java_web_contents) { + AppBannerManagerAndroid* manager = AppBannerManagerAndroid::FromWebContents( + content::WebContents::FromJavaWebContents(java_web_contents)); + if (!manager) + return ScopedJavaLocalRef<jobject>(); + + return ScopedJavaLocalRef<jobject>(manager->GetJavaBannerManager()); } -void SetTimeDeltaForTesting(JNIEnv* env, - const JavaParamRef<jclass>& clazz, - jint days) { - AppBannerDataFetcher::SetTimeDeltaForTesting(days); -} - +// static void DisableSecureSchemeCheckForTesting(JNIEnv* env, const JavaParamRef<jclass>& clazz) { AppBannerManager::DisableSecureSchemeCheckForTesting(); } +// static void SetEngagementWeights(JNIEnv* env, const JavaParamRef<jclass>& clazz, jdouble direct_engagement, @@ -220,4 +224,11 @@ indirect_engagement); } +// static +void SetTimeDeltaForTesting(JNIEnv* env, + const JavaParamRef<jclass>& clazz, + jint days) { + AppBannerDataFetcher::SetTimeDeltaForTesting(days); +} + } // namespace banners
diff --git a/chrome/browser/android/banners/app_banner_manager_android.h b/chrome/browser/android/banners/app_banner_manager_android.h index 69a2b78..d7f67684 100644 --- a/chrome/browser/android/banners/app_banner_manager_android.h +++ b/chrome/browser/android/banners/app_banner_manager_android.h
@@ -12,31 +12,21 @@ #include "chrome/browser/android/banners/app_banner_data_fetcher_android.h" #include "chrome/browser/banners/app_banner_debug_log.h" #include "chrome/browser/banners/app_banner_manager.h" +#include "content/public/browser/web_contents_user_data.h" namespace banners { class AppBannerDataFetcherAndroid; // Extends the AppBannerManager to support native Android apps. -// TODO(dfalcantara): Flip it so the C++ AppBannerManagerAndroid owns the -// Java AppBannerManager, move ownership of the AppBannerManagerAndroid to -// the TabAndroid class, then move functions for retriving info from Java to -// the AppBannerDataFetcherAndroid. -class AppBannerManagerAndroid : public AppBannerManager { +class AppBannerManagerAndroid + : public AppBannerManager, + public content::WebContentsUserData<AppBannerManagerAndroid> { public: - // Registers native methods. - static bool Register(JNIEnv* env); - - AppBannerManagerAndroid(JNIEnv* env, jobject obj); + explicit AppBannerManagerAndroid(content::WebContents* web_contents); ~AppBannerManagerAndroid() override; - // Destroys the AppBannerManagerAndroid. - void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); - - // Observes a new WebContents, if necessary. - void ReplaceWebContents( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj, - const base::android::JavaParamRef<jobject>& jweb_contents); + const base::android::ScopedJavaGlobalRef<jobject>& GetJavaBannerManager() + const; // Return whether a BitmapFetcher is active. bool IsFetcherActive(JNIEnv* env, @@ -52,9 +42,10 @@ const base::android::JavaParamRef<jstring>& japp_package, const base::android::JavaParamRef<jstring>& jicon_url); - // Requests the app banner. This method is called from the DevTools. - void RequestAppBanner(JNIEnv* env, - const base::android::JavaParamRef<jobject>& jobj); + void RequestAppBanner(const GURL& validated_url, bool is_debug_mode) override; + + // Registers native methods. + static bool Register(JNIEnv* env); protected: AppBannerDataFetcher* CreateAppBannerDataFetcher( @@ -62,23 +53,26 @@ bool is_debug_mode) override; private: + friend class content::WebContentsUserData<AppBannerManagerAndroid>; + // AppBannerDataFetcher::Delegate overrides. bool HandleNonWebApp(const std::string& platform, const GURL& url, const std::string& id, bool is_debug_mode) override; + void CreateJavaBannerManager(); + + bool CheckFetcherMatchesContents(bool is_debug_mode); bool CheckPlatformAndId(const std::string& platform, const std::string& id, bool is_debug_mode); - bool CheckFetcherMatchesContents(bool is_debug_mode); - std::string ExtractQueryValueForName(const GURL& url, const std::string& name); // AppBannerManager on the Java side. - JavaObjectWeakGlobalRef weak_java_banner_view_manager_; + base::android::ScopedJavaGlobalRef<jobject> java_banner_manager_; DISALLOW_COPY_AND_ASSIGN(AppBannerManagerAndroid); }; // class AppBannerManagerAndroid
diff --git a/chrome/browser/android/compositor/layer/contextual_search_layer.cc b/chrome/browser/android/compositor/layer/contextual_search_layer.cc index 07d716a1..eee52f3 100644 --- a/chrome/browser/android/compositor/layer/contextual_search_layer.cc +++ b/chrome/browser/android/compositor/layer/contextual_search_layer.cc
@@ -11,7 +11,6 @@ #include "cc/resources/scoped_ui_resource.h" #include "chrome/browser/android/compositor/layer/crushed_sprite_layer.h" #include "content/public/browser/android/compositor.h" -#include "content/public/browser/android/content_view_core.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/android/resources/crushed_sprite_resource.h" #include "ui/android/resources/resource_manager.h" @@ -77,7 +76,7 @@ int peek_promo_ripple_resource_id, int peek_promo_text_resource_id, float dp_to_px, - content::ContentViewCore* content_view_core, + const scoped_refptr<cc::Layer>& content_layer, bool search_promo_visible, float search_promo_height, float search_promo_opacity, @@ -146,7 +145,7 @@ // ----------------------------------------------------------------- OverlayPanelLayer::SetProperties( dp_to_px, - content_view_core, + content_layer, content_view_top, search_panel_x, search_panel_y,
diff --git a/chrome/browser/android/compositor/layer/contextual_search_layer.h b/chrome/browser/android/compositor/layer/contextual_search_layer.h index 5d28241..e09b5015 100644 --- a/chrome/browser/android/compositor/layer/contextual_search_layer.h +++ b/chrome/browser/android/compositor/layer/contextual_search_layer.h
@@ -16,8 +16,8 @@ class UIResourceLayer; } -namespace content { -class ContentViewCore; +namespace cc { +class Layer; } namespace ui { @@ -49,7 +49,7 @@ int peek_promo_ripple_resource_id, int peek_promo_text_resource_id, float dp_to_px, - content::ContentViewCore* content_view_core, + const scoped_refptr<cc::Layer>& content_layer, bool search_promo_visible, float search_promo_height, float search_promo_opacity,
diff --git a/chrome/browser/android/compositor/layer/overlay_panel_layer.cc b/chrome/browser/android/compositor/layer/overlay_panel_layer.cc index 48a8ef6..2edc8f6 100644 --- a/chrome/browser/android/compositor/layer/overlay_panel_layer.cc +++ b/chrome/browser/android/compositor/layer/overlay_panel_layer.cc
@@ -10,7 +10,6 @@ #include "cc/layers/ui_resource_layer.h" #include "cc/resources/scoped_ui_resource.h" #include "content/public/browser/android/compositor.h" -#include "content/public/browser/android/content_view_core.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/android/resources/crushed_sprite_resource.h" #include "ui/android/resources/resource_manager.h" @@ -66,8 +65,8 @@ void OverlayPanelLayer::SetProperties( float dp_to_px, - content::ContentViewCore* content_view_core, - float content_view_core_offset_y, + const scoped_refptr<cc::Layer>& content_layer, + float content_offset_y, float panel_x, float panel_y, float panel_width, @@ -197,17 +196,16 @@ close_icon_->SetOpacity(close_icon_opacity); // --------------------------------------------------------------------------- - // Content View + // Content // --------------------------------------------------------------------------- - content_view_container_->SetPosition( - gfx::PointF(0.f, content_view_core_offset_y)); - content_view_container_->SetBounds(gfx::Size(panel_width, panel_height)); - if (content_view_core && content_view_core->GetLayer()) { - scoped_refptr<cc::Layer> content_view_layer = content_view_core->GetLayer(); - if (content_view_layer->parent() != content_view_container_) - content_view_container_->AddChild(content_view_layer); + content_container_->SetPosition( + gfx::PointF(0.f, content_offset_y)); + content_container_->SetBounds(gfx::Size(panel_width, panel_height)); + if (content_layer) { + if (content_layer->parent() != content_container_) + content_container_->AddChild(content_layer); } else { - content_view_container_->RemoveAllChildren(); + content_container_->RemoveAllChildren(); } // --------------------------------------------------------------------------- @@ -266,7 +264,7 @@ bar_shadow_(cc::UIResourceLayer::Create()), panel_icon_(cc::UIResourceLayer::Create()), close_icon_(cc::UIResourceLayer::Create()), - content_view_container_(cc::SolidColorLayer::Create()), + content_container_(cc::SolidColorLayer::Create()), text_container_(cc::Layer::Create()), bar_border_(cc::SolidColorLayer::Create()) { layer_->SetMasksToBounds(false); @@ -297,10 +295,10 @@ close_icon_->SetIsDrawable(true); layer_->AddChild(close_icon_); - // Content View Container - content_view_container_->SetIsDrawable(true); - content_view_container_->SetBackgroundColor(kBarBackgroundColor); - layer_->AddChild(content_view_container_); + // Content Container + content_container_->SetIsDrawable(true); + content_container_->SetBackgroundColor(kBarBackgroundColor); + layer_->AddChild(content_container_); // Bar Border bar_border_->SetIsDrawable(true);
diff --git a/chrome/browser/android/compositor/layer/overlay_panel_layer.h b/chrome/browser/android/compositor/layer/overlay_panel_layer.h index 43667d7..cd073a5b 100644 --- a/chrome/browser/android/compositor/layer/overlay_panel_layer.h +++ b/chrome/browser/android/compositor/layer/overlay_panel_layer.h
@@ -16,10 +16,6 @@ class UIResourceLayer; } -namespace content { -class ContentViewCore; -} - namespace ui { class ResourceManager; } @@ -36,8 +32,8 @@ int close_icon_resource_id); void SetProperties(float dp_to_px, - content::ContentViewCore* content_view_core, - float content_view_core_offset_y, + const scoped_refptr<cc::Layer>& content_layer, + float content_offset_y, float panel_x, float panel_y, float panel_width, @@ -70,7 +66,7 @@ scoped_refptr<cc::UIResourceLayer> bar_shadow_; scoped_refptr<cc::UIResourceLayer> panel_icon_; scoped_refptr<cc::UIResourceLayer> close_icon_; - scoped_refptr<cc::Layer> content_view_container_; + scoped_refptr<cc::Layer> content_container_; scoped_refptr<cc::Layer> text_container_; scoped_refptr<cc::SolidColorLayer> bar_border_;
diff --git a/chrome/browser/android/compositor/layer/reader_mode_layer.cc b/chrome/browser/android/compositor/layer/reader_mode_layer.cc index 68690af..b55d21c 100644 --- a/chrome/browser/android/compositor/layer/reader_mode_layer.cc +++ b/chrome/browser/android/compositor/layer/reader_mode_layer.cc
@@ -7,7 +7,6 @@ #include "cc/layers/layer.h" #include "cc/resources/scoped_ui_resource.h" #include "content/public/browser/android/compositor.h" -#include "content/public/browser/android/content_view_core.h" #include "ui/android/resources/resource_manager.h" namespace chrome { @@ -21,7 +20,7 @@ void ReaderModeLayer::SetProperties( float dp_to_px, - content::ContentViewCore* content_view_core, + const scoped_refptr<cc::Layer>& content_layer, float panel_x, float panel_y, float panel_width, @@ -38,7 +37,7 @@ OverlayPanelLayer::SetProperties( dp_to_px, - content_view_core, + content_layer, bar_height, panel_x, panel_y,
diff --git a/chrome/browser/android/compositor/layer/reader_mode_layer.h b/chrome/browser/android/compositor/layer/reader_mode_layer.h index 5549510..d513dd5b 100644 --- a/chrome/browser/android/compositor/layer/reader_mode_layer.h +++ b/chrome/browser/android/compositor/layer/reader_mode_layer.h
@@ -9,8 +9,8 @@ #include "chrome/browser/android/compositor/layer/overlay_panel_layer.h" -namespace content { -class ContentViewCore; +namespace cc { +class Layer; } namespace ui { @@ -26,7 +26,7 @@ ui::ResourceManager* resource_manager); void SetProperties(float dp_to_px, - content::ContentViewCore* content_view_core, + const scoped_refptr<cc::Layer>& content_layer, float panel_x, float panel_y, float panel_width,
diff --git a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc index 603b2d2..2a1d59e 100644 --- a/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc +++ b/chrome/browser/android/compositor/scene_layer/contextual_search_scene_layer.cc
@@ -9,9 +9,10 @@ #include "cc/layers/solid_color_layer.h" #include "chrome/browser/android/compositor/layer/contextual_search_layer.h" #include "content/public/browser/android/compositor.h" -#include "content/public/browser/android/content_view_core.h" +#include "content/public/browser/web_contents.h" #include "jni/ContextualSearchSceneLayer_jni.h" #include "ui/android/resources/resource_manager_impl.h" +#include "ui/android/view_android.h" #include "ui/gfx/android/java_bitmap.h" namespace chrome { @@ -65,7 +66,7 @@ jfloat dp_to_px, jfloat base_page_brightness, jfloat base_page_offset, - const JavaParamRef<jobject>& jcontent_view_core, + const JavaParamRef<jobject>& jweb_contents, jboolean search_promo_visible, jfloat search_promo_height, jfloat search_promo_opacity, @@ -98,13 +99,14 @@ jfloat progress_bar_height, jfloat progress_bar_opacity, jint progress_bar_completion) { - // NOTE(pedrosimonetti): The ContentViewCore might not exist at this time if + // NOTE(pedrosimonetti): The WebContents might not exist at this time if // the Contextual Search Result has not been requested yet. In this case, // we'll pass NULL to Contextual Search's Layer Tree. - content::ContentViewCore* content_view_core = - !jcontent_view_core ? NULL - : content::ContentViewCore::GetNativeContentViewCore( - env, jcontent_view_core); + content::WebContents* web_contents = + content::WebContents::FromJavaWebContents(jweb_contents); + + scoped_refptr<cc::Layer> content_layer = + web_contents ? web_contents->GetNativeView()->GetLayer() : nullptr; // Fade the base page out. if (base_page_brightness_ != base_page_brightness) { @@ -136,7 +138,7 @@ peek_promo_ripple_resource_id, peek_promo_text_resource_id, dp_to_px, - content_view_core, + content_layer, search_promo_visible, search_promo_height, search_promo_opacity,
diff --git a/chrome/browser/android/compositor/scene_layer/reader_mode_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/reader_mode_scene_layer.cc index 16e41d87..ddce855 100644 --- a/chrome/browser/android/compositor/scene_layer/reader_mode_scene_layer.cc +++ b/chrome/browser/android/compositor/scene_layer/reader_mode_scene_layer.cc
@@ -9,9 +9,10 @@ #include "cc/layers/solid_color_layer.h" #include "chrome/browser/android/compositor/layer/reader_mode_layer.h" #include "content/public/browser/android/compositor.h" -#include "content/public/browser/android/content_view_core.h" +#include "content/public/browser/web_contents.h" #include "jni/ReaderModeSceneLayer_jni.h" #include "ui/android/resources/resource_manager_impl.h" +#include "ui/android/view_android.h" #include "ui/gfx/android/java_bitmap.h" namespace chrome { @@ -67,7 +68,7 @@ jfloat dp_to_px, jfloat base_page_brightness, jfloat base_page_offset, - const JavaParamRef<jobject>& jcontent_view_core, + const JavaParamRef<jobject>& jweb_contents, jfloat panel_X, jfloat panel_y, jfloat panel_width, @@ -80,12 +81,13 @@ jboolean bar_shadow_visible, jfloat bar_shadow_opacity) { // NOTE(mdjones): It is possible to render the panel before content has been - // created. If this is the case, do not attempt to access the ContentViewCore + // created. If this is the case, do not attempt to access the WebContents // and instead pass null. - content::ContentViewCore* content_view_core = - !jcontent_view_core ? NULL - : content::ContentViewCore::GetNativeContentViewCore( - env, jcontent_view_core); + content::WebContents* web_contents = + content::WebContents::FromJavaWebContents(jweb_contents); + + scoped_refptr<cc::Layer> content_layer = + web_contents ? web_contents->GetNativeView()->GetLayer() : nullptr; // Fade the base page out. if (base_page_brightness_ != base_page_brightness) { @@ -103,7 +105,7 @@ reader_mode_layer_->SetProperties( dp_to_px, - content_view_core, + content_layer, panel_X, panel_y, panel_width,
diff --git a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc index c4048e6..7c1d27a 100644 --- a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc +++ b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
@@ -427,43 +427,48 @@ int* mention_start, int* mention_end, std::string* lang) { - bool contains_xssi_escape = response.find(kXssiEscape) == 0; + bool contains_xssi_escape = + base::StartsWith(response, kXssiEscape, base::CompareCase::SENSITIVE); const std::string& proper_json = - contains_xssi_escape ? response.substr(strlen(kXssiEscape)) : response; + contains_xssi_escape ? response.substr(sizeof(kXssiEscape) - 1) + : response; JSONStringValueDeserializer deserializer(proper_json); - std::unique_ptr<base::Value> root = deserializer.Deserialize(NULL, NULL); + std::unique_ptr<base::Value> root = + deserializer.Deserialize(nullptr, nullptr); + std::unique_ptr<base::DictionaryValue> dict = + base::DictionaryValue::From(std::move(root)); + if (!dict) + return; - if (root.get() != NULL && root->IsType(base::Value::TYPE_DICTIONARY)) { - base::DictionaryValue* dict = - static_cast<base::DictionaryValue*>(root.get()); - dict->GetString(kContextualSearchPreventPreload, prevent_preload); - dict->GetString(kContextualSearchResponseSearchTermParam, search_term); - dict->GetString(kContextualSearchResponseLanguageParam, lang); - // For the display_text, if not present fall back to the "search_term". - if (!dict->GetString(kContextualSearchResponseDisplayTextParam, - display_text)) { - *display_text = *search_term; - } - // Extract mentions for selection expansion. - if (!field_trial_->IsDecodeMentionsDisabled()) { - base::ListValue* mentions_list = NULL; - dict->GetList(kContextualSearchMentions, &mentions_list); - if (mentions_list != NULL && mentions_list->GetSize() >= 2) - ExtractMentionsStartEnd(*mentions_list, mention_start, mention_end); - } - // If either the selected text or the resolved term is not the search term, - // use it as the alternate term. - std::string selected_text; - dict->GetString(kContextualSearchResponseSelectedTextParam, &selected_text); - if (selected_text != *search_term) { - *alternate_term = selected_text; - } else { - std::string resolved_term; - dict->GetString(kContextualSearchResponseResolvedTermParam, - &resolved_term); - if (resolved_term != *search_term) { - *alternate_term = resolved_term; - } + dict->GetString(kContextualSearchPreventPreload, prevent_preload); + dict->GetString(kContextualSearchResponseSearchTermParam, search_term); + dict->GetString(kContextualSearchResponseLanguageParam, lang); + + // For the display_text, if not present fall back to the "search_term". + if (!dict->GetString(kContextualSearchResponseDisplayTextParam, + display_text)) { + *display_text = *search_term; + } + + // Extract mentions for selection expansion. + if (!field_trial_->IsDecodeMentionsDisabled()) { + base::ListValue* mentions_list = nullptr; + dict->GetList(kContextualSearchMentions, &mentions_list); + if (mentions_list && mentions_list->GetSize() >= 2) + ExtractMentionsStartEnd(*mentions_list, mention_start, mention_end); + } + + // If either the selected text or the resolved term is not the search term, + // use it as the alternate term. + std::string selected_text; + dict->GetString(kContextualSearchResponseSelectedTextParam, &selected_text); + if (selected_text != *search_term) { + *alternate_term = selected_text; + } else { + std::string resolved_term; + dict->GetString(kContextualSearchResponseResolvedTermParam, &resolved_term); + if (resolved_term != *search_term) { + *alternate_term = resolved_term; } } }
diff --git a/chrome/browser/android/ntp/most_visited_sites_bridge.cc b/chrome/browser/android/ntp/most_visited_sites_bridge.cc index 54f2fd0c..73e68b4 100644 --- a/chrome/browser/android/ntp/most_visited_sites_bridge.cc +++ b/chrome/browser/android/ntp/most_visited_sites_bridge.cc
@@ -36,6 +36,7 @@ using base::android::ScopedJavaGlobalRef; using base::android::ScopedJavaLocalRef; using base::android::ToJavaArrayOfStrings; +using base::android::ToJavaIntArray; using content::BrowserThread; using ntp_tiles::MostVisitedSites; using ntp_tiles::MostVisitedSitesSupervisor; @@ -118,18 +119,23 @@ std::vector<base::string16> titles; std::vector<std::string> urls; std::vector<std::string> whitelist_icon_paths; + std::vector<int> sources; + titles.reserve(suggestions.size()); urls.reserve(suggestions.size()); whitelist_icon_paths.reserve(suggestions.size()); + sources.reserve(suggestions.size()); for (const auto& suggestion : suggestions) { titles.emplace_back(suggestion.title); urls.emplace_back(suggestion.url.spec()); whitelist_icon_paths.emplace_back(suggestion.whitelist_icon_path.value()); + sources.emplace_back(suggestion.source); } Java_MostVisitedURLsObserver_onMostVisitedURLsAvailable( env, observer_.obj(), ToJavaArrayOfStrings(env, titles).obj(), ToJavaArrayOfStrings(env, urls).obj(), - ToJavaArrayOfStrings(env, whitelist_icon_paths).obj()); + ToJavaArrayOfStrings(env, whitelist_icon_paths).obj(), + ToJavaIntArray(env, sources).obj()); } void MostVisitedSitesBridge::JavaObserver::OnPopularURLsAvailable( @@ -193,18 +199,24 @@ void MostVisitedSitesBridge::RecordTileTypeMetrics( JNIEnv* env, const JavaParamRef<jobject>& obj, - const JavaParamRef<jintArray>& jtile_types) { + const JavaParamRef<jintArray>& jtile_types, + const JavaParamRef<jintArray>& jsources) { std::vector<int> tile_types; + std::vector<int> sources; + base::android::JavaIntArrayToIntVector(env, jtile_types, &tile_types); - most_visited_.RecordTileTypeMetrics(tile_types); + base::android::JavaIntArrayToIntVector(env, jsources, &sources); + + most_visited_.RecordTileTypeMetrics(tile_types, sources); } void MostVisitedSitesBridge::RecordOpenedMostVisitedItem( JNIEnv* env, const JavaParamRef<jobject>& obj, jint index, - jint tile_type) { - most_visited_.RecordOpenedMostVisitedItem(index, tile_type); + jint tile_type, + jint source) { + most_visited_.RecordOpenedMostVisitedItem(index, tile_type, source); } // static
diff --git a/chrome/browser/android/ntp/most_visited_sites_bridge.h b/chrome/browser/android/ntp/most_visited_sites_bridge.h index 2959c92..5c907e5 100644 --- a/chrome/browser/android/ntp/most_visited_sites_bridge.h +++ b/chrome/browser/android/ntp/most_visited_sites_bridge.h
@@ -41,12 +41,14 @@ void RecordTileTypeMetrics( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, - const base::android::JavaParamRef<jintArray>& jtile_types); + const base::android::JavaParamRef<jintArray>& jtile_types, + const base::android::JavaParamRef<jintArray>& jsources); void RecordOpenedMostVisitedItem( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, jint index, - jint tile_type); + jint tile_type, + jint source); // Registers JNI methods. static bool Register(JNIEnv* env);
diff --git a/chrome/browser/android/ntp/ntp_snippets_bridge.cc b/chrome/browser/android/ntp/ntp_snippets_bridge.cc index e6e9cdd..373de14c8 100644 --- a/chrome/browser/android/ntp/ntp_snippets_bridge.cc +++ b/chrome/browser/android/ntp/ntp_snippets_bridge.cc
@@ -93,7 +93,7 @@ const JavaParamRef<jstring>& snippet_id, const JavaParamRef<jobject>& j_callback) { base::android::ScopedJavaGlobalRef<jobject> callback(j_callback); - ntp_snippets_service_->FetchSnippetImage( + ntp_snippets_service_->FetchSuggestionImage( ConvertJavaStringToUTF8(env, snippet_id), base::Bind(&NTPSnippetsBridge::OnImageFetched, weak_ptr_factory_.GetWeakPtr(), callback)); @@ -102,7 +102,7 @@ void NTPSnippetsBridge::DiscardSnippet(JNIEnv* env, const JavaParamRef<jobject>& obj, const JavaParamRef<jstring>& id) { - ntp_snippets_service_->DiscardSnippet(ConvertJavaStringToUTF8(env, id)); + ntp_snippets_service_->DiscardSuggestion(ConvertJavaStringToUTF8(env, id)); } void NTPSnippetsBridge::SnippetVisited(JNIEnv* env,
diff --git a/chrome/browser/android/offline_pages/prerendering_loader.cc b/chrome/browser/android/offline_pages/prerendering_loader.cc index b82a149..6f454028 100644 --- a/chrome/browser/android/offline_pages/prerendering_loader.cc +++ b/chrome/browser/android/offline_pages/prerendering_loader.cc
@@ -164,8 +164,8 @@ // Request status depends on whether we are still loading (failed) or // did load and then loading was stopped (cancel - from prerender stack). Offliner::RequestStatus request_status = - IsLoaded() ? Offliner::RequestStatus::CANCELED - : Offliner::RequestStatus::FAILED; + IsLoaded() ? Offliner::RequestStatus::PRERENDERING_CANCELED + : Offliner::RequestStatus::PRERENDERING_FAILED; // TODO(dougarnett): For failure, determine from final status if retry-able // and report different failure statuses if retry-able or not. snapshot_controller_.reset(nullptr); @@ -181,11 +181,6 @@ } snapshot_controller_.reset(nullptr); session_contents_.reset(nullptr); - if (!IsLoaded() && !IsIdle()) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(callback_, Offliner::RequestStatus::CANCELED, nullptr)); - } state_ = State::IDLE; }
diff --git a/chrome/browser/android/offline_pages/prerendering_loader_unittest.cc b/chrome/browser/android/offline_pages/prerendering_loader_unittest.cc index d7f28d9..f662f123 100644 --- a/chrome/browser/android/offline_pages/prerendering_loader_unittest.cc +++ b/chrome/browser/android/offline_pages/prerendering_loader_unittest.cc
@@ -223,7 +223,8 @@ PumpLoop(); EXPECT_TRUE(loader()->IsIdle()); EXPECT_FALSE(loader()->IsLoaded()); - EXPECT_EQ(Offliner::RequestStatus::CANCELED, callback_load_status()); + EXPECT_EQ(Offliner::RequestStatus::PRERENDERING_CANCELED, + callback_load_status()); } TEST_F(PrerenderingLoaderTest, LoadPageLoadFailedNoContent) { @@ -243,7 +244,8 @@ EXPECT_TRUE(loader()->IsIdle()); EXPECT_TRUE(callback_called()); // We did not provide any WebContents for the callback so expect did not load. - EXPECT_EQ(Offliner::RequestStatus::FAILED, callback_load_status()); + EXPECT_EQ(Offliner::RequestStatus::PRERENDERING_FAILED, + callback_load_status()); // Stopped event causes no harm. test_adapter()->GetObserver()->OnPrerenderStop(); @@ -262,8 +264,7 @@ loader()->StopLoading(); PumpLoop(); EXPECT_TRUE(loader()->IsIdle()); - EXPECT_TRUE(callback_called()); - EXPECT_EQ(Offliner::RequestStatus::CANCELED, callback_load_status()); + EXPECT_FALSE(callback_called()); } TEST_F(PrerenderingLoaderTest, LoadPageNotAcceptedWhenNotIdle) {
diff --git a/chrome/browser/android/offline_pages/prerendering_offliner.cc b/chrome/browser/android/offline_pages/prerendering_offliner.cc index bab7d7f..cf8625f 100644 --- a/chrome/browser/android/offline_pages/prerendering_offliner.cc +++ b/chrome/browser/android/offline_pages/prerendering_offliner.cc
@@ -97,7 +97,7 @@ } else { // TODO(dougarnett): Consider reflecting some recommendation to retry the // request based on specific save error cases. - save_status = RequestStatus::FAILED_SAVE; + save_status = RequestStatus::SAVE_FAILED; } completion_callback.Run(request, save_status); }
diff --git a/chrome/browser/android/offline_pages/prerendering_offliner_unittest.cc b/chrome/browser/android/offline_pages/prerendering_offliner_unittest.cc index eef086b..f2a4b78 100644 --- a/chrome/browser/android/offline_pages/prerendering_offliner_unittest.cc +++ b/chrome/browser/android/offline_pages/prerendering_offliner_unittest.cc
@@ -56,9 +56,9 @@ mock_loading_ = false; mock_loaded_ = false; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(load_page_callback_, Offliner::RequestStatus::FAILED, - nullptr /* web_contents */)); + FROM_HERE, base::Bind(load_page_callback_, + Offliner::RequestStatus::PRERENDERING_FAILED, + nullptr /* web_contents */)); } void CompleteLoadingAsLoaded() { @@ -77,9 +77,9 @@ mock_loading_ = false; mock_loaded_ = false; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(load_page_callback_, Offliner::RequestStatus::CANCELED, - nullptr /* web_contents */)); + FROM_HERE, base::Bind(load_page_callback_, + Offliner::RequestStatus::PRERENDERING_CANCELED, + nullptr /* web_contents */)); } void DisablePrerendering() { can_prerender_ = false; } @@ -221,7 +221,7 @@ loader()->CompleteLoadingAsFailed(); PumpLoop(); EXPECT_TRUE(completion_callback_called()); - EXPECT_EQ(Offliner::RequestStatus::FAILED, request_status()); + EXPECT_EQ(Offliner::RequestStatus::PRERENDERING_FAILED, request_status()); EXPECT_TRUE(loader()->IsIdle()); EXPECT_FALSE(SaveInProgress()); } @@ -280,7 +280,7 @@ model()->CompleteSavingAsArchiveCreationFailed(); PumpLoop(); EXPECT_TRUE(completion_callback_called()); - EXPECT_EQ(Offliner::RequestStatus::FAILED_SAVE, request_status()); + EXPECT_EQ(Offliner::RequestStatus::SAVE_FAILED, request_status()); EXPECT_FALSE(loader()->IsLoaded()); EXPECT_FALSE(SaveInProgress()); } @@ -322,7 +322,7 @@ loader()->CompleteLoadingAsCanceled(); PumpLoop(); EXPECT_TRUE(completion_callback_called()); - EXPECT_EQ(Offliner::RequestStatus::CANCELED, request_status()); + EXPECT_EQ(Offliner::RequestStatus::PRERENDERING_CANCELED, request_status()); EXPECT_FALSE(loader()->IsLoaded()); // Note: save still in progress since it does not support canceling. EXPECT_TRUE(SaveInProgress());
diff --git a/chrome/browser/android/preferences/website_preference_bridge.cc b/chrome/browser/android/preferences/website_preference_bridge.cc index c6b5d7d..fd92c2d1 100644 --- a/chrome/browser/android/preferences/website_preference_bridge.cc +++ b/chrome/browser/android/preferences/website_preference_bridge.cc
@@ -471,7 +471,7 @@ NULL); cookies_tree_model_.reset(new CookiesTreeModel( - container, profile_->GetExtensionSpecialStoragePolicy(), false)); + container, profile_->GetExtensionSpecialStoragePolicy())); cookies_tree_model_->AddCookiesTreeObserver(this); }
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.cc b/chrome/browser/android/tab_web_contents_delegate_android.cc index 81f87c8..ea60eac 100644 --- a/chrome/browser/android/tab_web_contents_delegate_android.cc +++ b/chrome/browser/android/tab_web_contents_delegate_android.cc
@@ -10,6 +10,7 @@ #include "base/android/jni_string.h" #include "base/command_line.h" #include "base/memory/ptr_util.h" +#include "chrome/browser/android/banners/app_banner_manager_android.h" #include "chrome/browser/android/feature_utilities.h" #include "chrome/browser/android/hung_renderer_infobar_delegate.h" #include "chrome/browser/android/media/media_throttle_infobar_delegate.h" @@ -417,11 +418,10 @@ void TabWebContentsDelegateAndroid::RequestAppBannerFromDevTools( content::WebContents* web_contents) { - JNIEnv* env = base::android::AttachCurrentThread(); - ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env); - if (obj.is_null()) - return; - Java_TabWebContentsDelegateAndroid_requestAppBanner(env, obj.obj()); + banners::AppBannerManagerAndroid* manager = + banners::AppBannerManagerAndroid::FromWebContents(web_contents); + DCHECK(manager); + manager->RequestAppBanner(web_contents->GetLastCommittedURL(), true); } } // namespace android
diff --git a/chrome/browser/apps/app_browsertest.cc b/chrome/browser/apps/app_browsertest.cc index fcc1f00..f6f699e 100644 --- a/chrome/browser/apps/app_browsertest.cc +++ b/chrome/browser/apps/app_browsertest.cc
@@ -90,7 +90,7 @@ protected: // RenderViewContextMenu implementation. bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override { + ui::Accelerator* accelerator) const override { return false; } };
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index a414b17..a587632 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -1541,16 +1541,9 @@ // This test makes sure the browser process does not crash if browser is shut // down while an interstitial page is being shown in guest. -// Flaky on Windows. http://crbug.com/619508. -#if defined(OS_WIN) -#define MAYBE_InterstitialTeardownOnBrowserShutdown \ - DISABLED_InterstitialTeardownOnBrowserShutdown -#else -#define MAYBE_InterstitialTeardownOnBrowserShutdown \ - InterstitialTeardownOnBrowserShutdown -#endif +// Flaky. http://crbug.com/627962. IN_PROC_BROWSER_TEST_P(WebViewTest, - MAYBE_InterstitialTeardownOnBrowserShutdown) { + DISABLED_InterstitialTeardownOnBrowserShutdown) { InterstitialTeardownTestHelper(); // Now close the app while interstitial page being shown in guest.
diff --git a/chrome/browser/banners/app_banner_data_fetcher.cc b/chrome/browser/banners/app_banner_data_fetcher.cc index fe4e8742..3cc2811 100644 --- a/chrome/browser/banners/app_banner_data_fetcher.cc +++ b/chrome/browser/banners/app_banner_data_fetcher.cc
@@ -106,8 +106,8 @@ transition_type_ = transition_type; validated_url_ = validated_url; referrer_.erase(); - web_contents->HasManifest( - base::Bind(&AppBannerDataFetcher::OnDidHasManifest, this)); + web_contents->GetManifest( + base::Bind(&AppBannerDataFetcher::OnDidGetManifest, this)); } void AppBannerDataFetcher::Cancel() { @@ -270,21 +270,6 @@ web_contents->GetURL()); } -void AppBannerDataFetcher::OnDidHasManifest(bool has_manifest) { - content::WebContents* web_contents = GetWebContents(); - - if (!CheckFetcherIsStillAlive(web_contents) || !has_manifest) { - if (!has_manifest) - OutputDeveloperNotShownMessage(web_contents, kNoManifest, is_debug_mode_); - - Cancel(); - return; - } - - web_contents->GetManifest( - base::Bind(&AppBannerDataFetcher::OnDidGetManifest, this)); -} - void AppBannerDataFetcher::OnDidGetManifest( const GURL& manifest_url, const content::Manifest& manifest) { @@ -293,6 +278,11 @@ Cancel(); return; } + if (manifest_url.is_empty()) { + OutputDeveloperNotShownMessage(web_contents, kNoManifest, is_debug_mode_); + Cancel(); + return; + } if (manifest.IsEmpty()) { OutputDeveloperNotShownMessage(web_contents, kManifestEmpty, is_debug_mode_);
diff --git a/chrome/browser/banners/app_banner_data_fetcher.h b/chrome/browser/banners/app_banner_data_fetcher.h index a1af6fc..e5b259ae 100644 --- a/chrome/browser/banners/app_banner_data_fetcher.h +++ b/chrome/browser/banners/app_banner_data_fetcher.h
@@ -147,7 +147,6 @@ private: // Callbacks for data retrieval. - void OnDidHasManifest(bool has_manifest); void OnDidGetManifest(const GURL& manifest_url, const content::Manifest& manifest); void OnDidCheckHasServiceWorker(bool has_service_worker);
diff --git a/chrome/browser/banners/app_banner_manager.h b/chrome/browser/banners/app_banner_manager.h index b42eb32..20969abb 100644 --- a/chrome/browser/banners/app_banner_manager.h +++ b/chrome/browser/banners/app_banner_manager.h
@@ -40,7 +40,7 @@ // Requests an app banner. Set |is_debug_mode| when it is triggered by the // developer's action in DevTools. - void RequestAppBanner(const GURL& validated_url, bool is_debug_mode); + virtual void RequestAppBanner(const GURL& validated_url, bool is_debug_mode); ~AppBannerManager() override;
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 39d810a1..f71c9bd3 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -347,9 +347,6 @@ </if> <include name="IDR_PROFILER_HTML" file="resources\profiler\profiler.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_PROFILER_JS" file="resources\profiler\profiler.js" flattenhtml="true" type="BINDATA" /> - <if expr="enable_settings_app"> - <include name="IDR_SETTINGS_APP_MANIFEST" file="resources\settings_app\manifest.json" type="BINDATA" /> - </if> <if expr="enable_google_now"> <include name="IDR_GOOGLE_NOW_MANIFEST" file="resources\google_now\manifest.json" type="BINDATA" /> </if>
diff --git a/chrome/browser/browsing_data/autofill_counter.cc b/chrome/browser/browsing_data/autofill_counter.cc index 72e7cd52..68eda9eaf1 100644 --- a/chrome/browser/browsing_data/autofill_counter.cc +++ b/chrome/browser/browsing_data/autofill_counter.cc
@@ -11,13 +11,13 @@ #include "base/memory/scoped_vector.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/web_data_service_factory.h" -#include "chrome/common/pref_names.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" +#include "components/browsing_data/pref_names.h" AutofillCounter::AutofillCounter(Profile* profile) - : BrowsingDataCounter(prefs::kDeleteFormData), + : BrowsingDataCounter(browsing_data::prefs::kDeleteFormData), profile_(profile), web_data_service_(nullptr), suggestions_query_(0),
diff --git a/chrome/browser/browsing_data/autofill_counter_browsertest.cc b/chrome/browser/browsing_data/autofill_counter_browsertest.cc index 6a4193b..f74a989 100644 --- a/chrome/browser/browsing_data/autofill_counter_browsertest.cc +++ b/chrome/browser/browsing_data/autofill_counter_browsertest.cc
@@ -14,7 +14,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/web_data_service_factory.h" -#include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/autofill_type.h" @@ -134,7 +133,8 @@ // Other utils --------------------------------------------------------------- void SetAutofillDeletionPref(bool value) { - browser()->profile()->GetPrefs()->SetBoolean(prefs::kDeleteFormData, value); + browser()->profile()->GetPrefs()->SetBoolean( + browsing_data::prefs::kDeleteFormData, value); } void SetDeletionPeriodPref(browsing_data::TimePeriod period) {
diff --git a/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc index 0220cd5..d8c9decf 100644 --- a/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc +++ b/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc
@@ -22,8 +22,6 @@ CookieExpectation() {} bool MatchesCookie(const net::CanonicalCookie& cookie) const { - if (!source_.is_empty() && source_ != cookie.Source()) - return false; if (!domain_.empty() && domain_ != cookie.Domain()) return false; if (!path_.empty() && path_ != cookie.Path()) @@ -189,9 +187,10 @@ ASSERT_EQ(3U, cookie_list.size()); } - void DeleteCookie(BrowsingDataCookieHelper* helper, const GURL origin) { + void DeleteCookie(BrowsingDataCookieHelper* helper, + const std::string& domain) { for (const auto& cookie : cookie_list_) { - if (cookie.Source() == origin) + if (cookie.Domain() == domain) helper->DeleteCookie(cookie); } } @@ -265,7 +264,7 @@ EXPECT_EQ(2u, helper->GetCookieCount()); - DeleteCookie(helper.get(), origin1); + DeleteCookie(helper.get(), origin1.host()); EXPECT_EQ(1u, helper->GetCookieCount()); helper->StartFetching(
diff --git a/chrome/browser/browsing_data/browsing_data_counter_factory.cc b/chrome/browser/browsing_data/browsing_data_counter_factory.cc index 6314600..40a749b1 100644 --- a/chrome/browser/browsing_data/browsing_data_counter_factory.cc +++ b/chrome/browser/browsing_data/browsing_data_counter_factory.cc
@@ -13,8 +13,8 @@ #include "chrome/browser/browsing_data/media_licenses_counter.h" #include "chrome/browser/browsing_data/passwords_counter.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/common/pref_names.h" #include "components/browsing_data/counters/browsing_data_counter.h" +#include "components/browsing_data/pref_names.h" #if defined(ENABLE_EXTENSIONS) #include "chrome/browser/browsing_data/hosted_apps_counter.h" @@ -27,26 +27,26 @@ if (!AreCountersEnabled()) return nullptr; - if (pref_name == prefs::kDeleteBrowsingHistory) + if (pref_name == browsing_data::prefs::kDeleteBrowsingHistory) return base::MakeUnique<HistoryCounter>(profile); - if (pref_name == prefs::kDeleteCache) + if (pref_name == browsing_data::prefs::kDeleteCache) return base::MakeUnique<CacheCounter>(profile); - if (pref_name == prefs::kDeletePasswords) + if (pref_name == browsing_data::prefs::kDeletePasswords) return base::MakeUnique<PasswordsCounter>(profile); - if (pref_name == prefs::kDeleteFormData) + if (pref_name == browsing_data::prefs::kDeleteFormData) return base::MakeUnique<AutofillCounter>(profile); - if (pref_name == prefs::kDeleteDownloadHistory) + if (pref_name == browsing_data::prefs::kDeleteDownloadHistory) return base::MakeUnique<DownloadsCounter>(profile); - if (pref_name == prefs::kDeleteMediaLicenses) + if (pref_name == browsing_data::prefs::kDeleteMediaLicenses) return base::MakeUnique<MediaLicensesCounter>(profile); #if defined(ENABLE_EXTENSIONS) - if (pref_name == prefs::kDeleteHostedAppsData) + if (pref_name == browsing_data::prefs::kDeleteHostedAppsData) return base::MakeUnique<HostedAppsCounter>(profile); #endif
diff --git a/chrome/browser/browsing_data/browsing_data_counter_utils.cc b/chrome/browser/browsing_data/browsing_data_counter_utils.cc index 9e855e6..387b503 100644 --- a/chrome/browser/browsing_data/browsing_data_counter_utils.cc +++ b/chrome/browser/browsing_data/browsing_data_counter_utils.cc
@@ -63,20 +63,20 @@ // The counter is still counting. text = l10n_util::GetStringUTF16(IDS_CLEAR_BROWSING_DATA_CALCULATING); - } else if (pref_name == prefs::kDeletePasswords || - pref_name == prefs::kDeleteDownloadHistory) { + } else if (pref_name == browsing_data::prefs::kDeletePasswords || + pref_name == browsing_data::prefs::kDeleteDownloadHistory) { // Counters with trivially formatted result: passwords and downloads. browsing_data::BrowsingDataCounter::ResultInt count = static_cast<const browsing_data::BrowsingDataCounter::FinishedResult*>( result) ->Value(); text = l10n_util::GetPluralStringFUTF16( - pref_name == prefs::kDeletePasswords + pref_name == browsing_data::prefs::kDeletePasswords ? IDS_DEL_PASSWORDS_COUNTER : IDS_DEL_DOWNLOADS_COUNTER, count); - } else if (pref_name == prefs::kDeleteCache) { + } else if (pref_name == browsing_data::prefs::kDeleteCache) { // Cache counter. browsing_data::BrowsingDataCounter::ResultInt cache_size_bytes = static_cast<const browsing_data::BrowsingDataCounter::FinishedResult*>( @@ -101,7 +101,7 @@ text = l10n_util::GetStringUTF16(IDS_DEL_CACHE_COUNTER_ALMOST_EMPTY); } - } else if (pref_name == prefs::kDeleteBrowsingHistory) { + } else if (pref_name == browsing_data::prefs::kDeleteBrowsingHistory) { // History counter. const HistoryCounter::HistoryResult* history_result = static_cast<const HistoryCounter::HistoryResult*>(result); @@ -115,7 +115,7 @@ : l10n_util::GetPluralStringFUTF16( IDS_DEL_BROWSING_HISTORY_COUNTER, local_item_count); - } else if (pref_name == prefs::kDeleteFormData) { + } else if (pref_name == browsing_data::prefs::kDeleteFormData) { // Autofill counter. const AutofillCounter::AutofillResult* autofill_result = static_cast<const AutofillCounter::AutofillResult*>(result); @@ -178,7 +178,7 @@ NOTREACHED(); } - } else if (pref_name == prefs::kDeleteMediaLicenses) { + } else if (pref_name == browsing_data::prefs::kDeleteMediaLicenses) { const MediaLicensesCounter::MediaLicenseResult* media_license_result = static_cast<const MediaLicensesCounter::MediaLicenseResult*>(result); if (media_license_result->Value() > 0) { @@ -191,7 +191,7 @@ } #if defined(ENABLE_EXTENSIONS) - } else if (pref_name == prefs::kDeleteHostedAppsData) { + } else if (pref_name == browsing_data::prefs::kDeleteHostedAppsData) { // Hosted apps counter. const HostedAppsCounter::HostedAppsResult* hosted_apps_result = static_cast<const HostedAppsCounter::HostedAppsResult*>(result); @@ -235,19 +235,19 @@ std::string* out_pref) { switch (data_type) { case browsing_data::HISTORY: - *out_pref = prefs::kDeleteBrowsingHistory; + *out_pref = browsing_data::prefs::kDeleteBrowsingHistory; return true; case browsing_data::CACHE: - *out_pref = prefs::kDeleteCache; + *out_pref = browsing_data::prefs::kDeleteCache; return true; case browsing_data::COOKIES: - *out_pref = prefs::kDeleteCookies; + *out_pref = browsing_data::prefs::kDeleteCookies; return true; case browsing_data::PASSWORDS: - *out_pref = prefs::kDeletePasswords; + *out_pref = browsing_data::prefs::kDeletePasswords; return true; case browsing_data::FORM_DATA: - *out_pref = prefs::kDeleteFormData; + *out_pref = browsing_data::prefs::kDeleteFormData; return true; case browsing_data::BOOKMARKS: // Bookmarks are deleted on the Android side. No corresponding deletion
diff --git a/chrome/browser/browsing_data/browsing_data_remover.cc b/chrome/browser/browsing_data/browsing_data_remover.cc index 455327d7..a877c039 100644 --- a/chrome/browser/browsing_data/browsing_data_remover.cc +++ b/chrome/browser/browsing_data/browsing_data_remover.cc
@@ -784,7 +784,8 @@ base::Closure on_cleared_auto_sign_in = base::Bind(&BrowsingDataRemover::OnClearedAutoSignIn, weak_ptr_factory_.GetWeakPtr()); - password_store->DisableAutoSignInForAllLogins(on_cleared_auto_sign_in); + password_store->DisableAutoSignInForOrigins( + filter, on_cleared_auto_sign_in); } }
diff --git a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc index 0084c25e..9567c8ea 100644 --- a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc +++ b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
@@ -2384,8 +2384,12 @@ TEST_F(BrowsingDataRemoverTest, DisableAutoSignIn) { RemovePasswordsTester tester(GetProfile()); + base::Callback<bool(const GURL&)> empty_filter = + BrowsingDataFilterBuilder::BuildNoopFilter(); - EXPECT_CALL(*tester.store(), DisableAutoSignInForAllLoginsImpl()) + EXPECT_CALL( + *tester.store(), + DisableAutoSignInForOriginsImpl(ProbablySameFilter(empty_filter))) .WillOnce(Return(password_manager::PasswordStoreChangeList())); BlockUntilBrowsingDataRemoved(browsing_data::EVERYTHING, @@ -2394,10 +2398,14 @@ TEST_F(BrowsingDataRemoverTest, DisableAutoSignInAfterRemovingPasswords) { RemovePasswordsTester tester(GetProfile()); + base::Callback<bool(const GURL&)> empty_filter = + BrowsingDataFilterBuilder::BuildNoopFilter(); EXPECT_CALL(*tester.store(), RemoveLoginsByURLAndTimeImpl(_, _, _)) .WillOnce(Return(password_manager::PasswordStoreChangeList())); - EXPECT_CALL(*tester.store(), DisableAutoSignInForAllLoginsImpl()) + EXPECT_CALL( + *tester.store(), + DisableAutoSignInForOriginsImpl(ProbablySameFilter(empty_filter))) .WillOnce(Return(password_manager::PasswordStoreChangeList())); BlockUntilBrowsingDataRemoved(browsing_data::EVERYTHING,
diff --git a/chrome/browser/browsing_data/cache_counter.cc b/chrome/browser/browsing_data/cache_counter.cc index ac72816d..97494341 100644 --- a/chrome/browser/browsing_data/cache_counter.cc +++ b/chrome/browser/browsing_data/cache_counter.cc
@@ -4,12 +4,12 @@ #include "chrome/browser/browsing_data/cache_counter.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/common/pref_names.h" +#include "components/browsing_data/pref_names.h" #include "components/browsing_data/storage_partition_http_cache_data_remover.h" #include "net/base/net_errors.h" CacheCounter::CacheCounter(Profile* profile) - : BrowsingDataCounter(prefs::kDeleteCache), + : BrowsingDataCounter(browsing_data::prefs::kDeleteCache), profile_(profile), pending_(false), weak_ptr_factory_(this) {}
diff --git a/chrome/browser/browsing_data/cache_counter_browsertest.cc b/chrome/browser/browsing_data/cache_counter_browsertest.cc index 8e23a78..d036ba8 100644 --- a/chrome/browser/browsing_data/cache_counter_browsertest.cc +++ b/chrome/browser/browsing_data/cache_counter_browsertest.cc
@@ -13,7 +13,6 @@ #include "base/run_loop.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" -#include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/browsing_data/browsing_data_utils.h" @@ -39,7 +38,8 @@ } void SetCacheDeletionPref(bool value) { - browser()->profile()->GetPrefs()->SetBoolean(prefs::kDeleteCache, value); + browser()->profile()->GetPrefs()->SetBoolean( + browsing_data::prefs::kDeleteCache, value); } void SetDeletionPeriodPref(browsing_data::TimePeriod period) {
diff --git a/chrome/browser/browsing_data/cookies_tree_model.cc b/chrome/browser/browsing_data/cookies_tree_model.cc index 959624e..0b7d81e 100644 --- a/chrome/browser/browsing_data/cookies_tree_model.cc +++ b/chrome/browser/browsing_data/cookies_tree_model.cc
@@ -117,21 +117,6 @@ return retval; } -// When creating a cookie tree node from a cookie, strip the port of the -// cookie source and treat all non-file:// URLs as http://. -GURL CanonicalizeCookieSource(const net::CanonicalCookie& cookie) { - GURL url = cookie.Source(); - if (url.SchemeIsFile()) - return url; - - url::Replacements<char> replacements; - replacements.ClearPort(); - if (url.SchemeIsCryptographic()) - replacements.SetScheme("http", url::Component(0, 4)); - - return url.GetOrigin().ReplaceComponents(replacements); -} - #if defined(ENABLE_EXTENSIONS) bool TypeIsProtected(CookieTreeNode::DetailedInfo::NodeType type) { switch (type) { @@ -971,14 +956,12 @@ // CookiesTreeModel, public: CookiesTreeModel::CookiesTreeModel( LocalDataContainer* data_container, - ExtensionSpecialStoragePolicy* special_storage_policy, - bool group_by_cookie_source) + ExtensionSpecialStoragePolicy* special_storage_policy) : ui::TreeNodeModel<CookieTreeNode>(new CookieTreeRootNode(this)), - data_container_(data_container), #if defined(ENABLE_EXTENSIONS) special_storage_policy_(special_storage_policy), #endif - group_by_cookie_source_(group_by_cookie_source) { + data_container_(data_container) { data_container_->Init(this); } @@ -1219,18 +1202,13 @@ notifier->StartBatchUpdate(); for (CookieList::iterator it = container->cookie_list_.begin(); it != container->cookie_list_.end(); ++it) { - GURL source = CanonicalizeCookieSource(*it); - if (source.is_empty() || !group_by_cookie_source_) { - std::string domain = it->Domain(); - if (domain.length() > 1 && domain[0] == '.') - domain = domain.substr(1); + std::string domain = it->Domain(); + if (domain.length() > 1 && domain[0] == '.') + domain = domain.substr(1); - // We treat secure cookies just the same as normal ones. - source = GURL(std::string(url::kHttpScheme) + - url::kStandardSchemeSeparator + domain + "/"); - } - if (!source.SchemeIsHTTPOrHTTPS()) - continue; + // Cookies ignore schemes, so group all HTTP and HTTPS cookies together. + GURL source(std::string(url::kHttpScheme) + url::kStandardSchemeSeparator + + domain + "/"); if (filter.empty() || (CookieTreeHostNode::TitleForUrl(source) .find(filter) != base::string16::npos)) {
diff --git a/chrome/browser/browsing_data/cookies_tree_model.h b/chrome/browser/browsing_data/cookies_tree_model.h index 5a050bf..c693ce79 100644 --- a/chrome/browser/browsing_data/cookies_tree_model.h +++ b/chrome/browser/browsing_data/cookies_tree_model.h
@@ -686,8 +686,7 @@ class CookiesTreeModel : public ui::TreeNodeModel<CookieTreeNode> { public: CookiesTreeModel(LocalDataContainer* data_container, - ExtensionSpecialStoragePolicy* special_storage_policy, - bool group_by_cookie_source); + ExtensionSpecialStoragePolicy* special_storage_policy); ~CookiesTreeModel() override; // Given a CanonicalCookie, return the ID of the message which should be @@ -849,23 +848,19 @@ ScopedBatchUpdateNotifier* notifier, const base::string16& filter); - // Map of app ids to LocalDataContainer objects to use when retrieving - // locally stored data. - std::unique_ptr<LocalDataContainer> data_container_; - #if defined(ENABLE_EXTENSIONS) // The extension special storage policy; see ExtensionsProtectingNode() above. scoped_refptr<ExtensionSpecialStoragePolicy> special_storage_policy_; #endif + // Map of app ids to LocalDataContainer objects to use when retrieving + // locally stored data. + std::unique_ptr<LocalDataContainer> data_container_; + // The CookiesTreeModel maintains a separate list of observers that are // specifically of the type CookiesTreeModel::Observer. base::ObserverList<Observer> cookies_observer_list_; - // If true, use the CanonicalCookie::Source attribute to group cookies. - // Otherwise, use the CanonicalCookie::Domain attribute. - bool group_by_cookie_source_; - // Keeps track of how many batches the consumer of this class says it is going // to send. int batches_expected_ = 0;
diff --git a/chrome/browser/browsing_data/cookies_tree_model_unittest.cc b/chrome/browser/browsing_data/cookies_tree_model_unittest.cc index 1170490..89a237a6 100644 --- a/chrome/browser/browsing_data/cookies_tree_model_unittest.cc +++ b/chrome/browser/browsing_data/cookies_tree_model_unittest.cc
@@ -125,7 +125,7 @@ mock_browsing_data_flash_lso_helper_.get()); CookiesTreeModel* cookies_model = - new CookiesTreeModel(container, special_storage_policy(), false); + new CookiesTreeModel(container, special_storage_policy()); mock_browsing_data_cookie_helper_-> AddCookieSamples(GURL("http://foo1"), "A=1"); mock_browsing_data_cookie_helper_-> @@ -1100,7 +1100,7 @@ mock_browsing_data_service_worker_helper_.get(), mock_browsing_data_cache_storage_helper_.get(), mock_browsing_data_flash_lso_helper_.get()); - CookiesTreeModel cookies_model(container, special_storage_policy(), false); + CookiesTreeModel cookies_model(container, special_storage_policy()); mock_browsing_data_cookie_helper_-> AddCookieSamples(GURL("http://foo1"), "A=1"); @@ -1207,7 +1207,7 @@ mock_browsing_data_service_worker_helper_.get(), mock_browsing_data_cache_storage_helper_.get(), mock_browsing_data_flash_lso_helper_.get()); - CookiesTreeModel cookies_model(container, special_storage_policy(), false); + CookiesTreeModel cookies_model(container, special_storage_policy()); mock_browsing_data_cookie_helper_-> AddCookieSamples(GURL("http://foo1"), "A=1"); @@ -1317,7 +1317,7 @@ mock_browsing_data_service_worker_helper_.get(), mock_browsing_data_cache_storage_helper_.get(), mock_browsing_data_flash_lso_helper_.get()); - CookiesTreeModel cookies_model(container, special_storage_policy(), false); + CookiesTreeModel cookies_model(container, special_storage_policy()); mock_browsing_data_cookie_helper_-> AddCookieSamples(GURL("http://foo1"), "A=1"); @@ -1361,7 +1361,7 @@ mock_browsing_data_service_worker_helper_.get(), mock_browsing_data_cache_storage_helper_.get(), mock_browsing_data_flash_lso_helper_.get()); - CookiesTreeModel cookies_model(container, special_storage_policy(), false); + CookiesTreeModel cookies_model(container, special_storage_policy()); mock_browsing_data_cookie_helper_-> AddCookieSamples(GURL("http://a.foo2.com"), "A=1"); @@ -1410,7 +1410,7 @@ mock_browsing_data_service_worker_helper_.get(), mock_browsing_data_cache_storage_helper_.get(), mock_browsing_data_flash_lso_helper_.get()); - CookiesTreeModel cookies_model(container, special_storage_policy(), false); + CookiesTreeModel cookies_model(container, special_storage_policy()); mock_browsing_data_cookie_helper_->AddCookieSamples(host, "A=1"); mock_browsing_data_cookie_helper_->Notify(); @@ -1515,7 +1515,7 @@ mock_browsing_data_service_worker_helper_.get(), mock_browsing_data_cache_storage_helper_.get(), mock_browsing_data_flash_lso_helper_.get()); - CookiesTreeModel cookies_model(container, special_storage_policy(), false); + CookiesTreeModel cookies_model(container, special_storage_policy()); mock_browsing_data_cookie_helper_-> AddCookieSamples(GURL("http://123.com"), "A=1"); @@ -1557,8 +1557,7 @@ mock_browsing_data_service_worker_helper_.get(), mock_browsing_data_cache_storage_helper_.get(), mock_browsing_data_flash_lso_helper_.get()); - CookiesTreeModel cookies_model(container, special_storage_policy(), - true /* group by cookie source */); + CookiesTreeModel cookies_model(container, special_storage_policy()); mock_browsing_data_cookie_helper_->AddCookieSamples( GURL("file:///tmp/test.html"), "A=1"); @@ -1646,7 +1645,7 @@ mock_browsing_data_service_worker_helper_.get(), mock_browsing_data_cache_storage_helper_.get(), mock_browsing_data_flash_lso_helper_.get()); - CookiesTreeModel cookies_model(container, special_storage_policy(), false); + CookiesTreeModel cookies_model(container, special_storage_policy()); mock_browsing_data_cookie_helper_-> AddCookieSamples(GURL(), "A=1");
diff --git a/chrome/browser/browsing_data/downloads_counter.cc b/chrome/browser/browsing_data/downloads_counter.cc index f0e78e2..dd205ad 100644 --- a/chrome/browser/browsing_data/downloads_counter.cc +++ b/chrome/browser/browsing_data/downloads_counter.cc
@@ -6,11 +6,12 @@ #include "chrome/browser/download/download_history.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/common/pref_names.h" +#include "components/browsing_data/pref_names.h" #include "content/public/browser/download_manager.h" DownloadsCounter::DownloadsCounter(Profile* profile) - : BrowsingDataCounter(prefs::kDeleteDownloadHistory), profile_(profile) {} + : BrowsingDataCounter(browsing_data::prefs::kDeleteDownloadHistory), + profile_(profile) {} DownloadsCounter::~DownloadsCounter() { }
diff --git a/chrome/browser/browsing_data/downloads_counter_browsertest.cc b/chrome/browser/browsing_data/downloads_counter_browsertest.cc index 4b444f0..c4a2ca6 100644 --- a/chrome/browser/browsing_data/downloads_counter_browsertest.cc +++ b/chrome/browser/browsing_data/downloads_counter_browsertest.cc
@@ -15,7 +15,6 @@ #include "chrome/browser/download/download_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" -#include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "components/browsing_data/browsing_data_utils.h" #include "components/browsing_data/pref_names.h" @@ -165,7 +164,7 @@ void SetDownloadsDeletionPref(bool value) { browser()->profile()->GetPrefs()->SetBoolean( - prefs::kDeleteDownloadHistory, value); + browsing_data::prefs::kDeleteDownloadHistory, value); } void SetDeletionPeriodPref(browsing_data::TimePeriod period) {
diff --git a/chrome/browser/browsing_data/history_counter.cc b/chrome/browser/browsing_data/history_counter.cc index cbe9021..1980fed 100644 --- a/chrome/browser/browsing_data/history_counter.cc +++ b/chrome/browser/browsing_data/history_counter.cc
@@ -13,8 +13,8 @@ #include "chrome/browser/history/web_history_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/profile_sync_service_factory.h" -#include "chrome/common/pref_names.h" #include "components/browser_sync/browser/profile_sync_service.h" +#include "components/browsing_data/pref_names.h" #include "components/history/core/browser/history_service.h" #include "components/history/core/browser/web_history_service.h" #include "content/public/browser/browser_thread.h" @@ -24,7 +24,7 @@ } HistoryCounter::HistoryCounter(Profile* profile) - : BrowsingDataCounter(prefs::kDeleteBrowsingHistory), + : BrowsingDataCounter(browsing_data::prefs::kDeleteBrowsingHistory), profile_(profile), has_synced_visits_(false), local_counting_finished_(false),
diff --git a/chrome/browser/browsing_data/history_counter_browsertest.cc b/chrome/browser/browsing_data/history_counter_browsertest.cc index c4e9e9762..be52400 100644 --- a/chrome/browser/browsing_data/history_counter_browsertest.cc +++ b/chrome/browser/browsing_data/history_counter_browsertest.cc
@@ -11,7 +11,6 @@ #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/sync/test/integration/sync_test.h" #include "chrome/browser/ui/browser.h" -#include "chrome/common/pref_names.h" #include "components/browser_sync/browser/profile_sync_service.h" #include "components/browsing_data/browsing_data_utils.h" #include "components/browsing_data/pref_names.h" @@ -59,7 +58,7 @@ void SetHistoryDeletionPref(bool value) { browser()->profile()->GetPrefs()->SetBoolean( - prefs::kDeleteBrowsingHistory, value); + browsing_data::prefs::kDeleteBrowsingHistory, value); } void SetDeletionPeriodPref(browsing_data::TimePeriod period) {
diff --git a/chrome/browser/browsing_data/hosted_apps_counter.cc b/chrome/browser/browsing_data/hosted_apps_counter.cc index faa0da2f..09c4ac8a 100644 --- a/chrome/browser/browsing_data/hosted_apps_counter.cc +++ b/chrome/browser/browsing_data/hosted_apps_counter.cc
@@ -9,12 +9,13 @@ #include "base/memory/ptr_util.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/common/pref_names.h" +#include "components/browsing_data/pref_names.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/extension.h" HostedAppsCounter::HostedAppsCounter(Profile* profile) - : BrowsingDataCounter(prefs::kDeleteHostedAppsData), profile_(profile) {} + : BrowsingDataCounter(browsing_data::prefs::kDeleteHostedAppsData), + profile_(profile) {} HostedAppsCounter::~HostedAppsCounter() {}
diff --git a/chrome/browser/browsing_data/hosted_apps_counter_unittest.cc b/chrome/browser/browsing_data/hosted_apps_counter_unittest.cc index 84a0c87..c3b3625 100644 --- a/chrome/browser/browsing_data/hosted_apps_counter_unittest.cc +++ b/chrome/browser/browsing_data/hosted_apps_counter_unittest.cc
@@ -12,7 +12,6 @@ #include "base/bind.h" #include "base/guid.h" #include "base/values.h" -#include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" #include "components/browsing_data/browsing_data_utils.h" #include "components/browsing_data/pref_names.h" @@ -98,7 +97,8 @@ // Setting preferences. ------------------------------------------------------ void SetHostedAppsDeletionPref(bool value) { - GetProfile()->GetPrefs()->SetBoolean(prefs::kDeleteHostedAppsData, value); + GetProfile()->GetPrefs()->SetBoolean( + browsing_data::prefs::kDeleteHostedAppsData, value); } void SetDeletionPeriodPref(browsing_data::TimePeriod period) {
diff --git a/chrome/browser/browsing_data/media_licenses_counter.cc b/chrome/browser/browsing_data/media_licenses_counter.cc index e5d19c8..32a8451 100644 --- a/chrome/browser/browsing_data/media_licenses_counter.cc +++ b/chrome/browser/browsing_data/media_licenses_counter.cc
@@ -10,7 +10,7 @@ #include "base/memory/ref_counted.h" #include "base/task_runner_util.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/common/pref_names.h" +#include "components/browsing_data/pref_names.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" #include "storage/browser/fileapi/file_system_context.h" @@ -52,7 +52,7 @@ } MediaLicensesCounter::MediaLicensesCounter(Profile* profile) - : BrowsingDataCounter(prefs::kDeleteMediaLicenses), + : BrowsingDataCounter(browsing_data::prefs::kDeleteMediaLicenses), profile_(profile), weak_ptr_factory_(this) {}
diff --git a/chrome/browser/browsing_data/media_licenses_counter_browsertest.cc b/chrome/browser/browsing_data/media_licenses_counter_browsertest.cc index 42fe2ca..f504acf 100644 --- a/chrome/browser/browsing_data/media_licenses_counter_browsertest.cc +++ b/chrome/browser/browsing_data/media_licenses_counter_browsertest.cc
@@ -8,8 +8,8 @@ #include "base/run_loop.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" -#include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" +#include "components/browsing_data/pref_names.h" #include "components/prefs/pref_service.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" @@ -33,8 +33,8 @@ void SetUpOnMainThread() override { SetMediaLicenseDeletionPref(true); } void SetMediaLicenseDeletionPref(bool value) { - browser()->profile()->GetPrefs()->SetBoolean(prefs::kDeleteMediaLicenses, - value); + browser()->profile()->GetPrefs()->SetBoolean( + browsing_data::prefs::kDeleteMediaLicenses, value); } // Create some test data for origin |kOrigin|.
diff --git a/chrome/browser/browsing_data/passwords_counter.cc b/chrome/browser/browsing_data/passwords_counter.cc index e235fa41..b8891ef4 100644 --- a/chrome/browser/browsing_data/passwords_counter.cc +++ b/chrome/browser/browsing_data/passwords_counter.cc
@@ -5,11 +5,12 @@ #include "chrome/browser/browsing_data/passwords_counter.h" #include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/common/pref_names.h" +#include "components/browsing_data/pref_names.h" #include "components/password_manager/core/browser/password_store.h" PasswordsCounter::PasswordsCounter(Profile* profile) - : BrowsingDataCounter(prefs::kDeletePasswords), profile_(profile) {} + : BrowsingDataCounter(browsing_data::prefs::kDeletePasswords), + profile_(profile) {} PasswordsCounter::~PasswordsCounter() { store_->RemoveObserver(this);
diff --git a/chrome/browser/browsing_data/passwords_counter_browsertest.cc b/chrome/browser/browsing_data/passwords_counter_browsertest.cc index 1b0ee91..8b87235e 100644 --- a/chrome/browser/browsing_data/passwords_counter_browsertest.cc +++ b/chrome/browser/browsing_data/passwords_counter_browsertest.cc
@@ -9,7 +9,6 @@ #include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/browser/sync/test/integration/passwords_helper.h" #include "chrome/browser/ui/browser.h" -#include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "components/autofill/core/common/password_form.h" #include "components/browsing_data/browsing_data_utils.h" @@ -65,7 +64,7 @@ void SetPasswordsDeletionPref(bool value) { browser()->profile()->GetPrefs()->SetBoolean( - prefs::kDeletePasswords, value); + browsing_data::prefs::kDeletePasswords, value); } void SetDeletionPeriodPref(browsing_data::TimePeriod period) {
diff --git a/chrome/browser/chooser_controller/chooser_controller.cc b/chrome/browser/chooser_controller/chooser_controller.cc index 00c52f9..1a3da0a 100644 --- a/chrome/browser/chooser_controller/chooser_controller.cc +++ b/chrome/browser/chooser_controller/chooser_controller.cc
@@ -4,15 +4,49 @@ #include "chrome/browser/chooser_controller/chooser_controller.h" +#include "base/strings/utf_string_conversions.h" +#include "components/url_formatter/elide_url.h" #include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents.h" +#include "extensions/browser/extension_registry.h" +#include "extensions/common/constants.h" +#include "ui/base/l10n/l10n_util.h" #include "url/origin.h" -ChooserController::ChooserController(content::RenderFrameHost* owner) - : owning_frame_(owner) {} +ChooserController::ChooserController(content::RenderFrameHost* owner, + int title_string_id_origin, + int title_string_id_extension) + : owning_frame_(owner), + title_string_id_origin_(title_string_id_origin), + title_string_id_extension_(title_string_id_extension) {} ChooserController::~ChooserController() {} -url::Origin ChooserController::GetOrigin() const { - return owning_frame_ ? owning_frame_->GetLastCommittedOrigin() - : url::Origin(); +base::string16 ChooserController::GetTitle() const { + if (!owning_frame_) + return base::string16(); + + url::Origin origin = owning_frame_->GetLastCommittedOrigin(); + + if (origin.scheme() == extensions::kExtensionScheme) { + content::WebContents* web_contents = + content::WebContents::FromRenderFrameHost(owning_frame_); + content::BrowserContext* browser_context = + web_contents->GetBrowserContext(); + extensions::ExtensionRegistry* extension_registry = + extensions::ExtensionRegistry::Get(browser_context); + if (extension_registry) { + const extensions::Extension* extension = + extension_registry->enabled_extensions().GetByID(origin.host()); + if (extension) { + return l10n_util::GetStringFUTF16(title_string_id_extension_, + base::UTF8ToUTF16(extension->name())); + } + } + } + + return l10n_util::GetStringFUTF16( + title_string_id_origin_, + url_formatter::FormatOriginForSecurityDisplay( + origin, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC)); }
diff --git a/chrome/browser/chooser_controller/chooser_controller.h b/chrome/browser/chooser_controller/chooser_controller.h index 275f0243..7ed166f 100644 --- a/chrome/browser/chooser_controller/chooser_controller.h +++ b/chrome/browser/chooser_controller/chooser_controller.h
@@ -12,10 +12,6 @@ class RenderFrameHost; } -namespace url { -class Origin; -} - // Subclass ChooserController to implement a chooser, which has some // introductory text and a list of options that users can pick one of. // Your subclass must define the set of options users can pick from; @@ -25,7 +21,9 @@ // calls back into it are not allowed. class ChooserController { public: - explicit ChooserController(content::RenderFrameHost* owner); + ChooserController(content::RenderFrameHost* owner, + int title_string_id_origin, + int title_string_id_extension); virtual ~ChooserController(); // Since the set of options can change while the UI is visible an @@ -52,8 +50,11 @@ virtual ~Observer() {} }; - // Return the origin URL to be displayed on the chooser title. - url::Origin GetOrigin() const; + // Returns the text to be displayed in the chooser title. + base::string16 GetTitle() const; + + // Returns the label for OK button. + virtual base::string16 GetOkButtonLabel() const = 0; // The number of options users can pick from. For example, it can be // the number of USB/Bluetooth device names which are listed in the @@ -83,7 +84,9 @@ Observer* observer() const { return observer_; } private: - content::RenderFrameHost* owning_frame_; + content::RenderFrameHost* const owning_frame_; + const int title_string_id_origin_; + const int title_string_id_extension_; Observer* observer_ = nullptr; DISALLOW_COPY_AND_ASSIGN(ChooserController);
diff --git a/chrome/browser/chooser_controller/mock_chooser_controller.cc b/chrome/browser/chooser_controller/mock_chooser_controller.cc index dbcd172..e585add 100644 --- a/chrome/browser/chooser_controller/mock_chooser_controller.cc +++ b/chrome/browser/chooser_controller/mock_chooser_controller.cc
@@ -3,12 +3,19 @@ // found in the LICENSE file. #include "chrome/browser/chooser_controller/mock_chooser_controller.h" +#include "chrome/grit/generated_resources.h" MockChooserController::MockChooserController(content::RenderFrameHost* owner) - : ChooserController(owner) {} + : ChooserController(owner, + IDS_USB_DEVICE_CHOOSER_PROMPT_ORIGIN, + IDS_USB_DEVICE_CHOOSER_PROMPT_EXTENSION_NAME) {} MockChooserController::~MockChooserController() {} +base::string16 MockChooserController::GetOkButtonLabel() const { + return base::string16(); +} + size_t MockChooserController::NumOptions() const { return option_names_.size(); }
diff --git a/chrome/browser/chooser_controller/mock_chooser_controller.h b/chrome/browser/chooser_controller/mock_chooser_controller.h index 85ab055..1ff9e25 100644 --- a/chrome/browser/chooser_controller/mock_chooser_controller.h +++ b/chrome/browser/chooser_controller/mock_chooser_controller.h
@@ -17,6 +17,7 @@ ~MockChooserController() override; // ChooserController: + base::string16 GetOkButtonLabel() const override; size_t NumOptions() const override; base::string16 GetOption(size_t index) const override; MOCK_METHOD1(Select, void(size_t index));
diff --git a/chrome/browser/chrome_browser_field_trials.cc b/chrome/browser/chrome_browser_field_trials.cc index 8dc2258..38589ebe 100644 --- a/chrome/browser/chrome_browser_field_trials.cc +++ b/chrome/browser/chrome_browser_field_trials.cc
@@ -11,6 +11,7 @@ #include "base/files/file_util.h" #include "base/metrics/field_trial.h" #include "base/metrics/histogram_base.h" +#include "base/metrics/histogram_macros.h" #include "base/metrics/persistent_histogram_allocator.h" #include "base/path_service.h" #include "base/strings/string_util.h" @@ -57,6 +58,18 @@ if (!base::ReplaceFile(active_file, metrics_file, nullptr)) base::DeleteFile(metrics_file, /*recursive=*/false); + // This is used to report results to an UMA histogram. It's an int because + // arithmetic is done on the value. The corresponding "failed" case must + // always appear directly after the "success" case. + enum : int { + LOCAL_MEMORY_SUCCESS, + LOCAL_MEMORY_FAILED, + MAPPED_FILE_SUCCESS, + MAPPED_FILE_FAILED, + CREATE_ALLOCATOR_RESULTS + }; + int result; + // Create persistent/shared memory and allow histograms to be stored in // it. Memory that is not actualy used won't be physically mapped by the // system. BrowserMetrics usage, as reported in UMA, peaked around 1.9MiB @@ -70,18 +83,29 @@ base::GlobalHistogramAllocator::CreateWithFile( active_file, kAllocSize, kAllocId, ChromeMetricsServiceClient::kBrowserMetricsName); + result = MAPPED_FILE_SUCCESS; } else if (storage == "LocalMemory") { // Use local memory for storage even though it will not persist across // an unclean shutdown. base::GlobalHistogramAllocator::CreateWithLocalMemory( kAllocSize, kAllocId, ChromeMetricsServiceClient::kBrowserMetricsName); + result = LOCAL_MEMORY_SUCCESS; } else { // Persistent metric storage is disabled. return; } + // Get the allocator that was just created and report result. Exit if the + // allocator could not be created. base::GlobalHistogramAllocator* allocator = base::GlobalHistogramAllocator::Get(); + UMA_HISTOGRAM_ENUMERATION("UMA.PersistentHistograms.InitResult", + result + (allocator ? 0 : 1), + CREATE_ALLOCATOR_RESULTS); + if (!allocator) + return; + + // Create tracking histograms for the allocator and record storage file. allocator->CreateTrackingHistograms( ChromeMetricsServiceClient::kBrowserMetricsName); allocator->SetPersistentLocation(active_file);
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index e1ac0da..64a3c5ee 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1385,7 +1385,10 @@ "LowPriorityIFrames", // Keys: disallowFetchForDocWrittenScriptsInMainFrame - "DisallowFetchForDocWrittenScriptsInMainFrame" + "DisallowFetchForDocWrittenScriptsInMainFrame", + + // Keys: parseHTMLOnMainThreadSyncTokenize + "ParseHTMLOnMainThread", }; std::vector<std::string> blink_settings;
diff --git a/chrome/browser/chrome_quota_permission_context.cc b/chrome/browser/chrome_quota_permission_context.cc index 9e853c8..e5aa8bc 100644 --- a/chrome/browser/chrome_quota_permission_context.cc +++ b/chrome/browser/chrome_quota_permission_context.cc
@@ -31,7 +31,7 @@ #include "components/infobars/core/confirm_infobar_delegate.h" #include "components/infobars/core/infobar.h" #else -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" +#include "chrome/browser/permissions/permission_request_manager.h" #endif namespace { @@ -270,10 +270,10 @@ return; } #else - PermissionBubbleManager* bubble_manager = - PermissionBubbleManager::FromWebContents(web_contents); - if (bubble_manager) { - bubble_manager->AddRequest( + PermissionRequestManager* permission_request_manager = + PermissionRequestManager::FromWebContents(web_contents); + if (permission_request_manager) { + permission_request_manager->AddRequest( new QuotaPermissionRequest(this, params.origin_url, callback)); return; }
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc index b27af48..8dee3337 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc +++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -10,7 +10,6 @@ #include <memory> #include <utility> -#include "ash/audio/sounds.h" #include "ash/autoclick/autoclick_controller.h" #include "ash/common/session/session_state_delegate.h" #include "ash/common/wm_shell.h" @@ -97,6 +96,13 @@ namespace { +// When this flag is set, system sounds will not be played. +const char kAshDisableSystemSounds[] = "ash-disable-system-sounds"; + +// When this flag is set, system sounds will be played whether the +// ChromeVox is enabled or not. +const char kAshEnableSystemSounds[] = "ash-enable-system-sounds"; + static chromeos::AccessibilityManager* g_accessibility_manager = NULL; static BrailleController* g_braille_controller_for_test = NULL; @@ -772,9 +778,16 @@ EnableSpokenFeedback(true, ash::A11Y_NOTIFICATION_NONE); } -void AccessibilityManager::PlayEarcon(int sound_key) { +bool AccessibilityManager::PlayEarcon(int sound_key, PlaySoundOption option) { DCHECK(sound_key < chromeos::SOUND_COUNT); - ash::PlaySystemSoundIfSpokenFeedback(sound_key); + base::CommandLine* cl = base::CommandLine::ForCurrentProcess(); + if (cl->HasSwitch(kAshDisableSystemSounds)) + return false; + if (option == PlaySoundOption::SPOKEN_FEEDBACK_ENABLED && + !IsSpokenFeedbackEnabled() && !cl->HasSwitch(kAshEnableSystemSounds)) { + return false; + } + return media::SoundsManager::Get()->Play(sound_key); } void AccessibilityManager::HandleAccessibilityGesture(ui::AXGesture gesture) { @@ -1305,7 +1318,7 @@ if (!system_sounds_enabled_) return base::TimeDelta(); system_sounds_enabled_ = false; - if (!ash::PlaySystemSoundIfSpokenFeedback(SOUND_SHUTDOWN)) + if (!PlayEarcon(SOUND_SHUTDOWN, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED)) return base::TimeDelta(); return media::SoundsManager::Get()->GetDuration(SOUND_SHUTDOWN); } @@ -1467,7 +1480,7 @@ void AccessibilityManager::PostLoadChromeVox(Profile* profile) { // Do any setup work needed immediately after ChromeVox actually loads. - ash::PlaySystemSoundAlways(SOUND_SPOKEN_FEEDBACK_ENABLED); + PlayEarcon(SOUND_SPOKEN_FEEDBACK_ENABLED, PlaySoundOption::ALWAYS); if (chrome_vox_loaded_on_lock_screen_ || should_speak_chrome_vox_announcements_on_user_screen_) { @@ -1497,7 +1510,7 @@ void AccessibilityManager::PostUnloadChromeVox(Profile* profile) { // Do any teardown work needed immediately after ChromeVox actually unloads. - ash::PlaySystemSoundAlways(SOUND_SPOKEN_FEEDBACK_DISABLED); + PlayEarcon(SOUND_SPOKEN_FEEDBACK_DISABLED, PlaySoundOption::ALWAYS); // Clear the accessibility focus ring. AccessibilityFocusRingController::GetInstance()->SetFocusRing( std::vector<gfx::Rect>(),
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h index 10db2c84..e35e5d3 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_manager.h +++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -76,6 +76,13 @@ class ChromeVoxPanelWidgetObserver; +enum class PlaySoundOption { + ALWAYS = 0, // The sound is always played. + SPOKEN_FEEDBACK_ENABLED, // The sound is played only if spoken feedback is + // enabled, or --ash-enable-system-sounds flag is + // used. +}; + // AccessibilityManager changes the statuses of accessibility features // watching profile notifications and pref-changes. // TODO(yoshiki): merge MagnificationManager with AccessibilityManager. @@ -244,7 +251,7 @@ // Plays an earcon. Earcons are brief and distinctive sounds that indicate // when their mapped event has occurred. The sound key enums can be found in // chromeos/audio/chromeos_sounds.h. - void PlayEarcon(int sound_key); + bool PlayEarcon(int sound_key, PlaySoundOption option); // Forward an accessibility gesture from the touch exploration controller // to ChromeVox.
diff --git a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc index e4db346..329f017 100644 --- a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc +++ b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
@@ -7,8 +7,8 @@ #include "ash/accelerators/accelerator_controller.h" #include "ash/accelerators/accelerator_table.h" #include "ash/common/accessibility_types.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/shell.h" -#include "ash/system/tray/system_tray.h" #include "base/command_line.h" #include "base/macros.h" #include "base/strings/pattern.h" @@ -567,7 +567,13 @@ EXPECT_EQ("Title", speech_monitor_.GetNextUtterance()); } -IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, ChromeVoxStickyMode) { +#if defined(MEMORY_SANITIZER) +// Fails under MemorySanitizer: http://crbug.com/628060 +#define MAYBE_ChromeVoxStickyMode DISABLED_ChromeVoxStickyMode +#else +#define MAYBE_ChromeVoxStickyMode ChromeVoxStickyMode +#endif +IN_PROC_BROWSER_TEST_P(SpokenFeedbackTest, MAYBE_ChromeVoxStickyMode) { LoadChromeVoxAndThenNavigateToURL( GURL("data:text/html;charset=utf-8," "<label>Enter your name <input autofocus></label>"
diff --git a/chrome/browser/chromeos/accessibility/sticky_keys_browsertest.cc b/chrome/browser/chromeos/accessibility/sticky_keys_browsertest.cc index 8021306..28a94b12 100644 --- a/chrome/browser/chromeos/accessibility/sticky_keys_browsertest.cc +++ b/chrome/browser/chromeos/accessibility/sticky_keys_browsertest.cc
@@ -4,10 +4,10 @@ #include <stddef.h> +#include "ash/common/system/tray/system_tray.h" #include "ash/shell.h" #include "ash/sticky_keys/sticky_keys_controller.h" #include "ash/sticky_keys/sticky_keys_overlay.h" -#include "ash/system/tray/system_tray.h" #include "base/command_line.h" #include "base/macros.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_data.cc b/chrome/browser/chromeos/app_mode/kiosk_app_data.cc index d0646be..b5bb0fb 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_data.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_app_data.cc
@@ -477,6 +477,20 @@ SetStatus(status); } +// static +std::unique_ptr<KioskAppData> KioskAppData::CreateForTest( + KioskAppDataDelegate* delegate, + const std::string& app_id, + const AccountId& account_id, + const GURL& update_url, + const std::string& required_platform_version) { + std::unique_ptr<KioskAppData> data(new KioskAppData( + delegate, app_id, account_id, update_url, base::FilePath())); + data->status_ = STATUS_LOADED; + data->required_platform_version_ = required_platform_version; + return data; +} + void KioskAppData::SetStatus(Status status) { if (status_ == status) return;
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_data.h b/chrome/browser/chromeos/app_mode/kiosk_app_data.h index 95a39a2..7f5d5c9 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_data.h +++ b/chrome/browser/chromeos/app_mode/kiosk_app_data.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_CHROMEOS_APP_MODE_KIOSK_APP_DATA_H_ #define CHROME_BROWSER_CHROMEOS_APP_MODE_KIOSK_APP_DATA_H_ +#include <memory> #include <string> #include "base/files/file_path.h" @@ -86,6 +87,13 @@ void SetStatusForTest(Status status); + static std::unique_ptr<KioskAppData> CreateForTest( + KioskAppDataDelegate* delegate, + const std::string& app_id, + const AccountId& account_id, + const GURL& update_url, + const std::string& required_platform_version); + private: class CrxLoader; class IconLoader;
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc index d3c295f..59ae973 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc
@@ -238,6 +238,22 @@ app_session_->Init(profile, app_id); } +void KioskAppManager::AddAppForTest( + const std::string& app_id, + const AccountId& account_id, + const GURL& update_url, + const std::string& required_platform_version) { + for (auto it = apps_.begin(); it != apps_.end(); ++it) { + if ((*it)->app_id() == app_id) { + apps_.erase(it); + break; + } + } + + apps_.emplace_back(KioskAppData::CreateForTest( + this, app_id, account_id, update_url, required_platform_version)); +} + void KioskAppManager::EnableConsumerKioskAutoLaunch( const KioskAppManager::EnableKioskAutoLaunchCallback& callback) { policy::BrowserPolicyConnectorChromeOS* connector =
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager.h b/chrome/browser/chromeos/app_mode/kiosk_app_manager.h index 6c8e2ae2..eb731f2 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_app_manager.h +++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager.h
@@ -22,6 +22,7 @@ #include "components/signin/core/account_id/account_id.h" #include "ui/gfx/image/image_skia.h" +class GURL; class PrefRegistrySimple; class Profile; @@ -234,6 +235,13 @@ // Initialize |app_session_|. void InitSession(Profile* profile, const std::string& app_id); + // Adds an app with the given meta data directly and skips meta data fetching + // for test. + void AddAppForTest(const std::string& app_id, + const AccountId& account_id, + const GURL& update_url, + const std::string& required_platform_version); + AppSession* app_session() { return app_session_.get(); } bool external_loader_created() const { return external_loader_created_; } bool secondary_app_external_loader_created() const {
diff --git a/chrome/browser/chromeos/arc/arc_auth_service.cc b/chrome/browser/chromeos/arc/arc_auth_service.cc index cc7bb452..b9e6986 100644 --- a/chrome/browser/chromeos/arc/arc_auth_service.cc +++ b/chrome/browser/chromeos/arc/arc_auth_service.cc
@@ -97,6 +97,7 @@ g_arc_auth_service = this; arc_bridge_service()->AddObserver(this); + arc_bridge_service()->auth()->AddObserver(this); } ArcAuthService::~ArcAuthService() { @@ -104,6 +105,7 @@ DCHECK_EQ(this, g_arc_auth_service); Shutdown(); + arc_bridge_service()->auth()->RemoveObserver(this); arc_bridge_service()->RemoveObserver(this); g_arc_auth_service = nullptr; @@ -185,12 +187,13 @@ return true; } -void ArcAuthService::OnAuthInstanceReady() { - arc_bridge_service()->auth_instance()->Init( +void ArcAuthService::OnInstanceReady() { + arc_bridge_service()->auth()->instance()->Init( binding_.CreateInterfacePtrAndBind()); } -void ArcAuthService::OnBridgeStopped() { +void ArcAuthService::OnBridgeStopped(ArcBridgeService::StopReason reason) { + // TODO(crbug.com/625923): Use |reason| to report more detailed errors. if (waiting_for_reply_) { // Using SERVICE_UNAVAILABLE instead of UNKNOWN_ERROR, since the latter // causes this code to not try to stop ARC, so it would retry without the
diff --git a/chrome/browser/chromeos/arc/arc_auth_service.h b/chrome/browser/chromeos/arc/arc_auth_service.h index 3c3a98b5..61c7ff19 100644 --- a/chrome/browser/chromeos/arc/arc_auth_service.h +++ b/chrome/browser/chromeos/arc/arc_auth_service.h
@@ -17,6 +17,7 @@ #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" #include "components/arc/common/auth.mojom.h" +#include "components/arc/instance_holder.h" #include "components/prefs/pref_change_registrar.h" #include "components/syncable_prefs/pref_service_syncable_observer.h" #include "components/syncable_prefs/synced_pref_observer.h" @@ -43,6 +44,7 @@ class ArcAuthService : public ArcService, public mojom::AuthHost, public ArcBridgeService::Observer, + public InstanceHolder<mojom::AuthInstance>::Observer, public ArcAndroidManagementCheckerDelegate, public ArcAuthContextDelegate, public syncable_prefs::PrefServiceSyncableObserver, @@ -122,8 +124,10 @@ void RemoveObserver(Observer* observer); // ArcBridgeService::Observer: - void OnAuthInstanceReady() override; - void OnBridgeStopped() override; + void OnBridgeStopped(ArcBridgeService::StopReason reason) override; + + // InstanceHolder<mojom::AuthInstance>::Observer: + void OnInstanceReady() override; // AuthHost: // For security reason this code can be used only once and exists for specific
diff --git a/chrome/browser/chromeos/arc/arc_downloads_watcher_service.cc b/chrome/browser/chromeos/arc/arc_downloads_watcher_service.cc index 348ea55..cf63bf4 100644 --- a/chrome/browser/chromeos/arc/arc_downloads_watcher_service.cc +++ b/chrome/browser/chromeos/arc/arc_downloads_watcher_service.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/chromeos/arc/arc_downloads_watcher_service.h" +#include <map> #include <memory> #include <utility> @@ -175,22 +176,22 @@ ArcBridgeService* bridge_service) : ArcService(bridge_service), weak_ptr_factory_(this) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - arc_bridge_service()->AddObserver(this); + arc_bridge_service()->file_system()->AddObserver(this); } ArcDownloadsWatcherService::~ArcDownloadsWatcherService() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - arc_bridge_service()->RemoveObserver(this); + arc_bridge_service()->file_system()->RemoveObserver(this); StopWatchingDownloads(); DCHECK(!watcher_); } -void ArcDownloadsWatcherService::OnFileSystemInstanceReady() { +void ArcDownloadsWatcherService::OnInstanceReady() { DCHECK_CURRENTLY_ON(BrowserThread::UI); StartWatchingDownloads(); } -void ArcDownloadsWatcherService::OnFileSystemInstanceClosed() { +void ArcDownloadsWatcherService::OnInstanceClosed() { DCHECK_CURRENTLY_ON(BrowserThread::UI); StopWatchingDownloads(); } @@ -219,7 +220,7 @@ const std::vector<base::FilePath>& paths) { DCHECK_CURRENTLY_ON(BrowserThread::FILE); - auto* instance = arc_bridge_service()->file_system_instance(); + auto* instance = arc_bridge_service()->file_system()->instance(); if (!instance) return;
diff --git a/chrome/browser/chromeos/arc/arc_downloads_watcher_service.h b/chrome/browser/chromeos/arc/arc_downloads_watcher_service.h index 42c28ce..598fc42d 100644 --- a/chrome/browser/chromeos/arc/arc_downloads_watcher_service.h +++ b/chrome/browser/chromeos/arc/arc_downloads_watcher_service.h
@@ -12,6 +12,7 @@ #include "base/memory/weak_ptr.h" #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/instance_holder.h" namespace base { class FilePath; @@ -21,15 +22,16 @@ // Watches Downloads directory and registers newly created media files to // Android MediaProvider. -class ArcDownloadsWatcherService : public ArcService, - public ArcBridgeService::Observer { +class ArcDownloadsWatcherService + : public ArcService, + public InstanceHolder<mojom::FileSystemInstance>::Observer { public: explicit ArcDownloadsWatcherService(ArcBridgeService* bridge_service); ~ArcDownloadsWatcherService() override; - // ArcBridgeService::Observer - void OnFileSystemInstanceReady() override; - void OnFileSystemInstanceClosed() override; + // InstanceHolder<mojom::FileSystemInstance>::Observer + void OnInstanceReady() override; + void OnInstanceClosed() override; private: class DownloadsWatcher;
diff --git a/chrome/browser/chromeos/arc/arc_navigation_throttle.cc b/chrome/browser/chromeos/arc/arc_navigation_throttle.cc index 26551d5..98f2507 100644 --- a/chrome/browser/chromeos/arc/arc_navigation_throttle.cc +++ b/chrome/browser/chromeos/arc/arc_navigation_throttle.cc
@@ -35,12 +35,12 @@ return nullptr; } mojom::IntentHelperInstance* intent_helper_instance = - bridge_service->intent_helper_instance(); + bridge_service->intent_helper()->instance(); if (!intent_helper_instance) { VLOG(1) << "ARC intent helper instance is not ready."; return nullptr; } - if (bridge_service->intent_helper_version() < kMinInstanceVersion) { + if (bridge_service->intent_helper()->version() < kMinInstanceVersion) { VLOG(1) << "ARC intent helper instance is too old."; return nullptr; }
diff --git a/chrome/browser/chromeos/arc/arc_policy_bridge.cc b/chrome/browser/chromeos/arc/arc_policy_bridge.cc index a9dff1d..e154398 100644 --- a/chrome/browser/chromeos/arc/arc_policy_bridge.cc +++ b/chrome/browser/chromeos/arc/arc_policy_bridge.cc
@@ -235,7 +235,7 @@ ArcPolicyBridge::ArcPolicyBridge(ArcBridgeService* bridge_service) : ArcService(bridge_service), binding_(this) { VLOG(2) << "ArcPolicyBridge::ArcPolicyBridge"; - arc_bridge_service()->AddObserver(this); + arc_bridge_service()->policy()->AddObserver(this); } ArcPolicyBridge::ArcPolicyBridge(ArcBridgeService* bridge_service, @@ -244,19 +244,19 @@ binding_(this), policy_service_(policy_service) { VLOG(2) << "ArcPolicyBridge::ArcPolicyBridge(bridge_service, policy_service)"; - arc_bridge_service()->AddObserver(this); + arc_bridge_service()->policy()->AddObserver(this); } ArcPolicyBridge::~ArcPolicyBridge() { VLOG(2) << "ArcPolicyBridge::~ArcPolicyBridge"; - arc_bridge_service()->RemoveObserver(this); + arc_bridge_service()->policy()->RemoveObserver(this); } void ArcPolicyBridge::OverrideIsManagedForTesting(bool is_managed) { is_managed_ = is_managed; } -void ArcPolicyBridge::OnPolicyInstanceReady() { +void ArcPolicyBridge::OnInstanceReady() { VLOG(1) << "ArcPolicyBridge::OnPolicyInstanceReady"; if (policy_service_ == nullptr) { InitializePolicyService(); @@ -264,7 +264,7 @@ policy_service_->AddObserver(policy::POLICY_DOMAIN_CHROME, this); mojom::PolicyInstance* const policy_instance = - arc_bridge_service()->policy_instance(); + arc_bridge_service()->policy()->instance(); if (!policy_instance) { LOG(ERROR) << "OnPolicyInstanceReady called, but no policy instance found"; return; @@ -273,7 +273,7 @@ policy_instance->Init(binding_.CreateInterfacePtrAndBind()); } -void ArcPolicyBridge::OnPolicyInstanceClosed() { +void ArcPolicyBridge::OnInstanceClosed() { VLOG(1) << "ArcPolicyBridge::OnPolicyInstanceClosed"; policy_service_->RemoveObserver(policy::POLICY_DOMAIN_CHROME, this); policy_service_ = nullptr; @@ -297,8 +297,8 @@ const policy::PolicyMap& previous, const policy::PolicyMap& current) { VLOG(1) << "ArcPolicyBridge::OnPolicyUpdated"; - DCHECK(arc_bridge_service()->policy_instance()); - arc_bridge_service()->policy_instance()->OnPolicyUpdated(); + DCHECK(arc_bridge_service()->policy()->instance()); + arc_bridge_service()->policy()->instance()->OnPolicyUpdated(); } void ArcPolicyBridge::InitializePolicyService() {
diff --git a/chrome/browser/chromeos/arc/arc_policy_bridge.h b/chrome/browser/chromeos/arc/arc_policy_bridge.h index e9e6558..b26697e 100644 --- a/chrome/browser/chromeos/arc/arc_policy_bridge.h +++ b/chrome/browser/chromeos/arc/arc_policy_bridge.h
@@ -8,6 +8,7 @@ #include "base/macros.h" #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/instance_holder.h" #include "components/policy/core/common/policy_service.h" #include "mojo/public/cpp/bindings/binding.h" @@ -27,7 +28,7 @@ }; class ArcPolicyBridge : public ArcService, - public ArcBridgeService::Observer, + public InstanceHolder<mojom::PolicyInstance>::Observer, public mojom::PolicyHost, public policy::PolicyService::Observer { public: @@ -38,9 +39,9 @@ void OverrideIsManagedForTesting(bool is_managed); - // ArcBridgeService::Observer overrides. - void OnPolicyInstanceReady() override; - void OnPolicyInstanceClosed() override; + // InstanceHolder<mojom::PolicyInstance>::Observer overrides. + void OnInstanceReady() override; + void OnInstanceClosed() override; // PolicyHost overrides. void GetPolicies(const GetPoliciesCallback& callback) override;
diff --git a/chrome/browser/chromeos/arc/arc_policy_bridge_unittest.cc b/chrome/browser/chromeos/arc/arc_policy_bridge_unittest.cc index 139333ab..22ab4a8 100644 --- a/chrome/browser/chromeos/arc/arc_policy_bridge_unittest.cc +++ b/chrome/browser/chromeos/arc/arc_policy_bridge_unittest.cc
@@ -108,7 +108,7 @@ mojom::PolicyInstancePtr policy_instance_ptr; policy_instance_ = base::MakeUnique<FakePolicyInstance>( GetProxy(&policy_instance_ptr), bridge_service_.get()); - bridge_service_->OnPolicyInstanceReady(std::move(policy_instance_ptr)); + bridge_service_->policy()->OnInstanceReady(std::move(policy_instance_ptr)); policy_instance()->WaitForOnPolicyInstanceReady(); } @@ -159,11 +159,11 @@ nullptr); policy_bridge()->GetPolicies(PolicyStringCallback( "{\"applications\":" - "[{\"installType\":\"REQUIRED\"," - "\"lockTaskAllowed\":false," - "\"packageName\":\"com.google.android.apps.youtube.kids\"," - "\"permissionGrants\":[]" - "}]," + "[{\"installType\":\"REQUIRED\"," + "\"lockTaskAllowed\":false," + "\"packageName\":\"com.google.android.apps.youtube.kids\"," + "\"permissionGrants\":[]" + "}]," "\"defaultPermissionPolicy\":\"GRANT\"" "}")); } @@ -319,13 +319,13 @@ base::WrapUnique(new base::FundamentalValue(false)), nullptr); policy_bridge()->GetPolicies(PolicyStringCallback( "{\"applications\":" - "[{\"installType\":\"REQUIRED\"," - "\"lockTaskAllowed\":false," - "\"packageName\":\"com.google.android.apps.youtube.kids\"," - "\"permissionGrants\":[]" - "}]," - "\"cameraDisabled\":true," - "\"defaultPermissionPolicy\":\"GRANT\"" + "[{\"installType\":\"REQUIRED\"," + "\"lockTaskAllowed\":false," + "\"packageName\":\"com.google.android.apps.youtube.kids\"," + "\"permissionGrants\":[]" + "}]," + "\"cameraDisabled\":true," + "\"defaultPermissionPolicy\":\"GRANT\"" "}")); }
diff --git a/chrome/browser/chromeos/arc/arc_process_service.cc b/chrome/browser/chromeos/arc/arc_process_service.cc index 550ea0a..b84ddaf 100644 --- a/chrome/browser/chromeos/arc/arc_process_service.cc +++ b/chrome/browser/chromeos/arc/arc_process_service.cc
@@ -43,7 +43,7 @@ worker_pool_(new SequencedWorkerPool(1, "arc_process_manager")), weak_ptr_factory_(this) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - arc_bridge_service()->AddObserver(this); + arc_bridge_service()->process()->AddObserver(this); DCHECK(!g_arc_process_service); g_arc_process_service = this; // Not intended to be used from the creating thread. @@ -53,7 +53,7 @@ ArcProcessService::~ArcProcessService() { DCHECK(g_arc_process_service == this); g_arc_process_service = nullptr; - arc_bridge_service()->RemoveObserver(this); + arc_bridge_service()->process()->RemoveObserver(this); worker_pool_->Shutdown(); } @@ -63,7 +63,7 @@ return g_arc_process_service; } -void ArcProcessService::OnProcessInstanceReady() { +void ArcProcessService::OnInstanceReady() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); worker_pool_->PostNamedSequencedWorkerTask( kSequenceToken, @@ -82,7 +82,7 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); arc::mojom::ProcessInstance* process_instance = - arc_bridge_service()->process_instance(); + arc_bridge_service()->process()->instance(); if (!process_instance) { return false; }
diff --git a/chrome/browser/chromeos/arc/arc_process_service.h b/chrome/browser/chromeos/arc/arc_process_service.h index 231c58d..32f1486 100644 --- a/chrome/browser/chromeos/arc/arc_process_service.h +++ b/chrome/browser/chromeos/arc/arc_process_service.h
@@ -16,6 +16,7 @@ #include "chrome/browser/chromeos/arc/arc_process.h" #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/instance_holder.h" namespace arc { @@ -34,8 +35,9 @@ // base::Bind(&OnUpdateProcessList)) { // LOG(ERROR) << "ARC process instance not ready."; // } -class ArcProcessService : public ArcService, - public ArcBridgeService::Observer { +class ArcProcessService + : public ArcService, + public InstanceHolder<mojom::ProcessInstance>::Observer { public: using RequestProcessListCallback = base::Callback<void(const std::vector<ArcProcess>&)>; @@ -46,8 +48,8 @@ // Returns nullptr before the global instance is ready. static ArcProcessService* Get(); - // ArcBridgeService::Observer overrides. - void OnProcessInstanceReady() override; + // InstanceHolder<mojom::ProcessInstance>::Observer overrides. + void OnInstanceReady() override; // Returns true if ARC IPC is ready for process list request, // otherwise false.
diff --git a/chrome/browser/chromeos/arc/arc_settings_service.cc b/chrome/browser/chromeos/arc/arc_settings_service.cc index 3c6afe3..74dd19c 100644 --- a/chrome/browser/chromeos/arc/arc_settings_service.cc +++ b/chrome/browser/chromeos/arc/arc_settings_service.cc
@@ -365,7 +365,7 @@ void ArcSettingsServiceImpl::SendSettingsBroadcast( const std::string& action, const base::DictionaryValue& extras) const { - if (!arc_bridge_service_->intent_helper_instance()) { + if (!arc_bridge_service_->intent_helper()->instance()) { LOG(ERROR) << "IntentHelper instance is not ready."; return; } @@ -374,8 +374,8 @@ bool write_success = base::JSONWriter::Write(extras, &extras_json); DCHECK(write_success); - if (arc_bridge_service_->intent_helper_version() >= 1) { - arc_bridge_service_->intent_helper_instance()->SendBroadcast( + if (arc_bridge_service_->intent_helper()->version() >= 1) { + arc_bridge_service_->intent_helper()->instance()->SendBroadcast( action, "org.chromium.arc.intent_helper", "org.chromium.arc.intent_helper.SettingsReceiver", extras_json); } @@ -383,18 +383,18 @@ ArcSettingsService::ArcSettingsService(ArcBridgeService* bridge_service) : ArcService(bridge_service) { - arc_bridge_service()->AddObserver(this); + arc_bridge_service()->intent_helper()->AddObserver(this); } ArcSettingsService::~ArcSettingsService() { - arc_bridge_service()->RemoveObserver(this); + arc_bridge_service()->intent_helper()->RemoveObserver(this); } -void ArcSettingsService::OnIntentHelperInstanceReady() { +void ArcSettingsService::OnInstanceReady() { impl_.reset(new ArcSettingsServiceImpl(arc_bridge_service())); } -void ArcSettingsService::OnIntentHelperInstanceClosed() { +void ArcSettingsService::OnInstanceClosed() { impl_.reset(); }
diff --git a/chrome/browser/chromeos/arc/arc_settings_service.h b/chrome/browser/chromeos/arc/arc_settings_service.h index d1cca0d..7096f3da 100644 --- a/chrome/browser/chromeos/arc/arc_settings_service.h +++ b/chrome/browser/chromeos/arc/arc_settings_service.h
@@ -10,20 +10,22 @@ #include "base/macros.h" #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/instance_holder.h" namespace arc { class ArcSettingsServiceImpl; -class ArcSettingsService : public ArcService, - public ArcBridgeService::Observer { +class ArcSettingsService + : public ArcService, + public InstanceHolder<mojom::IntentHelperInstance>::Observer { public: explicit ArcSettingsService(ArcBridgeService* bridge_service); ~ArcSettingsService() override; - // ArcBridgeService::Observer - void OnIntentHelperInstanceReady() override; - void OnIntentHelperInstanceClosed() override; + // InstanceHolder<mojom::IntentHelperInstance>::Observer + void OnInstanceReady() override; + void OnInstanceClosed() override; private: std::unique_ptr<ArcSettingsServiceImpl> impl_;
diff --git a/chrome/browser/chromeos/arc/arc_support_host.cc b/chrome/browser/chromeos/arc/arc_support_host.cc index ace97f7..f347717 100644 --- a/chrome/browser/chromeos/arc/arc_support_host.cc +++ b/chrome/browser/chromeos/arc/arc_support_host.cc
@@ -26,6 +26,7 @@ #include "components/user_manager/known_user.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" +#include "ui/display/screen.h" namespace { const char kAction[] = "action"; @@ -41,6 +42,7 @@ const char kText[] = "text"; const char kActionInitialize[] = "initialize"; const char kActionSetMetricsMode[] = "setMetricsMode"; +const char kActionSetWindowBounds[] = "setWindowBounds"; const char kActionStartLso[] = "startLso"; const char kActionCancelAuthCode[] = "cancelAuthCode"; const char kActionSetAuthCode[] = "setAuthCode"; @@ -73,6 +75,7 @@ arc::ArcAuthService* arc_auth_service = arc::ArcAuthService::Get(); DCHECK(arc_auth_service); arc_auth_service->AddObserver(this); + display::Screen::GetScreen()->AddObserver(this); pref_change_registrar_.Init(g_browser_process->local_state()); pref_change_registrar_.Add( @@ -82,6 +85,7 @@ } ArcSupportHost::~ArcSupportHost() { + display::Screen::GetScreen()->RemoveObserver(this); arc::ArcAuthService* arc_auth_service = arc::ArcAuthService::Get(); if (arc_auth_service) arc_auth_service->RemoveObserver(this); @@ -167,6 +171,19 @@ client_->PostMessageFromNativeHost(request_string); } +void ArcSupportHost::OnDisplayAdded(const display::Display& new_display) {} + +void ArcSupportHost::OnDisplayRemoved(const display::Display& old_display) {} + +void ArcSupportHost::OnDisplayMetricsChanged(const display::Display& display, + uint32_t changed_metrics) { + base::DictionaryValue request; + std::string request_string; + request.SetString(kAction, kActionSetWindowBounds); + base::JSONWriter::Write(request, &request_string); + client_->PostMessageFromNativeHost(request_string); +} + void ArcSupportHost::OnMetricsPreferenceChanged() { SendMetricsMode(); }
diff --git a/chrome/browser/chromeos/arc/arc_support_host.h b/chrome/browser/chromeos/arc/arc_support_host.h index a7164e3..75d786a 100644 --- a/chrome/browser/chromeos/arc/arc_support_host.h +++ b/chrome/browser/chromeos/arc/arc_support_host.h
@@ -9,10 +9,12 @@ #include "chrome/browser/chromeos/arc/arc_auth_service.h" #include "components/prefs/pref_change_registrar.h" #include "extensions/browser/api/messaging/native_message_host.h" +#include "ui/display/display_observer.h" // Supports communication with Arc support dialog. class ArcSupportHost : public extensions::NativeMessageHost, - public arc::ArcAuthService::Observer { + public arc::ArcAuthService::Observer, + public display::DisplayObserver { public: static const char kHostName[]; static const char kHostAppId[]; @@ -33,6 +35,12 @@ void OnOptInUIShowPage(arc::ArcAuthService::UIPage page, const base::string16& status) override; + // display::DisplayObserver: + void OnDisplayAdded(const display::Display& new_display) override; + void OnDisplayRemoved(const display::Display& old_display) override; + void OnDisplayMetricsChanged(const display::Display& display, + uint32_t changed_metrics) override; + private: ArcSupportHost();
diff --git a/chrome/browser/chromeos/arc/gpu_arc_video_service_host.cc b/chrome/browser/chromeos/arc/gpu_arc_video_service_host.cc index 9b82d1b..9da329c 100644 --- a/chrome/browser/chromeos/arc/gpu_arc_video_service_host.cc +++ b/chrome/browser/chromeos/arc/gpu_arc_video_service_host.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/chromeos/arc/gpu_arc_video_service_host.h" +#include <string> + #include "base/location.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" @@ -61,17 +63,17 @@ arc::ArcBridgeService* bridge_service) : ArcService(bridge_service), binding_(this) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - arc_bridge_service()->AddObserver(this); + arc_bridge_service()->video()->AddObserver(this); } GpuArcVideoServiceHost::~GpuArcVideoServiceHost() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - arc_bridge_service()->RemoveObserver(this); + arc_bridge_service()->video()->RemoveObserver(this); } -void GpuArcVideoServiceHost::OnVideoInstanceReady() { +void GpuArcVideoServiceHost::OnInstanceReady() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - auto video_instance = arc_bridge_service()->video_instance(); + auto video_instance = arc_bridge_service()->video()->instance(); DCHECK(video_instance); video_instance->Init(binding_.CreateInterfacePtrAndBind()); }
diff --git a/chrome/browser/chromeos/arc/gpu_arc_video_service_host.h b/chrome/browser/chromeos/arc/gpu_arc_video_service_host.h index 86a48c3..b6f9540 100644 --- a/chrome/browser/chromeos/arc/gpu_arc_video_service_host.h +++ b/chrome/browser/chromeos/arc/gpu_arc_video_service_host.h
@@ -9,6 +9,7 @@ #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" #include "components/arc/common/video.mojom.h" +#include "components/arc/instance_holder.h" #include "mojo/public/cpp/bindings/binding.h" namespace arc { @@ -21,15 +22,16 @@ // process. The corresponding end "GpuArcVideoService" runs in the GPU process. // // Lives on the UI thread. -class GpuArcVideoServiceHost : public arc::ArcService, - public arc::ArcBridgeService::Observer, - public arc::mojom::VideoHost { +class GpuArcVideoServiceHost + : public arc::ArcService, + public arc::InstanceHolder<mojom::VideoInstance>::Observer, + public arc::mojom::VideoHost { public: explicit GpuArcVideoServiceHost(arc::ArcBridgeService* bridge_service); ~GpuArcVideoServiceHost() override; - // arc::ArcBridgeService::Observer implementation. - void OnVideoInstanceReady() override; + // arc::InstanceHolder<mojom::VideoInstance>::Observer implementation. + void OnInstanceReady() override; // arc::mojom::VideoHost implementation. void DeprecatedOnRequestArcVideoAcceleratorChannel(
diff --git a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc index 1ebf97c..23f17aaf6 100644 --- a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc +++ b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc
@@ -10,6 +10,7 @@ #include <string> #include "base/logging.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "chrome/grit/generated_resources.h" @@ -488,9 +489,12 @@ } // Allow arbitrary web requests. Don't include <all_urls> because that // also matches file:// schemes. - if (permission_string.find("https://") == 0 || - permission_string.find("http://") == 0 || - permission_string.find("ftp://") == 0) { + if (base::StartsWith(permission_string, "https://", + base::CompareCase::SENSITIVE) || + base::StartsWith(permission_string, "http://", + base::CompareCase::SENSITIVE) || + base::StartsWith(permission_string, "ftp://", + base::CompareCase::SENSITIVE)) { continue; } LOG(ERROR) << extension->id()
diff --git a/chrome/browser/chromeos/file_manager/arc_file_tasks.cc b/chrome/browser/chromeos/file_manager/arc_file_tasks.cc index e16e6e5a..091fca0 100644 --- a/chrome/browser/chromeos/file_manager/arc_file_tasks.cc +++ b/chrome/browser/chromeos/file_manager/arc_file_tasks.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/chromeos/file_manager/arc_file_tasks.h" +#include <map> #include <memory> #include <string> #include <vector> @@ -52,7 +53,7 @@ // Returns the Mojo interface for ARC Intent Helper, with version |minVersion| // or above. If the ARC bridge is not established, returns null. arc::mojom::IntentHelperInstance* GetArcIntentHelper(Profile* profile, - int min_version) { + uint32_t min_version) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // File manager in secondary profile cannot access ARC. @@ -64,11 +65,11 @@ return nullptr; arc::mojom::IntentHelperInstance* intent_helper_instance = - arc_service->intent_helper_instance(); + arc_service->intent_helper()->instance(); if (!intent_helper_instance) return nullptr; - if (arc_service->intent_helper_version() < min_version) { + if (arc_service->intent_helper()->version() < min_version) { DLOG(WARNING) << "ARC intent helper instance is too old."; return nullptr; } @@ -296,6 +297,11 @@ mojo::Array<arc::mojom::UrlWithMimeTypePtr> urls; for (const extensions::EntryInfo& entry : entries) { + if (entry.is_directory) { // ARC apps don't support directories. + callback.Run(std::move(result_list)); + return; + } + GURL url; if (!ConvertToArcUrl(entry.path, &url)) { callback.Run(std::move(result_list));
diff --git a/chrome/browser/chromeos/first_run/chromeos_first_run_browsertest.cc b/chrome/browser/chromeos/first_run/chromeos_first_run_browsertest.cc index 4801d507..4a23cbff 100644 --- a/chrome/browser/chromeos/first_run/chromeos_first_run_browsertest.cc +++ b/chrome/browser/chromeos/first_run/chromeos_first_run_browsertest.cc
@@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ash/common/system/tray/system_tray.h" #include "ash/first_run/first_run_helper.h" #include "ash/shell.h" -#include "ash/system/tray/system_tray.h" #include "chrome/browser/chromeos/first_run/first_run.h" #include "chrome/browser/chromeos/first_run/first_run_controller.h" #include "chrome/browser/chromeos/first_run/step_names.h"
diff --git a/chrome/browser/chromeos/input_method/input_method_util.cc b/chrome/browser/chromeos/input_method/input_method_util.cc index ba72137..4caff1f5 100644 --- a/chrome/browser/chromeos/input_method/input_method_util.cc +++ b/chrome/browser/chromeos/input_method/input_method_util.cc
@@ -392,7 +392,7 @@ const InputMethodDescriptor& descriptor) const { // Localizes the input method name. const std::string& disp = descriptor.name(); - if (disp.find("__MSG_") == 0) { + if (base::StartsWith(disp, "__MSG_", base::CompareCase::SENSITIVE)) { const InputMethodNameMap* map = kInputMethodNameMap; size_t map_size = arraysize(kInputMethodNameMap); std::string name = base::ToUpperASCII(disp);
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.cc b/chrome/browser/chromeos/login/lock/screen_locker.cc index 10ccad0..bffe739 100644 --- a/chrome/browser/chromeos/login/lock/screen_locker.cc +++ b/chrome/browser/chromeos/login/lock/screen_locker.cc
@@ -7,7 +7,6 @@ #include <string> #include <vector> -#include "ash/audio/sounds.h" #include "ash/common/ash_switches.h" #include "ash/common/wm/window_state.h" #include "ash/common/wm/wm_event.h" @@ -29,6 +28,7 @@ #include "base/strings/string_util.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/login/lock/webui_screen_locker.h" #include "chrome/browser/chromeos/login/quick_unlock/pin_storage.h" #include "chrome/browser/chromeos/login/quick_unlock/pin_storage_factory.h" @@ -151,11 +151,12 @@ manager->Initialize(SOUND_UNLOCK, bundle.GetRawDataResource(IDR_SOUND_UNLOCK_WAV)); - ash::Shell::GetInstance()-> - lock_state_controller()->SetLockScreenDisplayedCallback( - base::Bind(base::IgnoreResult(&ash::PlaySystemSoundIfSpokenFeedback), - static_cast<media::SoundsManager::SoundKey>( - chromeos::SOUND_LOCK))); + ash::Shell::GetInstance() + ->lock_state_controller() + ->SetLockScreenDisplayedCallback(base::Bind( + base::IgnoreResult(&AccessibilityManager::PlayEarcon), + base::Unretained(AccessibilityManager::Get()), chromeos::SOUND_LOCK, + PlaySoundOption::SPOKEN_FEEDBACK_ENABLED)); } void ScreenLocker::Init() { @@ -464,7 +465,8 @@ return; VLOG(1) << "Deleting ScreenLocker " << screen_locker_; - ash::PlaySystemSoundIfSpokenFeedback(SOUND_UNLOCK); + AccessibilityManager::Get()->PlayEarcon( + SOUND_UNLOCK, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED); delete screen_locker_; screen_locker_ = NULL;
diff --git a/chrome/browser/chromeos/login/login_browsertest.cc b/chrome/browser/chromeos/login/login_browsertest.cc index 09ee904..eb75a67b 100644 --- a/chrome/browser/chromeos/login/login_browsertest.cc +++ b/chrome/browser/chromeos/login/login_browsertest.cc
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "ash/common/system/tray/system_tray.h" #include "ash/shell.h" -#include "ash/system/tray/system_tray.h" #include "base/command_line.h" #include "base/location.h" #include "base/single_thread_task_runner.h"
diff --git a/chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.cc b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.cc new file mode 100644 index 0000000..fbde9b41 --- /dev/null +++ b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.cc
@@ -0,0 +1,157 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.h" + +#include "ash/common/system/system_notifier.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/login/quick_unlock/pin_storage.h" +#include "chrome/browser/chromeos/login/quick_unlock/pin_storage_factory.h" +#include "chrome/browser/notifications/notification.h" +#include "chrome/browser/notifications/notification_ui_manager.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser_navigator.h" +#include "chrome/browser/ui/browser_navigator_params.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/url_constants.h" +#include "components/prefs/pref_service.h" +#include "content/public/browser/notification_service.h" +#include "grit/ash_strings.h" +#include "grit/theme_resources.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/strings/grit/ui_strings.h" + +namespace { + +const char kDelegateId[] = "quickunlock_delegate"; +const char kNotificationId[] = "quickunlock_notification"; +const char kChromeAuthenticationSettingsURL[] = + "chrome://md-settings/quickUnlock/authenticate"; + +void UpdatePreferenceForProfile(Profile* profile) { + PrefService* pref_service = profile->GetPrefs(); + pref_service->SetBoolean(prefs::kQuickUnlockFeatureNotificationShown, true); +} + +} // namespace + +namespace chromeos { + +QuickUnlockNotificationController::QuickUnlockNotificationController( + Profile* profile) + : profile_(profile) { + registrar_.Add(this, chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED, + content::NotificationService::AllSources()); +} + +QuickUnlockNotificationController::~QuickUnlockNotificationController() { + UnregisterObserver(); +} + +// static +// TODO(http://crbug.com/291747): Add check for a policy that might disable +// quick unlock. +bool QuickUnlockNotificationController::ShouldShow(Profile* profile) { + // Do not show notification if this is a guest session. + if (profile->IsGuestSession()) + return false; + + // Do not show notification to user if already displayed in the past. + if (profile->GetPrefs()->GetBoolean( + prefs::kQuickUnlockFeatureNotificationShown)) { + return false; + } + + // Do not show the notification if the pin is already set. + PinStorage* pin_storage = PinStorageFactory::GetForProfile(profile); + if (pin_storage->IsPinSet()) + return false; + + // TODO(jdufault): Enable once quick unlock settings land(crbug.com/291747). + return false; +} + +// NotificationDelegate override: +std::string QuickUnlockNotificationController::id() const { + return kDelegateId; +} + +void QuickUnlockNotificationController::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + if (type != chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED) + return; + + bool is_screen_locked = *content::Details<bool>(details).ptr(); + + // Return if the screen is locked, indicating that the notification was + // emitted due to a screen lock event. + if (is_screen_locked) + return; + + UnregisterObserver(); + + // The user may have enabled the quick unlock feature during the current + // session and after the notificaiton controller has already been initialized. + if (!ShouldShow(profile_)) { + UpdatePreferenceForProfile(profile_); + return; + } + + // Create and add notification to notification manager. + std::unique_ptr<Notification> notification(CreateNotification()); + g_browser_process->notification_ui_manager()->Add(*notification, profile_); +} + +// message_center::NotificationDelegate override: +void QuickUnlockNotificationController::Close(bool by_user) { + if (by_user) + UpdatePreferenceForProfile(profile_); +} + +// message_center::NotificationDelegate override: +void QuickUnlockNotificationController::Click() { + chrome::NavigateParams params(profile_, + GURL(kChromeAuthenticationSettingsURL), + ui::PAGE_TRANSITION_LINK); + params.disposition = NEW_FOREGROUND_TAB; + params.window_action = chrome::NavigateParams::SHOW_WINDOW; + chrome::Navigate(¶ms); + + UpdatePreferenceForProfile(profile_); + + // Remove the notification from tray. + g_browser_process->notification_ui_manager()->CancelById( + id(), NotificationUIManager::GetProfileID(profile_)); +} + +void QuickUnlockNotificationController::UnregisterObserver() { + if (registrar_.IsRegistered(this, + chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED, + content::NotificationService::AllSources())) { + registrar_.Remove(this, chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED, + content::NotificationService::AllSources()); + } +} + +Notification* QuickUnlockNotificationController::CreateNotification() { + return new Notification( + message_center::NOTIFICATION_TYPE_SIMPLE, + l10n_util::GetStringUTF16(IDS_ASH_QUICK_UNLOCK_NOTIFICATION_TITLE), + l10n_util::GetStringUTF16(IDS_ASH_QUICK_UNLOCK_NOTIFICATION_BODY), + // TODO(http://crbug.com/291747): Change this to actual icon for + // quick unlock feature notification. + ui::ResourceBundle::GetSharedInstance().GetImageNamed( + IDR_SCREENSHOT_NOTIFICATION_ICON), + message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT, + ash::system_notifier::kNotifierQuickUnlock), + l10n_util::GetStringUTF16( + IDS_MESSAGE_CENTER_NOTIFIER_QUICK_UNLOCK_FEATURE_NAME), + GURL(), kNotificationId, message_center::RichNotificationData(), this); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.h b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.h new file mode 100644 index 0000000..8a07b91 --- /dev/null +++ b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.h
@@ -0,0 +1,55 @@ +// Copyright (c) 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_QUICK_UNLOCK_QUICK_UNLOCK_NOTIFICATION_CONTROLLER_H_ +#define CHROME_BROWSER_CHROMEOS_LOGIN_QUICK_UNLOCK_QUICK_UNLOCK_NOTIFICATION_CONTROLLER_H_ + +#include "base/macros.h" +#include "base/time/time.h" +#include "chrome/browser/notifications/notification_delegate.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" + +class Profile; +class NetworkState; +class Notification; + +namespace chromeos { + +// Quick Unlock feature notification controller is responsible for managing the +// new feature notification displayed to the user. +class QuickUnlockNotificationController : public NotificationDelegate, + public content::NotificationObserver { + public: + explicit QuickUnlockNotificationController(Profile* profile); + + // Returns true if the notification needs to be displayed for the given + // |profile|. + static bool ShouldShow(Profile* profile); + + // content::NotificationObserver implementation. + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override; + + private: + ~QuickUnlockNotificationController() override; + + // NotificationDelegate overrides: + void Close(bool by_user) override; + void Click() override; + std::string id() const override; + + Notification* CreateNotification(); + void UnregisterObserver(); + + Profile* profile_; + content::NotificationRegistrar registrar_; + + DISALLOW_COPY_AND_ASSIGN(QuickUnlockNotificationController); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_LOGIN_QUICK_UNLOCK_QUICK_UNLOCK_NOTIFICATION_CONTROLLER_H_
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc index 3977a71..701b44b 100644 --- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc +++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -46,7 +46,6 @@ #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/grit/generated_resources.h" #include "chrome/test/base/in_process_browser_test.h" #include "chromeos/chromeos_switches.h" @@ -76,6 +75,7 @@ #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h" #include "extensions/browser/guest_view/web_view/web_view_guest.h" +#include "extensions/common/features/feature_channel.h" #include "google_apis/gaia/fake_gaia.h" #include "google_apis/gaia/gaia_constants.h" #include "google_apis/gaia/gaia_switches.h"
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index f461799a..4a7f9fc 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -1740,6 +1740,15 @@ if (HatsNotificationController::ShouldShowSurveyToProfile(profile)) hats_notification_controller_ = new HatsNotificationController(profile); + if (QuickUnlockNotificationController::ShouldShow(profile) && + quick_unlock_notification_handler_.find(profile) == + quick_unlock_notification_handler_.end()) { + auto* qu_feature_notification_controller = + new QuickUnlockNotificationController(profile); + quick_unlock_notification_handler_.insert( + std::make_pair(profile, qu_feature_notification_controller)); + } + // Mark login host for deletion after browser starts. This // guarantees that the message loop will be referenced by the // browser before it is dereferenced by the login host.
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.h b/chrome/browser/chromeos/login/session/user_session_manager.h index 06f51c7..b485d17 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.h +++ b/chrome/browser/chromeos/login/session/user_session_manager.h
@@ -16,6 +16,7 @@ #include "chrome/browser/chromeos/base/locale_util.h" #include "chrome/browser/chromeos/eol_notification.h" #include "chrome/browser/chromeos/hats/hats_notification_controller.h" +#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.h" #include "chrome/browser/chromeos/login/signin/oauth2_login_manager.h" #include "chrome/browser/chromeos/login/signin/token_handle_util.h" #include "chromeos/dbus/session_manager_client.h" @@ -475,6 +476,12 @@ std::map<Profile*, std::unique_ptr<EolNotification>, ProfileCompare> eol_notification_handler_; + // Per-user-session Quick Unlock Feature Notification + std::map<Profile*, + scoped_refptr<QuickUnlockNotificationController>, + ProfileCompare> + quick_unlock_notification_handler_; + // Manages Easy unlock cryptohome keys. std::unique_ptr<EasyUnlockKeyManager> easy_unlock_key_manager_; bool running_easy_unlock_key_ops_;
diff --git a/chrome/browser/chromeos/login/ui/keyboard_driven_oobe_key_handler.cc b/chrome/browser/chromeos/login/ui/keyboard_driven_oobe_key_handler.cc index 42dfcc5..5fc8e83 100644 --- a/chrome/browser/chromeos/login/ui/keyboard_driven_oobe_key_handler.cc +++ b/chrome/browser/chromeos/login/ui/keyboard_driven_oobe_key_handler.cc
@@ -4,8 +4,8 @@ #include "chrome/browser/chromeos/login/ui/keyboard_driven_oobe_key_handler.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/shell.h" -#include "ash/system/tray/system_tray.h" namespace chromeos {
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_impl.cc b/chrome/browser/chromeos/login/ui/login_display_host_impl.cc index 28312bf4..ebcb944 100644 --- a/chrome/browser/chromeos/login/ui/login_display_host_impl.cc +++ b/chrome/browser/chromeos/login/ui/login_display_host_impl.cc
@@ -7,7 +7,6 @@ #include <utility> #include <vector> -#include "ash/audio/sounds.h" #include "ash/common/shell_window_ids.h" #include "ash/common/wm_shell.h" #include "ash/desktop_background/desktop_background_controller.h" @@ -1221,13 +1220,15 @@ } if (!startup_sound_honors_spoken_feedback_ && - !ash::PlaySystemSoundAlways(SOUND_STARTUP)) { + !AccessibilityManager::Get()->PlayEarcon(SOUND_STARTUP, + PlaySoundOption::ALWAYS)) { EnableSystemSoundsForAccessibility(); return; } if (startup_sound_honors_spoken_feedback_ && - !ash::PlaySystemSoundIfSpokenFeedback(SOUND_STARTUP)) { + !AccessibilityManager::Get()->PlayEarcon( + SOUND_STARTUP, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED)) { EnableSystemSoundsForAccessibility(); return; }
diff --git a/chrome/browser/chromeos/login/ui/user_adding_screen.cc b/chrome/browser/chromeos/login/ui/user_adding_screen.cc index 3507d7aa..0e845847 100644 --- a/chrome/browser/chromeos/login/ui/user_adding_screen.cc +++ b/chrome/browser/chromeos/login/ui/user_adding_screen.cc
@@ -4,8 +4,8 @@ #include "chrome/browser/chromeos/login/ui/user_adding_screen.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/shell.h" -#include "ash/system/tray/system_tray.h" #include "base/bind.h" #include "base/memory/singleton.h" #include "base/observer_list.h"
diff --git a/chrome/browser/chromeos/login/ui/webui_login_view.cc b/chrome/browser/chromeos/login/ui/webui_login_view.cc index 408b9511..f346177e 100644 --- a/chrome/browser/chromeos/login/ui/webui_login_view.cc +++ b/chrome/browser/chromeos/login/ui/webui_login_view.cc
@@ -5,9 +5,9 @@ #include "chrome/browser/chromeos/login/ui/webui_login_view.h" #include "ash/common/focus_cycler.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/wm_shell.h" #include "ash/shell.h" -#include "ash/system/tray/system_tray.h" #include "base/bind.h" #include "base/callback.h" #include "base/i18n/rtl.h"
diff --git a/chrome/browser/chromeos/policy/blocking_login_browsertest.cc b/chrome/browser/chromeos/policy/blocking_login_browsertest.cc index 32e622a..fc0df0d 100644 --- a/chrome/browser/chromeos/policy/blocking_login_browsertest.cc +++ b/chrome/browser/chromeos/policy/blocking_login_browsertest.cc
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/run_loop.h" #include "base/stl_util.h" +#include "base/strings/string_util.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/login/existing_user_controller.h" @@ -177,8 +178,10 @@ GaiaUrls* gaia = GaiaUrls::GetInstance(); if (request.relative_url == gaia->client_login_to_oauth2_url().path() || request.relative_url == gaia->oauth2_token_url().path() || - request.relative_url.find(kDMRegisterRequest) == 0 || - request.relative_url.find(kDMPolicyRequest) == 0) { + base::StartsWith(request.relative_url, kDMRegisterRequest, + base::CompareCase::SENSITIVE) || + base::StartsWith(request.relative_url, kDMPolicyRequest, + base::CompareCase::SENSITIVE)) { if (!responses_.empty()) { response.reset(responses_.back()); responses_.pop_back();
diff --git a/chrome/browser/chromeos/policy/device_status_collector.cc b/chrome/browser/chromeos/policy/device_status_collector.cc index d731df4..97378795 100644 --- a/chrome/browser/chromeos/policy/device_status_collector.cc +++ b/chrome/browser/chromeos/policy/device_status_collector.cc
@@ -25,9 +25,11 @@ #include "base/posix/eintr_wrapper.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "base/sys_info.h" #include "base/task_runner_util.h" #include "base/values.h" +#include "base/version.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #include "chrome/browser/chromeos/login/users/chrome_user_manager.h" @@ -36,6 +38,8 @@ #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/common/pref_names.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/update_engine_client.h" #include "chromeos/disks/disk_mount_manager.h" #include "chromeos/network/device_state.h" #include "chromeos/network/network_handler.h" @@ -238,6 +242,16 @@ return std::unique_ptr<policy::DeviceLocalAccount>(); } +base::Version GetPlatformVersion() { + int32_t major_version; + int32_t minor_version; + int32_t bugfix_version; + base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version, + &bugfix_version); + return base::Version(base::StringPrintf("%d.%d.%d", major_version, + minor_version, bugfix_version)); +} + } // namespace namespace policy { @@ -253,24 +267,12 @@ max_stored_future_activity_days_(kMaxStoredFutureActivityDays), local_state_(local_state), last_idle_check_(Time()), - last_reported_day_(0), - duration_for_last_reported_day_(0), - geolocation_update_in_progress_(false), volume_info_fetcher_(volume_info_fetcher), cpu_statistics_fetcher_(cpu_statistics_fetcher), cpu_temp_fetcher_(cpu_temp_fetcher), statistics_provider_(provider), - last_cpu_active_(0), - last_cpu_idle_(0), + cros_settings_(chromeos::CrosSettings::Get()), location_update_requester_(location_update_requester), - report_version_info_(false), - report_activity_times_(false), - report_boot_mode_(false), - report_location_(false), - report_network_interfaces_(false), - report_users_(false), - report_hardware_status_(false), - report_session_status_(false), weak_factory_(this) { if (volume_info_fetcher_.is_null()) volume_info_fetcher_ = base::Bind(&GetVolumeInfo); @@ -289,9 +291,6 @@ TimeDelta::FromSeconds(kHardwareStatusSampleIntervalSeconds), this, &DeviceStatusCollector::SampleHardwareStatus); - cros_settings_ = chromeos::CrosSettings::Get(); - - // Watch for changes to the individual policies that control what the status // reports contain. base::Closure callback = @@ -313,6 +312,10 @@ chromeos::kReportDeviceHardwareStatus, callback); session_status_subscription_ = cros_settings_->AddSettingsObserver( chromeos::kReportDeviceSessionStatus, callback); + os_update_status_subscription_ = cros_settings_->AddSettingsObserver( + chromeos::kReportOsUpdateStatus, callback); + running_kiosk_app_subscription_ = cros_settings_->AddSettingsObserver( + chromeos::kReportRunningKioskApp, callback); // The last known location is persisted in local state. This makes location // information available immediately upon startup and avoids the need to @@ -438,6 +441,16 @@ // immediately instead of waiting for the sampling timer to fire. SampleHardwareStatus(); } + + // Os update status and running kiosk app reporting are disabled by default. + if (!cros_settings_->GetBoolean(chromeos::kReportOsUpdateStatus, + &report_os_update_status_)) { + report_os_update_status_ = false; + } + if (!cros_settings_->GetBoolean(chromeos::kReportRunningKioskApp, + &report_running_kiosk_app_)) { + report_running_kiosk_app_ = false; + } } Time DeviceStatusCollector::GetCurrentTime() { @@ -907,6 +920,89 @@ } } +bool DeviceStatusCollector::GetOsUpdateStatus( + em::DeviceStatusReportRequest* status) { + const base::Version platform_version(GetPlatformVersion()); + if (!platform_version.IsValid()) + return false; + + const std::string required_platform_version_string = + chromeos::KioskAppManager::Get() + ->GetAutoLaunchAppRequiredPlatformVersion(); + if (required_platform_version_string.empty()) + return false; + + const base::Version required_platfrom_version( + required_platform_version_string); + + em::OsUpdateStatus* os_update_status = status->mutable_os_update_status(); + os_update_status->set_new_required_platform_version( + required_platfrom_version.GetString()); + + if (platform_version == required_platfrom_version) { + os_update_status->set_update_status(em::OsUpdateStatus::OS_UP_TO_DATE); + return true; + } + + const chromeos::UpdateEngineClient::Status update_engine_status = + chromeos::DBusThreadManager::Get() + ->GetUpdateEngineClient() + ->GetLastStatus(); + if (update_engine_status.status == + chromeos::UpdateEngineClient::UPDATE_STATUS_DOWNLOADING || + update_engine_status.status == + chromeos::UpdateEngineClient::UPDATE_STATUS_VERIFYING || + update_engine_status.status == + chromeos::UpdateEngineClient::UPDATE_STATUS_FINALIZING) { + os_update_status->set_update_status( + em::OsUpdateStatus::OS_IMAGE_DOWNLOAD_IN_PROGRESS); + os_update_status->set_new_platform_version( + update_engine_status.new_version); + } else if (update_engine_status.status == + chromeos::UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) { + os_update_status->set_update_status( + em::OsUpdateStatus::OS_UPDATE_NEED_REBOOT); + // Note the new_version could be a dummy "0.0.0.0" for some edge cases, + // e.g. update engine is somehow restarted without a reboot. + os_update_status->set_new_platform_version( + update_engine_status.new_version); + } else { + os_update_status->set_update_status( + em::OsUpdateStatus::OS_IMAGE_DOWNLOAD_NOT_STARTED); + } + + return true; +} + +bool DeviceStatusCollector::GetRunningKioskApp( + em::DeviceStatusReportRequest* status) { + std::unique_ptr<const DeviceLocalAccount> account = + GetAutoLaunchedKioskSessionInfo(); + // Only generate running kiosk app reports if we are in an auto-launched kiosk + // session. + if (!account) + return false; + + em::AppStatus* running_kiosk_app = status->mutable_running_kiosk_app(); + running_kiosk_app->set_app_id(account->kiosk_app_id); + + const std::string app_version = GetAppVersion(account->kiosk_app_id); + if (app_version.empty()) { + DLOG(ERROR) << "Unable to get version for extension: " + << account->kiosk_app_id; + } else { + running_kiosk_app->set_extension_version(app_version); + } + + chromeos::KioskAppManager::App app_info; + if (chromeos::KioskAppManager::Get()->GetApp(account->kiosk_app_id, + &app_info)) { + running_kiosk_app->set_required_platform_version( + app_info.required_platform_version); + } + return true; +} + bool DeviceStatusCollector::GetDeviceStatus( em::DeviceStatusReportRequest* status) { if (report_activity_times_) @@ -930,13 +1026,23 @@ if (report_hardware_status_) GetHardwareStatus(status); + bool os_update_status_reported = false; + if (report_os_update_status_) + os_update_status_reported = GetOsUpdateStatus(status); + + bool running_kiosk_app_reported = false; + if (report_running_kiosk_app_) + running_kiosk_app_reported = GetRunningKioskApp(status); + return (report_activity_times_ || report_version_info_ || report_boot_mode_ || report_location_ || report_network_interfaces_ || report_users_ || - report_hardware_status_); + report_hardware_status_ || + os_update_status_reported || + running_kiosk_app_reported); } bool DeviceStatusCollector::GetDeviceSessionStatus(
diff --git a/chrome/browser/chromeos/policy/device_status_collector.h b/chrome/browser/chromeos/policy/device_status_collector.h index 53eba80..580b6b4 100644 --- a/chrome/browser/chromeos/policy/device_status_collector.h +++ b/chrome/browser/chromeos/policy/device_status_collector.h
@@ -178,6 +178,10 @@ enterprise_management::DeviceStatusReportRequest* request); void GetHardwareStatus( enterprise_management::DeviceStatusReportRequest* request); + bool GetOsUpdateStatus( + enterprise_management::DeviceStatusReportRequest* request); + bool GetRunningKioskApp( + enterprise_management::DeviceStatusReportRequest* request); // Update the cached values of the reporting settings. void UpdateReportingSettings(); @@ -202,7 +206,7 @@ // to dBm units expected by server. int ConvertWifiSignalStrength(int signal_strength); - PrefService* local_state_; + PrefService* const local_state_; // The last time an idle state check was performed. base::Time last_idle_check_; @@ -211,11 +215,11 @@ // GetDeviceStatus(), and the duration for it. This is used to trim the // stored data in OnSubmittedSuccessfully(). Trimming is delayed so // unsuccessful uploads don't result in dropped data. - int64_t last_reported_day_; - int duration_for_last_reported_day_; + int64_t last_reported_day_ = 0; + int duration_for_last_reported_day_ = 0; // Whether a geolocation update is currently in progress. - bool geolocation_update_in_progress_; + bool geolocation_update_in_progress_ = false; base::RepeatingTimer idle_poll_timer_; base::RepeatingTimer hardware_status_sampling_timer_; @@ -254,13 +258,13 @@ // Callback invoked to fetch information about cpu temperature. CPUTempFetcher cpu_temp_fetcher_; - chromeos::system::StatisticsProvider* statistics_provider_; + chromeos::system::StatisticsProvider* const statistics_provider_; - chromeos::CrosSettings* cros_settings_; + chromeos::CrosSettings* const cros_settings_; // The most recent CPU readings. - uint64_t last_cpu_active_; - uint64_t last_cpu_idle_; + uint64_t last_cpu_active_ = 0; + uint64_t last_cpu_idle_ = 0; // TODO(bartfab): Remove this once crbug.com/125931 is addressed and a proper // way to mock geolocation exists. @@ -270,14 +274,16 @@ geolocation_subscription_; // Cached values of the reporting settings from the device policy. - bool report_version_info_; - bool report_activity_times_; - bool report_boot_mode_; - bool report_location_; - bool report_network_interfaces_; - bool report_users_; - bool report_hardware_status_; - bool report_session_status_; + bool report_version_info_ = false; + bool report_activity_times_ = false; + bool report_boot_mode_ = false; + bool report_location_ = false; + bool report_network_interfaces_ = false; + bool report_users_ = false; + bool report_hardware_status_ = false; + bool report_session_status_ = false; + bool report_os_update_status_ = false; + bool report_running_kiosk_app_ = false; std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> version_info_subscription_; @@ -295,6 +301,10 @@ hardware_status_subscription_; std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> session_status_subscription_; + std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> + os_update_status_subscription_; + std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> + running_kiosk_app_subscription_; base::WeakPtrFactory<DeviceStatusCollector> weak_factory_;
diff --git a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc index fb811a20e..d064553 100644 --- a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc +++ b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
@@ -20,7 +20,11 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" +#include "base/sys_info.h" +#include "base/test/scoped_path_override.h" #include "base/threading/sequenced_worker_pool.h" +#include "chrome/browser/chromeos/app_mode/kiosk_app_data.h" +#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #include "chrome/browser/chromeos/login/users/mock_user_manager.h" #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" #include "chrome/browser/chromeos/ownership/fake_owner_settings_service.h" @@ -28,10 +32,12 @@ #include "chrome/browser/chromeos/policy/device_local_account.h" #include "chrome/browser/chromeos/policy/stub_enterprise_install_attributes.h" #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h" +#include "chrome/common/chrome_paths.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_browser_process.h" #include "chromeos/dbus/cros_disks_client.h" #include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/fake_update_engine_client.h" #include "chromeos/dbus/shill_device_client.h" #include "chromeos/dbus/shill_ipconfig_client.h" #include "chromeos/dbus/shill_service_client.h" @@ -260,7 +266,9 @@ fake_device_local_account_(policy::DeviceLocalAccount::TYPE_KIOSK_APP, kKioskAccountId, kKioskAppId, - std::string() /* kiosk_app_update_url */) { + std::string() /* kiosk_app_update_url */), + user_data_dir_override_(chrome::DIR_USER_DATA), + update_engine_client_(new chromeos::FakeUpdateEngineClient) { // Run this test with a well-known timezone so that Time::LocalMidnight() // returns the same values on all machines. std::unique_ptr<base::Environment> env(base::Environment::Create()); @@ -299,6 +307,16 @@ RestartStatusCollector(base::Bind(&GetEmptyVolumeInfo), base::Bind(&GetEmptyCPUStatistics), base::Bind(&GetEmptyCPUTempInfo)); + + // Set up a fake local state for KioskAppManager. + TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_); + chromeos::KioskAppManager::RegisterPrefs(local_state_.registry()); + + // Use FakeUpdateEngineClient. + std::unique_ptr<chromeos::DBusThreadManagerSetter> dbus_setter = + chromeos::DBusThreadManager::GetSetterForTesting(); + dbus_setter->SetUpdateEngineClient( + base::WrapUnique<chromeos::UpdateEngineClient>(update_engine_client_)); } void AddMountPoint(const std::string& mount_point) { @@ -310,6 +328,9 @@ } ~DeviceStatusCollectorTest() override { + chromeos::KioskAppManager::Shutdown(); + TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr); + // Finish pending tasks. content::BrowserThread::GetBlockingPool()->FlushForTesting(); message_loop_.RunUntilIdle(); @@ -323,7 +344,9 @@ false); } - void TearDown() override { settings_helper_.RestoreProvider(); } + void TearDown() override { + settings_helper_.RestoreProvider(); + } void RestartStatusCollector( const policy::DeviceStatusCollector::VolumeInfoFetcher& volume_info, @@ -391,6 +414,38 @@ Return(true)); } + void MockPlatformVersion(const std::string& platform_version) { + const std::string lsb_release = base::StringPrintf( + "CHROMEOS_RELEASE_VERSION=%s", platform_version.c_str()); + base::SysInfo::SetChromeOSVersionInfoForTest(lsb_release, + base::Time::Now()); + } + + void MockAutoLaunchKioskAppWithRequiredPlatformVersion( + const DeviceLocalAccount& auto_launch_app_account, + const std::string& required_platform_version) { + chromeos::KioskAppManager* manager = chromeos::KioskAppManager::Get(); + manager->AddAppForTest( + auto_launch_app_account.kiosk_app_id, + AccountId::FromUserEmail(auto_launch_app_account.user_id), + GURL("http://cws/"), // Dummy URL to avoid setup ExtensionsClient. + required_platform_version); + manager->SetEnableAutoLaunch(true); + + std::vector<DeviceLocalAccount> accounts; + accounts.push_back(auto_launch_app_account); + SetDeviceLocalAccounts(owner_settings_service_.get(), accounts); + + owner_settings_service_->SetString( + chromeos::kAccountsPrefDeviceLocalAccountAutoLoginId, + auto_launch_app_account.account_id); + + message_loop_.RunUntilIdle(); + + ASSERT_EQ(required_platform_version, + manager->GetAutoLaunchAppRequiredPlatformVersion()); + } + protected: // Convenience method. int64_t ActivePeriodMilliseconds() { @@ -413,11 +468,14 @@ chromeos::ScopedTestCrosSettings test_cros_settings_; chromeos::ScopedCrosSettingsTestHelper settings_helper_; std::unique_ptr<chromeos::FakeOwnerSettingsService> owner_settings_service_; - chromeos::MockUserManager* user_manager_; + chromeos::MockUserManager* const user_manager_; chromeos::ScopedUserManagerEnabler user_manager_enabler_; em::DeviceStatusReportRequest status_; std::unique_ptr<TestingDeviceStatusCollector> status_collector_; const policy::DeviceLocalAccount fake_device_local_account_; + base::ScopedPathOverride user_data_dir_override_; + TestingPrefServiceSimple local_state_; + chromeos::FakeUpdateEngineClient* const update_engine_client_; }; TEST_F(DeviceStatusCollectorTest, AllIdle) { @@ -1018,6 +1076,121 @@ EXPECT_FALSE(app.has_error()); } +TEST_F(DeviceStatusCollectorTest, NoOsUpdateStatusByDefault) { + MockPlatformVersion("1234.0.0"); + MockAutoLaunchKioskAppWithRequiredPlatformVersion(fake_device_local_account_, + "1234.0.0"); + + GetStatus(); + EXPECT_FALSE(status_.has_os_update_status()); +} + +TEST_F(DeviceStatusCollectorTest, ReportOsUpdateStatusUpToDate) { + MockPlatformVersion("1234.0.0"); + settings_helper_.SetBoolean(chromeos::kReportOsUpdateStatus, true); + + const char* kRequiredPlatformVersions[] = {"1234", "1234.0", "1234.0.0"}; + + for (size_t i = 0; i < arraysize(kRequiredPlatformVersions); ++i) { + MockAutoLaunchKioskAppWithRequiredPlatformVersion( + fake_device_local_account_, kRequiredPlatformVersions[i]); + + GetStatus(); + ASSERT_TRUE(status_.has_os_update_status()) << "Required platform version=" + << kRequiredPlatformVersions[i]; + EXPECT_EQ(em::OsUpdateStatus::OS_UP_TO_DATE, + status_.os_update_status().update_status()) + << "Required platform version=" << kRequiredPlatformVersions[i]; + EXPECT_EQ(kRequiredPlatformVersions[i], + status_.os_update_status().new_required_platform_version()) + << "Required platform version=" << kRequiredPlatformVersions[i]; + } +} + +TEST_F(DeviceStatusCollectorTest, ReportOsUpdateStatus) { + MockPlatformVersion("1234.0.0"); + settings_helper_.SetBoolean(chromeos::kReportOsUpdateStatus, true); + MockAutoLaunchKioskAppWithRequiredPlatformVersion(fake_device_local_account_, + "1235"); + + chromeos::UpdateEngineClient::Status update_status; + update_status.status = chromeos::UpdateEngineClient::UPDATE_STATUS_IDLE; + + GetStatus(); + ASSERT_TRUE(status_.has_os_update_status()); + EXPECT_EQ(em::OsUpdateStatus::OS_IMAGE_DOWNLOAD_NOT_STARTED, + status_.os_update_status().update_status()); + + const chromeos::UpdateEngineClient::UpdateStatusOperation kUpdateEngineOps[] = + { + chromeos::UpdateEngineClient::UPDATE_STATUS_DOWNLOADING, + chromeos::UpdateEngineClient::UPDATE_STATUS_VERIFYING, + chromeos::UpdateEngineClient::UPDATE_STATUS_FINALIZING, + }; + + for (size_t i = 0; i < arraysize(kUpdateEngineOps); ++i) { + update_status.status = kUpdateEngineOps[i]; + update_status.new_version = "1235.1.2"; + update_engine_client_->PushLastStatus(update_status); + + GetStatus(); + ASSERT_TRUE(status_.has_os_update_status()); + EXPECT_EQ(em::OsUpdateStatus::OS_IMAGE_DOWNLOAD_IN_PROGRESS, + status_.os_update_status().update_status()); + EXPECT_EQ("1235.1.2", status_.os_update_status().new_platform_version()); + EXPECT_EQ("1235", + status_.os_update_status().new_required_platform_version()); + } + + update_status.status = + chromeos::UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT; + update_engine_client_->PushLastStatus(update_status); + GetStatus(); + ASSERT_TRUE(status_.has_os_update_status()); + EXPECT_EQ(em::OsUpdateStatus::OS_UPDATE_NEED_REBOOT, + status_.os_update_status().update_status()); +} + +TEST_F(DeviceStatusCollectorTest, NoRunningKioskAppByDefault) { + MockPlatformVersion("1234.0.0"); + MockAutoLaunchKioskAppWithRequiredPlatformVersion(fake_device_local_account_, + "1234.0.0"); + status_collector_->set_kiosk_account(base::WrapUnique( + new policy::DeviceLocalAccount(fake_device_local_account_))); + MockRunningKioskApp(fake_device_local_account_); + + GetStatus(); + EXPECT_FALSE(status_.has_running_kiosk_app()); +} + +TEST_F(DeviceStatusCollectorTest, NoRunningKioskAppWhenNotInKioskSession) { + settings_helper_.SetBoolean(chromeos::kReportRunningKioskApp, true); + MockPlatformVersion("1234.0.0"); + MockAutoLaunchKioskAppWithRequiredPlatformVersion(fake_device_local_account_, + "1234.0.0"); + + GetStatus(); + EXPECT_FALSE(status_.has_running_kiosk_app()); +} + +TEST_F(DeviceStatusCollectorTest, ReportRunningKioskApp) { + settings_helper_.SetBoolean(chromeos::kReportRunningKioskApp, true); + MockPlatformVersion("1234.0.0"); + MockAutoLaunchKioskAppWithRequiredPlatformVersion(fake_device_local_account_, + "1235"); + MockRunningKioskApp(fake_device_local_account_); + status_collector_->set_kiosk_account(base::WrapUnique( + new policy::DeviceLocalAccount(fake_device_local_account_))); + + GetStatus(); + ASSERT_TRUE(status_.has_running_kiosk_app()); + const em::AppStatus app = status_.running_kiosk_app(); + EXPECT_EQ(kKioskAppId, app.app_id()); + EXPECT_EQ("1235", app.required_platform_version()); + EXPECT_FALSE(app.has_status()); + EXPECT_FALSE(app.has_error()); +} + // Fake device state. struct FakeDeviceData { const char* device_path;
diff --git a/chrome/browser/chromeos/policy/proto/chrome_device_policy.proto b/chrome/browser/chromeos/policy/proto/chrome_device_policy.proto index f5d2dd0..f1d63e6 100644 --- a/chrome/browser/chromeos/policy/proto/chrome_device_policy.proto +++ b/chrome/browser/chromeos/policy/proto/chrome_device_policy.proto
@@ -99,6 +99,8 @@ optional bool report_users = 6 [default = true]; optional bool report_hardware_status = 7 [default = true]; optional bool report_session_status = 8 [default = true]; + optional bool report_os_update_status = 10 [default = false]; + optional bool report_running_kiosk_app = 11 [default = false]; // Frequency to report device status, default to 3 hours. optional int64 device_status_frequency = 9 [default = 10800000];
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc index b80d87d..e3f59c5 100644 --- a/chrome/browser/chromeos/preferences.cc +++ b/chrome/browser/chromeos/preferences.cc
@@ -318,6 +318,9 @@ registry->RegisterInt64Pref(prefs::kHatsLastInteractionTimestamp, base::Time().ToInternalValue()); + registry->RegisterBooleanPref(prefs::kQuickUnlockFeatureNotificationShown, + false); + // We don't sync EOL related prefs because they are device specific. registry->RegisterBooleanPref(prefs::kEolNotificationDismissed, false); registry->RegisterIntegerPref(prefs::kEolStatus,
diff --git a/chrome/browser/chromeos/settings/device_settings_provider.cc b/chrome/browser/chromeos/settings/device_settings_provider.cc index 132e90cc..031449c 100644 --- a/chrome/browser/chromeos/settings/device_settings_provider.cc +++ b/chrome/browser/chromeos/settings/device_settings_provider.cc
@@ -85,6 +85,8 @@ kReportDeviceSessionStatus, kReportDeviceUsers, kReportDeviceVersionInfo, + kReportOsUpdateStatus, + kReportRunningKioskApp, kReportUploadFrequency, kServiceAccountIdentity, kSignedDataRoamingEnabled, @@ -368,6 +370,14 @@ kReportDeviceSessionStatus, reporting_policy.report_session_status()); } + if (reporting_policy.has_report_os_update_status()) { + new_values_cache->SetBoolean(kReportOsUpdateStatus, + reporting_policy.report_os_update_status()); + } + if (reporting_policy.has_report_running_kiosk_app()) { + new_values_cache->SetBoolean(kReportRunningKioskApp, + reporting_policy.report_running_kiosk_app()); + } if (reporting_policy.has_device_status_frequency()) { new_values_cache->SetInteger( kReportUploadFrequency,
diff --git a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc index e028dd84..c42e008b 100644 --- a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc +++ b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
@@ -80,6 +80,8 @@ proto->set_report_users(enable_reporting); proto->set_report_hardware_status(enable_reporting); proto->set_report_session_status(enable_reporting); + proto->set_report_os_update_status(enable_reporting); + proto->set_report_running_kiosk_app(enable_reporting); proto->set_device_status_frequency(frequency); device_policy_.Build(); device_settings_test_helper_.set_policy_blob(device_policy_.GetBlob()); @@ -151,7 +153,9 @@ kReportDeviceNetworkInterfaces, kReportDeviceUsers, kReportDeviceHardwareStatus, - kReportDeviceSessionStatus + kReportDeviceSessionStatus, + kReportOsUpdateStatus, + kReportRunningKioskApp }; const base::FundamentalValue expected_enable_value(expected_enable_state);
diff --git a/chrome/browser/chromeos/shutdown_policy_browsertest.cc b/chrome/browser/chromeos/shutdown_policy_browsertest.cc index 1367631..cb3f0ad9 100644 --- a/chrome/browser/chromeos/shutdown_policy_browsertest.cc +++ b/chrome/browser/chromeos/shutdown_policy_browsertest.cc
@@ -8,10 +8,10 @@ #include "ash/common/login_status.h" #include "ash/common/system/date/date_default_view.h" #include "ash/common/system/date/tray_date.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/tray_popup_header_button.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" -#include "ash/system/tray/system_tray.h" #include "base/command_line.h" #include "base/location.h" #include "base/macros.h"
diff --git a/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc b/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc index c6c440bf..a17ec6c 100644 --- a/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc +++ b/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc
@@ -4,10 +4,10 @@ #include "ash/common/accessibility_types.h" #include "ash/common/login_status.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray_accessibility.h" #include "ash/magnifier/magnification_controller.h" #include "ash/shell.h" -#include "ash/system/tray/system_tray.h" #include "ash/test/shell_test_api.h" #include "ash/test/test_session_state_delegate.h" #include "base/callback.h"
diff --git a/chrome/browser/component_updater/pepper_flash_component_installer.cc b/chrome/browser/component_updater/pepper_flash_component_installer.cc index 72b0cb21..d98a23a 100644 --- a/chrome/browser/component_updater/pepper_flash_component_installer.cc +++ b/chrome/browser/component_updater/pepper_flash_component_installer.cc
@@ -168,7 +168,9 @@ PathService::Override(chrome::DIR_PEPPER_FLASH_PLUGIN, path); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, - base::Bind(&RegisterPepperFlashWithChrome, path, version)); + base::Bind(&RegisterPepperFlashWithChrome, + path.Append(chrome::kPepperFlashPluginFilename), + version)); } #endif // !defined(OS_LINUX) && defined(GOOGLE_CHROME_BUILD)
diff --git a/chrome/browser/content_settings/local_shared_objects_container.cc b/chrome/browser/content_settings/local_shared_objects_container.cc index 7327d2a3..d82aa46d 100644 --- a/chrome/browser/content_settings/local_shared_objects_container.cc +++ b/chrome/browser/content_settings/local_shared_objects_container.cc
@@ -221,8 +221,8 @@ LocalSharedObjectsContainer::CreateCookiesTreeModel() const { LocalDataContainer* container = new LocalDataContainer( cookies(), databases(), local_storages(), session_storages(), appcaches(), - indexed_dbs(), file_systems(), NULL, channel_ids(), service_workers(), - cache_storages(), NULL); + indexed_dbs(), file_systems(), nullptr, channel_ids(), service_workers(), + cache_storages(), nullptr); - return base::WrapUnique(new CookiesTreeModel(container, NULL, true)); + return base::WrapUnique(new CookiesTreeModel(container, nullptr)); }
diff --git a/chrome/browser/devtools/device/adb/mock_adb_server.cc b/chrome/browser/devtools/device/adb/mock_adb_server.cc index 8008ffd1..fe35d99c 100644 --- a/chrome/browser/devtools/device/adb/mock_adb_server.cc +++ b/chrome/browser/devtools/device/adb/mock_adb_server.cc
@@ -427,8 +427,9 @@ SendSuccess(base::StringPrintf("%s\tdevice\n%s\toffline", kSerialOnline, kSerialOffline)); - } else if (command.find(kHostTransportPrefix) == 0) { - serial_ = command.substr(strlen(kHostTransportPrefix)); + } else if (base::StartsWith(command, kHostTransportPrefix, + base::CompareCase::SENSITIVE)) { + serial_ = command.substr(sizeof(kHostTransportPrefix) - 1); SendSuccess(std::string()); } else if (serial_ != kSerialOnline) { Send("FAIL", "device offline (x)"); @@ -540,7 +541,8 @@ SendHTTPResponse(kSampleChromeBetaPages); else NOTREACHED() << "Unknown command " << request; - } else if (socket_name_.find("noprocess_devtools_remote") == 0) { + } else if (base::StartsWith(socket_name_, "noprocess_devtools_remote", + base::CompareCase::SENSITIVE)) { if (path == kJsonVersionPath) SendHTTPResponse("{}"); else if (path == kJsonListPath) @@ -560,40 +562,42 @@ } void MockAndroidConnection::ProcessCommand(const std::string& command) { - if (command.find(kLocalAbstractPrefix) == 0) { - socket_name_ = command.substr(strlen(kLocalAbstractPrefix)); + if (base::StartsWith(command, kLocalAbstractPrefix, + base::CompareCase::SENSITIVE)) { + socket_name_ = command.substr(sizeof(kLocalAbstractPrefix) - 1); delegate_->SendSuccess(std::string()); - } else { - if (command.find(kShellPrefix) == 0) { - std::string result; - for (const auto& line : - base::SplitString(command.substr(strlen(kShellPrefix)), "\n", - base::KEEP_WHITESPACE, - base::SPLIT_WANT_NONEMPTY)) { - if (line == kDeviceModelCommand) { - result += kDeviceModel; - result += "\r\n"; - } else if (line == kOpenedUnixSocketsCommand) { - result += kSampleOpenedUnixSockets; - } else if (line == kDumpsysCommand) { - result += kSampleDumpsys; - } else if (line == kListProcessesCommand) { - result += kSampleListProcesses; - } else if (line == kListUsersCommand) { - result += kSampleListUsers; - } else if (line.find(kEchoCommandPrefix) == 0) { - result += line.substr(strlen(kEchoCommandPrefix)); - result += "\r\n"; - } else { - NOTREACHED() << "Unknown shell command - " << command; - } - } - delegate_->SendSuccess(result); - } else { - NOTREACHED() << "Unknown command - " << command; - } - delegate_->Close(); + return; } + + if (base::StartsWith(command, kShellPrefix, base::CompareCase::SENSITIVE)) { + std::string result; + for (const auto& line : + base::SplitString(command.substr(sizeof(kShellPrefix) - 1), "\n", + base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { + if (line == kDeviceModelCommand) { + result += kDeviceModel; + result += "\r\n"; + } else if (line == kOpenedUnixSocketsCommand) { + result += kSampleOpenedUnixSockets; + } else if (line == kDumpsysCommand) { + result += kSampleDumpsys; + } else if (line == kListProcessesCommand) { + result += kSampleListProcesses; + } else if (line == kListUsersCommand) { + result += kSampleListUsers; + } else if (base::StartsWith(line, kEchoCommandPrefix, + base::CompareCase::SENSITIVE)) { + result += line.substr(sizeof(kEchoCommandPrefix) - 1); + result += "\r\n"; + } else { + NOTREACHED() << "Unknown shell command - " << command; + } + } + delegate_->SendSuccess(result); + } else { + NOTREACHED() << "Unknown command - " << command; + } + delegate_->Close(); } void MockAndroidConnection::SendHTTPResponse(const std::string& body) {
diff --git a/chrome/browser/devtools/device/android_device_info_query.cc b/chrome/browser/devtools/device/android_device_info_query.cc index 5132681e..31f4b36 100644 --- a/chrome/browser/devtools/device/android_device_info_query.cc +++ b/chrome/browser/devtools/device/android_device_info_query.cc
@@ -262,11 +262,15 @@ AndroidDeviceManager::BrowserInfo::Type GetBrowserType(const std::string& socket) { - if (socket.find(kChromeDefaultSocket) == 0) + if (base::StartsWith(socket, kChromeDefaultSocket, + base::CompareCase::SENSITIVE)) { return AndroidDeviceManager::BrowserInfo::kTypeChrome; + } - if (socket.find(kWebViewSocketPrefix) == 0) + if (base::StartsWith(socket, kWebViewSocketPrefix, + base::CompareCase::SENSITIVE)) { return AndroidDeviceManager::BrowserInfo::kTypeWebView; + } return AndroidDeviceManager::BrowserInfo::kTypeOther; }
diff --git a/chrome/browser/devtools/device/devtools_android_bridge.cc b/chrome/browser/devtools/device/devtools_android_bridge.cc index 11d50ca..8593912 100644 --- a/chrome/browser/devtools/device/devtools_android_bridge.cc +++ b/chrome/browser/devtools/device/devtools_android_bridge.cc
@@ -364,9 +364,11 @@ void DevToolsAndroidBridge::AgentHostDelegate::Attach( content::DevToolsExternalAgentProxy* proxy) { proxy_ = proxy; - content::RecordAction(browser_id_.second.find(kWebViewSocketPrefix) == 0 ? - base::UserMetricsAction("DevTools_InspectAndroidWebView") : - base::UserMetricsAction("DevTools_InspectAndroidPage")); + content::RecordAction( + base::StartsWith(browser_id_.second, kWebViewSocketPrefix, + base::CompareCase::SENSITIVE) + ? base::UserMetricsAction("DevTools_InspectAndroidWebView") + : base::UserMetricsAction("DevTools_InspectAndroidPage")); // Retain the device so it's not released until AgentHost is detached. if (bridge_) @@ -466,7 +468,7 @@ size_t ws_param = frontend_url.find("?ws"); if (ws_param != std::string::npos) frontend_url = frontend_url.substr(0, ws_param); - if (frontend_url.find("http:") == 0) + if (base::StartsWith(frontend_url, "http:", base::CompareCase::SENSITIVE)) frontend_url = "https:" + frontend_url.substr(5); return frontend_url; } @@ -474,7 +476,7 @@ static std::string GetTargetPath(const base::DictionaryValue& value) { std::string target_path = GetStringProperty(value, "webSocketDebuggerUrl"); - if (target_path.find("ws://") == 0) { + if (base::StartsWith(target_path, "ws://", base::CompareCase::SENSITIVE)) { size_t pos = target_path.find("/", 5); if (pos == std::string::npos) pos = 5;
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc index f2a907b..8600f00 100644 --- a/chrome/browser/devtools/devtools_sanity_browsertest.cc +++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -42,6 +42,7 @@ #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/test_chrome_web_ui_controller_factory.h" #include "chrome/test/base/ui_test_utils.h" #include "components/app_modal/javascript_app_modal_dialog.h" #include "components/app_modal/native_app_modal_dialog.h" @@ -54,7 +55,9 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host.h" #include "content/public/browser/render_widget_host_view.h" +#include "content/public/browser/url_data_source.h" #include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui_controller.h" #include "content/public/browser/worker_service.h" #include "content/public/browser/worker_service_observer.h" #include "content/public/common/content_switches.h" @@ -1066,6 +1069,10 @@ RunTest("testDeviceMetricsOverrides", "about:blank"); } +IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestDispatchKeyEventDoesNotCrash) { + RunTest("testDispatchKeyEventDoesNotCrash", "about:blank"); +} + // Tests that settings are stored in profile correctly. IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestSettings) { OpenDevToolsWindow("about:blank", true); @@ -1355,3 +1362,74 @@ IN_PROC_BROWSER_TEST_F(DevToolsNetInfoTest, EmulateNetworkConditions) { RunTest("testEmulateNetworkConditions", kEmulateNetworkConditionsPage); } + +class StaticURLDataSource : public content::URLDataSource { + public: + StaticURLDataSource(const std::string& source, const std::string& content) + : source_(source), content_(content) {} + + std::string GetSource() const override { return source_; } + void StartDataRequest(const std::string& path, + int render_process_id, + int render_frame_id, + const GotDataCallback& callback) override { + std::string data(content_); + callback.Run(base::RefCountedString::TakeString(&data)); + } + std::string GetMimeType(const std::string& path) const override { + return "text/html"; + } + bool ShouldAddContentSecurityPolicy() const override { return false; } + + private: + std::string source_; + std::string content_; + DISALLOW_COPY_AND_ASSIGN(StaticURLDataSource); +}; + +class MockWebUIProvider + : public TestChromeWebUIControllerFactory::WebUIProvider { + public: + MockWebUIProvider(const std::string& source, const std::string& content) + : source_(source), content_(content) {} + + content::WebUIController* NewWebUI(content::WebUI* web_ui, + const GURL& url) override { + content::URLDataSource::Add(Profile::FromWebUI(web_ui), + new StaticURLDataSource(source_, content_)); + return new content::WebUIController(web_ui); + } + + private: + std::string source_; + std::string content_; + DISALLOW_COPY_AND_ASSIGN(MockWebUIProvider); +}; + +// This tests checks that window is correctly initialized when DevTools is +// opened while navigation through history with forward and back actions. +// (crbug.com/627407) +IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, + TestWindowInitializedOnNavigateBack) { + TestChromeWebUIControllerFactory test_factory; + MockWebUIProvider mock_provider("dummyurl", + "<script>\n" + " window.abc = 239;\n" + " console.log(abc);\n" + "</script>"); + test_factory.AddFactoryOverride(GURL("chrome://dummyurl").host(), + &mock_provider); + content::WebUIControllerFactory::RegisterFactory(&test_factory); + + ui_test_utils::NavigateToURL(browser(), GURL("chrome://dummyurl")); + DevToolsWindow* window = + DevToolsWindowTesting::OpenDevToolsWindowSync(GetInspectedTab(), true); + chrome::DuplicateTab(browser()); + chrome::SelectPreviousTab(browser()); + ui_test_utils::NavigateToURL(browser(), GURL("about:blank")); + chrome::GoBack(browser(), CURRENT_TAB); + RunTestFunction(window, "testWindowInitializedOnNavigateBack"); + + DevToolsWindowTesting::CloseDevToolsWindowSync(window); + content::WebUIControllerFactory::UnregisterFactoryForTesting(&test_factory); +}
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc index fc6b5fb..46cd6f1b9 100644 --- a/chrome/browser/download/download_browsertest.cc +++ b/chrome/browser/download/download_browsertest.cc
@@ -48,6 +48,7 @@ #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/net/url_request_mock_util.h" #include "chrome/browser/notifications/notification_ui_manager.h" +#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.h" #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h" @@ -59,7 +60,6 @@ #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" @@ -2776,17 +2776,17 @@ DownloadItem::COMPLETE)); } #else -IN_PROC_BROWSER_TEST_F(DownloadTest, TestMultipleDownloadsBubble) { +IN_PROC_BROWSER_TEST_F(DownloadTest, TestMultipleDownloadsRequests) { // Create a downloads observer. std::unique_ptr<content::DownloadTestObserver> downloads_observer( CreateWaiter(browser(), 2)); - PermissionBubbleManager* permission_bubble_manager = - PermissionBubbleManager::FromWebContents( + PermissionRequestManager* permission_request_manager = + PermissionRequestManager::FromWebContents( browser()->tab_strip_model()->GetActiveWebContents()); - permission_bubble_manager->DisplayPendingRequests(); - permission_bubble_manager->set_auto_response_for_test( - PermissionBubbleManager::ACCEPT_ALL); + permission_request_manager->DisplayPendingRequests(); + permission_request_manager->set_auto_response_for_test( + PermissionRequestManager::ACCEPT_ALL); ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( browser(), net::URLRequestMockHTTPJob::GetMockUrl(
diff --git a/chrome/browser/download/download_request_limiter.cc b/chrome/browser/download/download_request_limiter.cc index 8f2fceb..17247d4 100644 --- a/chrome/browser/download/download_request_limiter.cc +++ b/chrome/browser/download/download_request_limiter.cc
@@ -31,7 +31,7 @@ #include "chrome/browser/download/download_request_infobar_delegate_android.h" #else #include "chrome/browser/download/download_permission_request.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" +#include "chrome/browser/permissions/permission_request_manager.h" #endif using content::BrowserThread; @@ -135,7 +135,7 @@ bool promptable = InfoBarService::FromWebContents(web_contents()) != nullptr; #else bool promptable = - PermissionBubbleManager::FromWebContents(web_contents()) != nullptr; + PermissionRequestManager::FromWebContents(web_contents()) != nullptr; #endif // See PromptUserForDownload(): if there's no InfoBarService, then @@ -169,10 +169,10 @@ DownloadRequestInfoBarDelegateAndroid::Create( InfoBarService::FromWebContents(web_contents_), factory_.GetWeakPtr()); #else - PermissionBubbleManager* bubble_manager = - PermissionBubbleManager::FromWebContents(web_contents_); - if (bubble_manager) { - bubble_manager->AddRequest( + PermissionRequestManager* permission_request_manager = + PermissionRequestManager::FromWebContents(web_contents_); + if (permission_request_manager) { + permission_request_manager->AddRequest( new DownloadPermissionRequest(factory_.GetWeakPtr())); } else { Cancel();
diff --git a/chrome/browser/download/download_request_limiter_unittest.cc b/chrome/browser/download/download_request_limiter_unittest.cc index 3583e49..4dab572a 100644 --- a/chrome/browser/download/download_request_limiter_unittest.cc +++ b/chrome/browser/download/download_request_limiter_unittest.cc
@@ -27,8 +27,8 @@ #include "chrome/browser/infobars/infobar_service.h" #else #include "chrome/browser/download/download_permission_request.h" +#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/ui/website_settings/mock_permission_bubble_factory.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" #endif using content::WebContents; @@ -98,10 +98,10 @@ class TestingDelegate { public: void SetUp(WebContents* web_contents) { - PermissionBubbleManager::CreateForWebContents(web_contents); + PermissionRequestManager::CreateForWebContents(web_contents); mock_permission_bubble_factory_.reset(new MockPermissionBubbleFactory( - PermissionBubbleManager::FromWebContents(web_contents))); - PermissionBubbleManager::FromWebContents(web_contents) + PermissionRequestManager::FromWebContents(web_contents))); + PermissionRequestManager::FromWebContents(web_contents) ->DisplayPendingRequests(); } @@ -116,19 +116,19 @@ int AllowCount() { return mock_permission_bubble_factory_->show_count(); } void UpdateExpectations(TestingAction action) { - // Set expectations for PermissionBubbleManager. + // Set expectations for PermissionRequestManager. if (action == ACCEPT) { mock_permission_bubble_factory_->set_response_type( - PermissionBubbleManager::ACCEPT_ALL); + PermissionRequestManager::ACCEPT_ALL); } else if (action == CANCEL) { mock_permission_bubble_factory_->set_response_type( - PermissionBubbleManager::DENY_ALL); + PermissionRequestManager::DENY_ALL); } else if (action == WAIT) { mock_permission_bubble_factory_->set_response_type( - PermissionBubbleManager::NONE); + PermissionRequestManager::NONE); } else { mock_permission_bubble_factory_->set_response_type( - PermissionBubbleManager::DISMISS); + PermissionRequestManager::DISMISS); } }
diff --git a/chrome/browser/download/download_shelf_context_menu.cc b/chrome/browser/download/download_shelf_context_menu.cc index 53dc0235..fe8769c 100644 --- a/chrome/browser/download/download_shelf_context_menu.cc +++ b/chrome/browser/download/download_shelf_context_menu.cc
@@ -88,7 +88,7 @@ bool DownloadShelfContextMenu::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; }
diff --git a/chrome/browser/download/download_shelf_context_menu.h b/chrome/browser/download/download_shelf_context_menu.h index da4960e..22ba178 100644 --- a/chrome/browser/download/download_shelf_context_menu.h +++ b/chrome/browser/download/download_shelf_context_menu.h
@@ -44,7 +44,7 @@ bool IsCommandIdVisible(int command_id) const override; void ExecuteCommand(int command_id, int event_flags) override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; bool IsItemForCommandIdDynamic(int command_id) const override; base::string16 GetLabelForCommandId(int command_id) const override;
diff --git a/chrome/browser/extensions/active_tab_unittest.cc b/chrome/browser/extensions/active_tab_unittest.cc index 9a0908a..1b9504d5 100644 --- a/chrome/browser/extensions/active_tab_unittest.cc +++ b/chrome/browser/extensions/active_tab_unittest.cc
@@ -14,7 +14,6 @@ #include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sessions/session_tab_helper.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "components/version_info/version_info.h" #include "content/public/browser/browser_thread.h" @@ -29,6 +28,7 @@ #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" #include "extensions/common/features/feature.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/permissions/permissions_data.h" #include "extensions/common/value_builder.h"
diff --git a/chrome/browser/extensions/all_urls_apitest.cc b/chrome/browser/extensions/all_urls_apitest.cc index 13b702d..e1e8a6c 100644 --- a/chrome/browser/extensions/all_urls_apitest.cc +++ b/chrome/browser/extensions/all_urls_apitest.cc
@@ -88,7 +88,7 @@ embedded_test_server()->GetURL(kAllUrlsTarget).spec(), bystander->GetResourceURL("page.html").spec() }; - for (auto test_url : test_urls) + for (const auto& test_url : test_urls) NavigateAndWait(test_url); }
diff --git a/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc b/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc index bad2c65..82c81a7 100644 --- a/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc +++ b/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
@@ -135,10 +135,10 @@ new base::DictionaryValue); origin_types->SetBoolean( extension_browsing_data_api_constants::kUnprotectedWebKey, - prefs->GetBoolean(prefs::kDeleteCookies)); + prefs->GetBoolean(browsing_data::prefs::kDeleteCookies)); origin_types->SetBoolean( extension_browsing_data_api_constants::kProtectedWebKey, - prefs->GetBoolean(prefs::kDeleteHostedAppsData)); + prefs->GetBoolean(browsing_data::prefs::kDeleteHostedAppsData)); origin_types->SetBoolean( extension_browsing_data_api_constants::kExtensionsKey, false); @@ -161,8 +161,9 @@ std::unique_ptr<base::DictionaryValue> selected(new base::DictionaryValue); std::unique_ptr<base::DictionaryValue> permitted(new base::DictionaryValue); - bool delete_site_data = prefs->GetBoolean(prefs::kDeleteCookies) || - prefs->GetBoolean(prefs::kDeleteHostedAppsData); + bool delete_site_data = + prefs->GetBoolean(browsing_data::prefs::kDeleteCookies) || + prefs->GetBoolean(browsing_data::prefs::kDeleteHostedAppsData); SetDetails(selected.get(), permitted.get(), extension_browsing_data_api_constants::kAppCacheKey, @@ -198,19 +199,19 @@ SetDetails(selected.get(), permitted.get(), extension_browsing_data_api_constants::kHistoryKey, - prefs->GetBoolean(prefs::kDeleteBrowsingHistory)); + prefs->GetBoolean(browsing_data::prefs::kDeleteBrowsingHistory)); SetDetails(selected.get(), permitted.get(), extension_browsing_data_api_constants::kDownloadsKey, - prefs->GetBoolean(prefs::kDeleteDownloadHistory)); + prefs->GetBoolean(browsing_data::prefs::kDeleteDownloadHistory)); SetDetails(selected.get(), permitted.get(), extension_browsing_data_api_constants::kCacheKey, - prefs->GetBoolean(prefs::kDeleteCache)); + prefs->GetBoolean(browsing_data::prefs::kDeleteCache)); SetDetails(selected.get(), permitted.get(), extension_browsing_data_api_constants::kFormDataKey, - prefs->GetBoolean(prefs::kDeleteFormData)); + prefs->GetBoolean(browsing_data::prefs::kDeleteFormData)); SetDetails(selected.get(), permitted.get(), extension_browsing_data_api_constants::kPasswordsKey, - prefs->GetBoolean(prefs::kDeletePasswords)); + prefs->GetBoolean(browsing_data::prefs::kDeletePasswords)); std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue); result->Set(extension_browsing_data_api_constants::kOptionsKey,
diff --git a/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc b/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc index 24a8ce02..9558aea8 100644 --- a/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc +++ b/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
@@ -164,20 +164,20 @@ int expected_origin_type_mask, int expected_removal_mask) { PrefService* prefs = browser()->profile()->GetPrefs(); - prefs->SetBoolean(prefs::kDeleteCache, + prefs->SetBoolean(browsing_data::prefs::kDeleteCache, !!(data_type_flags & BrowsingDataRemover::REMOVE_CACHE)); - prefs->SetBoolean(prefs::kDeleteCookies, + prefs->SetBoolean(browsing_data::prefs::kDeleteCookies, !!(data_type_flags & BrowsingDataRemover::REMOVE_COOKIES)); - prefs->SetBoolean(prefs::kDeleteBrowsingHistory, + prefs->SetBoolean(browsing_data::prefs::kDeleteBrowsingHistory, !!(data_type_flags & BrowsingDataRemover::REMOVE_HISTORY)); - prefs->SetBoolean(prefs::kDeleteFormData, + prefs->SetBoolean(browsing_data::prefs::kDeleteFormData, !!(data_type_flags & BrowsingDataRemover::REMOVE_FORM_DATA)); - prefs->SetBoolean(prefs::kDeleteDownloadHistory, + prefs->SetBoolean(browsing_data::prefs::kDeleteDownloadHistory, !!(data_type_flags & BrowsingDataRemover::REMOVE_DOWNLOADS)); - prefs->SetBoolean(prefs::kDeleteHostedAppsData, + prefs->SetBoolean(browsing_data::prefs::kDeleteHostedAppsData, !!(data_type_flags & BrowsingDataRemover::REMOVE_HOSTED_APP_DATA_TESTONLY)); - prefs->SetBoolean(prefs::kDeletePasswords, + prefs->SetBoolean(browsing_data::prefs::kDeletePasswords, !!(data_type_flags & BrowsingDataRemover::REMOVE_PASSWORDS)); prefs->SetBoolean(prefs::kClearPluginLSODataEnabled, !!(data_type_flags & BrowsingDataRemover::REMOVE_PLUGIN_DATA)); @@ -405,13 +405,13 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, BrowsingDataRemovalInputFromSettings) { PrefService* prefs = browser()->profile()->GetPrefs(); - prefs->SetBoolean(prefs::kDeleteCache, true); - prefs->SetBoolean(prefs::kDeleteBrowsingHistory, true); - prefs->SetBoolean(prefs::kDeleteDownloadHistory, true); - prefs->SetBoolean(prefs::kDeleteCookies, false); - prefs->SetBoolean(prefs::kDeleteFormData, false); - prefs->SetBoolean(prefs::kDeleteHostedAppsData, false); - prefs->SetBoolean(prefs::kDeletePasswords, false); + prefs->SetBoolean(browsing_data::prefs::kDeleteCache, true); + prefs->SetBoolean(browsing_data::prefs::kDeleteBrowsingHistory, true); + prefs->SetBoolean(browsing_data::prefs::kDeleteDownloadHistory, true); + prefs->SetBoolean(browsing_data::prefs::kDeleteCookies, false); + prefs->SetBoolean(browsing_data::prefs::kDeleteFormData, false); + prefs->SetBoolean(browsing_data::prefs::kDeleteHostedAppsData, false); + prefs->SetBoolean(browsing_data::prefs::kDeletePasswords, false); prefs->SetBoolean(prefs::kClearPluginLSODataEnabled, false); int expected_mask = BrowsingDataRemover::REMOVE_CACHE | BrowsingDataRemover::REMOVE_DOWNLOADS |
diff --git a/chrome/browser/extensions/api/data_reduction_proxy/data_reduction_proxy_api.cc b/chrome/browser/extensions/api/data_reduction_proxy/data_reduction_proxy_api.cc index a2563e22..1f84f6a 100644 --- a/chrome/browser/extensions/api/data_reduction_proxy/data_reduction_proxy_api.cc +++ b/chrome/browser/extensions/api/data_reduction_proxy/data_reduction_proxy_api.cc
@@ -48,9 +48,9 @@ for (const auto& data_usage_bucket : *data_usage) { std::unique_ptr<base::ListValue> connection_usage_list( new base::ListValue()); - for (auto connection_usage : data_usage_bucket.connection_usage()) { + for (const auto& connection_usage : data_usage_bucket.connection_usage()) { std::unique_ptr<base::ListValue> site_usage_list(new base::ListValue()); - for (auto site_usage : connection_usage.site_usage()) { + for (const auto& site_usage : connection_usage.site_usage()) { std::unique_ptr<base::DictionaryValue> usage( new base::DictionaryValue()); usage->SetString("hostname", site_usage.hostname());
diff --git a/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc b/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc index 404e3225..e8798fd 100644 --- a/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc +++ b/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc
@@ -14,7 +14,6 @@ #include "chrome/browser/extensions/test_extension_environment.h" #include "chrome/browser/extensions/test_extension_system.h" #include "chrome/common/extensions/extension_test_util.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/test/base/testing_profile.h" #include "components/version_info/version_info.h" #include "content/public/test/test_browser_thread_bundle.h" @@ -25,6 +24,7 @@ #include "extensions/browser/extension_registry.h" #include "extensions/browser/value_store/testing_value_store.h" #include "extensions/common/extension.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/permissions/permissions_data.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/extensions/api/declarative_content/set_icon_apitest.cc b/chrome/browser/extensions/api/declarative_content/set_icon_apitest.cc index a1936a2..fd0e3d3 100644 --- a/chrome/browser/extensions/api/declarative_content/set_icon_apitest.cc +++ b/chrome/browser/extensions/api/declarative_content/set_icon_apitest.cc
@@ -7,8 +7,8 @@ #include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/extensions/test_extension_dir.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "components/version_info/version_info.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/test/extension_test_message_listener.h" #include "ui/gfx/image/image.h"
diff --git a/chrome/browser/extensions/api/idltest/idltest_apitest.cc b/chrome/browser/extensions/api/idltest/idltest_apitest.cc index eb564da..a81cb23 100644 --- a/chrome/browser/extensions/api/idltest/idltest_apitest.cc +++ b/chrome/browser/extensions/api/idltest/idltest_apitest.cc
@@ -3,8 +3,8 @@ // found in the LICENSE file. #include "chrome/browser/extensions/extension_apitest.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "components/version_info/version_info.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/switches.h" class ExtensionIdltestApiTest : public ExtensionApiTest {
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc b/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc index 15e9495..8293095 100644 --- a/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc +++ b/chrome/browser/extensions/api/messaging/native_message_process_host_unittest.cc
@@ -28,11 +28,11 @@ #include "build/build_config.h" #include "chrome/browser/extensions/api/messaging/native_messaging_test_util.h" #include "chrome/browser/extensions/api/messaging/native_process_launcher.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "components/version_info/version_info.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_browser_thread_bundle.h" #include "extensions/common/extension.h" +#include "extensions/common/features/feature_channel.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(OS_WIN)
diff --git a/chrome/browser/extensions/api/permissions/permissions_apitest.cc b/chrome/browser/extensions/api/permissions/permissions_apitest.cc index bab711a9..3de54c7 100644 --- a/chrome/browser/extensions/api/permissions/permissions_apitest.cc +++ b/chrome/browser/extensions/api/permissions/permissions_apitest.cc
@@ -79,8 +79,7 @@ // Test functions and APIs that are always allowed (even if you ask for no // permissions). -// Disabled: http://crbug.com/125193 -IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_AlwaysAllowed) { +IN_PROC_BROWSER_TEST_F(ExtensionApiTest, AlwaysAllowed) { ASSERT_TRUE(RunExtensionTest("permissions/always_allowed")) << message_; }
diff --git a/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc b/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc index b89d3b8..f22e8b3 100644 --- a/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc +++ b/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
@@ -78,7 +78,7 @@ bool GetPacMandatoryFromExtensionPref(const base::DictionaryValue* proxy_config, bool* out, std::string* error, - bool* bad_message){ + bool* bad_message) { const base::DictionaryValue* pac_dict = NULL; proxy_config->GetDictionary(keys::kProxyConfigPacScript, &pac_dict); if (!pac_dict) @@ -475,7 +475,7 @@ return NULL; } - if (pac_url.find("data") == 0) { + if (base::StartsWith(pac_url, "data", base::CompareCase::SENSITIVE)) { std::string pac_data; if (!CreatePACScriptFromDataURL(pac_url, &pac_data)) { LOG(ERROR) << "Cannot decode base64-encoded PAC data URL: " << pac_url;
diff --git a/chrome/browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc b/chrome/browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc index e465f59..4d0ffce 100644 --- a/chrome/browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc +++ b/chrome/browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc
@@ -10,12 +10,12 @@ #include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search_engines/template_url_service_factory.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" #include "components/search_engines/template_url.h" #include "components/search_engines/template_url_service.h" #include "components/version_info/version_info.h" +#include "extensions/common/features/feature_channel.h" namespace {
diff --git a/chrome/browser/extensions/api/webrtc_from_web_accessible_resource_browsertest.cc b/chrome/browser/extensions/api/webrtc_from_web_accessible_resource_browsertest.cc index 32306a74..7db1679d 100644 --- a/chrome/browser/extensions/api/webrtc_from_web_accessible_resource_browsertest.cc +++ b/chrome/browser/extensions/api/webrtc_from_web_accessible_resource_browsertest.cc
@@ -5,8 +5,8 @@ #include "base/command_line.h" #include "base/macros.h" #include "chrome/browser/extensions/extension_apitest.h" +#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" #include "chrome/test/base/ui_test_utils.h" #include "extensions/test/result_catcher.h" #include "media/base/media_switches.h" @@ -18,28 +18,29 @@ namespace { // Used to observe the creation of permission prompt without responding. -class PermissionRequestObserver : public PermissionBubbleManager::Observer { +class PermissionRequestObserver : public PermissionRequestManager::Observer { public: explicit PermissionRequestObserver(content::WebContents* web_contents) - : bubble_manager_(PermissionBubbleManager::FromWebContents(web_contents)), + : request_manager_( + PermissionRequestManager::FromWebContents(web_contents)), request_shown_(false) { - bubble_manager_->AddObserver(this); + request_manager_->AddObserver(this); } ~PermissionRequestObserver() override { // Safe to remove twice if it happens. - bubble_manager_->RemoveObserver(this); + request_manager_->RemoveObserver(this); } bool request_shown() const { return request_shown_; } private: - // PermissionBubbleManager::Observer + // PermissionRequestManager::Observer void OnBubbleAdded() override { request_shown_ = true; - bubble_manager_->RemoveObserver(this); + request_manager_->RemoveObserver(this); } - PermissionBubbleManager* bubble_manager_; + PermissionRequestManager* request_manager_; bool request_shown_; DISALLOW_COPY_AND_ASSIGN(PermissionRequestObserver); @@ -91,10 +92,10 @@ GURL url = GetTestServerInsecureUrl("/extensions/test_file.html?succeed"); content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); - PermissionBubbleManager* bubble_manager = - PermissionBubbleManager::FromWebContents(web_contents); - bubble_manager->set_auto_response_for_test( - PermissionBubbleManager::ACCEPT_ALL); + PermissionRequestManager* request_manager = + PermissionRequestManager::FromWebContents(web_contents); + request_manager->set_auto_response_for_test( + PermissionRequestManager::ACCEPT_ALL); PermissionRequestObserver permission_request_observer(web_contents); extensions::ResultCatcher catcher; ui_test_utils::NavigateToURL(browser(), url); @@ -104,7 +105,7 @@ } // Verify that a chrome-extension:// web accessible URL will fail to access -// getUserMedia() if it is denied by the permission bubble, even if it is +// getUserMedia() if it is denied by the permission request, even if it is // embedded in an insecure context. IN_PROC_BROWSER_TEST_F(WebRtcFromWebAccessibleResourceTest, GetUserMediaInWebAccessibleResourceFail) { @@ -115,9 +116,10 @@ GURL url = GetTestServerInsecureUrl("/extensions/test_file.html?fail"); content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); - PermissionBubbleManager* bubble_manager = - PermissionBubbleManager::FromWebContents(web_contents); - bubble_manager->set_auto_response_for_test(PermissionBubbleManager::DENY_ALL); + PermissionRequestManager* request_manager = + PermissionRequestManager::FromWebContents(web_contents); + request_manager->set_auto_response_for_test( + PermissionRequestManager::DENY_ALL); PermissionRequestObserver permission_request_observer(web_contents); extensions::ResultCatcher catcher; ui_test_utils::NavigateToURL(browser(), url);
diff --git a/chrome/browser/extensions/chrome_component_extension_resource_manager.cc b/chrome/browser/extensions/chrome_component_extension_resource_manager.cc index cb1b9625..3207a71 100644 --- a/chrome/browser/extensions/chrome_component_extension_resource_manager.cc +++ b/chrome/browser/extensions/chrome_component_extension_resource_manager.cc
@@ -36,12 +36,6 @@ {"webstore_widget/app/icons/icon_32.png", IDR_WEBSTORE_ICON_32}, {"webstore_widget/app/icons/icon_128.png", IDR_WEBSTORE_ICON}, #endif -#if defined(ENABLE_SETTINGS_APP) - {"settings_app/settings_app_icon_128.png", IDR_SETTINGS_APP_ICON_128}, - {"settings_app/settings_app_icon_16.png", IDR_SETTINGS_APP_ICON_16}, - {"settings_app/settings_app_icon_32.png", IDR_SETTINGS_APP_ICON_32}, - {"settings_app/settings_app_icon_48.png", IDR_SETTINGS_APP_ICON_48}, -#endif }; AddComponentResourceEntries(
diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.cc b/chrome/browser/extensions/chrome_extensions_browser_client.cc index 7ee9827..f1c6956 100644 --- a/chrome/browser/extensions/chrome_extensions_browser_client.cc +++ b/chrome/browser/extensions/chrome_extensions_browser_client.cc
@@ -41,7 +41,6 @@ #include "chrome/common/channel_info.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/common/pref_names.h" #include "components/net_log/chrome_net_log.h" #include "components/update_client/update_client.h" @@ -54,6 +53,7 @@ #include "extensions/browser/mojo/service_registration.h" #include "extensions/browser/pref_names.h" #include "extensions/browser/url_request_util.h" +#include "extensions/common/features/feature_channel.h" #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/profiles/profile_helper.h"
diff --git a/chrome/browser/extensions/chrome_notification_observer.cc b/chrome/browser/extensions/chrome_notification_observer.cc index b15598e..5c654258 100644 --- a/chrome/browser/extensions/chrome_notification_observer.cc +++ b/chrome/browser/extensions/chrome_notification_observer.cc
@@ -4,11 +4,11 @@ #include "chrome/browser/extensions/chrome_notification_observer.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/render_process_host.h" #include "extensions/common/extension_messages.h" +#include "extensions/common/features/feature_channel.h" namespace extensions {
diff --git a/chrome/browser/extensions/component_extensions_whitelist/whitelist.cc b/chrome/browser/extensions/component_extensions_whitelist/whitelist.cc index ddabb67..39783ef 100644 --- a/chrome/browser/extensions/component_extensions_whitelist/whitelist.cc +++ b/chrome/browser/extensions/component_extensions_whitelist/whitelist.cc
@@ -80,7 +80,6 @@ IDR_HOTWORD_MANIFEST, IDR_IDENTITY_API_SCOPE_APPROVAL_MANIFEST, IDR_NETWORK_SPEECH_SYNTHESIS_MANIFEST, - IDR_SETTINGS_APP_MANIFEST, IDR_WALLPAPERMANAGER_MANIFEST, IDR_WEBSTORE_MANIFEST, #if defined(IMAGE_LOADER_EXTENSION)
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc index 0760fe2..c750cbb 100644 --- a/chrome/browser/extensions/component_loader.cc +++ b/chrome/browser/extensions/component_loader.cc
@@ -589,11 +589,6 @@ #endif // defined(GOOGLE_CHROME_BUILD) if (install_feedback) Add(IDR_FEEDBACK_MANIFEST, base::FilePath(FILE_PATH_LITERAL("feedback"))); - -#if defined(ENABLE_SETTINGS_APP) - Add(IDR_SETTINGS_APP_MANIFEST, - base::FilePath(FILE_PATH_LITERAL("settings_app"))); -#endif } #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/extensions/error_console/error_console.cc b/chrome/browser/extensions/error_console/error_console.cc index 088f553..07574f3 100644 --- a/chrome/browser/extensions/error_console/error_console.cc +++ b/chrome/browser/extensions/error_console/error_console.cc
@@ -15,7 +15,6 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/error_console/error_console_factory.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/common/pref_names.h" #include "components/crx_file/id_util.h" #include "components/prefs/pref_service.h" @@ -30,6 +29,7 @@ #include "extensions/common/extension.h" #include "extensions/common/extension_set.h" #include "extensions/common/feature_switch.h" +#include "extensions/common/features/feature_channel.h" namespace extensions {
diff --git a/chrome/browser/extensions/error_console/error_console_unittest.cc b/chrome/browser/extensions/error_console/error_console_unittest.cc index 6794b951a..71f77e2 100644 --- a/chrome/browser/extensions/error_console/error_console_unittest.cc +++ b/chrome/browser/extensions/error_console/error_console_unittest.cc
@@ -11,7 +11,6 @@ #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/strings/string_number_conversions.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" #include "components/crx_file/id_util.h" @@ -24,6 +23,7 @@ #include "extensions/common/constants.h" #include "extensions/common/extension_builder.h" #include "extensions/common/feature_switch.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/value_builder.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h index cdb9714..31ad88e 100644 --- a/chrome/browser/extensions/extension_browsertest.h +++ b/chrome/browser/extensions/extension_browsertest.h
@@ -16,13 +16,13 @@ #include "chrome/browser/extensions/extension_test_notification_observer.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/test/base/in_process_browser_test.h" #include "content/public/browser/web_contents.h" #include "extensions/browser/extension_host.h" #include "extensions/browser/extension_system.h" #include "extensions/common/extension.h" #include "extensions/common/feature_switch.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/manifest.h" class ExtensionService;
diff --git a/chrome/browser/extensions/extension_context_menu_model.cc b/chrome/browser/extensions/extension_context_menu_model.cc index b5079f9..34be392 100644 --- a/chrome/browser/extensions/extension_context_menu_model.cc +++ b/chrome/browser/extensions/extension_context_menu_model.cc
@@ -228,7 +228,8 @@ } bool ExtensionContextMenuModel::GetAcceleratorForCommandId( - int command_id, ui::Accelerator* accelerator) { + int command_id, + ui::Accelerator* accelerator) const { return false; }
diff --git a/chrome/browser/extensions/extension_context_menu_model.h b/chrome/browser/extensions/extension_context_menu_model.h index 7543dc3..095e84db 100644 --- a/chrome/browser/extensions/extension_context_menu_model.h +++ b/chrome/browser/extensions/extension_context_menu_model.h
@@ -81,7 +81,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; ui::SimpleMenuModel* page_access_submenu_for_testing() {
diff --git a/chrome/browser/extensions/extension_loading_browsertest.cc b/chrome/browser/extensions/extension_loading_browsertest.cc index 3967881..430c531 100644 --- a/chrome/browser/extensions/extension_loading_browsertest.cc +++ b/chrome/browser/extensions/extension_loading_browsertest.cc
@@ -101,12 +101,6 @@ // Tests the behavior described in http://crbug.com/532088. IN_PROC_BROWSER_TEST_F(ExtensionLoadingTest, KeepAliveWithDevToolsOpenOnReload) { -#if defined(OS_WIN) - // Flaky on Win XP SP3. http://crbug.com/560716. - if (base::win::GetVersion() <= base::win::VERSION_SERVER_2003) - return; -#endif - embedded_test_server()->ServeFilesFromDirectory( base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc b/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc index 84630720..f87a3bd4 100644 --- a/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc +++ b/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc
@@ -28,7 +28,6 @@ #include "chrome/browser/extensions/test_extension_system.h" #include "chrome/browser/ui/toolbar/toolbar_actions_model.h" #include "chrome/browser/ui/toolbar/toolbar_actions_model_factory.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/testing_profile.h" #include "components/proxy_config/proxy_config_pref_names.h" @@ -44,6 +43,7 @@ #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" #include "extensions/common/feature_switch.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/value_builder.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index fd3e8f36..773f349 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc
@@ -58,7 +58,6 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/crash_keys.h" #include "chrome/common/extensions/extension_constants.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/common/url_constants.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/crx_file/id_util.h" @@ -82,6 +81,7 @@ #include "extensions/common/extension_messages.h" #include "extensions/common/extension_urls.h" #include "extensions/common/feature_switch.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/file_util.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/manifest_handlers/background_info.h"
diff --git a/chrome/browser/extensions/extension_special_storage_policy.cc b/chrome/browser/extensions/extension_special_storage_policy.cc index 07ac1465..eed89f2 100644 --- a/chrome/browser/extensions/extension_special_storage_policy.cc +++ b/chrome/browser/extensions/extension_special_storage_policy.cc
@@ -314,7 +314,7 @@ bool ExtensionSpecialStoragePolicy::SpecialCollection::GrantsCapabilitiesTo( const GURL& origin) { - for (scoped_refptr<const Extension> extension : extensions_) { + for (const auto& extension : extensions_) { if (extensions::ContentCapabilitiesInfo::Get(extension.get()) .url_patterns.MatchesURL(origin)) { return true;
diff --git a/chrome/browser/extensions/extension_system_impl.cc b/chrome/browser/extensions/extension_system_impl.cc index 365ef91..fa7596f 100644 --- a/chrome/browser/extensions/extension_system_impl.cc +++ b/chrome/browser/extensions/extension_system_impl.cc
@@ -37,7 +37,6 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/url_data_source.h" #include "extensions/browser/content_verifier.h" @@ -54,6 +53,7 @@ #include "extensions/browser/uninstall_ping_sender.h" #include "extensions/browser/value_store/value_store_factory_impl.h" #include "extensions/common/constants.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/manifest_url_handlers.h" #if defined(ENABLE_NOTIFICATIONS)
diff --git a/chrome/browser/extensions/extension_test_notification_observer.cc b/chrome/browser/extensions/extension_test_notification_observer.cc index 4d6c9b0f..a9f3d8f2 100644 --- a/chrome/browser/extensions/extension_test_notification_observer.cc +++ b/chrome/browser/extensions/extension_test_notification_observer.cc
@@ -7,6 +7,7 @@ #include <stddef.h> #include "base/callback_list.h" +#include "base/scoped_observer.h" #include "chrome/browser/extensions/extension_action_test_util.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_util.h" @@ -20,6 +21,7 @@ #include "content/public/test/test_utils.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/process_manager.h" +#include "extensions/browser/process_manager_observer.h" #include "extensions/common/extension.h" using extensions::Extension; @@ -58,10 +60,15 @@ // ExtensionTestNotificationObserver::NotificationSet class ExtensionTestNotificationObserver::NotificationSet - : public content::NotificationObserver { + : public content::NotificationObserver, + public extensions::ProcessManagerObserver { public: + NotificationSet() : process_manager_observer_(this) {} + ~NotificationSet() override {} + void Add(int type, const content::NotificationSource& source); void Add(int type); + void AddExtensionFrameUnregistration(extensions::ProcessManager* manager); // Notified any time an Add()ed notification is received. // The details of the notification are dropped. @@ -75,8 +82,15 @@ const content::NotificationSource& source, const content::NotificationDetails& details) override; + // extensions::ProcessManagerObserver: + void OnExtensionFrameUnregistered( + const std::string& extension_id, + content::RenderFrameHost* render_frame_host) override; + content::NotificationRegistrar notification_registrar_; base::CallbackList<void()> callback_list_; + ScopedObserver<extensions::ProcessManager, extensions::ProcessManagerObserver> + process_manager_observer_; }; void ExtensionTestNotificationObserver::NotificationSet::Add( @@ -89,6 +103,11 @@ Add(type, content::NotificationService::AllSources()); } +void ExtensionTestNotificationObserver::NotificationSet:: + AddExtensionFrameUnregistration(extensions::ProcessManager* manager) { + process_manager_observer_.Add(manager); +} + void ExtensionTestNotificationObserver::NotificationSet::Observe( int type, const content::NotificationSource& source, @@ -96,6 +115,12 @@ callback_list_.Notify(); } +void ExtensionTestNotificationObserver::NotificationSet:: + OnExtensionFrameUnregistered(const std::string& extension_id, + content::RenderFrameHost* render_frame_host) { + callback_list_.Notify(); +} + //////////////////////////////////////////////////////////////////////////////// // ExtensionTestNotificationObserver @@ -149,6 +174,7 @@ NotificationSet notification_set; notification_set.Add(content::NOTIFICATION_WEB_CONTENTS_DESTROYED); notification_set.Add(content::NOTIFICATION_LOAD_STOP); + notification_set.AddExtensionFrameUnregistration(manager); WaitForCondition( base::Bind(&HaveAllExtensionRenderFrameHostsFinishedLoading, manager), ¬ification_set);
diff --git a/chrome/browser/extensions/shared_module_service_unittest.cc b/chrome/browser/extensions/shared_module_service_unittest.cc index e53cc40..54a5b37 100644 --- a/chrome/browser/extensions/shared_module_service_unittest.cc +++ b/chrome/browser/extensions/shared_module_service_unittest.cc
@@ -13,13 +13,13 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_service_test_base.h" #include "chrome/browser/extensions/pending_extension_manager.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "components/crx_file/id_util.h" #include "components/version_info/version_info.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/install_flag.h" #include "extensions/browser/uninstall_reason.h" #include "extensions/common/extension_builder.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/value_builder.h" #include "sync/api/string_ordinal.h"
diff --git a/chrome/browser/geolocation/geolocation_browsertest.cc b/chrome/browser/geolocation/geolocation_browsertest.cc index d440c861..ced160d 100644 --- a/chrome/browser/geolocation/geolocation_browsertest.cc +++ b/chrome/browser/geolocation/geolocation_browsertest.cc
@@ -17,11 +17,11 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/content_settings/tab_specific_content_settings.h" +#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/content_settings/core/browser/content_settings_usages_state.h" @@ -127,21 +127,22 @@ base::MessageLoopForUI::current()->QuitWhenIdle(); } -// PermissionBubbleObserver --------------------------------------------------- +// PermissionRequestObserver --------------------------------------------------- -// Used to observe the creation of a single permission bubble without +// Used to observe the creation of a single permission request without // responding. -class PermissionBubbleObserver : public PermissionBubbleManager::Observer { +class PermissionRequestObserver : public PermissionRequestManager::Observer { public: - explicit PermissionBubbleObserver(content::WebContents* web_contents) - : bubble_manager_(PermissionBubbleManager::FromWebContents(web_contents)), + explicit PermissionRequestObserver(content::WebContents* web_contents) + : request_manager_( + PermissionRequestManager::FromWebContents(web_contents)), request_shown_(false), message_loop_runner_(new content::MessageLoopRunner) { - bubble_manager_->AddObserver(this); + request_manager_->AddObserver(this); } - ~PermissionBubbleObserver() override { + ~PermissionRequestObserver() override { // Safe to remove twice if it happens. - bubble_manager_->RemoveObserver(this); + request_manager_->RemoveObserver(this); } void Wait() { message_loop_runner_->Run(); } @@ -149,18 +150,18 @@ bool request_shown() { return request_shown_; } private: - // PermissionBubbleManager::Observer + // PermissionRequestManager::Observer void OnBubbleAdded() override { request_shown_ = true; - bubble_manager_->RemoveObserver(this); + request_manager_->RemoveObserver(this); message_loop_runner_->Quit(); } - PermissionBubbleManager* bubble_manager_; + PermissionRequestManager* request_manager_; bool request_shown_; scoped_refptr<content::MessageLoopRunner> message_loop_runner_; - DISALLOW_COPY_AND_ASSIGN(PermissionBubbleObserver); + DISALLOW_COPY_AND_ASSIGN(PermissionRequestObserver); }; } // namespace @@ -221,14 +222,14 @@ HostContentSettingsMap* GetHostContentSettingsMap(); // Calls watchPosition in JavaScript and accepts or denies the resulting - // permission bubble. Returns |true| if the expected behavior happened. + // permission request. Returns |true| if the expected behavior happened. bool WatchPositionAndGrantPermission() WARN_UNUSED_RESULT; bool WatchPositionAndDenyPermission() WARN_UNUSED_RESULT; // Calls watchPosition in JavaScript and observes whether the permission - // bubble is shown without interacting with it. Callers should set - // |bubble_should_display| to |true| if they expect a bubble to display. - void WatchPositionAndObservePermissionBubble(bool bubble_should_display); + // request is shown without interacting with it. Callers should set + // |request_should_display| to |true| if they expect a request to display. + void WatchPositionAndObservePermissionRequest(bool request_should_display); // Checks that no errors have been received in JavaScript, and checks that the // position most recently received matches |latitude| and |longitude|. @@ -250,14 +251,14 @@ // successfully in JavaScript. bool SetPositionAndWaitUntilUpdated(double latitude, double longitude); - // Convenience method to look up the number of queued permission bubbles. - int GetBubbleQueueSize(PermissionBubbleManager* manager); + // Convenience method to look up the number of queued permission requests. + int GetRequestQueueSize(PermissionRequestManager* manager); private: // Calls watchPosition() in JavaScript and accepts or denies the resulting - // permission bubble. Returns the JavaScript response. - std::string WatchPositionAndRespondToPermissionBubble( - PermissionBubbleManager::AutoResponseType bubble_response); + // permission request. Returns the JavaScript response. + std::string WatchPositionAndRespondToPermissionRequest( + PermissionRequestManager::AutoResponseType request_response); // The current Browser as set in Initialize. May be for an incognito profile. Browser* current_browser_ = nullptr; @@ -347,39 +348,39 @@ } bool GeolocationBrowserTest::WatchPositionAndGrantPermission() { - std::string result = WatchPositionAndRespondToPermissionBubble( - PermissionBubbleManager::ACCEPT_ALL); + std::string result = WatchPositionAndRespondToPermissionRequest( + PermissionRequestManager::ACCEPT_ALL); return "request-callback-success" == result; } bool GeolocationBrowserTest::WatchPositionAndDenyPermission() { - std::string result = WatchPositionAndRespondToPermissionBubble( - PermissionBubbleManager::DENY_ALL); + std::string result = WatchPositionAndRespondToPermissionRequest( + PermissionRequestManager::DENY_ALL); return "request-callback-error" == result; } -std::string GeolocationBrowserTest::WatchPositionAndRespondToPermissionBubble( - PermissionBubbleManager::AutoResponseType bubble_response) { - PermissionBubbleManager::FromWebContents( +std::string GeolocationBrowserTest::WatchPositionAndRespondToPermissionRequest( + PermissionRequestManager::AutoResponseType request_response) { + PermissionRequestManager::FromWebContents( current_browser_->tab_strip_model()->GetActiveWebContents()) - ->set_auto_response_for_test(bubble_response); + ->set_auto_response_for_test(request_response); return RunScript(render_frame_host_, "geoStartWithAsyncResponse()"); } -void GeolocationBrowserTest::WatchPositionAndObservePermissionBubble( - bool bubble_should_display) { - PermissionBubbleObserver observer( +void GeolocationBrowserTest::WatchPositionAndObservePermissionRequest( + bool request_should_display) { + PermissionRequestObserver observer( current_browser_->tab_strip_model()->GetActiveWebContents()); - if (bubble_should_display) { + if (request_should_display) { // Control will return as soon as the API call is made, and then the - // observer will wait for the bubble to display. + // observer will wait for the request to display. RunScript(render_frame_host_, "geoStartWithSyncResponse()"); observer.Wait(); } else { // Control will return once one of the callbacks fires. RunScript(render_frame_host_, "geoStartWithAsyncResponse()"); } - EXPECT_EQ(bubble_should_display, observer.request_shown()); + EXPECT_EQ(request_should_display, observer.request_shown()); } void GeolocationBrowserTest::ExpectPosition(double latitude, double longitude) { @@ -423,8 +424,8 @@ return result == "geoposition-updated"; } -int GeolocationBrowserTest::GetBubbleQueueSize( - PermissionBubbleManager* manager) { +int GeolocationBrowserTest::GetRequestQueueSize( + PermissionRequestManager* manager) { return static_cast<int>(manager->requests_.size()); } @@ -469,9 +470,9 @@ ASSERT_NO_FATAL_FAILURE(Initialize(INITIALIZATION_DEFAULT)); ASSERT_TRUE(WatchPositionAndGrantPermission()); - // Checks bubble is not needed in a second tab. + // Checks request is not needed in a second tab. ASSERT_NO_FATAL_FAILURE(Initialize(INITIALIZATION_NEWTAB)); - WatchPositionAndObservePermissionBubble(false); + WatchPositionAndObservePermissionRequest(false); ExpectPosition(fake_latitude(), fake_longitude()); } @@ -481,13 +482,13 @@ current_url(), current_url(), CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string(), CONTENT_SETTING_BLOCK); - // Check that the bubble wasn't shown but we get an error for this origin. - WatchPositionAndObservePermissionBubble(false); + // Check that the request wasn't shown but we get an error for this origin. + WatchPositionAndObservePermissionRequest(false); ExpectValueFromScript(GetErrorCodePermissionDenied(), "geoGetLastError()"); // Checks prompt will not be created a second tab. ASSERT_NO_FATAL_FAILURE(Initialize(INITIALIZATION_NEWTAB)); - WatchPositionAndObservePermissionBubble(false); + WatchPositionAndObservePermissionRequest(false); ExpectValueFromScript(GetErrorCodePermissionDenied(), "geoGetLastError()"); } @@ -502,9 +503,9 @@ GetHostContentSettingsMap()->SetContentSettingDefaultScope( current_url(), current_url(), CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string(), CONTENT_SETTING_ALLOW); - // The bubble is not shown, there is no error, and the position gets to the + // The request is not shown, there is no error, and the position gets to the // script. - WatchPositionAndObservePermissionBubble(false); + WatchPositionAndObservePermissionRequest(false); ExpectPosition(fake_latitude(), fake_longitude()); } @@ -519,7 +520,7 @@ // incognito profile. Go incognito, and check that the user is not prompted // again and the position gets to the script. ASSERT_NO_FATAL_FAILURE(Initialize(INITIALIZATION_OFFTHERECORD)); - WatchPositionAndObservePermissionBubble(false); + WatchPositionAndObservePermissionRequest(false); ExpectPosition(fake_latitude(), fake_longitude()); } @@ -558,7 +559,7 @@ // In a second iframe from a different origin with a cached position the user // is prompted. SetFrameForScriptExecution("iframe_1"); - WatchPositionAndObservePermissionBubble(true); + WatchPositionAndObservePermissionRequest(true); // Back to the first frame, enable navigation and refresh geoposition. SetFrameForScriptExecution("iframe_0"); @@ -620,15 +621,15 @@ // Test second iframe from a different origin with a cached position will // create the prompt. SetFrameForScriptExecution("iframe_1"); - WatchPositionAndObservePermissionBubble(true); + WatchPositionAndObservePermissionRequest(true); // Navigate the iframe, and ensure the prompt is gone. content::WebContents* web_contents = current_browser()->tab_strip_model()->GetActiveWebContents(); IFrameLoader change_iframe_1(current_browser(), 1, current_url()); - int num_bubbles_after_cancel = GetBubbleQueueSize( - PermissionBubbleManager::FromWebContents(web_contents)); - EXPECT_EQ(0, num_bubbles_after_cancel); + int num_requests_after_cancel = GetRequestQueueSize( + PermissionRequestManager::FromWebContents(web_contents)); + EXPECT_EQ(0, num_requests_after_cancel); } IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, InvalidUrlRequest) { @@ -710,15 +711,15 @@ LoadIFrames(); SetFrameForScriptExecution("iframe_0"); - WatchPositionAndObservePermissionBubble(true); + WatchPositionAndObservePermissionRequest(true); SetFrameForScriptExecution("iframe_1"); - WatchPositionAndObservePermissionBubble(true); + WatchPositionAndObservePermissionRequest(true); } IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, TabDestroyed) { ASSERT_NO_FATAL_FAILURE(Initialize(INITIALIZATION_DEFAULT)); - WatchPositionAndObservePermissionBubble(true); + WatchPositionAndObservePermissionRequest(true); // TODO(mvanouwerkerk): Can't close a window you did not open. Maybe this was // valid when the test was written, but now it just prints "Scripts may close @@ -755,7 +756,7 @@ clock_->Advance(base::TimeDelta::FromSeconds(3)); // Calling watchPosition should trigger the last usage update. - WatchPositionAndObservePermissionBubble(false); + WatchPositionAndObservePermissionRequest(false); ExpectPosition(fake_latitude(), fake_longitude()); // Last usage has been updated.
diff --git a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc index ad3a68d67..047dfd3 100644 --- a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc +++ b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc
@@ -55,8 +55,8 @@ #include "chrome/browser/geolocation/geolocation_permission_context_android.h" #include "components/prefs/pref_service.h" #else +#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/ui/website_settings/mock_permission_bubble_factory.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" #endif #if defined(ENABLE_EXTENSIONS) @@ -150,14 +150,14 @@ void CheckTabContentsState(const GURL& requesting_frame, ContentSetting expected_content_setting); #if !BUILDFLAG(ANDROID_JAVA_UI) - void SetupBubbleManager(content::WebContents* web_contents); - size_t GetBubblesQueueSize(PermissionBubbleManager* manager); - void AcceptBubble(PermissionBubbleManager* manager); - void DenyBubble(PermissionBubbleManager* manager); - void CloseBubble(PermissionBubbleManager* manager); + void SetupRequestManager(content::WebContents* web_contents); + size_t GetBubblesQueueSize(PermissionRequestManager* manager); + void AcceptBubble(PermissionRequestManager* manager); + void DenyBubble(PermissionRequestManager* manager); + void CloseBubble(PermissionRequestManager* manager); #endif - void BubbleManagerDocumentLoadCompleted(); - void BubbleManagerDocumentLoadCompleted(content::WebContents* web_contents); + void RequestManagerDocumentLoadCompleted(); + void RequestManagerDocumentLoadCompleted(content::WebContents* web_contents); ContentSetting GetGeolocationContentSetting(GURL frame_0, GURL frame_1); size_t GetNumberOfPrompts(); void AcceptPrompt(); @@ -254,7 +254,7 @@ #if BUILDFLAG(ANDROID_JAVA_UI) InfoBarService::CreateForWebContents(new_tab); #else - SetupBubbleManager(new_tab); + SetupRequestManager(new_tab); #endif extra_tabs_.push_back(base::WrapUnique(new_tab)); @@ -295,7 +295,7 @@ std::unique_ptr<LocationSettings>(new MockLocationSettings())); MockLocationSettings::SetLocationStatus(true, true); #else - SetupBubbleManager(web_contents()); + SetupRequestManager(web_contents()); #endif } @@ -308,51 +308,51 @@ } #if !BUILDFLAG(ANDROID_JAVA_UI) -void GeolocationPermissionContextTests::SetupBubbleManager( +void GeolocationPermissionContextTests::SetupRequestManager( content::WebContents* web_contents) { - // Create PermissionBubbleManager. - PermissionBubbleManager::CreateForWebContents(web_contents); - PermissionBubbleManager* permission_bubble_manager = - PermissionBubbleManager::FromWebContents(web_contents); + // Create PermissionRequestManager. + PermissionRequestManager::CreateForWebContents(web_contents); + PermissionRequestManager* permission_request_manager = + PermissionRequestManager::FromWebContents(web_contents); - // Create a MockPermissionBubbleFactory for the PermissionBubbleManager. + // Create a MockPermissionBubbleFactory for the PermissionRequestManager. mock_permission_bubble_factories_.push_back(base::WrapUnique( - new MockPermissionBubbleFactory(permission_bubble_manager))); + new MockPermissionBubbleFactory(permission_request_manager))); - // Prepare the PermissionBubbleManager to display a mock bubble. - permission_bubble_manager->DisplayPendingRequests(); + // Prepare the PermissionRequestManager to display a mock bubble. + permission_request_manager->DisplayPendingRequests(); } size_t GeolocationPermissionContextTests::GetBubblesQueueSize( - PermissionBubbleManager* manager) { + PermissionRequestManager* manager) { return manager->requests_.size(); } void GeolocationPermissionContextTests::AcceptBubble( - PermissionBubbleManager* manager) { + PermissionRequestManager* manager) { manager->Accept(); } void GeolocationPermissionContextTests::DenyBubble( - PermissionBubbleManager* manager) { + PermissionRequestManager* manager) { manager->Deny(); } void GeolocationPermissionContextTests::CloseBubble( - PermissionBubbleManager* manager) { + PermissionRequestManager* manager) { manager->Closing(); } #endif -void GeolocationPermissionContextTests::BubbleManagerDocumentLoadCompleted() { - GeolocationPermissionContextTests::BubbleManagerDocumentLoadCompleted( +void GeolocationPermissionContextTests::RequestManagerDocumentLoadCompleted() { + GeolocationPermissionContextTests::RequestManagerDocumentLoadCompleted( web_contents()); } -void GeolocationPermissionContextTests::BubbleManagerDocumentLoadCompleted( +void GeolocationPermissionContextTests::RequestManagerDocumentLoadCompleted( content::WebContents* web_contents) { #if !BUILDFLAG(ANDROID_JAVA_UI) - PermissionBubbleManager::FromWebContents(web_contents)-> + PermissionRequestManager::FromWebContents(web_contents)-> DocumentOnLoadCompletedInMainFrame(); #endif } @@ -368,8 +368,8 @@ size_t GeolocationPermissionContextTests::GetNumberOfPrompts() { #if !BUILDFLAG(ANDROID_JAVA_UI) - PermissionBubbleManager* manager = - PermissionBubbleManager::FromWebContents(web_contents()); + PermissionRequestManager* manager = + PermissionRequestManager::FromWebContents(web_contents()); return GetBubblesQueueSize(manager); #else return infobar_service()->infobar_count(); @@ -378,8 +378,8 @@ void GeolocationPermissionContextTests::AcceptPrompt() { #if !BUILDFLAG(ANDROID_JAVA_UI) - PermissionBubbleManager* manager = - PermissionBubbleManager::FromWebContents(web_contents()); + PermissionRequestManager* manager = + PermissionRequestManager::FromWebContents(web_contents()); AcceptBubble(manager); #else infobars::InfoBar* infobar = infobar_service()->infobar_at(0); @@ -391,8 +391,8 @@ base::string16 GeolocationPermissionContextTests::GetPromptText() { #if !BUILDFLAG(ANDROID_JAVA_UI) - PermissionBubbleManager* manager = - PermissionBubbleManager::FromWebContents(web_contents()); + PermissionRequestManager* manager = + PermissionRequestManager::FromWebContents(web_contents()); PermissionBubbleRequest* request = manager->requests_.front(); return base::ASCIIToUTF16(request->GetOrigin().spec()) + request->GetMessageTextFragment(); @@ -409,7 +409,7 @@ TEST_F(GeolocationPermissionContextTests, SinglePermissionBubble) { GURL requesting_frame("https://www.example.com/geolocation"); NavigateAndCommit(requesting_frame); - BubbleManagerDocumentLoadCompleted(); + RequestManagerDocumentLoadCompleted(); EXPECT_EQ(0U, GetNumberOfPrompts()); RequestGeolocationPermission( @@ -421,7 +421,7 @@ SinglePermissionBubbleFailsOnInsecureOrigin) { GURL requesting_frame("http://www.example.com/geolocation"); NavigateAndCommit(requesting_frame); - BubbleManagerDocumentLoadCompleted(); + RequestManagerDocumentLoadCompleted(); EXPECT_EQ(0U, GetNumberOfPrompts()); RequestGeolocationPermission(web_contents(), RequestID(0), requesting_frame, @@ -508,7 +508,7 @@ GetGeolocationContentSetting(requesting_frame_1, requesting_frame_1)); NavigateAndCommit(requesting_frame_0); - BubbleManagerDocumentLoadCompleted(); + RequestManagerDocumentLoadCompleted(); // Check that no permission requests have happened yet. EXPECT_EQ(0U, GetNumberOfPrompts()); @@ -544,8 +544,8 @@ // Cancel (block) this frame. #if !BUILDFLAG(ANDROID_JAVA_UI) - PermissionBubbleManager* manager = - PermissionBubbleManager::FromWebContents(web_contents()); + PermissionRequestManager* manager = + PermissionRequestManager::FromWebContents(web_contents()); DenyBubble(manager); #else infobars::InfoBar* infobar_1 = infobar_service()->infobar_at(0); @@ -569,7 +569,7 @@ // Navigate to the first url. NavigateAndCommit(url_a); - BubbleManagerDocumentLoadCompleted(); + RequestManagerDocumentLoadCompleted(); // Check permission is requested. ASSERT_EQ(0U, GetNumberOfPrompts()); @@ -584,7 +584,7 @@ // Change the hash, we'll still be on the same page. NavigateAndCommit(url_b); - BubbleManagerDocumentLoadCompleted(); + RequestManagerDocumentLoadCompleted(); // Accept. AcceptPrompt(); @@ -611,7 +611,7 @@ TEST_F(GeolocationPermissionContextTests, MAYBE_PermissionForFileScheme) { GURL requesting_frame("file://example/geolocation.html"); NavigateAndCommit(requesting_frame); - BubbleManagerDocumentLoadCompleted(); + RequestManagerDocumentLoadCompleted(); // Check permission is requested. ASSERT_EQ(0U, GetNumberOfPrompts()); @@ -639,7 +639,7 @@ CONTENT_SETTING_ASK, GetGeolocationContentSetting(frame_1, frame_0)); NavigateAndCommit(frame_0); - BubbleManagerDocumentLoadCompleted(); + RequestManagerDocumentLoadCompleted(); ASSERT_EQ(0U, GetNumberOfPrompts()); @@ -656,8 +656,8 @@ // Simulate the frame going away; the request should be removed. #if !BUILDFLAG(ANDROID_JAVA_UI) - PermissionBubbleManager* manager = - PermissionBubbleManager::FromWebContents(web_contents()); + PermissionRequestManager* manager = + PermissionRequestManager::FromWebContents(web_contents()); CloseBubble(manager); #else geolocation_permission_context_->CancelPermissionRequest(web_contents(), @@ -685,7 +685,7 @@ GURL invalid_embedder("about:blank"); GURL requesting_frame; NavigateAndCommit(invalid_embedder); - BubbleManagerDocumentLoadCompleted(); + RequestManagerDocumentLoadCompleted(); // Nothing should be displayed. EXPECT_EQ(0U, GetNumberOfPrompts()); @@ -701,16 +701,16 @@ NavigateAndCommit(url_a); // Tab A0 AddNewTab(url_b); // Tab B (extra_tabs_[0]) AddNewTab(url_a); // Tab A1 (extra_tabs_[1]) - BubbleManagerDocumentLoadCompleted(); - BubbleManagerDocumentLoadCompleted(extra_tabs_[0].get()); - BubbleManagerDocumentLoadCompleted(extra_tabs_[1].get()); + RequestManagerDocumentLoadCompleted(); + RequestManagerDocumentLoadCompleted(extra_tabs_[0].get()); + RequestManagerDocumentLoadCompleted(extra_tabs_[1].get()); #if !BUILDFLAG(ANDROID_JAVA_UI) - PermissionBubbleManager* manager_a0 = - PermissionBubbleManager::FromWebContents(web_contents()); - PermissionBubbleManager* manager_b = - PermissionBubbleManager::FromWebContents(extra_tabs_[0].get()); - PermissionBubbleManager* manager_a1 = - PermissionBubbleManager::FromWebContents(extra_tabs_[1].get()); + PermissionRequestManager* manager_a0 = + PermissionRequestManager::FromWebContents(web_contents()); + PermissionRequestManager* manager_b = + PermissionRequestManager::FromWebContents(extra_tabs_[0].get()); + PermissionRequestManager* manager_a1 = + PermissionRequestManager::FromWebContents(extra_tabs_[1].get()); #endif // Request permission in all three tabs. @@ -762,12 +762,12 @@ NavigateAndCommit(url_a); // Tab A0. AddNewTab(url_a); // Tab A1. #if !BUILDFLAG(ANDROID_JAVA_UI) - BubbleManagerDocumentLoadCompleted(); - BubbleManagerDocumentLoadCompleted(extra_tabs_[0].get()); - PermissionBubbleManager* manager_a0 = - PermissionBubbleManager::FromWebContents(web_contents()); - PermissionBubbleManager* manager_a1 = - PermissionBubbleManager::FromWebContents(extra_tabs_[0].get()); + RequestManagerDocumentLoadCompleted(); + RequestManagerDocumentLoadCompleted(extra_tabs_[0].get()); + PermissionRequestManager* manager_a0 = + PermissionRequestManager::FromWebContents(web_contents()); + PermissionRequestManager* manager_a1 = + PermissionRequestManager::FromWebContents(extra_tabs_[0].get()); #endif // Request permission in both tabs; the extra tab will have two permission @@ -842,7 +842,7 @@ GetGeolocationContentSetting(requesting_frame_1, requesting_frame_0)); NavigateAndCommit(requesting_frame_0); - BubbleManagerDocumentLoadCompleted(); + RequestManagerDocumentLoadCompleted(); // Request permission for two frames. RequestGeolocationPermission( @@ -873,7 +873,7 @@ TEST_F(GeolocationPermissionContextTests, LastUsageAudited) { GURL requesting_frame("https://www.example.com/geolocation"); NavigateAndCommit(requesting_frame); - BubbleManagerDocumentLoadCompleted(); + RequestManagerDocumentLoadCompleted(); base::SimpleTestClock* test_clock = new base::SimpleTestClock; test_clock->SetNow(base::Time::UnixEpoch() + @@ -937,7 +937,7 @@ 0); NavigateAndCommit(requesting_frame_0); - BubbleManagerDocumentLoadCompleted(); + RequestManagerDocumentLoadCompleted(); EXPECT_EQ(0U, GetNumberOfPrompts());
diff --git a/chrome/browser/media/media_stream_device_permission_context_unittest.cc b/chrome/browser/media/media_stream_device_permission_context_unittest.cc index 9082e45..e3aa150e 100644 --- a/chrome/browser/media/media_stream_device_permission_context_unittest.cc +++ b/chrome/browser/media/media_stream_device_permission_context_unittest.cc
@@ -22,7 +22,7 @@ #include "testing/gtest/include/gtest/gtest.h" #if !defined(OS_ANDROID) -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" +#include "chrome/browser/permissions/permission_request_manager.h" #endif namespace { @@ -103,7 +103,7 @@ #if defined(OS_ANDROID) InfoBarService::CreateForWebContents(web_contents()); #else - PermissionBubbleManager::CreateForWebContents(web_contents()); + PermissionRequestManager::CreateForWebContents(web_contents()); #endif }
diff --git a/chrome/browser/media/media_stream_devices_controller.cc b/chrome/browser/media/media_stream_devices_controller.cc index 57e1dbcc..8995a28 100644 --- a/chrome/browser/media/media_stream_devices_controller.cc +++ b/chrome/browser/media/media_stream_devices_controller.cc
@@ -72,23 +72,25 @@ } using PermissionActionCallback = - base::Callback<void(content::PermissionType, const GURL&)>; + base::Callback<void(content::PermissionType, const GURL&, Profile*)>; void RecordSinglePermissionAction(const content::MediaStreamRequest& request, content::PermissionType permission_type, + Profile* profile, PermissionActionCallback callback) { if (ContentTypeIsRequested(permission_type, request)) { - callback.Run(permission_type, request.security_origin); + callback.Run(permission_type, request.security_origin, profile); } } // Calls |action_function| for each permission requested by |request|. void RecordPermissionAction(const content::MediaStreamRequest& request, + Profile* profile, PermissionActionCallback callback) { RecordSinglePermissionAction(request, content::PermissionType::AUDIO_CAPTURE, - callback); + profile, callback); RecordSinglePermissionAction(request, content::PermissionType::VIDEO_CAPTURE, - callback); + profile, callback); } // This helper class helps to measure the number of media stream requests that @@ -204,8 +206,8 @@ MediaStreamDevicesController::~MediaStreamDevicesController() { if (!callback_.is_null()) { - RecordPermissionAction( - request_, base::Bind(PermissionUmaUtil::PermissionIgnored)); + RecordPermissionAction(request_, profile_, + base::Bind(PermissionUmaUtil::PermissionIgnored)); callback_.Run(content::MediaStreamDevices(), content::MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN, std::unique_ptr<content::MediaStreamUI>()); @@ -280,8 +282,8 @@ } void MediaStreamDevicesController::PermissionGranted() { - RecordPermissionAction( - request_, base::Bind(PermissionUmaUtil::PermissionGranted)); + RecordPermissionAction(request_, profile_, + base::Bind(PermissionUmaUtil::PermissionGranted)); RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, old_audio_setting_, CONTENT_SETTING_ALLOW), GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, @@ -290,8 +292,8 @@ } void MediaStreamDevicesController::PermissionDenied() { - RecordPermissionAction( - request_, base::Bind(PermissionUmaUtil::PermissionDenied)); + RecordPermissionAction(request_, profile_, + base::Bind(PermissionUmaUtil::PermissionDenied)); RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, old_audio_setting_, CONTENT_SETTING_BLOCK), GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, @@ -302,11 +304,11 @@ void MediaStreamDevicesController::GroupedRequestFinished(bool audio_accepted, bool video_accepted) { RecordSinglePermissionAction( - request_, content::PermissionType::AUDIO_CAPTURE, + request_, content::PermissionType::AUDIO_CAPTURE, profile_, base::Bind(audio_accepted ? PermissionUmaUtil::PermissionGranted : PermissionUmaUtil::PermissionDenied)); RecordSinglePermissionAction( - request_, content::PermissionType::VIDEO_CAPTURE, + request_, content::PermissionType::VIDEO_CAPTURE, profile_, base::Bind(video_accepted ? PermissionUmaUtil::PermissionGranted : PermissionUmaUtil::PermissionDenied)); @@ -322,8 +324,8 @@ } void MediaStreamDevicesController::Cancelled() { - RecordPermissionAction( - request_, base::Bind(PermissionUmaUtil::PermissionDismissed)); + RecordPermissionAction(request_, profile_, + base::Bind(PermissionUmaUtil::PermissionDismissed)); RunCallback(old_audio_setting_, old_video_setting_, content::MEDIA_DEVICE_PERMISSION_DISMISSED); }
diff --git a/chrome/browser/media/media_stream_infobar_browsertest.cc b/chrome/browser/media/media_stream_infobar_browsertest.cc index 1ba1799..51c72282 100644 --- a/chrome/browser/media/media_stream_infobar_browsertest.cc +++ b/chrome/browser/media/media_stream_infobar_browsertest.cc
@@ -15,7 +15,6 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/test_switches.h"
diff --git a/chrome/browser/media/midi_permission_context_unittest.cc b/chrome/browser/media/midi_permission_context_unittest.cc index 77675ec..6a73e470 100644 --- a/chrome/browser/media/midi_permission_context_unittest.cc +++ b/chrome/browser/media/midi_permission_context_unittest.cc
@@ -22,7 +22,7 @@ #if defined(OS_ANDROID) #include "chrome/browser/infobars/infobar_service.h" #else -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" +#include "chrome/browser/permissions/permission_request_manager.h" #endif namespace { @@ -80,7 +80,7 @@ #if defined(OS_ANDROID) InfoBarService::CreateForWebContents(web_contents()); #else - PermissionBubbleManager::CreateForWebContents(web_contents()); + PermissionRequestManager::CreateForWebContents(web_contents()); #endif }
diff --git a/chrome/browser/media/permission_bubble_media_access_handler.cc b/chrome/browser/media/permission_bubble_media_access_handler.cc index 7a11015..4d2f701 100644 --- a/chrome/browser/media/permission_bubble_media_access_handler.cc +++ b/chrome/browser/media/permission_bubble_media_access_handler.cc
@@ -27,7 +27,7 @@ #include "chrome/browser/media/media_stream_infobar_delegate_android.h" #include "chrome/browser/permissions/permission_update_infobar_delegate_android.h" #else -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" +#include "chrome/browser/permissions/permission_request_manager.h" #endif // BUILDFLAG(ANDROID_JAVA_UI) #if BUILDFLAG(ANDROID_JAVA_UI) @@ -163,10 +163,10 @@ MediaStreamInfoBarDelegateAndroid::Create(web_contents, std::move(controller)); #else - PermissionBubbleManager* bubble_manager = - PermissionBubbleManager::FromWebContents(web_contents); - if (bubble_manager) - bubble_manager->AddRequest(controller.release()); + PermissionRequestManager* permission_request_manager = + PermissionRequestManager::FromWebContents(web_contents); + if (permission_request_manager) + permission_request_manager->AddRequest(controller.release()); #endif }
diff --git a/chrome/browser/media/router/BUILD.gn b/chrome/browser/media/router/BUILD.gn index 8389c16..34114c8 100644 --- a/chrome/browser/media/router/BUILD.gn +++ b/chrome/browser/media/router/BUILD.gn
@@ -83,7 +83,7 @@ ] } -source_set("test_support") { +static_library("test_support") { testonly = true deps = [ ":router",
diff --git a/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc b/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc index c56fba5a..3769258 100644 --- a/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc +++ b/chrome/browser/media/router/mojo/media_router_mojo_impl_unittest.cc
@@ -1289,6 +1289,9 @@ void TearDown() override { media_router_.reset(); profile_.reset(); + // Explicitly delete the TestingBrowserProcess before |thread_bundle_|. + // This allows it to do cleanup before |thread_bundle_| goes away. + TestingBrowserProcess::DeleteInstance(); } // Constructs bindings so that |media_router_| delegates calls to
diff --git a/chrome/browser/media/webrtc_apprtc_browsertest.cc b/chrome/browser/media/webrtc_apprtc_browsertest.cc index 0af80d4..52cde589 100644 --- a/chrome/browser/media/webrtc_apprtc_browsertest.cc +++ b/chrome/browser/media/webrtc_apprtc_browsertest.cc
@@ -14,10 +14,10 @@ #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/media/webrtc_browsertest_base.h" #include "chrome/browser/media/webrtc_browsertest_common.h" +#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/common/content_switches.h" @@ -243,8 +243,8 @@ chrome::AddTabAt(browser(), GURL(), -1, true); content::WebContents* left_tab = browser()->tab_strip_model()->GetActiveWebContents(); - PermissionBubbleManager::FromWebContents(left_tab) - ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL); + PermissionRequestManager::FromWebContents(left_tab) + ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL); InfoBarResponder left_infobar_responder( InfoBarService::FromWebContents(left_tab), InfoBarResponder::ACCEPT); ui_test_utils::NavigateToURL(browser(), room_url); @@ -253,8 +253,8 @@ chrome::AddTabAt(browser(), GURL(), -1, true); content::WebContents* right_tab = browser()->tab_strip_model()->GetActiveWebContents(); - PermissionBubbleManager::FromWebContents(right_tab) - ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL); + PermissionRequestManager::FromWebContents(right_tab) + ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL); InfoBarResponder right_infobar_responder( InfoBarService::FromWebContents(right_tab), InfoBarResponder::ACCEPT); ui_test_utils::NavigateToURL(browser(), room_url); @@ -291,8 +291,8 @@ chrome::AddTabAt(browser(), GURL(), -1, true); content::WebContents* chrome_tab = browser()->tab_strip_model()->GetActiveWebContents(); - PermissionBubbleManager::FromWebContents(chrome_tab) - ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL); + PermissionRequestManager::FromWebContents(chrome_tab) + ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL); InfoBarResponder infobar_responder( InfoBarService::FromWebContents(chrome_tab), InfoBarResponder::ACCEPT); ui_test_utils::NavigateToURL(browser(), room_url);
diff --git a/chrome/browser/media/webrtc_browsertest_base.cc b/chrome/browser/media/webrtc_browsertest_base.cc index 9a40c5b..2213da9 100644 --- a/chrome/browser/media/webrtc_browsertest_base.cc +++ b/chrome/browser/media/webrtc_browsertest_base.cc
@@ -12,10 +12,10 @@ #include "base/strings/stringprintf.h" #include "build/build_config.h" #include "chrome/browser/media/webrtc_browsertest_common.h" +#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test_utils.h" #include "net/test/embedded_test_server/embedded_test_server.h" @@ -87,17 +87,18 @@ // PermissionRequestObserver --------------------------------------------------- // Used to observe the creation of permission prompt without responding. -class PermissionRequestObserver : public PermissionBubbleManager::Observer { +class PermissionRequestObserver : public PermissionRequestManager::Observer { public: explicit PermissionRequestObserver(content::WebContents* web_contents) - : bubble_manager_(PermissionBubbleManager::FromWebContents(web_contents)), + : request_manager_( + PermissionRequestManager::FromWebContents(web_contents)), request_shown_(false), message_loop_runner_(new content::MessageLoopRunner) { - bubble_manager_->AddObserver(this); + request_manager_->AddObserver(this); } ~PermissionRequestObserver() override { // Safe to remove twice if it happens. - bubble_manager_->RemoveObserver(this); + request_manager_->RemoveObserver(this); } void Wait() { message_loop_runner_->Run(); } @@ -105,14 +106,14 @@ bool request_shown() const { return request_shown_; } private: - // PermissionBubbleManager::Observer + // PermissionRequestManager::Observer void OnBubbleAdded() override { request_shown_ = true; - bubble_manager_->RemoveObserver(this); + request_manager_->RemoveObserver(this); message_loop_runner_->Quit(); } - PermissionBubbleManager* bubble_manager_; + PermissionRequestManager* request_manager_; bool request_shown_; scoped_refptr<content::MessageLoopRunner> message_loop_runner_; @@ -148,8 +149,8 @@ content::WebContents* tab_contents, const std::string& constraints) const { std::string result; - PermissionBubbleManager::FromWebContents(tab_contents) - ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL); + PermissionRequestManager::FromWebContents(tab_contents) + ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL); PermissionRequestObserver permissionRequestObserver(tab_contents); GetUserMedia(tab_contents, constraints); EXPECT_TRUE(permissionRequestObserver.request_shown()); @@ -162,8 +163,8 @@ content::WebContents* tab_contents, const std::string& constraints) const { std::string result; - PermissionBubbleManager::FromWebContents(tab_contents) - ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL); + PermissionRequestManager::FromWebContents(tab_contents) + ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL); GetUserMedia(tab_contents, constraints); EXPECT_TRUE(content::ExecuteScriptAndExtractString( tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result)); @@ -179,8 +180,8 @@ content::WebContents* tab_contents, const std::string& constraints) const { std::string result; - PermissionBubbleManager::FromWebContents(tab_contents) - ->set_auto_response_for_test(PermissionBubbleManager::DENY_ALL); + PermissionRequestManager::FromWebContents(tab_contents) + ->set_auto_response_for_test(PermissionRequestManager::DENY_ALL); PermissionRequestObserver permissionRequestObserver(tab_contents); GetUserMedia(tab_contents, constraints); EXPECT_TRUE(permissionRequestObserver.request_shown()); @@ -192,8 +193,8 @@ void WebRtcTestBase::GetUserMediaAndDismiss( content::WebContents* tab_contents) const { std::string result; - PermissionBubbleManager::FromWebContents(tab_contents) - ->set_auto_response_for_test(PermissionBubbleManager::DISMISS); + PermissionRequestManager::FromWebContents(tab_contents) + ->set_auto_response_for_test(PermissionRequestManager::DISMISS); PermissionRequestObserver permissionRequestObserver(tab_contents); GetUserMedia(tab_contents, kAudioVideoCallConstraints); EXPECT_TRUE(permissionRequestObserver.request_shown()); @@ -214,8 +215,8 @@ // we set an auto-response to avoid leaving the prompt hanging. The choice of // DENY_ALL makes sure that the response to the prompt doesn't accidentally // result in a newly granted media stream permission. - PermissionBubbleManager::FromWebContents(tab_contents) - ->set_auto_response_for_test(PermissionBubbleManager::DENY_ALL); + PermissionRequestManager::FromWebContents(tab_contents) + ->set_auto_response_for_test(PermissionRequestManager::DENY_ALL); PermissionRequestObserver permissionRequestObserver(tab_contents); GetUserMedia(tab_contents, kAudioVideoCallConstraints); EXPECT_FALSE(permissionRequestObserver.request_shown()); @@ -235,8 +236,8 @@ // we set an auto-response to avoid leaving the prompt hanging. The choice of // ACCEPT_ALL makes sure that the response to the prompt doesn't accidentally // result in a newly granted media stream permission. - PermissionBubbleManager::FromWebContents(tab_contents) - ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL); + PermissionRequestManager::FromWebContents(tab_contents) + ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL); PermissionRequestObserver permissionRequestObserver(tab_contents); GetUserMedia(tab_contents, kAudioVideoCallConstraints); EXPECT_FALSE(permissionRequestObserver.request_shown()); @@ -271,8 +272,8 @@ browser()->tab_strip_model()->GetActiveWebContents(); // Accept if necessary, but don't expect a prompt (because auto-accept is also // okay). - PermissionBubbleManager::FromWebContents(new_tab) - ->set_auto_response_for_test(PermissionBubbleManager::ACCEPT_ALL); + PermissionRequestManager::FromWebContents(new_tab) + ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL); GetUserMedia(new_tab, constraints); std::string result; EXPECT_TRUE(content::ExecuteScriptAndExtractString(
diff --git a/chrome/browser/media_galleries/media_gallery_context_menu.cc b/chrome/browser/media_galleries/media_gallery_context_menu.cc index 1e637a1..79d021d 100644 --- a/chrome/browser/media_galleries/media_gallery_context_menu.cc +++ b/chrome/browser/media_galleries/media_gallery_context_menu.cc
@@ -30,7 +30,8 @@ } bool MediaGalleryContextMenu::GetAcceleratorForCommandId( - int command_id, ui::Accelerator* accelerator) { + int command_id, + ui::Accelerator* accelerator) const { return false; }
diff --git a/chrome/browser/media_galleries/media_gallery_context_menu.h b/chrome/browser/media_galleries/media_gallery_context_menu.h index 35bc8c6..f3a44452 100644 --- a/chrome/browser/media_galleries/media_gallery_context_menu.h +++ b/chrome/browser/media_galleries/media_gallery_context_menu.h
@@ -28,7 +28,7 @@ bool IsCommandIdEnabled(int command_id) const override; bool IsCommandIdVisible(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; private:
diff --git a/chrome/browser/memory/tab_manager_delegate_chromeos.cc b/chrome/browser/memory/tab_manager_delegate_chromeos.cc index 482efe3..5ffbd0b 100644 --- a/chrome/browser/memory/tab_manager_delegate_chromeos.cc +++ b/chrome/browser/memory/tab_manager_delegate_chromeos.cc
@@ -72,7 +72,8 @@ if (!window || window->name() != kExoShellSurfaceWindowName) return false; std::string application_id = exo::ShellSurface::GetApplicationId(window); - return application_id.find(kArcProcessNamePrefix) == 0; + return base::StartsWith(application_id, kArcProcessNamePrefix, + base::CompareCase::SENSITIVE); } bool IsArcWindowInForeground() { @@ -284,15 +285,15 @@ } class TabManagerDelegate::UmaReporter { - public: - UmaReporter() - : last_kill_time_(), total_kills_(0) {} - ~UmaReporter() {} - void ReportKill(const int memory_freed); + public: + UmaReporter() : total_kills_(0) {} + ~UmaReporter() {} - private: - base::Time last_kill_time_; - int total_kills_; + void ReportKill(const int memory_freed); + + private: + base::Time last_kill_time_; + int total_kills_; }; void TabManagerDelegate::UmaReporter::ReportKill(const int memory_freed) { @@ -336,7 +337,7 @@ content::NotificationService::AllBrowserContextsAndSources()); auto arc_bridge_service = arc::ArcBridgeService::Get(); if (arc_bridge_service) - arc_bridge_service->AddObserver(this); + arc_bridge_service->process()->AddObserver(this); auto activation_client = GetActivationClient(); if (activation_client) activation_client->AddObserver(this); @@ -350,7 +351,7 @@ activation_client->RemoveObserver(this); auto arc_bridge_service = arc::ArcBridgeService::Get(); if (arc_bridge_service) - arc_bridge_service->RemoveObserver(this); + arc_bridge_service->process()->RemoveObserver(this); } void TabManagerDelegate::OnBrowserSetLastActive(Browser* browser) { @@ -369,12 +370,12 @@ AdjustFocusedTabScore(pid); } -void TabManagerDelegate::OnProcessInstanceReady() { +void TabManagerDelegate::OnInstanceReady() { auto arc_bridge_service = arc::ArcBridgeService::Get(); DCHECK(arc_bridge_service); - arc_process_instance_ = arc_bridge_service->process_instance(); - arc_process_instance_version_ = arc_bridge_service->process_version(); + arc_process_instance_ = arc_bridge_service->process()->instance(); + arc_process_instance_version_ = arc_bridge_service->process()->version(); DCHECK(arc_process_instance_); @@ -399,7 +400,7 @@ arc_process_instance_->DisableLowMemoryKiller(); } -void TabManagerDelegate::OnProcessInstanceClosed() { +void TabManagerDelegate::OnInstanceClosed() { arc_process_instance_ = nullptr; arc_process_instance_version_ = 0; }
diff --git a/chrome/browser/memory/tab_manager_delegate_chromeos.h b/chrome/browser/memory/tab_manager_delegate_chromeos.h index 3722980..dbd6d46 100644 --- a/chrome/browser/memory/tab_manager_delegate_chromeos.h +++ b/chrome/browser/memory/tab_manager_delegate_chromeos.h
@@ -20,6 +20,7 @@ #include "chrome/browser/memory/tab_stats.h" #include "chrome/browser/ui/browser_list_observer.h" #include "components/arc/arc_bridge_service.h" +#include "components/arc/instance_holder.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "ui/wm/public/activation_change_observer.h" @@ -75,10 +76,11 @@ // Note that AdjustOomPriorities will be called on the UI thread by // TabManager, but the actual work will take place on the file thread // (see implementation of AdjustOomPriorities). -class TabManagerDelegate : public arc::ArcBridgeService::Observer, - public aura::client::ActivationChangeObserver, - public content::NotificationObserver, - public chrome::BrowserListObserver { +class TabManagerDelegate + : public arc::InstanceHolder<arc::mojom::ProcessInstance>::Observer, + public aura::client::ActivationChangeObserver, + public content::NotificationObserver, + public chrome::BrowserListObserver { public: class MemoryStat; @@ -91,9 +93,9 @@ void OnBrowserSetLastActive(Browser* browser) override; - // ArcBridgeService::Observer overrides. - void OnProcessInstanceReady() override; - void OnProcessInstanceClosed() override; + // InstanceHolder<arc::mojom::ProcessInstance>::Observer overrides. + void OnInstanceReady() override; + void OnInstanceClosed() override; // aura::ActivationChangeObserver overrides. void OnWindowActivated( @@ -136,8 +138,8 @@ class FocusedProcess; class UmaReporter; - friend std::ostream& operator<<( - std::ostream& out, const Candidate& candidate); + friend std::ostream& operator<<(std::ostream& out, + const Candidate& candidate); // content::NotificationObserver: void Observe(int type, @@ -243,9 +245,7 @@ Candidate(const arc::ArcProcess* _app, int _priority) : app(_app), priority(_priority), is_arc_app(true) {} - bool operator<(const Candidate& rhs) const { - return priority < rhs.priority; - } + bool operator<(const Candidate& rhs) const { return priority < rhs.priority; } union { const TabStats* tab;
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc index 8aa3b212..f094afcf 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.cc +++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -27,6 +27,7 @@ #include "chrome/browser/google/google_brand.h" #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" #include "chrome/browser/metrics/chrome_stability_metrics_provider.h" +#include "chrome/browser/metrics/https_engagement_metrics_provider.h" #include "chrome/browser/metrics/metrics_reporting_state.h" #include "chrome/browser/metrics/subprocess_metrics_provider.h" #include "chrome/browser/metrics/time_ticks_experiment_win.h" @@ -524,6 +525,10 @@ new sync_driver::DeviceCountMetricsProvider(base::Bind( &browser_sync::ChromeSyncClient::GetDeviceInfoTrackers)))); + metrics_service_->RegisterMetricsProvider( + std::unique_ptr<metrics::MetricsProvider>( + new HttpsEngagementMetricsProvider())); + // Clear stability metrics if it is the first time cellular upload logic // should apply to avoid sudden bulk uploads. It needs to be done after all // providers are registered.
diff --git a/chrome/browser/metrics/https_engagement_metrics_provider.cc b/chrome/browser/metrics/https_engagement_metrics_provider.cc new file mode 100644 index 0000000..d75bd91c --- /dev/null +++ b/chrome/browser/metrics/https_engagement_metrics_provider.cc
@@ -0,0 +1,28 @@ +// 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/metrics/https_engagement_metrics_provider.h" + +#include "chrome/browser/browser_process.h" +#include "chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service.h" +#include "chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service_factory.h" +#include "chrome/browser/profiles/profile_manager.h" + +HttpsEngagementMetricsProvider::HttpsEngagementMetricsProvider() {} + +HttpsEngagementMetricsProvider::~HttpsEngagementMetricsProvider() {} + +void HttpsEngagementMetricsProvider::ProvideGeneralMetrics( + metrics::ChromeUserMetricsExtension* uma_proto) { + ProfileManager* profile_manager = g_browser_process->profile_manager(); + if (!profile_manager) + return; + + HttpsEngagementService* engagement_service = + HttpsEngagementServiceFactory::GetForBrowserContext( + profile_manager->GetLastUsedProfile()); + if (!engagement_service) + return; + engagement_service->StoreMetricsAndClear(); +}
diff --git a/chrome/browser/metrics/https_engagement_metrics_provider.h b/chrome/browser/metrics/https_engagement_metrics_provider.h new file mode 100644 index 0000000..730d975 --- /dev/null +++ b/chrome/browser/metrics/https_engagement_metrics_provider.h
@@ -0,0 +1,24 @@ +// 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_METRICS_HTTPS_ENGAGEMENT_METRICS_PROVIDER_H_ +#define CHROME_BROWSER_METRICS_HTTPS_ENGAGEMENT_METRICS_PROVIDER_H_ + +#include "base/macros.h" +#include "components/metrics/metrics_provider.h" + +// When user metrics are about to be uploaded, HttpsEngagementMetricsProvider +// looks up the HttpsEngagementService for the current profile and tells it to +// record its metrics before the upload occurs. +class HttpsEngagementMetricsProvider : public metrics::MetricsProvider { + public: + HttpsEngagementMetricsProvider(); + ~HttpsEngagementMetricsProvider() override; + + // metrics:MetricsProvider: + void ProvideGeneralMetrics( + metrics::ChromeUserMetricsExtension* uma_proto) override; +}; + +#endif // CHROME_BROWSER_METRICS_HTTPS_ENGAGEMENT_METRICS_PROVIDER_H_
diff --git a/chrome/browser/notifications/notification_interactive_uitest.cc b/chrome/browser/notifications/notification_interactive_uitest.cc index 454830e..453fb59 100644 --- a/chrome/browser/notifications/notification_interactive_uitest.cc +++ b/chrome/browser/notifications/notification_interactive_uitest.cc
@@ -23,12 +23,12 @@ #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/notifications/desktop_notification_profile_util.h" #include "chrome/browser/notifications/notification.h" +#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/content_settings/core/browser/host_content_settings_map.h" @@ -141,17 +141,18 @@ }; // Used to observe the creation of permission prompt without responding. -class PermissionRequestObserver : public PermissionBubbleManager::Observer { +class PermissionRequestObserver : public PermissionRequestManager::Observer { public: explicit PermissionRequestObserver(content::WebContents* web_contents) - : bubble_manager_(PermissionBubbleManager::FromWebContents(web_contents)), + : request_manager_( + PermissionRequestManager::FromWebContents(web_contents)), request_shown_(false), message_loop_runner_(new content::MessageLoopRunner) { - bubble_manager_->AddObserver(this); + request_manager_->AddObserver(this); } ~PermissionRequestObserver() override { // Safe to remove twice if it happens. - bubble_manager_->RemoveObserver(this); + request_manager_->RemoveObserver(this); } void Wait() { message_loop_runner_->Run(); } @@ -159,14 +160,14 @@ bool request_shown() { return request_shown_; } private: - // PermissionBubbleManager::Observer + // PermissionRequestManager::Observer void OnBubbleAdded() override { request_shown_ = true; - bubble_manager_->RemoveObserver(this); + request_manager_->RemoveObserver(this); message_loop_runner_->Quit(); } - PermissionBubbleManager* bubble_manager_; + PermissionRequestManager* request_manager_; bool request_shown_; scoped_refptr<content::MessageLoopRunner> message_loop_runner_; @@ -226,7 +227,7 @@ void DropOriginPreference(const GURL& origin); std::string RequestAndRespondToPermission( Browser* browser, - PermissionBubbleManager::AutoResponseType bubble_response); + PermissionRequestManager::AutoResponseType bubble_response); }; int NotificationsTest::GetNotificationCount() { @@ -303,10 +304,10 @@ std::string NotificationsTest::RequestAndRespondToPermission( Browser* browser, - PermissionBubbleManager::AutoResponseType bubble_response) { + PermissionRequestManager::AutoResponseType bubble_response) { std::string result; content::WebContents* web_contents = GetActiveWebContents(browser); - PermissionBubbleManager::FromWebContents(web_contents) + PermissionRequestManager::FromWebContents(web_contents) ->set_auto_response_for_test(bubble_response); EXPECT_TRUE(content::ExecuteScriptAndExtractString( web_contents, "requestPermission();", &result)); @@ -315,19 +316,19 @@ bool NotificationsTest::RequestAndAcceptPermission(Browser* browser) { std::string result = RequestAndRespondToPermission( - browser, PermissionBubbleManager::ACCEPT_ALL); + browser, PermissionRequestManager::ACCEPT_ALL); return "request-callback-granted" == result; } bool NotificationsTest::RequestAndDenyPermission(Browser* browser) { - std::string result = - RequestAndRespondToPermission(browser, PermissionBubbleManager::DENY_ALL); + std::string result = RequestAndRespondToPermission( + browser, PermissionRequestManager::DENY_ALL); return "request-callback-denied" == result; } bool NotificationsTest::RequestAndDismissPermission(Browser* browser) { std::string result = - RequestAndRespondToPermission(browser, PermissionBubbleManager::DISMISS); + RequestAndRespondToPermission(browser, PermissionRequestManager::DISMISS); return "request-callback-default" == result; }
diff --git a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc index 3d5530f..ddfa643 100644 --- a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc +++ b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
@@ -17,9 +17,9 @@ #include "chrome/browser/notifications/notification_test_util.h" #include "chrome/browser/notifications/platform_notification_service_impl.h" #include "chrome/browser/permissions/permission_manager.h" +#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" #include "chrome/grit/generated_resources.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" @@ -87,7 +87,7 @@ private: std::string RequestAndRespondToPermission( - PermissionBubbleManager::AutoResponseType bubble_response); + PermissionRequestManager::AutoResponseType bubble_response); content::WebContents* GetActiveWebContents(Browser* browser) { return browser->tab_strip_model()->GetActiveWebContents(); @@ -175,10 +175,10 @@ std::string PlatformNotificationServiceBrowserTest::RequestAndRespondToPermission( - PermissionBubbleManager::AutoResponseType bubble_response) { + PermissionRequestManager::AutoResponseType bubble_response) { std::string result; content::WebContents* web_contents = GetActiveWebContents(browser()); - PermissionBubbleManager::FromWebContents(web_contents) + PermissionRequestManager::FromWebContents(web_contents) ->set_auto_response_for_test(bubble_response); EXPECT_TRUE(RunScript("RequestPermission();", &result)); return result; @@ -186,13 +186,13 @@ bool PlatformNotificationServiceBrowserTest::RequestAndAcceptPermission() { std::string result = - RequestAndRespondToPermission(PermissionBubbleManager::ACCEPT_ALL); + RequestAndRespondToPermission(PermissionRequestManager::ACCEPT_ALL); return "granted" == result; } bool PlatformNotificationServiceBrowserTest::RequestAndDenyPermission() { std::string result = - RequestAndRespondToPermission(PermissionBubbleManager::DENY_ALL); + RequestAndRespondToPermission(PermissionRequestManager::DENY_ALL); return "denied" == result; }
diff --git a/chrome/browser/ntp_snippets/ntp_snippets_service_factory.cc b/chrome/browser/ntp_snippets/ntp_snippets_service_factory.cc index ab7bfc0..4e3a6865 100644 --- a/chrome/browser/ntp_snippets/ntp_snippets_service_factory.cc +++ b/chrome/browser/ntp_snippets/ntp_snippets_service_factory.cc
@@ -9,6 +9,7 @@ #include "base/memory/ptr_util.h" #include "base/memory/singleton.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/ntp_snippets/content_suggestions_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search/suggestions/image_decoder_impl.h" #include "chrome/browser/search/suggestions/suggestions_service_factory.h" @@ -22,6 +23,7 @@ #include "components/image_fetcher/image_fetcher.h" #include "components/image_fetcher/image_fetcher_impl.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "components/ntp_snippets/content_suggestions_service.h" #include "components/ntp_snippets/ntp_snippets_constants.h" #include "components/ntp_snippets/ntp_snippets_database.h" #include "components/ntp_snippets/ntp_snippets_fetcher.h" @@ -48,6 +50,7 @@ using suggestions::ImageDecoderImpl; using suggestions::SuggestionsService; using suggestions::SuggestionsServiceFactory; +using ntp_snippets::ContentSuggestionsService; // static NTPSnippetsServiceFactory* NTPSnippetsServiceFactory::GetInstance() { @@ -70,6 +73,7 @@ DependsOn(ProfileSyncServiceFactory::GetInstance()); DependsOn(SigninManagerFactory::GetInstance()); DependsOn(SuggestionsServiceFactory::GetInstance()); + DependsOn(ContentSuggestionsServiceFactory::GetInstance()); } NTPSnippetsServiceFactory::~NTPSnippetsServiceFactory() {} @@ -78,6 +82,13 @@ content::BrowserContext* context) const { Profile* profile = Profile::FromBrowserContext(context); + ContentSuggestionsService* content_suggestions_service = + ContentSuggestionsServiceFactory::GetForProfile(profile); + // TODO(pke): When the AndroidBridge does not access the NTPSnippetsService + // directly anymore (for retrieving content), the NTPSnippetsService does not + // need to be created if content_suggestions_service->state() == DISABLED, + // just return nullptr then and remove the other "if" below. + // TODO(mvanouwerkerk): Move the enable logic into the service once we start // observing pref changes. bool enabled = false; @@ -111,18 +122,25 @@ base::SequencedWorkerPool::GetSequenceToken(), base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); - return new ntp_snippets::NTPSnippetsService( - enabled, profile->GetPrefs(), suggestions_service, - g_browser_process->GetApplicationLocale(), scheduler, - base::MakeUnique<ntp_snippets::NTPSnippetsFetcher>( - signin_manager, token_service, request_context, - base::Bind(&safe_json::SafeJsonParser::Parse), - chrome::GetChannel() == version_info::Channel::STABLE), - base::MakeUnique<ImageFetcherImpl>( - base::MakeUnique<ImageDecoderImpl>(), request_context.get()), - base::MakeUnique<ImageDecoderImpl>(), - base::MakeUnique<ntp_snippets::NTPSnippetsDatabase>(database_dir, - task_runner), - base::MakeUnique<ntp_snippets::NTPSnippetsStatusService>(signin_manager, - sync_service)); + ntp_snippets::NTPSnippetsService* ntp_snippets_service = + new ntp_snippets::NTPSnippetsService( + enabled, profile->GetPrefs(), suggestions_service, + g_browser_process->GetApplicationLocale(), scheduler, + base::MakeUnique<ntp_snippets::NTPSnippetsFetcher>( + signin_manager, token_service, request_context, + base::Bind(&safe_json::SafeJsonParser::Parse), + chrome::GetChannel() == version_info::Channel::STABLE), + base::MakeUnique<ImageFetcherImpl>( + base::MakeUnique<ImageDecoderImpl>(), request_context.get()), + base::MakeUnique<ImageDecoderImpl>(), + base::MakeUnique<ntp_snippets::NTPSnippetsDatabase>(database_dir, + task_runner), + base::MakeUnique<ntp_snippets::NTPSnippetsStatusService>( + signin_manager, sync_service)); + + if (content_suggestions_service->state() == + ContentSuggestionsService::State::ENABLED) { + content_suggestions_service->RegisterProvider(ntp_snippets_service); + } + return ntp_snippets_service; }
diff --git a/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer.cc index 56cbe9b..e5f88cd 100644 --- a/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer.cc
@@ -6,6 +6,7 @@ #include <string> +#include "base/optional.h" #include "base/time/time.h" #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h" #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h" @@ -126,28 +127,26 @@ } // Only consider timing events that happened before the first background // event. - base::TimeDelta response_start; - base::TimeDelta load_event_start; - base::TimeDelta first_image_paint; - base::TimeDelta first_contentful_paint; + base::Optional<base::TimeDelta> response_start; + base::Optional<base::TimeDelta> load_event_start; + base::Optional<base::TimeDelta> first_image_paint; + base::Optional<base::TimeDelta> first_contentful_paint; if (WasStartedInForegroundOptionalEventInForeground(timing.response_start, info)) { - response_start = timing.response_start.value(); + response_start = timing.response_start; } if (WasStartedInForegroundOptionalEventInForeground(timing.load_event_start, info)) { - load_event_start = timing.load_event_start.value(); + load_event_start = timing.load_event_start; } if (WasStartedInForegroundOptionalEventInForeground(timing.first_image_paint, info)) { - first_image_paint = timing.first_image_paint.value(); + first_image_paint = timing.first_image_paint; } if (WasStartedInForegroundOptionalEventInForeground( timing.first_contentful_paint, info)) { - first_contentful_paint = timing.first_contentful_paint.value(); + first_contentful_paint = timing.first_contentful_paint; } - // TODO(ryansturm): Change DataReductionProxyPageLoadTiming to take - // base::Optional<>s (see crbug.com/626040). DataReductionProxyPageLoadTiming data_reduction_proxy_timing( timing.navigation_start, response_start, load_event_start, first_image_paint, first_contentful_paint);
diff --git a/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer_unittest.cc index 5323504..0137ae6 100644 --- a/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer_unittest.cc
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/metrics/field_trial.h" +#include "base/optional.h" #include "base/time/time.h" #include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h" #include "chrome/browser/renderer_host/chrome_navigation_data.h" @@ -152,14 +153,15 @@ NavigateAndCommit(GURL(kDefaultTestUrl2)); } - // Verify that, if expected is set, its value equals that of - // actual. Otherwise, if expected is unset, verify that actual is zero. + // Verify that, if expected and actual are set, their values are equal. + // Otherwise, verify that both are unset. void ExpectEqualOrUnset(const base::Optional<base::TimeDelta>& expected, - base::TimeDelta actual) { - if (expected) { - EXPECT_EQ(expected.value(), actual); + const base::Optional<base::TimeDelta>& actual) { + if (expected && actual) { + EXPECT_EQ(expected.value(), actual.value()); } else { - EXPECT_TRUE(actual.is_zero()); + EXPECT_TRUE(!expected); + EXPECT_TRUE(!actual); } } @@ -168,13 +170,13 @@ EXPECT_EQ(timing_.navigation_start, pingback_client_->timing()->navigation_start); ExpectEqualOrUnset(timing_.first_contentful_paint, - pingback_client_->timing()->first_contentful_paint); + pingback_client_->timing()->first_contentful_paint); ExpectEqualOrUnset(timing_.response_start, - pingback_client_->timing()->response_start); + pingback_client_->timing()->response_start); ExpectEqualOrUnset(timing_.load_event_start, - pingback_client_->timing()->load_event_start); + pingback_client_->timing()->load_event_start); ExpectEqualOrUnset(timing_.first_image_paint, - pingback_client_->timing()->first_image_paint); + pingback_client_->timing()->first_image_paint); } void ValidateHistograms() {
diff --git a/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.cc new file mode 100644 index 0000000..f49f0c6 --- /dev/null +++ b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.cc
@@ -0,0 +1,69 @@ +// 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/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.h" + +#include "base/metrics/histogram_macros.h" +#include "chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service_factory.h" +#include "url/url_constants.h" + +namespace internal { +const char kHttpsEngagementHistogram[] = "Navigation.EngagementTime.HTTPS"; +const char kHttpEngagementHistogram[] = "Navigation.EngagementTime.HTTP"; +} + +HttpsEngagementPageLoadMetricsObserver::HttpsEngagementPageLoadMetricsObserver( + content::BrowserContext* context) + : currently_in_foreground_(false) { + engagement_service_ = + HttpsEngagementServiceFactory::GetForBrowserContext(context); +} + +void HttpsEngagementPageLoadMetricsObserver::OnStart( + content::NavigationHandle* navigation_handle, + const GURL& currently_committed_url, + bool started_in_foreground) { + if (started_in_foreground) + OnShown(); +} + +void HttpsEngagementPageLoadMetricsObserver::OnHidden() { + if (!currently_in_foreground_) + return; + foreground_time_ += base::TimeTicks::Now() - last_time_shown_; + currently_in_foreground_ = false; +} + +void HttpsEngagementPageLoadMetricsObserver::OnShown() { + last_time_shown_ = base::TimeTicks::Now(); + currently_in_foreground_ = true; +} + +void HttpsEngagementPageLoadMetricsObserver::OnComplete( + const page_load_metrics::PageLoadTiming& timing, + const page_load_metrics::PageLoadExtraInfo& extra_info) { + if (!extra_info.committed_url.is_valid() || !extra_info.time_to_commit) + return; + + // Don't record anything if the user never saw it. + if (!currently_in_foreground_ && foreground_time_.is_zero()) + return; + + if (currently_in_foreground_) + OnHidden(); + + if (extra_info.committed_url.SchemeIs(url::kHttpsScheme)) { + if (engagement_service_) + engagement_service_->RecordTimeOnPage(foreground_time_, + HttpsEngagementService::HTTPS); + UMA_HISTOGRAM_LONG_TIMES_100(internal::kHttpsEngagementHistogram, + foreground_time_); + } else if (extra_info.committed_url.SchemeIs(url::kHttpScheme)) { + if (engagement_service_) + engagement_service_->RecordTimeOnPage(foreground_time_, + HttpsEngagementService::HTTP); + UMA_HISTOGRAM_LONG_TIMES_100(internal::kHttpEngagementHistogram, + foreground_time_); + } +}
diff --git a/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.h new file mode 100644 index 0000000..4077f59 --- /dev/null +++ b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.h
@@ -0,0 +1,48 @@ +// 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_PAGE_LOAD_METRICS_OBSERVERS_HTTPS_ENGAGEMENT_METRICS_HTTPS_ENGAGEMENT_PAGE_LOAD_METRICS_OBSERVER_H_ +#define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_HTTPS_ENGAGEMENT_METRICS_HTTPS_ENGAGEMENT_PAGE_LOAD_METRICS_OBSERVER_H_ + +#include "base/macros.h" +#include "base/time/time.h" +#include "chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service.h" +#include "components/page_load_metrics/browser/page_load_metrics_observer.h" +#include "url/gurl.h" + +namespace content { +class BrowserContext; +} // namespace content + +namespace internal { +extern const char kHttpsEngagementHistogram[]; +extern const char kHttpEngagementHistogram[]; +} // namespace internal + +class HttpsEngagementPageLoadMetricsObserver + : public page_load_metrics::PageLoadMetricsObserver { + public: + explicit HttpsEngagementPageLoadMetricsObserver( + content::BrowserContext* context); + + // page_load_metrics::PageLoadMetricsObserver: + void OnStart(content::NavigationHandle* navigation_handle, + const GURL& currently_committed_url, + bool started_in_foreground) override; + void OnHidden() override; + void OnShown() override; + void OnComplete( + const page_load_metrics::PageLoadTiming& timing, + const page_load_metrics::PageLoadExtraInfo& extra_info) override; + + private: + bool currently_in_foreground_; + base::TimeDelta foreground_time_; + base::TimeTicks last_time_shown_; + HttpsEngagementService* engagement_service_; + + DISALLOW_COPY_AND_ASSIGN(HttpsEngagementPageLoadMetricsObserver); +}; + +#endif // CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_HTTPS_ENGAGEMENT_METRICS_HTTPS_ENGAGEMENT_PAGE_LOAD_METRICS_OBSERVER_H_
diff --git a/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer_browsertest.cc new file mode 100644 index 0000000..74a8fe8 --- /dev/null +++ b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer_browsertest.cc
@@ -0,0 +1,505 @@ +// 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/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.h" + +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "base/test/histogram_tester.h" +#include "base/threading/platform_thread.h" +#include "base/time/time.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/metrics/https_engagement_metrics_provider.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/url_constants.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "components/metrics/metrics_service.h" +#include "content/public/test/test_utils.h" +#include "net/ssl/client_cert_store.h" +#include "net/ssl/ssl_server_config.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "url/gurl.h" + +class HttpsEngagementPageLoadMetricsBrowserTest : public InProcessBrowserTest { + public: + HttpsEngagementPageLoadMetricsBrowserTest() + : metrics_provider_(new HttpsEngagementMetricsProvider()) {} + ~HttpsEngagementPageLoadMetricsBrowserTest() override {} + + void StartHttpsServer(bool cert_error) { + https_test_server_.reset( + new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS)); + https_test_server_->SetSSLConfig(cert_error + ? net::EmbeddedTestServer::CERT_EXPIRED + : net::EmbeddedTestServer::CERT_OK); + https_test_server_->ServeFilesFromSourceDirectory("chrome/test/data"); + ASSERT_TRUE(https_test_server_->Start()); + } + + void StartHttpServer() { + http_test_server_.reset( + new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTP)); + http_test_server_->ServeFilesFromSourceDirectory("chrome/test/data"); + ASSERT_TRUE(http_test_server_->Start()); + } + + // Navigate to a URL in a foreground tab, and close it. Return the upper bound + // for how long the URL was open in the foreground. + base::TimeDelta NavigateInForegroundAndCloseWithTiming(GURL target_url) { + base::TimeTicks start = base::TimeTicks::Now(); + ui_test_utils::NavigateToURL(browser(), target_url); + + TabStripModel* tab_strip_model = browser()->tab_strip_model(); + content::WebContentsDestroyedWatcher destroyed_watcher( + tab_strip_model->GetActiveWebContents()); + tab_strip_model->CloseAllTabs(); + destroyed_watcher.Wait(); + return (base::TimeTicks::Now() - start); + } + + // Navigate to two URLs in the same foreground tab, and close it. + void NavigateTwiceInTabAndClose(GURL first_url, GURL second_url) { + ui_test_utils::NavigateToURL(browser(), first_url); + ui_test_utils::NavigateToURL(browser(), second_url); + + TabStripModel* tab_strip_model = browser()->tab_strip_model(); + EXPECT_EQ(1, tab_strip_model->count()); + content::WebContentsDestroyedWatcher destroyed_watcher( + tab_strip_model->GetActiveWebContents()); + tab_strip_model->CloseAllTabs(); + destroyed_watcher.Wait(); + } + + // Navigate to a URL in a foreground tab, move it to the background, then + // close it. Return the upper bound for how long the URL was open in the + // foreground. + base::TimeDelta NavigateInForegroundAndCloseInBackgroundWithTiming(GURL url) { + base::TimeTicks start = base::TimeTicks::Now(); + ui_test_utils::NavigateToURL(browser(), url); + ui_test_utils::NavigateToURLWithDisposition( + browser(), GURL(chrome::kChromeUIVersionURL), NEW_FOREGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); + base::TimeDelta upper_bound_delta = base::TimeTicks::Now() - start; + + // Make sure the correct tab is in the foreground. + TabStripModel* tab_strip_model = browser()->tab_strip_model(); + EXPECT_EQ(2, tab_strip_model->count()); + EXPECT_EQ(url, tab_strip_model->GetWebContentsAt(0)->GetURL()); + EXPECT_NE(url, tab_strip_model->GetActiveWebContents()->GetURL()); + + content::WebContentsDestroyedWatcher destroyed_watcher( + tab_strip_model->GetWebContentsAt(0)); + EXPECT_TRUE(tab_strip_model->CloseWebContentsAt(0, 0)); + destroyed_watcher.Wait(); + EXPECT_EQ(1, tab_strip_model->count()); + + return upper_bound_delta; + } + + // Open and close a tab without ever bringing it to the foreground. + void NavigateInBackgroundAndClose(GURL url) { + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL)); + ui_test_utils::NavigateToURLWithDisposition( + browser(), url, NEW_BACKGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); + + // Make sure the correct tab is in the foreground. + TabStripModel* tab_strip_model = browser()->tab_strip_model(); + EXPECT_EQ(2, tab_strip_model->count()); + EXPECT_EQ(url, tab_strip_model->GetWebContentsAt(1)->GetURL()); + EXPECT_NE(url, tab_strip_model->GetActiveWebContents()->GetURL()); + + content::WebContentsDestroyedWatcher destroyed_watcher( + tab_strip_model->GetWebContentsAt(1)); + EXPECT_TRUE(tab_strip_model->CloseWebContentsAt(1, 0)); + destroyed_watcher.Wait(); + EXPECT_EQ(1, tab_strip_model->count()); + } + + // Open a tab in the background, then bring it to the foreground. Return the + // upper bound for how long the URL was open in the foreground. + base::TimeDelta NavigateInBackgroundAndCloseInForegroundWithTiming(GURL url) { + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL)); + ui_test_utils::NavigateToURLWithDisposition( + browser(), url, NEW_BACKGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); + + // Make sure the correct tab is in the foreground. + TabStripModel* tab_strip_model = browser()->tab_strip_model(); + EXPECT_EQ(2, tab_strip_model->count()); + EXPECT_EQ(url, tab_strip_model->GetWebContentsAt(1)->GetURL()); + EXPECT_NE(url, tab_strip_model->GetActiveWebContents()->GetURL()); + + // Close the foreground tab. + base::TimeTicks start = base::TimeTicks::Now(); + content::WebContentsDestroyedWatcher destroyed_watcher( + tab_strip_model->GetWebContentsAt(0)); + EXPECT_TRUE(tab_strip_model->CloseWebContentsAt(0, 0)); + destroyed_watcher.Wait(); + + // Now the background tab should have moved to the foreground. + EXPECT_EQ(1, tab_strip_model->count()); + EXPECT_EQ(url, tab_strip_model->GetActiveWebContents()->GetURL()); + + content::WebContentsDestroyedWatcher second_watcher( + tab_strip_model->GetActiveWebContents()); + tab_strip_model->CloseAllTabs(); + second_watcher.Wait(); + + return (base::TimeTicks::Now() - start); + } + + void FakeUserMetricsUpload() { + metrics_provider_->ProvideGeneralMetrics(NULL); + } + + protected: + base::HistogramTester histogram_tester_; + std::unique_ptr<net::EmbeddedTestServer> https_test_server_; + std::unique_ptr<net::EmbeddedTestServer> http_test_server_; + std::unique_ptr<HttpsEngagementMetricsProvider> metrics_provider_; + + DISALLOW_COPY_AND_ASSIGN(HttpsEngagementPageLoadMetricsBrowserTest); +}; + +IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, + Simple_Https) { + StartHttpsServer(false); + base::TimeDelta upper_bound = NavigateInForegroundAndCloseWithTiming( + https_test_server_->GetURL("/simple.html")); + + // Test the page load metrics. + histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 0); + histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 1); + int32_t bucket_min = + histogram_tester_.GetAllSamples(internal::kHttpsEngagementHistogram)[0] + .min; + EXPECT_GE(upper_bound.InMilliseconds(), bucket_min); + EXPECT_LT(0, bucket_min); + + // Test the ratio metric. + FakeUserMetricsUpload(); + histogram_tester_.ExpectTotalCount( + internal::kHttpsEngagementSessionPercentage, 1); + int32_t ratio_bucket = + histogram_tester_ + .GetAllSamples(internal::kHttpsEngagementSessionPercentage)[0] + .min; + EXPECT_EQ(100, ratio_bucket); +} + +IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, Simple_Http) { + StartHttpServer(); + base::TimeDelta upper_bound = NavigateInForegroundAndCloseWithTiming( + http_test_server_->GetURL("/simple.html")); + + // Test the page load metrics. + histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 1); + histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 0); + int32_t bucket_min = + histogram_tester_.GetAllSamples(internal::kHttpEngagementHistogram)[0] + .min; + EXPECT_GE(upper_bound.InMilliseconds(), bucket_min); + EXPECT_LT(0, bucket_min); + + // Test the ratio metric. + FakeUserMetricsUpload(); + histogram_tester_.ExpectTotalCount( + internal::kHttpsEngagementSessionPercentage, 1); + int32_t ratio_bucket = + histogram_tester_ + .GetAllSamples(internal::kHttpsEngagementSessionPercentage)[0] + .min; + EXPECT_EQ(0, ratio_bucket); +} + +IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, OtherScheme) { + NavigateInForegroundAndCloseWithTiming(GURL(chrome::kChromeUIVersionURL)); + histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 0); + histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 0); + FakeUserMetricsUpload(); + histogram_tester_.ExpectTotalCount( + internal::kHttpsEngagementSessionPercentage, 0); +} + +IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, + SameOrigin_Https) { + StartHttpsServer(false); + NavigateTwiceInTabAndClose(https_test_server_->GetURL("/simple.html"), + https_test_server_->GetURL("/empty.html")); + + // Test the page load metrics. + histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 0); + histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 2); + + // Test the ratio metric. + FakeUserMetricsUpload(); + histogram_tester_.ExpectTotalCount( + internal::kHttpsEngagementSessionPercentage, 1); + int32_t ratio_bucket = + histogram_tester_ + .GetAllSamples(internal::kHttpsEngagementSessionPercentage)[0] + .min; + EXPECT_EQ(100, ratio_bucket); +} + +IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, + SameOrigin_Http) { + StartHttpServer(); + NavigateTwiceInTabAndClose(http_test_server_->GetURL("/simple.html"), + http_test_server_->GetURL("/empty.html")); + + // Test the page load metrics. + histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 2); + histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 0); + + // Test the ratio metric. + FakeUserMetricsUpload(); + histogram_tester_.ExpectTotalCount( + internal::kHttpsEngagementSessionPercentage, 1); + int32_t ratio_bucket = + histogram_tester_ + .GetAllSamples(internal::kHttpsEngagementSessionPercentage)[0] + .min; + EXPECT_EQ(0, ratio_bucket); +} + +IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, + UncommittedLoadWithError) { + StartHttpsServer(true); + TabStripModel* tab_strip_model = browser()->tab_strip_model(); + ui_test_utils::NavigateToURL(browser(), + https_test_server_->GetURL("/simple.html")); + content::WebContentsDestroyedWatcher destroyed_watcher( + tab_strip_model->GetActiveWebContents()); + EXPECT_TRUE( + tab_strip_model->CloseWebContentsAt(tab_strip_model->active_index(), 0)); + destroyed_watcher.Wait(); + histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 0); + histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 0); + FakeUserMetricsUpload(); + histogram_tester_.ExpectTotalCount( + internal::kHttpsEngagementSessionPercentage, 0); +} + +IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, + Navigate_Https) { + StartHttpsServer(false); + NavigateTwiceInTabAndClose(https_test_server_->GetURL("/simple.html"), + GURL(chrome::kChromeUIVersionURL)); + + // Test the page load metrics. + histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 0); + histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 1); + + // Test the ratio metric. + FakeUserMetricsUpload(); + histogram_tester_.ExpectTotalCount( + internal::kHttpsEngagementSessionPercentage, 1); + int32_t ratio_bucket = + histogram_tester_ + .GetAllSamples(internal::kHttpsEngagementSessionPercentage)[0] + .min; + EXPECT_EQ(100, ratio_bucket); +} + +IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, + Navigate_Http) { + StartHttpServer(); + + // Test the page load metrics. + NavigateTwiceInTabAndClose(http_test_server_->GetURL("/simple.html"), + GURL(chrome::kChromeUIVersionURL)); + histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 1); + histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 0); + + // Test the ratio metric. + FakeUserMetricsUpload(); + histogram_tester_.ExpectTotalCount( + internal::kHttpsEngagementSessionPercentage, 1); + int32_t ratio_bucket = + histogram_tester_ + .GetAllSamples(internal::kHttpsEngagementSessionPercentage)[0] + .min; + EXPECT_EQ(0, ratio_bucket); +} + +IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, + Navigate_Both) { + StartHttpServer(); + StartHttpsServer(false); + + NavigateTwiceInTabAndClose(http_test_server_->GetURL("/simple.html"), + https_test_server_->GetURL("/simple.html")); + histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 1); + histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 1); +} + +IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, + Navigate_Both_NonHtmlMainResource) { + StartHttpServer(); + StartHttpsServer(false); + NavigateTwiceInTabAndClose(http_test_server_->GetURL("/circle.svg"), + https_test_server_->GetURL("/circle.svg")); + + // TODO(bmcquade): for the time being, the page load metrics infrastructure + // also tracks non-HTML resources. We should update these to expect 0 + // histogram events once that gets fixed. See crbug.com/627536. + + // Test the page load metrics. + histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 1); + histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 1); + + // Test the ratio metric. + FakeUserMetricsUpload(); + histogram_tester_.ExpectTotalCount( + internal::kHttpsEngagementSessionPercentage, 1); + int32_t ratio_bucket = + histogram_tester_ + .GetAllSamples(internal::kHttpsEngagementSessionPercentage)[0] + .min; + EXPECT_GT(100, ratio_bucket); + EXPECT_LT(0, ratio_bucket); +} + +IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, + ClosedWhileHidden_Https) { + StartHttpsServer(false); + base::TimeDelta upper_bound = + NavigateInForegroundAndCloseInBackgroundWithTiming( + https_test_server_->GetURL("/simple.html")); + + // Test the page load metrics. + histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 0); + histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 1); + int32_t bucket_min = + histogram_tester_.GetAllSamples(internal::kHttpsEngagementHistogram)[0] + .min; + EXPECT_GE(upper_bound.InMilliseconds(), bucket_min); + EXPECT_LT(0, bucket_min); + + // Test the ratio metric. + FakeUserMetricsUpload(); + histogram_tester_.ExpectTotalCount( + internal::kHttpsEngagementSessionPercentage, 1); + int32_t ratio_bucket = + histogram_tester_ + .GetAllSamples(internal::kHttpsEngagementSessionPercentage)[0] + .min; + EXPECT_EQ(100, ratio_bucket); +} + +IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, + ClosedWhileHidden_Http) { + StartHttpServer(); + base::TimeDelta upper_bound = + NavigateInForegroundAndCloseInBackgroundWithTiming( + http_test_server_->GetURL("/simple.html")); + + // Test the page load metrics. + histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 1); + histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 0); + int32_t bucket_min = + histogram_tester_.GetAllSamples(internal::kHttpEngagementHistogram)[0] + .min; + EXPECT_GE(upper_bound.InMilliseconds(), bucket_min); + EXPECT_LT(0, bucket_min); + + // Test the ratio metric. + FakeUserMetricsUpload(); + histogram_tester_.ExpectTotalCount( + internal::kHttpsEngagementSessionPercentage, 1); + int32_t ratio_bucket = + histogram_tester_ + .GetAllSamples(internal::kHttpsEngagementSessionPercentage)[0] + .min; + EXPECT_EQ(0, ratio_bucket); +} + +IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, + BackgroundThenForeground_Https) { + StartHttpsServer(false); + base::TimeDelta upper_bound = + NavigateInBackgroundAndCloseInForegroundWithTiming( + https_test_server_->GetURL("/simple.html")); + + // Test the page load metrics. + histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 0); + histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 1); + int32_t bucket_min = + histogram_tester_.GetAllSamples(internal::kHttpsEngagementHistogram)[0] + .min; + EXPECT_GE(upper_bound.InMilliseconds(), bucket_min); + EXPECT_LT(0, bucket_min); + + // Test the ratio metric. + FakeUserMetricsUpload(); + histogram_tester_.ExpectTotalCount( + internal::kHttpsEngagementSessionPercentage, 1); + int32_t ratio_bucket = + histogram_tester_ + .GetAllSamples(internal::kHttpsEngagementSessionPercentage)[0] + .min; + EXPECT_EQ(100, ratio_bucket); +} + +IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, + BackgroundThenForeground_Http) { + StartHttpServer(); + base::TimeDelta upper_bound = + NavigateInBackgroundAndCloseInForegroundWithTiming( + http_test_server_->GetURL("/simple.html")); + + // Test the page load metrics. + histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 1); + histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 0); + int32_t bucket_min = + histogram_tester_.GetAllSamples(internal::kHttpEngagementHistogram)[0] + .min; + EXPECT_GE(upper_bound.InMilliseconds(), bucket_min); + EXPECT_LT(0, bucket_min); + + // Test the ratio metric. + FakeUserMetricsUpload(); + histogram_tester_.ExpectTotalCount( + internal::kHttpsEngagementSessionPercentage, 1); + int32_t ratio_bucket = + histogram_tester_ + .GetAllSamples(internal::kHttpsEngagementSessionPercentage)[0] + .min; + EXPECT_EQ(0, ratio_bucket); +} + +IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, + AlwaysInBackground) { + StartHttpsServer(false); + StartHttpServer(); + NavigateInBackgroundAndClose(https_test_server_->GetURL("/simple.html")); + NavigateInBackgroundAndClose(http_test_server_->GetURL("/simple.html")); + + // Test the page load metrics. + histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 0); + histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 0); + + // Test the ratio metric. + FakeUserMetricsUpload(); + histogram_tester_.ExpectTotalCount( + internal::kHttpsEngagementSessionPercentage, 0); +} + +IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, + MultipleUploads) { + StartHttpsServer(false); + + NavigateInForegroundAndCloseWithTiming(https_test_server_->GetURL("/")); + histogram_tester_.ExpectTotalCount( + internal::kHttpsEngagementSessionPercentage, 0); + FakeUserMetricsUpload(); + FakeUserMetricsUpload(); + FakeUserMetricsUpload(); + histogram_tester_.ExpectTotalCount( + internal::kHttpsEngagementSessionPercentage, 1); +}
diff --git a/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service.cc b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service.cc new file mode 100644 index 0000000..190a35e --- /dev/null +++ b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service.cc
@@ -0,0 +1,44 @@ +// 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/page_load_metrics/observers/https_engagement_metrics/https_engagement_service.h" + +#include "base/metrics/histogram_macros.h" + +namespace internal { +const char kHttpsEngagementSessionPercentage[] = + "Navigation.EngagementTime.Ratio"; +} + +HttpsEngagementService::HttpsEngagementService() {} + +HttpsEngagementService::~HttpsEngagementService() {} + +void HttpsEngagementService::RecordTimeOnPage(base::TimeDelta foreground_time, + PageScheme scheme) { + switch (scheme) { + case HTTPS: + time_on_https_ += foreground_time; + break; + case HTTP: + time_on_http_ += foreground_time; + break; + case OTHER: + return; + } +} + +void HttpsEngagementService::StoreMetricsAndClear() { + double total_time = + time_on_https_.InMillisecondsF() + time_on_http_.InMillisecondsF(); + if (total_time == 0) + return; + + double https_ratio = 100.0 * (time_on_https_.InMillisecondsF() / total_time); + UMA_HISTOGRAM_PERCENTAGE(internal::kHttpsEngagementSessionPercentage, + https_ratio); + + time_on_https_ = base::TimeDelta(); + time_on_http_ = base::TimeDelta(); +}
diff --git a/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service.h b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service.h new file mode 100644 index 0000000..5f4ed2b --- /dev/null +++ b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service.h
@@ -0,0 +1,37 @@ +// 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_PAGE_LOAD_METRICS_OBSERVERS_HTTPS_ENGAGEMENT_METRICS_HTTPS_ENGAGEMENT_SERVICE_H_ +#define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_HTTPS_ENGAGEMENT_METRICS_HTTPS_ENGAGEMENT_SERVICE_H_ + +#include "base/macros.h" +#include "base/time/time.h" +#include "components/keyed_service/core/keyed_service.h" +#include "components/metrics/metrics_provider.h" + +namespace internal { +extern const char kHttpsEngagementSessionPercentage[]; +} // namespace internal + +class HttpsEngagementService : public KeyedService { + public: + enum PageScheme { HTTP, HTTPS, OTHER }; + + HttpsEngagementService(); + ~HttpsEngagementService() override; + + // Save that the user spent |time| on either HTTPS or HTTP. + void RecordTimeOnPage(base::TimeDelta time_spent, PageScheme scheme); + + // Persist the current state with the metrics service, and reset state. + void StoreMetricsAndClear(); + + private: + base::TimeDelta time_on_https_; + base::TimeDelta time_on_http_; + + DISALLOW_COPY_AND_ASSIGN(HttpsEngagementService); +}; + +#endif // CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_HTTPS_ENGAGEMENT_METRICS_HTTPS_ENGAGEMENT_SERVICE_H_
diff --git a/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service_factory.cc b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service_factory.cc new file mode 100644 index 0000000..6111eec --- /dev/null +++ b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service_factory.cc
@@ -0,0 +1,47 @@ +// 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/page_load_metrics/observers/https_engagement_metrics/https_engagement_service_factory.h" + +#include "base/memory/singleton.h" +#include "chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service.h" +#include "chrome/browser/profiles/incognito_helpers.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" + +// static +HttpsEngagementService* HttpsEngagementServiceFactory::GetForBrowserContext( + content::BrowserContext* context) { + return static_cast<HttpsEngagementService*>( + GetInstance()->GetServiceForBrowserContext(context, true)); +} + +// static +HttpsEngagementServiceFactory* HttpsEngagementServiceFactory::GetInstance() { + return base::Singleton<HttpsEngagementServiceFactory>::get(); +} + +HttpsEngagementServiceFactory::HttpsEngagementServiceFactory() + : BrowserContextKeyedServiceFactory( + "HttpEngagementKeyService", + BrowserContextDependencyManager::GetInstance()) {} + +HttpsEngagementServiceFactory::~HttpsEngagementServiceFactory() {} + +KeyedService* HttpsEngagementServiceFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + return new HttpsEngagementService(); +} + +content::BrowserContext* HttpsEngagementServiceFactory::GetBrowserContextToUse( + content::BrowserContext* context) const { + return chrome::GetBrowserContextRedirectedInIncognito(context); +} + +bool HttpsEngagementServiceFactory::ServiceIsCreatedWithBrowserContext() const { + return true; +} + +bool HttpsEngagementServiceFactory::ServiceIsNULLWhileTesting() const { + return false; +}
diff --git a/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service_factory.h b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service_factory.h new file mode 100644 index 0000000..134aec4 --- /dev/null +++ b/chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service_factory.h
@@ -0,0 +1,47 @@ +// 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_PAGE_LOAD_METRICS_OBSERVERS_HTTPS_ENGAGEMENT_METRICS_HTTPS_ENGAGEMENT_SERVICE_FACTORY_H_ +#define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_HTTPS_ENGAGEMENT_METRICS_HTTPS_ENGAGEMENT_SERVICE_FACTORY_H_ + +#include "base/macros.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +namespace content { +class BrowserContext; +} // namespace content + +namespace base { +template <typename T> +struct DefaultSingletonTraits; +} + +class HttpsEngagementService; + +// Singleton that owns all HttpsEngagementKeyServices and associates them with +// BrowserContexts. +class HttpsEngagementServiceFactory : public BrowserContextKeyedServiceFactory { + public: + static HttpsEngagementService* GetForBrowserContext( + content::BrowserContext* context); + static HttpsEngagementServiceFactory* GetInstance(); + + private: + friend struct base::DefaultSingletonTraits<HttpsEngagementServiceFactory>; + + HttpsEngagementServiceFactory(); + ~HttpsEngagementServiceFactory() override; + + // BrowserContextKeyedServiceFactory: + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* context) const override; + content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* context) const override; + bool ServiceIsCreatedWithBrowserContext() const override; + bool ServiceIsNULLWhileTesting() const override; + + DISALLOW_COPY_AND_ASSIGN(HttpsEngagementServiceFactory); +}; + +#endif // CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_HTTPS_ENGAGEMENT_METRICS_HTTPS_ENGAGEMENT_SERVICE_FACTORY_H_
diff --git a/chrome/browser/page_load_metrics/observers/https_engagement_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/https_engagement_page_load_metrics_observer.cc deleted file mode 100644 index 02c25e7..0000000 --- a/chrome/browser/page_load_metrics/observers/https_engagement_page_load_metrics_observer.cc +++ /dev/null
@@ -1,58 +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/page_load_metrics/observers/https_engagement_page_load_metrics_observer.h" - -#include "base/metrics/histogram_macros.h" -#include "url/url_constants.h" - -namespace internal { -const char kHttpsEngagementHistogram[] = "Navigation.EngagementTime.HTTPS"; -const char kHttpEngagementHistogram[] = "Navigation.EngagementTime.HTTP"; -} - -HttpsEngagementPageLoadMetricsObserver::HttpsEngagementPageLoadMetricsObserver() - : currently_in_foreground_(false) {} - -void HttpsEngagementPageLoadMetricsObserver::OnStart( - content::NavigationHandle* navigation_handle, - const GURL& currently_committed_url, - bool started_in_foreground) { - if (started_in_foreground) - OnShown(); -} - -void HttpsEngagementPageLoadMetricsObserver::OnHidden() { - if (!currently_in_foreground_) - return; - foreground_time_ += base::TimeTicks::Now() - last_time_shown_; - currently_in_foreground_ = false; -} - -void HttpsEngagementPageLoadMetricsObserver::OnShown() { - last_time_shown_ = base::TimeTicks::Now(); - currently_in_foreground_ = true; -} - -void HttpsEngagementPageLoadMetricsObserver::OnComplete( - const page_load_metrics::PageLoadTiming& timing, - const page_load_metrics::PageLoadExtraInfo& extra_info) { - if (!extra_info.committed_url.is_valid() || !extra_info.time_to_commit) - return; - - // Don't record anything if the user never saw it. - if (!currently_in_foreground_ && foreground_time_.is_zero()) - return; - - if (currently_in_foreground_) - OnHidden(); - - if (extra_info.committed_url.SchemeIs(url::kHttpsScheme)) { - UMA_HISTOGRAM_LONG_TIMES_100(internal::kHttpsEngagementHistogram, - foreground_time_); - } else if (extra_info.committed_url.SchemeIs(url::kHttpScheme)) { - UMA_HISTOGRAM_LONG_TIMES_100(internal::kHttpEngagementHistogram, - foreground_time_); - } -}
diff --git a/chrome/browser/page_load_metrics/observers/https_engagement_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/https_engagement_page_load_metrics_observer.h deleted file mode 100644 index 58552f5..0000000 --- a/chrome/browser/page_load_metrics/observers/https_engagement_page_load_metrics_observer.h +++ /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. - -#ifndef CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_HTTPS_ENGAGEMENT_PAGE_LOAD_METRICS_OBSERVER_H_ -#define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_HTTPS_ENGAGEMENT_PAGE_LOAD_METRICS_OBSERVER_H_ - -#include "base/macros.h" -#include "base/time/time.h" -#include "components/page_load_metrics/browser/page_load_metrics_observer.h" -#include "url/gurl.h" - -namespace internal { -extern const char kHttpsEngagementHistogram[]; -extern const char kHttpEngagementHistogram[]; -} // namespace internal - -class HttpsEngagementPageLoadMetricsObserver - : public page_load_metrics::PageLoadMetricsObserver { - public: - HttpsEngagementPageLoadMetricsObserver(); - - // page_load_metrics::PageLoadMetricsObserver: - void OnStart(content::NavigationHandle* navigation_handle, - const GURL& currently_committed_url, - bool started_in_foreground) override; - void OnHidden() override; - void OnShown() override; - void OnComplete( - const page_load_metrics::PageLoadTiming& timing, - const page_load_metrics::PageLoadExtraInfo& extra_info) override; - - private: - bool currently_in_foreground_; - base::TimeDelta foreground_time_; - base::TimeTicks last_time_shown_; - - DISALLOW_COPY_AND_ASSIGN(HttpsEngagementPageLoadMetricsObserver); -}; - -#endif // CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_HTTPS_ENGAGEMENT_PAGE_LOAD_METRICS_OBSERVER_H_
diff --git a/chrome/browser/page_load_metrics/observers/https_engagement_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/https_engagement_page_load_metrics_observer_browsertest.cc deleted file mode 100644 index 78d4c11..0000000 --- a/chrome/browser/page_load_metrics/observers/https_engagement_page_load_metrics_observer_browsertest.cc +++ /dev/null
@@ -1,320 +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/page_load_metrics/observers/https_engagement_page_load_metrics_observer.h" - -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/test/histogram_tester.h" -#include "base/threading/platform_thread.h" -#include "base/time/time.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/common/url_constants.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "chrome/test/base/ui_test_utils.h" -#include "content/public/test/test_utils.h" -#include "net/ssl/client_cert_store.h" -#include "net/ssl/ssl_server_config.h" -#include "net/test/embedded_test_server/embedded_test_server.h" -#include "url/gurl.h" - -class HttpsEngagementPageLoadMetricsBrowserTest : public InProcessBrowserTest { - public: - HttpsEngagementPageLoadMetricsBrowserTest() {} - ~HttpsEngagementPageLoadMetricsBrowserTest() override {} - - void StartHttpsServer(bool cert_error) { - https_test_server_.reset( - new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS)); - https_test_server_->SetSSLConfig(cert_error - ? net::EmbeddedTestServer::CERT_EXPIRED - : net::EmbeddedTestServer::CERT_OK); - https_test_server_->ServeFilesFromSourceDirectory("chrome/test/data"); - ASSERT_TRUE(https_test_server_->Start()); - } - - void StartHttpServer() { - http_test_server_.reset( - new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTP)); - http_test_server_->ServeFilesFromSourceDirectory("chrome/test/data"); - ASSERT_TRUE(http_test_server_->Start()); - } - - // Navigate to a URL in a foreground tab, and close it. Return the upper bound - // for how long the URL was open in the foreground. - base::TimeDelta NavigateInForegroundAndCloseWithTiming(GURL target_url) { - base::TimeTicks start = base::TimeTicks::Now(); - ui_test_utils::NavigateToURL(browser(), target_url); - - TabStripModel* tab_strip_model = browser()->tab_strip_model(); - content::WebContentsDestroyedWatcher destroyed_watcher( - tab_strip_model->GetActiveWebContents()); - tab_strip_model->CloseAllTabs(); - destroyed_watcher.Wait(); - return (base::TimeTicks::Now() - start); - } - - // Navigate to two URLs in the same foreground tab, and close it. - void NavigateTwiceInTabAndClose(GURL first_url, GURL second_url) { - ui_test_utils::NavigateToURL(browser(), first_url); - ui_test_utils::NavigateToURL(browser(), second_url); - - TabStripModel* tab_strip_model = browser()->tab_strip_model(); - EXPECT_EQ(1, tab_strip_model->count()); - content::WebContentsDestroyedWatcher destroyed_watcher( - tab_strip_model->GetActiveWebContents()); - tab_strip_model->CloseAllTabs(); - destroyed_watcher.Wait(); - } - - // Navigate to a URL in a foreground tab, move it to the background, then - // close it. Return the upper bound for how long the URL was open in the - // foreground. - base::TimeDelta NavigateInForegroundAndCloseInBackgroundWithTiming(GURL url) { - base::TimeTicks start = base::TimeTicks::Now(); - ui_test_utils::NavigateToURL(browser(), url); - ui_test_utils::NavigateToURLWithDisposition( - browser(), GURL(chrome::kChromeUIVersionURL), NEW_FOREGROUND_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); - base::TimeDelta upper_bound_delta = base::TimeTicks::Now() - start; - - // Make sure the correct tab is in the foreground. - TabStripModel* tab_strip_model = browser()->tab_strip_model(); - EXPECT_EQ(2, tab_strip_model->count()); - EXPECT_EQ(url, tab_strip_model->GetWebContentsAt(0)->GetURL()); - EXPECT_NE(url, tab_strip_model->GetActiveWebContents()->GetURL()); - - content::WebContentsDestroyedWatcher destroyed_watcher( - tab_strip_model->GetWebContentsAt(0)); - EXPECT_TRUE(tab_strip_model->CloseWebContentsAt(0, 0)); - destroyed_watcher.Wait(); - EXPECT_EQ(1, tab_strip_model->count()); - - return upper_bound_delta; - } - - // Open and close a tab without ever bringing it to the foreground. - void NavigateInBackgroundAndClose(GURL url) { - ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL)); - ui_test_utils::NavigateToURLWithDisposition( - browser(), url, NEW_BACKGROUND_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); - - // Make sure the correct tab is in the foreground. - TabStripModel* tab_strip_model = browser()->tab_strip_model(); - EXPECT_EQ(2, tab_strip_model->count()); - EXPECT_EQ(url, tab_strip_model->GetWebContentsAt(1)->GetURL()); - EXPECT_NE(url, tab_strip_model->GetActiveWebContents()->GetURL()); - - content::WebContentsDestroyedWatcher destroyed_watcher( - tab_strip_model->GetWebContentsAt(1)); - EXPECT_TRUE(tab_strip_model->CloseWebContentsAt(1, 0)); - destroyed_watcher.Wait(); - EXPECT_EQ(1, tab_strip_model->count()); - } - - // Open a tab in the background, then bring it to the foreground. Return the - // upper bound for how long the URL was open in the foreground. - base::TimeDelta NavigateInBackgroundAndCloseInForegroundWithTiming(GURL url) { - ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL)); - ui_test_utils::NavigateToURLWithDisposition( - browser(), url, NEW_BACKGROUND_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); - - // Make sure the correct tab is in the foreground. - TabStripModel* tab_strip_model = browser()->tab_strip_model(); - EXPECT_EQ(2, tab_strip_model->count()); - EXPECT_EQ(url, tab_strip_model->GetWebContentsAt(1)->GetURL()); - EXPECT_NE(url, tab_strip_model->GetActiveWebContents()->GetURL()); - - // Close the foreground tab. - base::TimeTicks start = base::TimeTicks::Now(); - content::WebContentsDestroyedWatcher destroyed_watcher( - tab_strip_model->GetWebContentsAt(0)); - EXPECT_TRUE(tab_strip_model->CloseWebContentsAt(0, 0)); - destroyed_watcher.Wait(); - - // Now the background tab should have moved to the foreground. - EXPECT_EQ(1, tab_strip_model->count()); - EXPECT_EQ(url, tab_strip_model->GetActiveWebContents()->GetURL()); - - content::WebContentsDestroyedWatcher second_watcher( - tab_strip_model->GetActiveWebContents()); - tab_strip_model->CloseAllTabs(); - second_watcher.Wait(); - - return (base::TimeTicks::Now() - start); - } - - protected: - base::HistogramTester histogram_tester_; - std::unique_ptr<net::EmbeddedTestServer> https_test_server_; - std::unique_ptr<net::EmbeddedTestServer> http_test_server_; - - DISALLOW_COPY_AND_ASSIGN(HttpsEngagementPageLoadMetricsBrowserTest); -}; - -IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, - Simple_Https) { - StartHttpsServer(false); - base::TimeDelta upper_bound = - NavigateInForegroundAndCloseWithTiming(https_test_server_->GetURL("/")); - histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 0); - histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 1); - int32_t bucket_min = - histogram_tester_.GetAllSamples(internal::kHttpsEngagementHistogram)[0] - .min; - EXPECT_GE(upper_bound.InMilliseconds(), bucket_min); - EXPECT_LT(0, bucket_min); -} - -IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, Simple_Http) { - StartHttpServer(); - base::TimeDelta upper_bound = - NavigateInForegroundAndCloseWithTiming(http_test_server_->GetURL("/")); - histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 1); - histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 0); - int32_t bucket_min = - histogram_tester_.GetAllSamples(internal::kHttpEngagementHistogram)[0] - .min; - EXPECT_GE(upper_bound.InMilliseconds(), bucket_min); - EXPECT_LT(0, bucket_min); -} - -IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, OtherScheme) { - NavigateInForegroundAndCloseWithTiming(GURL(chrome::kChromeUIVersionURL)); - histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 0); - histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 0); -} - -IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, - SameOrigin_Https) { - StartHttpsServer(false); - NavigateTwiceInTabAndClose(https_test_server_->GetURL("/simple.html"), - https_test_server_->GetURL("/empty.html")); - histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 0); - histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 2); -} - -IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, - SameOrigin_Http) { - StartHttpServer(); - NavigateTwiceInTabAndClose(http_test_server_->GetURL("/simple.html"), - http_test_server_->GetURL("/empty.html")); - histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 2); - histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 0); -} - -IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, - UncommittedLoadWithError) { - StartHttpsServer(true); - TabStripModel* tab_strip_model = browser()->tab_strip_model(); - ui_test_utils::NavigateToURL(browser(), https_test_server_->GetURL("/")); - content::WebContentsDestroyedWatcher destroyed_watcher( - tab_strip_model->GetActiveWebContents()); - EXPECT_TRUE( - tab_strip_model->CloseWebContentsAt(tab_strip_model->active_index(), 0)); - destroyed_watcher.Wait(); - histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 0); - histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 0); -} - -IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, - Navigate_Https) { - StartHttpsServer(false); - NavigateTwiceInTabAndClose(https_test_server_->GetURL("/"), - GURL(chrome::kChromeUIVersionURL)); - histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 0); - histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 1); -} - -IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, - Navigate_Http) { - StartHttpServer(); - NavigateTwiceInTabAndClose(http_test_server_->GetURL("/"), - GURL(chrome::kChromeUIVersionURL)); - histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 1); - histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 0); -} - -IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, - Navigate_Both) { - StartHttpServer(); - StartHttpsServer(false); - NavigateTwiceInTabAndClose(http_test_server_->GetURL("/"), - https_test_server_->GetURL("/")); - histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 1); - histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 1); -} - -IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, - ClosedWhileHidden_Https) { - StartHttpsServer(false); - base::TimeDelta upper_bound = - NavigateInForegroundAndCloseInBackgroundWithTiming( - https_test_server_->GetURL("/")); - histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 0); - histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 1); - int32_t bucket_min = - histogram_tester_.GetAllSamples(internal::kHttpsEngagementHistogram)[0] - .min; - EXPECT_GE(upper_bound.InMilliseconds(), bucket_min); - EXPECT_LT(0, bucket_min); -} - -IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, - ClosedWhileHidden_Http) { - StartHttpServer(); - base::TimeDelta upper_bound = - NavigateInForegroundAndCloseInBackgroundWithTiming( - http_test_server_->GetURL("/")); - histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 1); - histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 0); - int32_t bucket_min = - histogram_tester_.GetAllSamples(internal::kHttpEngagementHistogram)[0] - .min; - EXPECT_GE(upper_bound.InMilliseconds(), bucket_min); - EXPECT_LT(0, bucket_min); -} - -IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, - BackgroundThenForeground_Https) { - StartHttpsServer(false); - base::TimeDelta upper_bound = - NavigateInBackgroundAndCloseInForegroundWithTiming( - https_test_server_->GetURL("/")); - histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 0); - histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 1); - int32_t bucket_min = - histogram_tester_.GetAllSamples(internal::kHttpsEngagementHistogram)[0] - .min; - EXPECT_GE(upper_bound.InMilliseconds(), bucket_min); - EXPECT_LT(0, bucket_min); -} - -IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, - BackgroundThenForeground_Http) { - StartHttpServer(); - base::TimeDelta upper_bound = - NavigateInBackgroundAndCloseInForegroundWithTiming( - http_test_server_->GetURL("/")); - histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 1); - histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 0); - int32_t bucket_min = - histogram_tester_.GetAllSamples(internal::kHttpEngagementHistogram)[0] - .min; - EXPECT_GE(upper_bound.InMilliseconds(), bucket_min); - EXPECT_LT(0, bucket_min); -} - -IN_PROC_BROWSER_TEST_F(HttpsEngagementPageLoadMetricsBrowserTest, - AlwaysInBackground) { - StartHttpsServer(false); - StartHttpServer(); - NavigateInBackgroundAndClose(https_test_server_->GetURL("/")); - NavigateInBackgroundAndClose(http_test_server_->GetURL("/")); - histogram_tester_.ExpectTotalCount(internal::kHttpEngagementHistogram, 0); - histogram_tester_.ExpectTotalCount(internal::kHttpsEngagementHistogram, 0); -}
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 50927ff..609afa06 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
@@ -12,7 +12,7 @@ #include "chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/google_captcha_observer.h" -#include "chrome/browser/page_load_metrics/observers/https_engagement_page_load_metrics_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/service_worker_page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/observers/stale_while_revalidate_metrics_observer.h" #include "chrome/browser/prerender/prerender_contents.h" @@ -68,7 +68,8 @@ tracker->AddObserver( base::WrapUnique(new ServiceWorkerPageLoadMetricsObserver())); tracker->AddObserver( - base::WrapUnique(new HttpsEngagementPageLoadMetricsObserver())); + base::WrapUnique(new HttpsEngagementPageLoadMetricsObserver( + web_contents_->GetBrowserContext()))); } bool PageLoadMetricsEmbedder::IsPrerendering(
diff --git a/chrome/browser/password_manager/credential_manager_browsertest.cc b/chrome/browser/password_manager/credential_manager_browsertest.cc index 84792c6..d9fc7fe 100644 --- a/chrome/browser/password_manager/credential_manager_browsertest.cc +++ b/chrome/browser/password_manager/credential_manager_browsertest.cc
@@ -81,8 +81,16 @@ EXPECT_FALSE(form.skip_zero_click); } +// TODO(crbug.com/626759): flakily failing on Mac. +#if defined(OS_MACOSX) +#define MAYBE_AutoSigninOldCredentialAndNavigation \ + DISABLED_AutoSigninOldCredentialAndNavigation +#else +#define MAYBE_AutoSigninOldCredentialAndNavigation \ + AutoSigninOldCredentialAndNavigation +#endif IN_PROC_BROWSER_TEST_F(CredentialManagerBrowserTest, - AutoSigninOldCredentialAndNavigation) { + MAYBE_AutoSigninOldCredentialAndNavigation) { // Save credentials with 'skip_zero_click' false. scoped_refptr<password_manager::TestPasswordStore> password_store = static_cast<password_manager::TestPasswordStore*>(
diff --git a/chrome/browser/password_manager/native_backend_gnome_x.cc b/chrome/browser/password_manager/native_backend_gnome_x.cc index 75dde044..5b3e38e 100644 --- a/chrome/browser/password_manager/native_backend_gnome_x.cc +++ b/chrome/browser/password_manager/native_backend_gnome_x.cc
@@ -699,14 +699,15 @@ return RemoveLoginsBetween(delete_begin, delete_end, SYNC_TIMESTAMP, changes); } -bool NativeBackendGnome::DisableAutoSignInForAllLogins( +bool NativeBackendGnome::DisableAutoSignInForOrigins( + const base::Callback<bool(const GURL&)>& origin_filter, password_manager::PasswordStoreChangeList* changes) { ScopedVector<PasswordForm> forms; if (!GetAllLogins(&forms)) return false; for (auto& form : forms) { - if (!form->skip_zero_click) { + if (origin_filter.Run(form->origin) && !form->skip_zero_click) { form->skip_zero_click = true; if (!UpdateLogin(*form, changes)) return false;
diff --git a/chrome/browser/password_manager/native_backend_gnome_x.h b/chrome/browser/password_manager/native_backend_gnome_x.h index 1867bcf..7c81abce 100644 --- a/chrome/browser/password_manager/native_backend_gnome_x.h +++ b/chrome/browser/password_manager/native_backend_gnome_x.h
@@ -107,7 +107,8 @@ base::Time delete_begin, base::Time delete_end, password_manager::PasswordStoreChangeList* changes) override; - bool DisableAutoSignInForAllLogins( + bool DisableAutoSignInForOrigins( + const base::Callback<bool(const GURL&)>& origin_filter, password_manager::PasswordStoreChangeList* changes) override; bool GetLogins(const autofill::PasswordForm& form, ScopedVector<autofill::PasswordForm>* forms) override;
diff --git a/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc b/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc index 6875891..5f0d40b 100644 --- a/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc +++ b/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
@@ -1177,7 +1177,7 @@ CheckRemoveLoginsBetween(SYNCED); } -TEST_F(NativeBackendGnomeTest, DisableAutoSignInForAllLogins) { +TEST_F(NativeBackendGnomeTest, DisableAutoSignInForOrigins) { NativeBackendGnome backend(42); backend.Init(); form_google_.skip_zero_click = false; @@ -1204,20 +1204,25 @@ PasswordStoreChangeList expected_changes; expected_changes.push_back( PasswordStoreChange(PasswordStoreChange::UPDATE, form_facebook_)); - expected_changes.push_back( - PasswordStoreChange(PasswordStoreChange::UPDATE, form_google_)); PasswordStoreChangeList changes; BrowserThread::PostTaskAndReplyWithResult( BrowserThread::DB, FROM_HERE, - base::Bind(&NativeBackendGnome::DisableAutoSignInForAllLogins, - base::Unretained(&backend), &changes), + base::Bind(&NativeBackendGnome::DisableAutoSignInForOrigins, + base::Unretained(&backend), + base::Bind(&GURL::operator==, + base::Unretained(&form_facebook_.origin)), + &changes), base::Bind(&CheckPasswordChangesWithResult, &expected_changes, &changes)); RunBothThreads(); EXPECT_EQ(2u, mock_keyring_items.size()); - for (const auto& item : mock_keyring_items) - CheckUint32Attribute(&item, "should_skip_zero_click", 1); + CheckStringAttribute( + &mock_keyring_items[0], "origin_url", form_google_.origin.spec()); + CheckUint32Attribute(&mock_keyring_items[0], "should_skip_zero_click", 0); + CheckStringAttribute( + &mock_keyring_items[1], "origin_url", form_facebook_.origin.spec()); + CheckUint32Attribute(&mock_keyring_items[1], "should_skip_zero_click", 1); } TEST_F(NativeBackendGnomeTest, ReadDuplicateForms) {
diff --git a/chrome/browser/password_manager/native_backend_kwallet_x.cc b/chrome/browser/password_manager/native_backend_kwallet_x.cc index 08813a2..a2346ba 100644 --- a/chrome/browser/password_manager/native_backend_kwallet_x.cc +++ b/chrome/browser/password_manager/native_backend_kwallet_x.cc
@@ -502,14 +502,15 @@ return RemoveLoginsBetween(delete_begin, delete_end, SYNC_TIMESTAMP, changes); } -bool NativeBackendKWallet::DisableAutoSignInForAllLogins( +bool NativeBackendKWallet::DisableAutoSignInForOrigins( + const base::Callback<bool(const GURL&)>& origin_filter, password_manager::PasswordStoreChangeList* changes) { ScopedVector<autofill::PasswordForm> all_forms; if (!GetAllLogins(&all_forms)) return false; for (auto& form : all_forms) { - if (!form->skip_zero_click) { + if (origin_filter.Run(form->origin) && !form->skip_zero_click) { form->skip_zero_click = true; if (!UpdateLogin(*form, changes)) return false;
diff --git a/chrome/browser/password_manager/native_backend_kwallet_x.h b/chrome/browser/password_manager/native_backend_kwallet_x.h index 313f7c4b..bad33d1 100644 --- a/chrome/browser/password_manager/native_backend_kwallet_x.h +++ b/chrome/browser/password_manager/native_backend_kwallet_x.h
@@ -54,7 +54,8 @@ base::Time delete_begin, base::Time delete_end, password_manager::PasswordStoreChangeList* changes) override; - bool DisableAutoSignInForAllLogins( + bool DisableAutoSignInForOrigins( + const base::Callback<bool(const GURL&)>& origin_filter, password_manager::PasswordStoreChangeList* changes) override; bool GetLogins(const autofill::PasswordForm& form, ScopedVector<autofill::PasswordForm>* forms) override;
diff --git a/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc b/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc index d892a71a..ac77b99 100644 --- a/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc +++ b/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc
@@ -13,6 +13,7 @@ #include <vector> #include "base/bind.h" +#include "base/callback.h" #include "base/location.h" #include "base/pickle.h" #include "base/single_thread_task_runner.h" @@ -1000,15 +1001,20 @@ TestRemoveLoginsBetween(SYNCED); } -TEST_P(NativeBackendKWalletTest, DisableAutoSignInForAllLogins) { +TEST_P(NativeBackendKWalletTest, DisableAutoSignInForOrigins) { NativeBackendKWalletStub backend(42, desktop_env_); EXPECT_TRUE(backend.InitWithBus(mock_session_bus_)); + form_isc_.skip_zero_click = false; form_google_.skip_zero_click = false; BrowserThread::PostTask( BrowserThread::DB, FROM_HERE, base::Bind(base::IgnoreResult(&NativeBackendKWallet::AddLogin), + base::Unretained(&backend), form_isc_)); + BrowserThread::PostTask( + BrowserThread::DB, FROM_HERE, + base::Bind(base::IgnoreResult(&NativeBackendKWallet::AddLogin), base::Unretained(&backend), form_google_)); RunDBThread(); @@ -1022,8 +1028,11 @@ PasswordStoreChangeList changes; BrowserThread::PostTaskAndReplyWithResult( BrowserThread::DB, FROM_HERE, - base::Bind(&NativeBackendKWallet::DisableAutoSignInForAllLogins, - base::Unretained(&backend), &changes), + base::Bind(&NativeBackendKWallet::DisableAutoSignInForOrigins, + base::Unretained(&backend), + base::Bind(&GURL::operator==, + base::Unretained(&form_google_.origin)), + &changes), base::Bind(&CheckPasswordChangesWithResult, &expected_changes, &changes)); RunDBThread(); @@ -1031,6 +1040,9 @@ forms.push_back(&form_google_); ExpectationArray expected; expected.push_back(make_pair(std::string(form_google_.signon_realm), forms)); + forms.clear(); + forms.push_back(&form_isc_); + expected.push_back(make_pair(std::string(form_isc_.signon_realm), forms)); CheckPasswordForms("Chrome Form Data (42)", expected); }
diff --git a/chrome/browser/password_manager/native_backend_libsecret.cc b/chrome/browser/password_manager/native_backend_libsecret.cc index 7d5b258..7ad4ed4d 100644 --- a/chrome/browser/password_manager/native_backend_libsecret.cc +++ b/chrome/browser/password_manager/native_backend_libsecret.cc
@@ -281,14 +281,15 @@ return RemoveLoginsBetween(delete_begin, delete_end, SYNC_TIMESTAMP, changes); } -bool NativeBackendLibsecret::DisableAutoSignInForAllLogins( +bool NativeBackendLibsecret::DisableAutoSignInForOrigins( + const base::Callback<bool(const GURL&)>& origin_filter, password_manager::PasswordStoreChangeList* changes) { ScopedVector<autofill::PasswordForm> all_forms; if (!GetLoginsList(nullptr, ALL_LOGINS, &all_forms)) return false; for (auto& form : all_forms) { - if (!form->skip_zero_click) { + if (origin_filter.Run(form->origin) && !form->skip_zero_click) { form->skip_zero_click = true; if (!UpdateLogin(*form, changes)) return false;
diff --git a/chrome/browser/password_manager/native_backend_libsecret.h b/chrome/browser/password_manager/native_backend_libsecret.h index f125e2ad..bfdf5bf 100644 --- a/chrome/browser/password_manager/native_backend_libsecret.h +++ b/chrome/browser/password_manager/native_backend_libsecret.h
@@ -43,7 +43,8 @@ base::Time delete_begin, base::Time delete_end, password_manager::PasswordStoreChangeList* changes) override; - bool DisableAutoSignInForAllLogins( + bool DisableAutoSignInForOrigins( + const base::Callback<bool(const GURL&)>& origin_filter, password_manager::PasswordStoreChangeList* changes) override; bool GetLogins(const autofill::PasswordForm& form, ScopedVector<autofill::PasswordForm>* forms) override;
diff --git a/chrome/browser/password_manager/native_backend_libsecret_unittest.cc b/chrome/browser/password_manager/native_backend_libsecret_unittest.cc index 85fac00..f3ecee1 100644 --- a/chrome/browser/password_manager/native_backend_libsecret_unittest.cc +++ b/chrome/browser/password_manager/native_backend_libsecret_unittest.cc
@@ -887,7 +887,7 @@ CheckRemoveLoginsBetween(SYNCED); } -TEST_F(NativeBackendLibsecretTest, DisableAutoSignInForAllLogins) { +TEST_F(NativeBackendLibsecretTest, DisableAutoSignInForOrigins) { NativeBackendLibsecret backend(42); backend.Init(); form_google_.skip_zero_click = false; @@ -906,16 +906,22 @@ PasswordStoreChangeList expected_changes; expected_changes.push_back( PasswordStoreChange(PasswordStoreChange::UPDATE, form_facebook_)); - expected_changes.push_back( - PasswordStoreChange(PasswordStoreChange::UPDATE, form_google_)); PasswordStoreChangeList changes; - EXPECT_TRUE(backend.DisableAutoSignInForAllLogins(&changes)); + EXPECT_TRUE(backend.DisableAutoSignInForOrigins( + base::Bind(&GURL::operator==, base::Unretained(&form_facebook_.origin)), + &changes)); CheckPasswordChanges(expected_changes, changes); EXPECT_EQ(2u, global_mock_libsecret_items->size()); - for (const auto& item : *global_mock_libsecret_items) - CheckUint32Attribute(item, "should_skip_zero_click", 1); + CheckStringAttribute((*global_mock_libsecret_items)[0], + "origin_url", form_google_.origin.spec()); + CheckUint32Attribute((*global_mock_libsecret_items)[0], + "should_skip_zero_click", 0); + CheckStringAttribute((*global_mock_libsecret_items)[1], + "origin_url", form_facebook_.origin.spec()); + CheckUint32Attribute((*global_mock_libsecret_items)[1], + "should_skip_zero_click", 1); } TEST_F(NativeBackendLibsecretTest, SomeKeyringAttributesAreMissing) {
diff --git a/chrome/browser/password_manager/password_store_mac.cc b/chrome/browser/password_manager/password_store_mac.cc index fb82842..b39fdef8 100644 --- a/chrome/browser/password_manager/password_store_mac.cc +++ b/chrome/browser/password_manager/password_store_mac.cc
@@ -1196,16 +1196,35 @@ return changes; } -PasswordStoreChangeList PasswordStoreMac::DisableAutoSignInForAllLoginsImpl() { - ScopedVector<PasswordForm> forms; - PasswordStoreChangeList list; - if (login_metadata_db_ && login_metadata_db_->GetAutoSignInLogins(&forms) && - login_metadata_db_->DisableAutoSignInForAllLogins()) { - for (const auto& form : forms) - list.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE, *form)); +PasswordStoreChangeList PasswordStoreMac::DisableAutoSignInForOriginsImpl( + const base::Callback<bool(const GURL&)>& origin_filter) { + ScopedVector<autofill::PasswordForm> forms; + PasswordStoreChangeList changes; + if (!login_metadata_db_ || + !login_metadata_db_->GetAutoSignInLogins(&forms)) { + return changes; } - return list; + std::set<GURL> origins_to_update; + for (const auto* form : forms) { + if (origin_filter.Run(form->origin)) + origins_to_update.insert(form->origin); + } + + std::set<GURL> origins_updated; + for (const GURL& origin : origins_to_update) { + if (login_metadata_db_->DisableAutoSignInForOrigin(origin)) + origins_updated.insert(origin); + } + + for (const auto* form : forms) { + if (origins_updated.count(form->origin)) { + changes.push_back( + PasswordStoreChange(PasswordStoreChange::UPDATE, *form)); + } + } + + return changes; } bool PasswordStoreMac::RemoveStatisticsCreatedBetweenImpl(
diff --git a/chrome/browser/password_manager/password_store_mac.h b/chrome/browser/password_manager/password_store_mac.h index 9d0682a..f42ebb2 100644 --- a/chrome/browser/password_manager/password_store_mac.h +++ b/chrome/browser/password_manager/password_store_mac.h
@@ -89,8 +89,8 @@ password_manager::PasswordStoreChangeList RemoveLoginsSyncedBetweenImpl( base::Time delete_begin, base::Time delete_end) override; - password_manager::PasswordStoreChangeList DisableAutoSignInForAllLoginsImpl() - override; + password_manager::PasswordStoreChangeList DisableAutoSignInForOriginsImpl( + const base::Callback<bool(const GURL&)>& origin_filter) override; bool RemoveStatisticsCreatedBetweenImpl(base::Time delete_begin, base::Time delete_end) override; ScopedVector<autofill::PasswordForm> FillMatchingLogins(
diff --git a/chrome/browser/password_manager/password_store_mac_unittest.cc b/chrome/browser/password_manager/password_store_mac_unittest.cc index b0cc46f..76836e70 100644 --- a/chrome/browser/password_manager/password_store_mac_unittest.cc +++ b/chrome/browser/password_manager/password_store_mac_unittest.cc
@@ -1778,7 +1778,7 @@ CheckRemoveLoginsBetween(this, false); } -TEST_F(PasswordStoreMacTest, TestDisableAutoSignInForAllLogins) { +TEST_F(PasswordStoreMacTest, TestDisableAutoSignInForOrigins) { PasswordFormData www_form_data_facebook = { PasswordForm::SCHEME_HTML, "http://www.facebook.com/", @@ -1796,22 +1796,45 @@ CreatePasswordFormFromDataForTesting(www_form_data_facebook); form_facebook->skip_zero_click = false; - // Add the zero-clickable form to the database. + PasswordFormData www_form_data_google = { + PasswordForm::SCHEME_HTML, + "http://www.google.com/", + "http://www.google.com/foo/bar/index.html", + "login", + L"submit", + L"username", + L"password", + L"joe_user", + L"sekrit", + true, + false, + 0}; + std::unique_ptr<PasswordForm> form_google = + CreatePasswordFormFromDataForTesting(www_form_data_google); + form_google->skip_zero_click = false; + + // Add the zero-clickable forms to the database. PasswordsChangeObserver observer(store()); store()->AddLogin(*form_facebook); + store()->AddLogin(*form_google); EXPECT_CALL(observer, OnLoginsChanged(GetAddChangeList(*form_facebook))); + EXPECT_CALL(observer, OnLoginsChanged(GetAddChangeList(*form_google))); observer.WaitAndVerify(this); ScopedVector<autofill::PasswordForm> forms; EXPECT_TRUE(login_db()->GetAutoSignInLogins(&forms)); - EXPECT_EQ(1u, forms.size()); + EXPECT_EQ(2u, forms.size()); EXPECT_FALSE(forms[0]->skip_zero_click); + EXPECT_FALSE(forms[1]->skip_zero_click); - store()->DisableAutoSignInForAllLogins(base::Closure()); + store()->DisableAutoSignInForOrigins( + base::Bind(&GURL::operator==, base::Unretained(&form_google->origin)), + base::Closure()); FinishAsyncProcessing(); EXPECT_TRUE(login_db()->GetAutoSignInLogins(&forms)); - EXPECT_EQ(0u, forms.size()); + EXPECT_EQ(1u, forms.size()); + EXPECT_EQ(form_facebook->origin, forms[0]->origin); } TEST_F(PasswordStoreMacTest, TestRemoveLoginsMultiProfile) {
diff --git a/chrome/browser/password_manager/password_store_proxy_mac.cc b/chrome/browser/password_manager/password_store_proxy_mac.cc index 4a3fe4f6..c42c2c2 100644 --- a/chrome/browser/password_manager/password_store_proxy_mac.cc +++ b/chrome/browser/password_manager/password_store_proxy_mac.cc
@@ -190,8 +190,9 @@ } PasswordStoreChangeList -PasswordStoreProxyMac::DisableAutoSignInForAllLoginsImpl() { - return GetBackend()->DisableAutoSignInForAllLoginsImpl(); +PasswordStoreProxyMac::DisableAutoSignInForOriginsImpl( + const base::Callback<bool(const GURL&)>& origin_filter) { + return GetBackend()->DisableAutoSignInForOriginsImpl(origin_filter); } bool PasswordStoreProxyMac::RemoveStatisticsCreatedBetweenImpl(
diff --git a/chrome/browser/password_manager/password_store_proxy_mac.h b/chrome/browser/password_manager/password_store_proxy_mac.h index 40ba71f..8326376 100644 --- a/chrome/browser/password_manager/password_store_proxy_mac.h +++ b/chrome/browser/password_manager/password_store_proxy_mac.h
@@ -86,8 +86,8 @@ password_manager::PasswordStoreChangeList RemoveLoginsSyncedBetweenImpl( base::Time delete_begin, base::Time delete_end) override; - password_manager::PasswordStoreChangeList DisableAutoSignInForAllLoginsImpl() - override; + password_manager::PasswordStoreChangeList DisableAutoSignInForOriginsImpl( + const base::Callback<bool(const GURL&)>& origin_filter) override; bool RemoveStatisticsCreatedBetweenImpl(base::Time delete_begin, base::Time delete_end) override; ScopedVector<autofill::PasswordForm> FillMatchingLogins(
diff --git a/chrome/browser/password_manager/password_store_x.cc b/chrome/browser/password_manager/password_store_x.cc index 1cfa3d0..75f8244 100644 --- a/chrome/browser/password_manager/password_store_x.cc +++ b/chrome/browser/password_manager/password_store_x.cc
@@ -161,14 +161,16 @@ return changes; } -PasswordStoreChangeList PasswordStoreX::DisableAutoSignInForAllLoginsImpl() { +PasswordStoreChangeList PasswordStoreX::DisableAutoSignInForOriginsImpl( + const base::Callback<bool(const GURL&)>& origin_filter) { CheckMigration(); PasswordStoreChangeList changes; if (use_native_backend() && - backend_->DisableAutoSignInForAllLogins(&changes)) { + backend_->DisableAutoSignInForOrigins(origin_filter, &changes)) { allow_fallback_ = false; } else if (allow_default_store()) { - changes = PasswordStoreDefault::DisableAutoSignInForAllLoginsImpl(); + changes = + PasswordStoreDefault::DisableAutoSignInForOriginsImpl(origin_filter); } return changes; }
diff --git a/chrome/browser/password_manager/password_store_x.h b/chrome/browser/password_manager/password_store_x.h index a33709d..f6851bc 100644 --- a/chrome/browser/password_manager/password_store_x.h +++ b/chrome/browser/password_manager/password_store_x.h
@@ -69,8 +69,10 @@ base::Time delete_end, password_manager::PasswordStoreChangeList* changes) = 0; - // Sets the 'skip_zero_click' flag to 'true' for all logins in the database. - virtual bool DisableAutoSignInForAllLogins( + // Sets the 'skip_zero_click' flag to 'true' for all logins in the database + // that match |origin_filter|. + virtual bool DisableAutoSignInForOrigins( + const base::Callback<bool(const GURL&)>& origin_filter, password_manager::PasswordStoreChangeList* changes) = 0; // The three methods below overwrite |forms| with all stored credentials @@ -116,8 +118,8 @@ password_manager::PasswordStoreChangeList RemoveLoginsSyncedBetweenImpl( base::Time delete_begin, base::Time delete_end) override; - password_manager::PasswordStoreChangeList DisableAutoSignInForAllLoginsImpl() - override; + password_manager::PasswordStoreChangeList DisableAutoSignInForOriginsImpl( + const base::Callback<bool(const GURL&)>& origin_filter) override; ScopedVector<autofill::PasswordForm> FillMatchingLogins( const autofill::PasswordForm& form) override; bool FillAutofillableLogins(
diff --git a/chrome/browser/password_manager/password_store_x_unittest.cc b/chrome/browser/password_manager/password_store_x_unittest.cc index 36a99f3..2f26468 100644 --- a/chrome/browser/password_manager/password_store_x_unittest.cc +++ b/chrome/browser/password_manager/password_store_x_unittest.cc
@@ -84,7 +84,8 @@ return false; } - bool DisableAutoSignInForAllLogins( + bool DisableAutoSignInForOrigins( + const base::Callback<bool(const GURL&)>& origin_filter, password_manager::PasswordStoreChangeList* changes) override { return false; } @@ -191,7 +192,8 @@ return true; } - bool DisableAutoSignInForAllLogins( + bool DisableAutoSignInForOrigins( + const base::Callback<bool(const GURL&)>& origin_filter, password_manager::PasswordStoreChangeList* changes) override { return true; }
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc index 3e11df7..03e31b51b 100644 --- a/chrome/browser/pdf/pdf_extension_test.cc +++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -39,6 +39,7 @@ #include "content/public/browser/download_manager.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" +#include "content/public/browser/notification_service.h" #include "content/public/browser/plugin_service.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" @@ -48,6 +49,7 @@ #include "extensions/browser/extension_registry.h" #include "extensions/common/manifest_handlers/mime_types_handler.h" #include "extensions/test/result_catcher.h" +#include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "ui/base/resource/resource_bundle.h" #include "url/gurl.h" @@ -585,3 +587,57 @@ << "Expected:\n" << expected_ax_tree << "\n\nActual:\n" << ax_tree_dump; } + +IN_PROC_BROWSER_TEST_F(PDFExtensionTest, LinkMiddleClick) { + host_resolver()->AddRule("www.example.com", "127.0.0.1"); + GURL test_pdf_url(embedded_test_server()->GetURL("/pdf/test-link.pdf")); + content::WebContents* guest_contents = LoadPdfGetGuestContents(test_pdf_url); + ASSERT_TRUE(guest_contents); + + // The link position of the test-link.pdf in page coordinates is (110, 110). + // Convert the link position from page coordinates to screen coordinates. + ASSERT_TRUE(content::ExecuteScript(guest_contents, + "var visiblePage = viewer.viewport.getMostVisiblePage();" + "var visiblePageDimensions =" + " viewer.viewport.getPageScreenRect(visiblePage);" + "var viewportPosition = viewer.viewport.position;" + "var screenOffsetX = visiblePageDimensions.x - viewportPosition.x;" + "var screenOffsetY = visiblePageDimensions.y - viewportPosition.y;" + "var linkScreenPositionX = Math.floor(110 + screenOffsetX);" + "var linkScreenPositionY = Math.floor(110 + screenOffsetY);")); + + int x; + ASSERT_TRUE(content::ExecuteScriptAndExtractInt( + guest_contents, + "window.domAutomationController.send(linkScreenPositionX);", + &x)); + + int y; + ASSERT_TRUE(content::ExecuteScriptAndExtractInt( + guest_contents, + "window.domAutomationController.send(linkScreenPositionY);", + &y)); + + gfx::Point point(x, y); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + content::WindowedNotificationObserver observer( + chrome::NOTIFICATION_TAB_ADDED, + content::NotificationService::AllSources()); + content::SimulateMouseClickAt(web_contents, 0, + blink::WebMouseEvent::ButtonMiddle, point); + observer.Wait(); + + int tab_count = browser()->tab_strip_model()->count(); + ASSERT_EQ(2, tab_count); + + // TODO(jaepark): Middle mouse clicking on a link should not change + // the focus of the tab. See http://crbug.com/628054. + content::WebContents* new_web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + ASSERT_NE(web_contents, new_web_contents); + + const GURL& url = new_web_contents->GetURL(); + ASSERT_EQ(std::string("http://www.example.com/"), url.spec()); +}
diff --git a/chrome/browser/permissions/permission_bubble_request_impl.cc b/chrome/browser/permissions/permission_bubble_request_impl.cc index 2001775..e2389b16 100644 --- a/chrome/browser/permissions/permission_bubble_request_impl.cc +++ b/chrome/browser/permissions/permission_bubble_request_impl.cc
@@ -29,7 +29,9 @@ PermissionBubbleRequestImpl::~PermissionBubbleRequestImpl() { DCHECK(is_finished_); if (!action_taken_) - PermissionUmaUtil::PermissionIgnored(permission_type_, request_origin_); + // TODO(stefanocs): Pass in a non null profile. + PermissionUmaUtil::PermissionIgnored(permission_type_, request_origin_, + nullptr); } gfx::VectorIconId PermissionBubbleRequestImpl::GetVectorIconId() const {
diff --git a/chrome/browser/permissions/permission_context_base.cc b/chrome/browser/permissions/permission_context_base.cc index 093f6b2..802cb50 100644 --- a/chrome/browser/permissions/permission_context_base.cc +++ b/chrome/browser/permissions/permission_context_base.cc
@@ -29,7 +29,7 @@ #include "chrome/browser/permissions/permission_queue_controller.h" #else #include "chrome/browser/permissions/permission_bubble_request_impl.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" +#include "chrome/browser/permissions/permission_request_manager.h" #endif // static @@ -153,8 +153,8 @@ #else PermissionBubbleRequest* cancelling = pending_bubbles_.get(id.ToString()); if (cancelling != NULL && web_contents != NULL && - PermissionBubbleManager::FromWebContents(web_contents) != NULL) { - PermissionBubbleManager::FromWebContents(web_contents) + PermissionRequestManager::FromWebContents(web_contents) != NULL) { + PermissionRequestManager::FromWebContents(web_contents) ->CancelRequest(cancelling); } #endif @@ -170,11 +170,11 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); #if !defined(OS_ANDROID) - PermissionBubbleManager* bubble_manager = - PermissionBubbleManager::FromWebContents(web_contents); - // TODO(felt): sometimes |bubble_manager| is null. This check is meant to - // prevent crashes. See crbug.com/457091. - if (!bubble_manager) + PermissionRequestManager* permission_request_manager = + PermissionRequestManager::FromWebContents(web_contents); + // TODO(felt): sometimes |permission_request_manager| is null. This check is + // meant to prevent crashes. See crbug.com/457091. + if (!permission_request_manager) return; std::unique_ptr<PermissionBubbleRequest> request_ptr( new PermissionBubbleRequestImpl( @@ -189,7 +189,7 @@ bool inserted = pending_bubbles_.add(id.ToString(), std::move(request_ptr)).second; DCHECK(inserted) << "Duplicate id " << id.ToString(); - bubble_manager->AddRequest(request); + permission_request_manager->AddRequest(request); #else GetQueueController()->CreateInfoBarRequest( id, requesting_origin, embedding_origin, @@ -216,12 +216,15 @@ DCHECK(content_setting == CONTENT_SETTING_ALLOW || content_setting == CONTENT_SETTING_BLOCK); if (content_setting == CONTENT_SETTING_ALLOW) - PermissionUmaUtil::PermissionGranted(permission_type_, requesting_origin); + PermissionUmaUtil::PermissionGranted(permission_type_, requesting_origin, + profile_); else - PermissionUmaUtil::PermissionDenied(permission_type_, requesting_origin); + PermissionUmaUtil::PermissionDenied(permission_type_, requesting_origin, + profile_); } else { DCHECK_EQ(content_setting, CONTENT_SETTING_DEFAULT); - PermissionUmaUtil::PermissionDismissed(permission_type_, requesting_origin); + PermissionUmaUtil::PermissionDismissed(permission_type_, requesting_origin, + profile_); } #endif
diff --git a/chrome/browser/permissions/permission_context_base_unittest.cc b/chrome/browser/permissions/permission_context_base_unittest.cc index 62d3bd88..13a1f34a 100644 --- a/chrome/browser/permissions/permission_context_base_unittest.cc +++ b/chrome/browser/permissions/permission_context_base_unittest.cc
@@ -17,7 +17,6 @@ #include "chrome/browser/permissions/permission_queue_controller.h" #include "chrome/browser/permissions/permission_request_id.h" #include "chrome/browser/permissions/permission_util.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" @@ -34,7 +33,7 @@ #if defined(OS_ANDROID) #include "chrome/browser/permissions/permission_queue_controller.h" #else -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" +#include "chrome/browser/permissions/permission_request_manager.h" #endif const char* kPermissionsKillSwitchFieldStudy = @@ -122,8 +121,8 @@ context->GetInfoBarController()->OnPermissionSet( id, url, url, update_content_setting, allowed); #else - PermissionBubbleManager* manager = - PermissionBubbleManager::FromWebContents(web_contents()); + PermissionRequestManager* manager = + PermissionRequestManager::FromWebContents(web_contents()); switch (response) { case CONTENT_SETTING_ALLOW: manager->Accept(); @@ -314,7 +313,7 @@ #if defined(OS_ANDROID) InfoBarService::CreateForWebContents(web_contents()); #else - PermissionBubbleManager::CreateForWebContents(web_contents()); + PermissionRequestManager::CreateForWebContents(web_contents()); #endif }
diff --git a/chrome/browser/permissions/permission_infobar_delegate.cc b/chrome/browser/permissions/permission_infobar_delegate.cc index 14a9f5d..32cea3dd 100644 --- a/chrome/browser/permissions/permission_infobar_delegate.cc +++ b/chrome/browser/permissions/permission_infobar_delegate.cc
@@ -12,7 +12,9 @@ PermissionInfobarDelegate::~PermissionInfobarDelegate() { if (!action_taken_) - PermissionUmaUtil::PermissionIgnored(permission_type_, requesting_origin_); + // TODO(stefanocs): Pass in a non null profile. + PermissionUmaUtil::PermissionIgnored(permission_type_, requesting_origin_, + nullptr); } PermissionInfobarDelegate::PermissionInfobarDelegate(
diff --git a/chrome/browser/permissions/permission_queue_controller.cc b/chrome/browser/permissions/permission_queue_controller.cc index 76e1a6d2..5f6bbfc0 100644 --- a/chrome/browser/permissions/permission_queue_controller.cc +++ b/chrome/browser/permissions/permission_queue_controller.cc
@@ -205,11 +205,14 @@ if (update_content_setting) { UpdateContentSetting(requesting_frame, embedder, allowed); if (allowed) - PermissionUmaUtil::PermissionGranted(permission_type_, requesting_frame); + PermissionUmaUtil::PermissionGranted(permission_type_, requesting_frame, + profile_); else - PermissionUmaUtil::PermissionDenied(permission_type_, requesting_frame); + PermissionUmaUtil::PermissionDenied(permission_type_, requesting_frame, + profile_); } else { - PermissionUmaUtil::PermissionDismissed(permission_type_, requesting_frame); + PermissionUmaUtil::PermissionDismissed(permission_type_, requesting_frame, + profile_); } // Cancel this request first, then notify listeners. TODO(pkasting): Why
diff --git a/chrome/browser/permissions/permission_request_manager.cc b/chrome/browser/permissions/permission_request_manager.cc new file mode 100644 index 0000000..5d500c3 --- /dev/null +++ b/chrome/browser/permissions/permission_request_manager.cc
@@ -0,0 +1,514 @@ +// 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. + +#include "chrome/browser/permissions/permission_request_manager.h" + +#include <algorithm> + +#include "base/command_line.h" +#include "base/metrics/user_metrics_action.h" +#include "build/build_config.h" +#include "chrome/browser/permissions/permission_uma_util.h" +#include "chrome/browser/ui/website_settings/permission_bubble_request.h" +#include "chrome/common/chrome_switches.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/navigation_details.h" +#include "content/public/browser/user_metrics.h" +#include "url/origin.h" + +#if !defined(OS_ANDROID) +#include "chrome/browser/ui/browser_finder.h" +#endif + +namespace { + +class CancelledRequest : public PermissionBubbleRequest { + public: + explicit CancelledRequest(PermissionBubbleRequest* cancelled) + : icon_(cancelled->GetIconId()), + message_fragment_(cancelled->GetMessageTextFragment()), + origin_(cancelled->GetOrigin()) {} + ~CancelledRequest() override {} + + int GetIconId() const override { return icon_; } + base::string16 GetMessageTextFragment() const override { + return message_fragment_; + } + GURL GetOrigin() const override { return origin_; } + + // These are all no-ops since the placeholder is non-forwarding. + void PermissionGranted() override {} + void PermissionDenied() override {} + void Cancelled() override {} + + void RequestFinished() override { delete this; } + + private: + int icon_; + base::string16 message_fragment_; + GURL origin_; +}; + +bool IsMessageTextEqual(PermissionBubbleRequest* a, + PermissionBubbleRequest* b) { + if (a == b) + return true; + if (a->GetMessageTextFragment() == b->GetMessageTextFragment() && + a->GetOrigin() == b->GetOrigin()) { + return true; + } + return false; +} + +} // namespace + +// PermissionRequestManager::Observer ------------------------------------------ + +PermissionRequestManager::Observer::~Observer() { +} + +void PermissionRequestManager::Observer::OnBubbleAdded() { +} + +// PermissionRequestManager ---------------------------------------------------- + +DEFINE_WEB_CONTENTS_USER_DATA_KEY(PermissionRequestManager); + +PermissionRequestManager::PermissionRequestManager( + content::WebContents* web_contents) + : content::WebContentsObserver(web_contents), +#if !defined(OS_ANDROID) // No bubbles in android tests. + view_factory_(base::Bind(&PermissionBubbleView::Create)), +#endif + view_(nullptr), + main_frame_has_fully_loaded_(false), + auto_response_for_test_(NONE), + weak_factory_(this) { +} + +PermissionRequestManager::~PermissionRequestManager() { + if (view_ != NULL) + view_->SetDelegate(NULL); + + for (PermissionBubbleRequest* request : requests_) + request->RequestFinished(); + for (PermissionBubbleRequest* request : queued_requests_) + request->RequestFinished(); + for (PermissionBubbleRequest* request : queued_frame_requests_) + request->RequestFinished(); + for (const auto& entry : duplicate_requests_) + entry.second->RequestFinished(); +} + +void PermissionRequestManager::AddRequest(PermissionBubbleRequest* request) { + content::RecordAction(base::UserMetricsAction("PermissionBubbleRequest")); + // TODO(gbillock): is there a race between an early request on a + // newly-navigated page and the to-be-cleaned-up requests on the previous + // page? We should maybe listen to DidStartNavigationToPendingEntry (and + // any other renderer-side nav initiations?). Double-check this for + // correct behavior on interstitials -- we probably want to basically queue + // any request for which GetVisibleURL != GetLastCommittedURL. + request_url_ = web_contents()->GetLastCommittedURL(); + bool is_main_frame = url::Origin(request_url_) + .IsSameOriginWith(url::Origin(request->GetOrigin())); + + // Don't re-add an existing request or one with a duplicate text request. + PermissionBubbleRequest* existing_request = GetExistingRequest(request); + if (existing_request) { + // |request| is a duplicate. Add it to |duplicate_requests_| unless it's the + // same object as |existing_request| or an existing duplicate. + if (request == existing_request) + return; + auto range = duplicate_requests_.equal_range(existing_request); + for (auto it = range.first; it != range.second; ++it) { + if (request == it->second) + return; + } + duplicate_requests_.insert(std::make_pair(existing_request, request)); + return; + } + + if (IsBubbleVisible()) { + if (is_main_frame) { + content::RecordAction( + base::UserMetricsAction("PermissionBubbleRequestQueued")); + queued_requests_.push_back(request); + } else { + content::RecordAction( + base::UserMetricsAction("PermissionBubbleIFrameRequestQueued")); + queued_frame_requests_.push_back(request); + } + return; + } + + if (is_main_frame) { + requests_.push_back(request); + accept_states_.push_back(true); + } else { + content::RecordAction( + base::UserMetricsAction("PermissionBubbleIFrameRequestQueued")); + queued_frame_requests_.push_back(request); + } + + ScheduleShowBubble(); +} + +void PermissionRequestManager::CancelRequest(PermissionBubbleRequest* request) { + // First look in the queued requests, where we can simply finish the request + // and go on. + std::vector<PermissionBubbleRequest*>::iterator requests_iter; + for (requests_iter = queued_requests_.begin(); + requests_iter != queued_requests_.end(); + requests_iter++) { + if (*requests_iter == request) { + RequestFinishedIncludingDuplicates(*requests_iter); + queued_requests_.erase(requests_iter); + return; + } + } + for (requests_iter = queued_frame_requests_.begin(); + requests_iter != queued_frame_requests_.end(); requests_iter++) { + if (*requests_iter == request) { + RequestFinishedIncludingDuplicates(*requests_iter); + queued_frame_requests_.erase(requests_iter); + return; + } + } + + std::vector<bool>::iterator accepts_iter = accept_states_.begin(); + for (requests_iter = requests_.begin(), accepts_iter = accept_states_.begin(); + requests_iter != requests_.end(); + requests_iter++, accepts_iter++) { + if (*requests_iter != request) + continue; + + // We can simply erase the current entry in the request table if we aren't + // showing the dialog, or if we are showing it and it can accept the update. + bool can_erase = !IsBubbleVisible() || view_->CanAcceptRequestUpdate(); + if (can_erase) { + RequestFinishedIncludingDuplicates(*requests_iter); + requests_.erase(requests_iter); + accept_states_.erase(accepts_iter); + + if (IsBubbleVisible()) { + view_->Hide(); + // Will redraw the bubble if it is being shown. + TriggerShowBubble(); + } + return; + } + + // Cancel the existing request and replace it with a dummy. + PermissionBubbleRequest* cancelled_request = + new CancelledRequest(*requests_iter); + RequestFinishedIncludingDuplicates(*requests_iter); + *requests_iter = cancelled_request; + return; + } + + // Since |request| wasn't found in queued_requests_, queued_frame_requests_ or + // requests_ it must have been marked as a duplicate. We can't search + // duplicate_requests_ by value, so instead use GetExistingRequest to find the + // key (request it was duped against), and iterate through duplicates of that. + PermissionBubbleRequest* existing_request = GetExistingRequest(request); + auto range = duplicate_requests_.equal_range(existing_request); + for (auto it = range.first; it != range.second; ++it) { + if (request == it->second) { + it->second->RequestFinished(); + duplicate_requests_.erase(it); + return; + } + } + + NOTREACHED(); // Callers should not cancel requests that are not pending. +} + +void PermissionRequestManager::HideBubble() { + // Disengage from the existing view if there is one. + if (!view_) + return; + + view_->SetDelegate(nullptr); + view_->Hide(); + view_.reset(); +} + +void PermissionRequestManager::DisplayPendingRequests() { + if (IsBubbleVisible()) + return; + +#if defined(OS_ANDROID) + NOTREACHED(); + return; +#else + view_ = view_factory_.Run(chrome::FindBrowserWithWebContents(web_contents())); + view_->SetDelegate(this); +#endif + + TriggerShowBubble(); +} + +void PermissionRequestManager::UpdateAnchorPosition() { + if (view_) + view_->UpdateAnchorPosition(); +} + +bool PermissionRequestManager::IsBubbleVisible() { + return view_ && view_->IsVisible(); +} + +gfx::NativeWindow PermissionRequestManager::GetBubbleWindow() { + if (view_) + return view_->GetNativeWindow(); + return nullptr; +} + +void PermissionRequestManager::DidNavigateMainFrame( + const content::LoadCommittedDetails& details, + const content::FrameNavigateParams& params) { + if (details.is_in_page) + return; + + CancelPendingQueues(); + FinalizeBubble(); + main_frame_has_fully_loaded_ = false; +} + +void PermissionRequestManager::DocumentOnLoadCompletedInMainFrame() { + main_frame_has_fully_loaded_ = true; + // This is scheduled because while all calls to the browser have been + // issued at DOMContentLoaded, they may be bouncing around in scheduled + // callbacks finding the UI thread still. This makes sure we allow those + // scheduled calls to AddRequest to complete before we show the page-load + // permissions bubble. + ScheduleShowBubble(); +} + +void PermissionRequestManager::DocumentLoadedInFrame( + content::RenderFrameHost* render_frame_host) { + ScheduleShowBubble(); +} + +void PermissionRequestManager::WebContentsDestroyed() { + // If the web contents has been destroyed, treat the bubble as cancelled. + CancelPendingQueues(); + FinalizeBubble(); + + // The WebContents is going away; be aggressively paranoid and delete + // ourselves lest other parts of the system attempt to add permission bubbles + // or use us otherwise during the destruction. + web_contents()->RemoveUserData(UserDataKey()); + // That was the equivalent of "delete this". This object is now destroyed; + // returning from this function is the only safe thing to do. +} + +void PermissionRequestManager::ToggleAccept(int request_index, bool new_value) { + DCHECK(request_index < static_cast<int>(accept_states_.size())); + accept_states_[request_index] = new_value; +} + +void PermissionRequestManager::Accept() { + PermissionUmaUtil::PermissionPromptAccepted(requests_, accept_states_); + + std::vector<PermissionBubbleRequest*>::iterator requests_iter; + std::vector<bool>::iterator accepts_iter = accept_states_.begin(); + for (requests_iter = requests_.begin(), accepts_iter = accept_states_.begin(); + requests_iter != requests_.end(); + requests_iter++, accepts_iter++) { + if (*accepts_iter) { + PermissionGrantedIncludingDuplicates(*requests_iter); + } else { + PermissionDeniedIncludingDuplicates(*requests_iter); + } + } + FinalizeBubble(); +} + +void PermissionRequestManager::Deny() { + PermissionUmaUtil::PermissionPromptDenied(requests_); + + std::vector<PermissionBubbleRequest*>::iterator requests_iter; + for (requests_iter = requests_.begin(); + requests_iter != requests_.end(); + requests_iter++) { + PermissionDeniedIncludingDuplicates(*requests_iter); + } + FinalizeBubble(); +} + +void PermissionRequestManager::Closing() { + std::vector<PermissionBubbleRequest*>::iterator requests_iter; + for (requests_iter = requests_.begin(); + requests_iter != requests_.end(); + requests_iter++) { + CancelledIncludingDuplicates(*requests_iter); + } + FinalizeBubble(); +} + +void PermissionRequestManager::ScheduleShowBubble() { + // ::ScheduleShowBubble() will be called again when the main frame will be + // loaded. + if (!main_frame_has_fully_loaded_) + return; + + content::BrowserThread::PostTask( + content::BrowserThread::UI, + FROM_HERE, + base::Bind(&PermissionRequestManager::TriggerShowBubble, + weak_factory_.GetWeakPtr())); +} + +void PermissionRequestManager::TriggerShowBubble() { + if (!view_) + return; + if (IsBubbleVisible()) + return; + if (!main_frame_has_fully_loaded_) + return; + if (requests_.empty() && queued_requests_.empty() && + queued_frame_requests_.empty()) { + return; + } + + if (requests_.empty()) { + if (queued_requests_.size()) + requests_.swap(queued_requests_); + else + requests_.swap(queued_frame_requests_); + + // Sets the default value for each request to be 'accept'. + accept_states_.resize(requests_.size(), true); + } + + view_->Show(requests_, accept_states_); + PermissionUmaUtil::PermissionPromptShown(requests_); + NotifyBubbleAdded(); + + // If in testing mode, automatically respond to the bubble that was shown. + if (auto_response_for_test_ != NONE) + DoAutoResponseForTesting(); +} + +void PermissionRequestManager::FinalizeBubble() { + if (view_) + view_->Hide(); + + std::vector<PermissionBubbleRequest*>::iterator requests_iter; + for (requests_iter = requests_.begin(); + requests_iter != requests_.end(); + requests_iter++) { + RequestFinishedIncludingDuplicates(*requests_iter); + } + requests_.clear(); + accept_states_.clear(); + if (queued_requests_.size() || queued_frame_requests_.size()) + TriggerShowBubble(); + else + request_url_ = GURL(); +} + +void PermissionRequestManager::CancelPendingQueues() { + std::vector<PermissionBubbleRequest*>::iterator requests_iter; + for (requests_iter = queued_requests_.begin(); + requests_iter != queued_requests_.end(); + requests_iter++) { + RequestFinishedIncludingDuplicates(*requests_iter); + } + for (requests_iter = queued_frame_requests_.begin(); + requests_iter != queued_frame_requests_.end(); + requests_iter++) { + RequestFinishedIncludingDuplicates(*requests_iter); + } + queued_requests_.clear(); + queued_frame_requests_.clear(); +} + +PermissionBubbleRequest* PermissionRequestManager::GetExistingRequest( + PermissionBubbleRequest* request) { + for (PermissionBubbleRequest* existing_request : requests_) + if (IsMessageTextEqual(existing_request, request)) + return existing_request; + for (PermissionBubbleRequest* existing_request : queued_requests_) + if (IsMessageTextEqual(existing_request, request)) + return existing_request; + for (PermissionBubbleRequest* existing_request : queued_frame_requests_) + if (IsMessageTextEqual(existing_request, request)) + return existing_request; + return nullptr; +} + +void PermissionRequestManager::PermissionGrantedIncludingDuplicates( + PermissionBubbleRequest* request) { + DCHECK_EQ(request, GetExistingRequest(request)) + << "Only requests in [queued_[frame_]]requests_ can have duplicates"; + request->PermissionGranted(); + auto range = duplicate_requests_.equal_range(request); + for (auto it = range.first; it != range.second; ++it) + it->second->PermissionGranted(); +} +void PermissionRequestManager::PermissionDeniedIncludingDuplicates( + PermissionBubbleRequest* request) { + DCHECK_EQ(request, GetExistingRequest(request)) + << "Only requests in [queued_[frame_]]requests_ can have duplicates"; + request->PermissionDenied(); + auto range = duplicate_requests_.equal_range(request); + for (auto it = range.first; it != range.second; ++it) + it->second->PermissionDenied(); +} +void PermissionRequestManager::CancelledIncludingDuplicates( + PermissionBubbleRequest* request) { + DCHECK_EQ(request, GetExistingRequest(request)) + << "Only requests in [queued_[frame_]]requests_ can have duplicates"; + request->Cancelled(); + auto range = duplicate_requests_.equal_range(request); + for (auto it = range.first; it != range.second; ++it) + it->second->Cancelled(); +} +void PermissionRequestManager::RequestFinishedIncludingDuplicates( + PermissionBubbleRequest* request) { + // We can't call GetExistingRequest here, because other entries in requests_, + // queued_requests_ or queued_frame_requests_ might already have been deleted. + DCHECK_EQ(1, std::count(requests_.begin(), requests_.end(), request) + + std::count(queued_requests_.begin(), queued_requests_.end(), + request) + + std::count(queued_frame_requests_.begin(), + queued_frame_requests_.end(), request)) + << "Only requests in [queued_[frame_]]requests_ can have duplicates"; + request->RequestFinished(); + // Beyond this point, |request| has probably been deleted. + auto range = duplicate_requests_.equal_range(request); + for (auto it = range.first; it != range.second; ++it) + it->second->RequestFinished(); + // Additionally, we can now remove the duplicates. + duplicate_requests_.erase(request); +} + +void PermissionRequestManager::AddObserver(Observer* observer) { + observer_list_.AddObserver(observer); +} + +void PermissionRequestManager::RemoveObserver(Observer* observer) { + observer_list_.RemoveObserver(observer); +} + +void PermissionRequestManager::NotifyBubbleAdded() { + FOR_EACH_OBSERVER(Observer, observer_list_, OnBubbleAdded()); +} + +void PermissionRequestManager::DoAutoResponseForTesting() { + switch (auto_response_for_test_) { + case ACCEPT_ALL: + Accept(); + break; + case DENY_ALL: + Deny(); + break; + case DISMISS: + Closing(); + break; + case NONE: + NOTREACHED(); + } +}
diff --git a/chrome/browser/permissions/permission_request_manager.h b/chrome/browser/permissions/permission_request_manager.h new file mode 100644 index 0000000..78b626c --- /dev/null +++ b/chrome/browser/permissions/permission_request_manager.h
@@ -0,0 +1,194 @@ +// 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 CHROME_BROWSER_PERMISSIONS_PERMISSION_REQUEST_MANAGER_H_ +#define CHROME_BROWSER_PERMISSIONS_PERMISSION_REQUEST_MANAGER_H_ + +#include <unordered_map> +#include <vector> + +#include "base/gtest_prod_util.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "chrome/browser/ui/website_settings/permission_bubble_view.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" + +class PermissionBubbleRequest; + +// Provides access to permissions bubbles. Allows clients to add a request +// callback interface to the existing permission bubble configuration. +// Depending on the situation and policy, that may add new UI to an existing +// permission bubble, create and show a new permission bubble, or provide no +// visible UI action at all. (In that case, the request will be immediately +// informed that the permission request failed.) +// +// A PermissionRequestManager is associated with a particular WebContents. +// Requests attached to a particular WebContents' PBM must outlive it. +// +// The PermissionRequestManager should be addressed on the UI thread. +class PermissionRequestManager + : public content::WebContentsObserver, + public content::WebContentsUserData<PermissionRequestManager>, + public PermissionBubbleView::Delegate { + public: + class Observer { + public: + virtual ~Observer(); + virtual void OnBubbleAdded(); + }; + + enum AutoResponseType { + NONE, + ACCEPT_ALL, + DENY_ALL, + DISMISS + }; + + ~PermissionRequestManager() override; + + // Adds a new request to the permission bubble. Ownership of the request + // remains with the caller. The caller must arrange for the request to + // outlive the PermissionRequestManager. If a bubble is visible when this + // call is made, the request will be queued up and shown after the current + // bubble closes. A request with message text identical to an outstanding + // request will be merged with the outstanding request, and will have the same + // callbacks called as the outstanding request. + void AddRequest(PermissionBubbleRequest* request); + + // Cancels an outstanding request. This may have different effects depending + // on what is going on with the bubble. If the request is pending, it will be + // removed and never shown. If the request is showing, it will continue to be + // shown, but the user's action won't be reported back to the request object. + // In some circumstances, we can remove the request from the bubble, and may + // do so. The request will have RequestFinished executed on it if it is found, + // at which time the caller is free to delete the request. + void CancelRequest(PermissionBubbleRequest* request); + + // Hides the bubble. + void HideBubble(); + + // Will show a permission bubble if there is a pending permission request on + // the web contents that the PermissionRequestManager belongs to. + void DisplayPendingRequests(); + + // Will reposition the bubble (may change parent if necessary). + void UpdateAnchorPosition(); + + // True if a permission bubble is currently visible. + // TODO(hcarmona): Remove this as part of the bubble API work. + bool IsBubbleVisible(); + + // Get the native window of the bubble. + // TODO(hcarmona): Remove this as part of the bubble API work. + gfx::NativeWindow GetBubbleWindow(); + + // For observing the status of the permission bubble manager. + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + // Do NOT use this methods in production code. Use this methods in browser + // tests that need to accept or deny permissions when requested in + // JavaScript. Your test needs to set this appropriately, and then the bubble + // will proceed as desired as soon as Show() is called. + void set_auto_response_for_test(AutoResponseType response) { + auto_response_for_test_ = response; + } + + private: + // TODO(felt): Update testing so that it doesn't involve a lot of friends. + friend class GeolocationBrowserTest; + friend class GeolocationPermissionContextTests; + friend class MockPermissionBubbleFactory; + friend class MockPermissionBubbleView; + friend class PermissionRequestManagerTest; + friend class PermissionContextBaseTests; + friend class content::WebContentsUserData<PermissionRequestManager>; + FRIEND_TEST_ALL_PREFIXES(DownloadTest, TestMultipleDownloadsBubble); + + explicit PermissionRequestManager(content::WebContents* web_contents); + + // WebContentsObserver: + void DidNavigateMainFrame( + const content::LoadCommittedDetails& details, + const content::FrameNavigateParams& params) override; + void DocumentOnLoadCompletedInMainFrame() override; + void DocumentLoadedInFrame( + content::RenderFrameHost* render_frame_host) override; + void WebContentsDestroyed() override; + + // PermissionBubbleView::Delegate: + void ToggleAccept(int request_index, bool new_value) override; + void Accept() override; + void Deny() override; + void Closing() override; + + // Posts a task which will allow the bubble to become visible if it is needed. + void ScheduleShowBubble(); + + // Shows the bubble if it is not already visible and there are pending + // requests. + void TriggerShowBubble(); + + // Finalize the pending permissions request. + void FinalizeBubble(); + + // Cancel any pending requests. This is called if the WebContents + // on which permissions calls are pending is destroyed or navigated away + // from the requesting page. + void CancelPendingQueues(); + + // Searches |requests_|, |queued_requests_| and |queued_frame_requests_| - but + // *not* |duplicate_requests_| - for a request matching |request|, and returns + // the matching request, or |nullptr| if no match. Note that the matching + // request may or may not be the same object as |request|. + PermissionBubbleRequest* GetExistingRequest(PermissionBubbleRequest* request); + + // Returns true if |queue| contains a request which was generated by a user + // gesture. Returns false otherwise. + bool HasUserGestureRequest( + const std::vector<PermissionBubbleRequest*>& queue); + + // Calls PermissionGranted on a request and all its duplicates. + void PermissionGrantedIncludingDuplicates(PermissionBubbleRequest* request); + // Calls PermissionDenied on a request and all its duplicates. + void PermissionDeniedIncludingDuplicates(PermissionBubbleRequest* request); + // Calls Cancelled on a request and all its duplicates. + void CancelledIncludingDuplicates(PermissionBubbleRequest* request); + // Calls RequestFinished on a request and all its duplicates. + void RequestFinishedIncludingDuplicates(PermissionBubbleRequest* request); + + void NotifyBubbleAdded(); + + void DoAutoResponseForTesting(); + + // Factory to be used to create views when needed. + PermissionBubbleView::Factory view_factory_; + + // The UI surface to be used to display the permissions requests. + std::unique_ptr<PermissionBubbleView> view_; + + std::vector<PermissionBubbleRequest*> requests_; + std::vector<PermissionBubbleRequest*> queued_requests_; + std::vector<PermissionBubbleRequest*> queued_frame_requests_; + // Maps from the first request of a kind to subsequent requests that were + // duped against it. + std::unordered_multimap<PermissionBubbleRequest*, PermissionBubbleRequest*> + duplicate_requests_; + + // URL of the main frame in the WebContents to which this manager is attached. + // TODO(gbillock): if there are iframes in the page, we need to deal with it. + GURL request_url_; + bool main_frame_has_fully_loaded_; + + // Whether each of the requests in |requests_| is accepted by the user. + std::vector<bool> accept_states_; + + base::ObserverList<Observer> observer_list_; + AutoResponseType auto_response_for_test_; + + base::WeakPtrFactory<PermissionRequestManager> weak_factory_; +}; + +#endif // CHROME_BROWSER_PERMISSIONS_PERMISSION_REQUEST_MANAGER_H_
diff --git a/chrome/browser/permissions/permission_request_manager_browsertest.cc b/chrome/browser/permissions/permission_request_manager_browsertest.cc new file mode 100644 index 0000000..694a11e --- /dev/null +++ b/chrome/browser/permissions/permission_request_manager_browsertest.cc
@@ -0,0 +1,251 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/permissions/permission_request_manager.h" + +#include "base/command_line.h" +#include "base/metrics/field_trial.h" +#include "build/build_config.h" +#include "chrome/browser/permissions/permission_context_base.h" +#include "chrome/browser/permissions/permission_util.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/website_settings/mock_permission_bubble_factory.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "components/variations/variations_associated_data.h" +#include "content/public/browser/permission_type.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/test_utils.h" +#include "net/test/embedded_test_server/embedded_test_server.h" + +namespace { + +const char* kPermissionsKillSwitchFieldStudy = + PermissionContextBase::kPermissionsKillSwitchFieldStudy; +const char* kPermissionsKillSwitchBlockedValue = + PermissionContextBase::kPermissionsKillSwitchBlockedValue; +const char kPermissionsKillSwitchTestGroup[] = "TestGroup"; + +class PermissionRequestManagerBrowserTest : public InProcessBrowserTest { + public: + PermissionRequestManagerBrowserTest() = default; + ~PermissionRequestManagerBrowserTest() override = default; + + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + PermissionRequestManager* manager = GetPermissionRequestManager(); + mock_permission_bubble_factory_.reset( + new MockPermissionBubbleFactory(manager)); + manager->DisplayPendingRequests(); + } + + void TearDownOnMainThread() override { + mock_permission_bubble_factory_.reset(); + InProcessBrowserTest::TearDownOnMainThread(); + } + + PermissionRequestManager* GetPermissionRequestManager() { + return PermissionRequestManager::FromWebContents( + browser()->tab_strip_model()->GetActiveWebContents()); + } + + MockPermissionBubbleFactory* bubble_factory() { + return mock_permission_bubble_factory_.get(); + } + + void EnableKillSwitch(content::PermissionType permission_type) { + std::map<std::string, std::string> params; + params[PermissionUtil::GetPermissionString(permission_type)] = + kPermissionsKillSwitchBlockedValue; + variations::AssociateVariationParams( + kPermissionsKillSwitchFieldStudy, kPermissionsKillSwitchTestGroup, + params); + base::FieldTrialList::CreateFieldTrial(kPermissionsKillSwitchFieldStudy, + kPermissionsKillSwitchTestGroup); + } + + private: + std::unique_ptr<MockPermissionBubbleFactory> mock_permission_bubble_factory_; +}; + +// Requests before the load event should be bundled into one bubble. +// http://crbug.com/512849 flaky +IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, + DISABLED_RequestsBeforeLoad) { + ASSERT_TRUE(embedded_test_server()->Start()); + + ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( + browser(), + embedded_test_server()->GetURL("/permissions/requests-before-load.html"), + 1); + bubble_factory()->WaitForPermissionBubble(); + + EXPECT_EQ(1, bubble_factory()->show_count()); + EXPECT_EQ(2, bubble_factory()->total_request_count()); +} + +// Requests before the load should not be bundled with a request after the load. +IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, + RequestsBeforeAfterLoad) { + ASSERT_TRUE(embedded_test_server()->Start()); + + ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( + browser(), + embedded_test_server()->GetURL( + "/permissions/requests-before-after-load.html"), + 1); + bubble_factory()->WaitForPermissionBubble(); + + EXPECT_EQ(1, bubble_factory()->show_count()); + EXPECT_EQ(1, bubble_factory()->total_request_count()); +} + +// Navigating twice to the same URL should be equivalent to refresh. This means +// showing the bubbles twice. +// http://crbug.com/512849 flaky +#if defined(OS_WIN) +#define MAYBE_NavTwice DISABLED_NavTwice +#else +#define MAYBE_NavTwice NavTwice +#endif +IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, MAYBE_NavTwice) { + ASSERT_TRUE(embedded_test_server()->Start()); + + ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( + browser(), + embedded_test_server()->GetURL("/permissions/requests-before-load.html"), + 1); + bubble_factory()->WaitForPermissionBubble(); + + ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( + browser(), + embedded_test_server()->GetURL("/permissions/requests-before-load.html"), + 1); + bubble_factory()->WaitForPermissionBubble(); + + EXPECT_EQ(2, bubble_factory()->show_count()); + EXPECT_EQ(4, bubble_factory()->total_request_count()); +} + +// Navigating twice to the same URL with a hash should be navigation within the +// page. This means the bubble is only shown once. +// http://crbug.com/512849 flaky +#if defined(OS_WIN) +#define MAYBE_NavTwiceWithHash DISABLED_NavTwiceWithHash +#else +#define MAYBE_NavTwiceWithHash NavTwiceWithHash +#endif +IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, + MAYBE_NavTwiceWithHash) { + ASSERT_TRUE(embedded_test_server()->Start()); + + ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( + browser(), + embedded_test_server()->GetURL("/permissions/requests-before-load.html"), + 1); + bubble_factory()->WaitForPermissionBubble(); + + ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( + browser(), + embedded_test_server()->GetURL( + "/permissions/requests-before-load.html#0"), + 1); + bubble_factory()->WaitForPermissionBubble(); + + EXPECT_EQ(1, bubble_factory()->show_count()); + EXPECT_EQ(2, bubble_factory()->total_request_count()); +} + +// Bubble requests should be shown after in-page navigation. +IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, InPageNavigation) { + ASSERT_TRUE(embedded_test_server()->Start()); + + ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( + browser(), + embedded_test_server()->GetURL("/empty.html"), + 1); + + ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( + browser(), + embedded_test_server()->GetURL("/empty.html#0"), + 1); + + // Request 'geolocation' permission. + ExecuteScriptAndGetValue( + browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(), + "navigator.geolocation.getCurrentPosition(function(){});"); + bubble_factory()->WaitForPermissionBubble(); + + EXPECT_EQ(1, bubble_factory()->show_count()); + EXPECT_EQ(1, bubble_factory()->total_request_count()); +} + +// Bubble requests should not be shown when the killswitch is on. +IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, + KillSwitchGeolocation) { + ASSERT_TRUE(embedded_test_server()->Start()); + + ui_test_utils::NavigateToURL( + browser(), + embedded_test_server()->GetURL("/permissions/killswitch_tester.html")); + + // Now enable the geolocation killswitch. + EnableKillSwitch(content::PermissionType::GEOLOCATION); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + std::string result; + EXPECT_TRUE(content::ExecuteScriptAndExtractString( + web_contents, "requestGeolocation();", &result)); + EXPECT_EQ("denied", result); + EXPECT_EQ(0, bubble_factory()->show_count()); + EXPECT_EQ(0, bubble_factory()->total_request_count()); + + // Disable the trial. + variations::testing::ClearAllVariationParams(); + + // Reload the page to get around blink layer caching for geolocation + // requests. + ui_test_utils::NavigateToURL( + browser(), + embedded_test_server()->GetURL("/permissions/killswitch_tester.html")); + + EXPECT_TRUE(content::ExecuteScript(web_contents, "requestGeolocation();")); + bubble_factory()->WaitForPermissionBubble(); + EXPECT_EQ(1, bubble_factory()->show_count()); + EXPECT_EQ(1, bubble_factory()->total_request_count()); +} + +// Bubble requests should not be shown when the killswitch is on. +IN_PROC_BROWSER_TEST_F(PermissionRequestManagerBrowserTest, + KillSwitchNotifications) { + ASSERT_TRUE(embedded_test_server()->Start()); + + ui_test_utils::NavigateToURL( + browser(), + embedded_test_server()->GetURL("/permissions/killswitch_tester.html")); + + // Now enable the notifications killswitch. + EnableKillSwitch(content::PermissionType::NOTIFICATIONS); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + std::string result; + EXPECT_TRUE(content::ExecuteScriptAndExtractString( + web_contents, "requestNotification();", &result)); + EXPECT_EQ("denied", result); + EXPECT_EQ(0, bubble_factory()->show_count()); + EXPECT_EQ(0, bubble_factory()->total_request_count()); + + // Disable the trial. + variations::testing::ClearAllVariationParams(); + + EXPECT_TRUE(content::ExecuteScript(web_contents, "requestNotification();")); + bubble_factory()->WaitForPermissionBubble(); + EXPECT_EQ(1, bubble_factory()->show_count()); + EXPECT_EQ(1, bubble_factory()->total_request_count()); +} + +} // anonymous namespace
diff --git a/chrome/browser/permissions/permission_request_manager_unittest.cc b/chrome/browser/permissions/permission_request_manager_unittest.cc new file mode 100644 index 0000000..66d056e --- /dev/null +++ b/chrome/browser/permissions/permission_request_manager_unittest.cc
@@ -0,0 +1,606 @@ +// 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. + +#include <stddef.h> + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/histogram_tester.h" +#include "chrome/browser/permissions/permission_request_manager.h" +#include "chrome/browser/permissions/permission_uma_util.h" +#include "chrome/browser/ui/website_settings/mock_permission_bubble_factory.h" +#include "chrome/browser/ui/website_settings/mock_permission_bubble_request.h" +#include "chrome/browser/ui/website_settings/permission_bubble_request.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "testing/gtest/include/gtest/gtest.h" + +class PermissionRequestManagerTest : public ChromeRenderViewHostTestHarness { + public: + PermissionRequestManagerTest() + : ChromeRenderViewHostTestHarness(), + request1_("test1", PermissionBubbleType::QUOTA), + request2_("test2", PermissionBubbleType::DOWNLOAD), + iframe_request_same_domain_("iframe", + GURL("http://www.google.com/some/url")), + iframe_request_other_domain_("iframe", + GURL("http://www.youtube.com")) {} + ~PermissionRequestManagerTest() override {} + + void SetUp() override { + ChromeRenderViewHostTestHarness::SetUp(); + SetContents(CreateTestWebContents()); + NavigateAndCommit(GURL("http://www.google.com")); + + manager_.reset(new PermissionRequestManager(web_contents())); + view_factory_.reset(new MockPermissionBubbleFactory(manager_.get())); + } + + void TearDown() override { + view_factory_.reset(); + manager_.reset(); + ChromeRenderViewHostTestHarness::TearDown(); + } + + void ToggleAccept(int index, bool value) { + manager_->ToggleAccept(index, value); + } + + void Accept() { + manager_->Accept(); + } + + void Deny() { + manager_->Deny(); + } + + void Closing() { + manager_->Closing(); + } + + void WaitForFrameLoad() { + // PermissionRequestManager ignores all parameters. Yay? + manager_->DocumentLoadedInFrame(NULL); + base::RunLoop().RunUntilIdle(); + } + + void WaitForCoalescing() { + manager_->DocumentOnLoadCompletedInMainFrame(); + base::RunLoop().RunUntilIdle(); + } + + void MockTabSwitchAway() { manager_->HideBubble(); } + + void MockTabSwitchBack() { manager_->DisplayPendingRequests(); } + + virtual void NavigationEntryCommitted( + const content::LoadCommittedDetails& details) { + manager_->NavigationEntryCommitted(details); + } + + protected: + MockPermissionBubbleRequest request1_; + MockPermissionBubbleRequest request2_; + MockPermissionBubbleRequest iframe_request_same_domain_; + MockPermissionBubbleRequest iframe_request_other_domain_; + std::unique_ptr<PermissionRequestManager> manager_; + std::unique_ptr<MockPermissionBubbleFactory> view_factory_; +}; + +TEST_F(PermissionRequestManagerTest, SingleRequest) { + manager_->AddRequest(&request1_); + manager_->DisplayPendingRequests(); + WaitForCoalescing(); + + EXPECT_TRUE(view_factory_->is_visible()); + ASSERT_EQ(view_factory_->request_count(), 1); + + ToggleAccept(0, true); + Accept(); + EXPECT_TRUE(request1_.granted()); +} + +TEST_F(PermissionRequestManagerTest, SingleRequestViewFirst) { + manager_->DisplayPendingRequests(); + manager_->AddRequest(&request1_); + WaitForCoalescing(); + + EXPECT_TRUE(view_factory_->is_visible()); + ASSERT_EQ(view_factory_->request_count(), 1); + + ToggleAccept(0, true); + Accept(); + EXPECT_TRUE(request1_.granted()); +} + +TEST_F(PermissionRequestManagerTest, TwoRequests) { + manager_->AddRequest(&request1_); + manager_->AddRequest(&request2_); + manager_->DisplayPendingRequests(); + WaitForCoalescing(); + + EXPECT_TRUE(view_factory_->is_visible()); + ASSERT_EQ(view_factory_->request_count(), 2); + + ToggleAccept(0, true); + ToggleAccept(1, false); + Accept(); + EXPECT_TRUE(request1_.granted()); + EXPECT_FALSE(request2_.granted()); +} + +TEST_F(PermissionRequestManagerTest, TwoRequestsTabSwitch) { + manager_->AddRequest(&request1_); + manager_->AddRequest(&request2_); + manager_->DisplayPendingRequests(); + WaitForCoalescing(); + + EXPECT_TRUE(view_factory_->is_visible()); + ASSERT_EQ(view_factory_->request_count(), 2); + + ToggleAccept(0, true); + ToggleAccept(1, false); + + MockTabSwitchAway(); + EXPECT_FALSE(view_factory_->is_visible()); + + MockTabSwitchBack(); + WaitForCoalescing(); + EXPECT_TRUE(view_factory_->is_visible()); + ASSERT_EQ(view_factory_->request_count(), 2); + + Accept(); + EXPECT_TRUE(request1_.granted()); + EXPECT_FALSE(request2_.granted()); +} + +TEST_F(PermissionRequestManagerTest, NoRequests) { + manager_->DisplayPendingRequests(); + WaitForCoalescing(); + EXPECT_FALSE(view_factory_->is_visible()); +} + +TEST_F(PermissionRequestManagerTest, NoView) { + manager_->AddRequest(&request1_); + // Don't display the pending requests. + WaitForCoalescing(); + EXPECT_FALSE(view_factory_->is_visible()); +} + +TEST_F(PermissionRequestManagerTest, TwoRequestsCoalesce) { + manager_->DisplayPendingRequests(); + manager_->AddRequest(&request1_); + manager_->AddRequest(&request2_); + EXPECT_FALSE(view_factory_->is_visible()); + WaitForCoalescing(); + + EXPECT_TRUE(view_factory_->is_visible()); + ASSERT_EQ(view_factory_->request_count(), 2); +} + +TEST_F(PermissionRequestManagerTest, TwoRequestsDoNotCoalesce) { + manager_->DisplayPendingRequests(); + manager_->AddRequest(&request1_); + WaitForCoalescing(); + manager_->AddRequest(&request2_); + + EXPECT_TRUE(view_factory_->is_visible()); + ASSERT_EQ(view_factory_->request_count(), 1); +} + +TEST_F(PermissionRequestManagerTest, TwoRequestsShownInTwoBubbles) { + manager_->DisplayPendingRequests(); + manager_->AddRequest(&request1_); + WaitForCoalescing(); + manager_->AddRequest(&request2_); + + EXPECT_TRUE(view_factory_->is_visible()); + ASSERT_EQ(view_factory_->request_count(), 1); + + Accept(); + WaitForCoalescing(); + + EXPECT_TRUE(view_factory_->is_visible()); + ASSERT_EQ(view_factory_->request_count(), 1); + ASSERT_EQ(view_factory_->show_count(), 2); +} + +TEST_F(PermissionRequestManagerTest, TestAddDuplicateRequest) { + manager_->DisplayPendingRequests(); + manager_->AddRequest(&request1_); + manager_->AddRequest(&request2_); + manager_->AddRequest(&request1_); + + WaitForCoalescing(); + EXPECT_TRUE(view_factory_->is_visible()); + ASSERT_EQ(view_factory_->request_count(), 2); +} + +TEST_F(PermissionRequestManagerTest, SequentialRequests) { + manager_->DisplayPendingRequests(); + manager_->AddRequest(&request1_); + WaitForCoalescing(); + EXPECT_TRUE(view_factory_->is_visible()); + + Accept(); + EXPECT_TRUE(request1_.granted()); + + EXPECT_FALSE(view_factory_->is_visible()); + + manager_->AddRequest(&request2_); + WaitForCoalescing(); + EXPECT_TRUE(view_factory_->is_visible()); + Accept(); + EXPECT_FALSE(view_factory_->is_visible()); + EXPECT_TRUE(request2_.granted()); +} + +TEST_F(PermissionRequestManagerTest, SameRequestRejected) { + manager_->DisplayPendingRequests(); + manager_->AddRequest(&request1_); + manager_->AddRequest(&request1_); + EXPECT_FALSE(request1_.finished()); + + WaitForCoalescing(); + EXPECT_TRUE(view_factory_->is_visible()); + ASSERT_EQ(view_factory_->request_count(), 1); +} + +TEST_F(PermissionRequestManagerTest, DuplicateRequestCancelled) { + manager_->DisplayPendingRequests(); + manager_->AddRequest(&request1_); + MockPermissionBubbleRequest dupe_request("test1"); + manager_->AddRequest(&dupe_request); + EXPECT_FALSE(dupe_request.finished()); + EXPECT_FALSE(request1_.finished()); + manager_->CancelRequest(&request1_); + EXPECT_TRUE(dupe_request.finished()); + EXPECT_TRUE(request1_.finished()); +} + +TEST_F(PermissionRequestManagerTest, DuplicateQueuedRequest) { + manager_->DisplayPendingRequests(); + manager_->AddRequest(&request1_); + WaitForCoalescing(); + manager_->AddRequest(&request2_); + + MockPermissionBubbleRequest dupe_request("test1"); + manager_->AddRequest(&dupe_request); + EXPECT_FALSE(dupe_request.finished()); + EXPECT_FALSE(request1_.finished()); + + MockPermissionBubbleRequest dupe_request2("test2"); + manager_->AddRequest(&dupe_request2); + EXPECT_FALSE(dupe_request2.finished()); + EXPECT_FALSE(request2_.finished()); + + manager_->CancelRequest(&request1_); + EXPECT_TRUE(dupe_request.finished()); + EXPECT_TRUE(request1_.finished()); + + manager_->CancelRequest(&request2_); + EXPECT_TRUE(dupe_request2.finished()); + EXPECT_TRUE(request2_.finished()); +} + +TEST_F(PermissionRequestManagerTest, ForgetRequestsOnPageNavigation) { + manager_->DisplayPendingRequests(); + manager_->AddRequest(&request1_); + WaitForCoalescing(); + manager_->AddRequest(&request2_); + manager_->AddRequest(&iframe_request_other_domain_); + + EXPECT_TRUE(view_factory_->is_visible()); + ASSERT_EQ(view_factory_->request_count(), 1); + + NavigateAndCommit(GURL("http://www2.google.com/")); + WaitForCoalescing(); + + EXPECT_FALSE(view_factory_->is_visible()); + EXPECT_TRUE(request1_.finished()); + EXPECT_TRUE(request2_.finished()); + EXPECT_TRUE(iframe_request_other_domain_.finished()); +} + +TEST_F(PermissionRequestManagerTest, TestCancelQueued) { + manager_->AddRequest(&request1_); + EXPECT_FALSE(view_factory_->is_visible()); + + manager_->CancelRequest(&request1_); + EXPECT_TRUE(request1_.finished()); + EXPECT_FALSE(view_factory_->is_visible()); + manager_->DisplayPendingRequests(); + EXPECT_FALSE(view_factory_->is_visible()); + + manager_->AddRequest(&request2_); + WaitForCoalescing(); + EXPECT_TRUE(view_factory_->is_visible()); + ASSERT_EQ(view_factory_->request_count(), 1); +} + +TEST_F(PermissionRequestManagerTest, TestCancelWhileDialogShown) { + manager_->DisplayPendingRequests(); + manager_->AddRequest(&request1_); + WaitForCoalescing(); + + view_factory_->SetCanUpdateUi(true); + EXPECT_TRUE(view_factory_->is_visible()); + EXPECT_FALSE(request1_.finished()); + manager_->CancelRequest(&request1_); + WaitForCoalescing(); + EXPECT_TRUE(request1_.finished()); + EXPECT_FALSE(view_factory_->is_visible()); +} + +TEST_F(PermissionRequestManagerTest, TestCancelWhileDialogShownNoUpdate) { + manager_->DisplayPendingRequests(); + view_factory_->SetCanUpdateUi(false); + manager_->AddRequest(&request1_); + WaitForCoalescing(); + view_factory_->SetCanUpdateUi(false); + + EXPECT_TRUE(view_factory_->is_visible()); + EXPECT_FALSE(request1_.finished()); + manager_->CancelRequest(&request1_); + EXPECT_TRUE(request1_.finished()); + EXPECT_TRUE(view_factory_->is_visible()); + Closing(); +} + +TEST_F(PermissionRequestManagerTest, TestCancelPendingRequest) { + manager_->DisplayPendingRequests(); + manager_->AddRequest(&request1_); + WaitForCoalescing(); + manager_->AddRequest(&request2_); + + EXPECT_TRUE(view_factory_->is_visible()); + ASSERT_EQ(view_factory_->request_count(), 1); + manager_->CancelRequest(&request2_); + + EXPECT_TRUE(view_factory_->is_visible()); + EXPECT_FALSE(request1_.finished()); + EXPECT_TRUE(request2_.finished()); +} + +TEST_F(PermissionRequestManagerTest, MainFrameNoRequestIFrameRequest) { + manager_->DisplayPendingRequests(); + manager_->AddRequest(&iframe_request_same_domain_); + WaitForCoalescing(); + WaitForFrameLoad(); + + EXPECT_TRUE(view_factory_->is_visible()); + Closing(); + EXPECT_TRUE(iframe_request_same_domain_.finished()); +} + +TEST_F(PermissionRequestManagerTest, MainFrameAndIFrameRequestSameDomain) { + manager_->DisplayPendingRequests(); + manager_->AddRequest(&request1_); + manager_->AddRequest(&iframe_request_same_domain_); + WaitForFrameLoad(); + WaitForCoalescing(); + + EXPECT_TRUE(view_factory_->is_visible()); + ASSERT_EQ(view_factory_->request_count(), 2); + Closing(); + EXPECT_TRUE(request1_.finished()); + EXPECT_TRUE(iframe_request_same_domain_.finished()); + EXPECT_FALSE(view_factory_->is_visible()); +} + +TEST_F(PermissionRequestManagerTest, MainFrameAndIFrameRequestOtherDomain) { + manager_->DisplayPendingRequests(); + manager_->AddRequest(&request1_); + manager_->AddRequest(&iframe_request_other_domain_); + WaitForFrameLoad(); + WaitForCoalescing(); + + EXPECT_TRUE(view_factory_->is_visible()); + Closing(); + EXPECT_TRUE(request1_.finished()); + EXPECT_FALSE(iframe_request_other_domain_.finished()); + EXPECT_TRUE(view_factory_->is_visible()); + Closing(); + EXPECT_TRUE(iframe_request_other_domain_.finished()); +} + +TEST_F(PermissionRequestManagerTest, IFrameRequestWhenMainRequestVisible) { + manager_->DisplayPendingRequests(); + manager_->AddRequest(&request1_); + WaitForCoalescing(); + EXPECT_TRUE(view_factory_->is_visible()); + + manager_->AddRequest(&iframe_request_same_domain_); + WaitForFrameLoad(); + ASSERT_EQ(view_factory_->request_count(), 1); + Closing(); + EXPECT_TRUE(request1_.finished()); + EXPECT_FALSE(iframe_request_same_domain_.finished()); + EXPECT_TRUE(view_factory_->is_visible()); + ASSERT_EQ(view_factory_->request_count(), 1); + Closing(); + EXPECT_TRUE(iframe_request_same_domain_.finished()); +} + +TEST_F(PermissionRequestManagerTest, + IFrameRequestOtherDomainWhenMainRequestVisible) { + manager_->DisplayPendingRequests(); + manager_->AddRequest(&request1_); + WaitForCoalescing(); + EXPECT_TRUE(view_factory_->is_visible()); + + manager_->AddRequest(&iframe_request_other_domain_); + WaitForFrameLoad(); + Closing(); + EXPECT_TRUE(request1_.finished()); + EXPECT_FALSE(iframe_request_other_domain_.finished()); + EXPECT_TRUE(view_factory_->is_visible()); + Closing(); + EXPECT_TRUE(iframe_request_other_domain_.finished()); +} + +TEST_F(PermissionRequestManagerTest, RequestsDontNeedUserGesture) { + manager_->DisplayPendingRequests(); + WaitForFrameLoad(); + WaitForCoalescing(); + manager_->AddRequest(&request1_); + manager_->AddRequest(&iframe_request_other_domain_); + manager_->AddRequest(&request2_); + base::RunLoop().RunUntilIdle(); + + EXPECT_TRUE(view_factory_->is_visible()); +} + +TEST_F(PermissionRequestManagerTest, UMAForSimpleAcceptedBubble) { + base::HistogramTester histograms; + + manager_->AddRequest(&request1_); + manager_->DisplayPendingRequests(); + WaitForCoalescing(); + histograms.ExpectUniqueSample( + PermissionUmaUtil::kPermissionsPromptShown, + static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), + 1); + histograms.ExpectUniqueSample( + PermissionUmaUtil::kPermissionsPromptRequestsPerPrompt, 1, 1); + + ToggleAccept(0, true); + Accept(); + histograms.ExpectUniqueSample( + PermissionUmaUtil::kPermissionsPromptAccepted, + static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), 1); +} + +TEST_F(PermissionRequestManagerTest, UMAForSimpleDeniedBubble) { + base::HistogramTester histograms; + + manager_->AddRequest(&request1_); + manager_->DisplayPendingRequests(); + WaitForCoalescing(); + // No need to test UMA for showing prompts again, they were tested in + // UMAForSimpleAcceptedBubble. + + Deny(); + histograms.ExpectUniqueSample( + PermissionUmaUtil::kPermissionsPromptDenied, + static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), 1); +} + +// This code path (calling Accept on a non-merged bubble, with no accepted +// permission) would never be used in actual Chrome, but its still tested for +// completeness. +TEST_F(PermissionRequestManagerTest, UMAForSimpleDeniedBubbleAlternatePath) { + base::HistogramTester histograms; + + manager_->AddRequest(&request1_); + manager_->DisplayPendingRequests(); + WaitForCoalescing(); + // No need to test UMA for showing prompts again, they were tested in + // UMAForSimpleAcceptedBubble. + + ToggleAccept(0, false); + Accept(); + histograms.ExpectUniqueSample( + PermissionUmaUtil::kPermissionsPromptDenied, + static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), 1); +} + +TEST_F(PermissionRequestManagerTest, UMAForMergedAcceptedBubble) { + base::HistogramTester histograms; + + manager_->AddRequest(&request1_); + manager_->AddRequest(&request2_); + manager_->DisplayPendingRequests(); + WaitForCoalescing(); + + histograms.ExpectUniqueSample( + PermissionUmaUtil::kPermissionsPromptShown, + static_cast<base::HistogramBase::Sample>(PermissionBubbleType::MULTIPLE), + 1); + histograms.ExpectBucketCount( + PermissionUmaUtil::kPermissionsPromptMergedBubbleTypes, + static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), + 1); + histograms.ExpectBucketCount( + PermissionUmaUtil::kPermissionsPromptMergedBubbleTypes, + static_cast<base::HistogramBase::Sample>(PermissionBubbleType::DOWNLOAD), + 1); + histograms.ExpectUniqueSample( + PermissionUmaUtil::kPermissionsPromptRequestsPerPrompt, 2, 1); + + ToggleAccept(0, true); + ToggleAccept(1, true); + Accept(); + + histograms.ExpectUniqueSample( + PermissionUmaUtil::kPermissionsPromptAccepted, + static_cast<base::HistogramBase::Sample>(PermissionBubbleType::MULTIPLE), + 1); + histograms.ExpectBucketCount( + PermissionUmaUtil::kPermissionsPromptMergedBubbleAccepted, + static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), + 1); + histograms.ExpectBucketCount( + PermissionUmaUtil::kPermissionsPromptMergedBubbleAccepted, + static_cast<base::HistogramBase::Sample>(PermissionBubbleType::DOWNLOAD), + 1); +} + +TEST_F(PermissionRequestManagerTest, UMAForMergedMixedBubble) { + base::HistogramTester histograms; + + manager_->AddRequest(&request1_); + manager_->AddRequest(&request2_); + manager_->DisplayPendingRequests(); + WaitForCoalescing(); + // No need to test UMA for showing prompts again, they were tested in + // UMAForMergedAcceptedBubble. + + ToggleAccept(0, true); + ToggleAccept(1, false); + Accept(); + + histograms.ExpectUniqueSample( + PermissionUmaUtil::kPermissionsPromptDenied, + static_cast<base::HistogramBase::Sample>(PermissionBubbleType::MULTIPLE), + 1); + histograms.ExpectBucketCount( + PermissionUmaUtil::kPermissionsPromptMergedBubbleAccepted, + static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), + 1); + histograms.ExpectBucketCount( + PermissionUmaUtil::kPermissionsPromptMergedBubbleDenied, + static_cast<base::HistogramBase::Sample>(PermissionBubbleType::DOWNLOAD), + 1); +} + +TEST_F(PermissionRequestManagerTest, UMAForMergedDeniedBubble) { + base::HistogramTester histograms; + + manager_->AddRequest(&request1_); + manager_->AddRequest(&request2_); + manager_->DisplayPendingRequests(); + WaitForCoalescing(); + // No need to test UMA for showing prompts again, they were tested in + // UMAForMergedAcceptedBubble. + + ToggleAccept(0, false); + ToggleAccept(1, false); + Accept(); + + histograms.ExpectUniqueSample( + PermissionUmaUtil::kPermissionsPromptDenied, + static_cast<base::HistogramBase::Sample>(PermissionBubbleType::MULTIPLE), + 1); + histograms.ExpectBucketCount( + PermissionUmaUtil::kPermissionsPromptMergedBubbleDenied, + static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), + 1); + histograms.ExpectBucketCount( + PermissionUmaUtil::kPermissionsPromptMergedBubbleDenied, + static_cast<base::HistogramBase::Sample>(PermissionBubbleType::DOWNLOAD), + 1); +}
diff --git a/chrome/browser/permissions/permission_uma_util.cc b/chrome/browser/permissions/permission_uma_util.cc index efbdf5f0..70324dd5 100644 --- a/chrome/browser/permissions/permission_uma_util.cc +++ b/chrome/browser/permissions/permission_uma_util.cc
@@ -6,13 +6,21 @@ #include <utility> +#include "base/command_line.h" #include "base/metrics/histogram_macros.h" #include "base/strings/stringprintf.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/permissions/permission_manager.h" #include "chrome/browser/permissions/permission_util.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/safe_browsing/safe_browsing_service.h" +#include "chrome/browser/safe_browsing/ui_manager.h" +#include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/ui/website_settings/permission_bubble_request.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/pref_names.h" +#include "components/browser_sync/browser/profile_sync_service.h" +#include "components/prefs/pref_service.h" #include "components/rappor/rappor_service.h" #include "components/rappor/rappor_utils.h" #include "content/public/browser/permission_type.h" @@ -74,99 +82,6 @@ permission_str.c_str(), action_str.c_str()); } -void RecordPermissionAction(PermissionType permission, - PermissionAction action, - const GURL& requesting_origin) { - bool secure_origin = content::IsOriginSecure(requesting_origin); - - switch (permission) { - case PermissionType::GEOLOCATION: - PERMISSION_ACTION_UMA( - secure_origin, - "Permissions.Action.Geolocation", - "Permissions.Action.SecureOrigin.Geolocation", - "Permissions.Action.InsecureOrigin.Geolocation", - action); - break; - case PermissionType::NOTIFICATIONS: - PERMISSION_ACTION_UMA( - secure_origin, - "Permissions.Action.Notifications", - "Permissions.Action.SecureOrigin.Notifications", - "Permissions.Action.InsecureOrigin.Notifications", - action); - break; - case PermissionType::MIDI_SYSEX: - PERMISSION_ACTION_UMA( - secure_origin, - "Permissions.Action.MidiSysEx", - "Permissions.Action.SecureOrigin.MidiSysEx", - "Permissions.Action.InsecureOrigin.MidiSysEx", - action); - break; - case PermissionType::PUSH_MESSAGING: - PERMISSION_ACTION_UMA( - secure_origin, - "Permissions.Action.PushMessaging", - "Permissions.Action.SecureOrigin.PushMessaging", - "Permissions.Action.InsecureOrigin.PushMessaging", - action); - break; - case PermissionType::PROTECTED_MEDIA_IDENTIFIER: - PERMISSION_ACTION_UMA( - secure_origin, - "Permissions.Action.ProtectedMedia", - "Permissions.Action.SecureOrigin.ProtectedMedia", - "Permissions.Action.InsecureOrigin.ProtectedMedia", - action); - break; - case PermissionType::DURABLE_STORAGE: - PERMISSION_ACTION_UMA( - secure_origin, - "Permissions.Action.DurableStorage", - "Permissions.Action.SecureOrigin.DurableStorage", - "Permissions.Action.InsecureOrigin.DurableStorage", - action); - break; - case PermissionType::AUDIO_CAPTURE: - // Media permissions are disabled on insecure origins, so there's no - // need to record metrics for secure/insecue. - UMA_HISTOGRAM_ENUMERATION("Permissions.Action.AudioCapture", action, - PERMISSION_ACTION_NUM); - break; - case PermissionType::VIDEO_CAPTURE: - UMA_HISTOGRAM_ENUMERATION("Permissions.Action.VideoCapture", action, - PERMISSION_ACTION_NUM); - break; - // The user is not prompted for these permissions, thus there is no - // permission action recorded for them. - case PermissionType::MIDI: - case PermissionType::BACKGROUND_SYNC: - case PermissionType::NUM: - NOTREACHED() << "PERMISSION " - << PermissionUtil::GetPermissionString(permission) - << " not accounted for"; - } - - // Retrieve the name of the RAPPOR metric. Currently, the new metric name is - // the deprecated name with "2" on the end, e.g. - // ContentSettings.PermissionActions_Geolocation.Granted.Url2. For simplicity, - // we retrieve the deprecated name and append the "2" for the new name. - // TODO(dominickn): remove the deprecated metric and replace it solely with - // the new one in GetRapporMetric - crbug.com/605836. - const std::string deprecated_metric = GetRapporMetric(permission, action); - rappor::RapporService* rappor_service = g_browser_process->rappor_service(); - if (!deprecated_metric.empty() && rappor_service) { - rappor::SampleDomainAndRegistryFromGURL(rappor_service, deprecated_metric, - requesting_origin); - - std::string rappor_metric = deprecated_metric + "2"; - rappor_service->RecordSample( - rappor_metric, rappor::LOW_FREQUENCY_ETLD_PLUS_ONE_RAPPOR_TYPE, - rappor::GetDomainAndRegistrySampleFromGURL(requesting_origin)); - } -} - void RecordPermissionRequest(PermissionType permission, const GURL& requesting_origin, const GURL& embedding_origin, @@ -280,34 +195,39 @@ } void PermissionUmaUtil::PermissionGranted(PermissionType permission, - const GURL& requesting_origin) { - RecordPermissionAction(permission, GRANTED, requesting_origin); + const GURL& requesting_origin, + Profile* profile) { + RecordPermissionAction(permission, GRANTED, requesting_origin, profile); } void PermissionUmaUtil::PermissionDenied(PermissionType permission, - const GURL& requesting_origin) { - RecordPermissionAction(permission, DENIED, requesting_origin); + const GURL& requesting_origin, + Profile* profile) { + RecordPermissionAction(permission, DENIED, requesting_origin, profile); } void PermissionUmaUtil::PermissionDismissed(PermissionType permission, - const GURL& requesting_origin) { - RecordPermissionAction(permission, DISMISSED, requesting_origin); + const GURL& requesting_origin, + Profile* profile) { + RecordPermissionAction(permission, DISMISSED, requesting_origin, profile); } void PermissionUmaUtil::PermissionIgnored(PermissionType permission, - const GURL& requesting_origin) { - RecordPermissionAction(permission, IGNORED, requesting_origin); + const GURL& requesting_origin, + Profile* profile) { + RecordPermissionAction(permission, IGNORED, requesting_origin, profile); } void PermissionUmaUtil::PermissionRevoked(PermissionType permission, - const GURL& revoked_origin) { + const GURL& revoked_origin, + Profile* profile) { // TODO(tsergeant): Expand metrics definitions for revocation to include all // permissions. if (permission == PermissionType::NOTIFICATIONS || permission == PermissionType::GEOLOCATION || permission == PermissionType::AUDIO_CAPTURE || permission == PermissionType::VIDEO_CAPTURE) { - RecordPermissionAction(permission, REVOKED, revoked_origin); + RecordPermissionAction(permission, REVOKED, revoked_origin, profile); } } @@ -374,3 +294,127 @@ PERMISSION_BUBBLE_TYPE_UMA(kPermissionsPromptDenied, requests[0]->GetPermissionBubbleType()); } + +bool PermissionUmaUtil::IsOptedIntoPermissionActionReporting(Profile* profile) { + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnablePermissionActionReporting)) + return false; + // TODO(stefanocs): Remove this check once all callsites have been updated + // to not pass a nullptr. + if (!profile) + return false; + if (profile->GetProfileType() == Profile::INCOGNITO_PROFILE) + return false; + if (!profile->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled)) + return false; + + ProfileSyncService* profile_sync_service = + ProfileSyncServiceFactory::GetForProfile(profile); + + // Do not report if profile can't get a profile sync service due to disable + // sync flag. + if (!profile_sync_service) + return false; + + if (!profile_sync_service->CanSyncStart()) + return false; + + syncer::ModelTypeSet preferred_data_types = + profile_sync_service->GetPreferredDataTypes(); + if (!preferred_data_types.Has(syncer::PROXY_TABS)) + return false; + if (!preferred_data_types.Has(syncer::PRIORITY_PREFERENCES)) + return false; + + return true; +} + +void PermissionUmaUtil::RecordPermissionAction(PermissionType permission, + PermissionAction action, + const GURL& requesting_origin, + Profile* profile) { + if (IsOptedIntoPermissionActionReporting(profile)) { + // TODO(stefanocs): Add browsertests to make sure the reports are being + // sent. + g_browser_process->safe_browsing_service() + ->ui_manager() + ->ReportPermissionAction(requesting_origin, permission, action); + } + + bool secure_origin = content::IsOriginSecure(requesting_origin); + + switch (permission) { + case PermissionType::GEOLOCATION: + PERMISSION_ACTION_UMA(secure_origin, "Permissions.Action.Geolocation", + "Permissions.Action.SecureOrigin.Geolocation", + "Permissions.Action.InsecureOrigin.Geolocation", + action); + break; + case PermissionType::NOTIFICATIONS: + PERMISSION_ACTION_UMA(secure_origin, "Permissions.Action.Notifications", + "Permissions.Action.SecureOrigin.Notifications", + "Permissions.Action.InsecureOrigin.Notifications", + action); + break; + case PermissionType::MIDI_SYSEX: + PERMISSION_ACTION_UMA(secure_origin, "Permissions.Action.MidiSysEx", + "Permissions.Action.SecureOrigin.MidiSysEx", + "Permissions.Action.InsecureOrigin.MidiSysEx", + action); + break; + case PermissionType::PUSH_MESSAGING: + PERMISSION_ACTION_UMA(secure_origin, "Permissions.Action.PushMessaging", + "Permissions.Action.SecureOrigin.PushMessaging", + "Permissions.Action.InsecureOrigin.PushMessaging", + action); + break; + case PermissionType::PROTECTED_MEDIA_IDENTIFIER: + PERMISSION_ACTION_UMA(secure_origin, "Permissions.Action.ProtectedMedia", + "Permissions.Action.SecureOrigin.ProtectedMedia", + "Permissions.Action.InsecureOrigin.ProtectedMedia", + action); + break; + case PermissionType::DURABLE_STORAGE: + PERMISSION_ACTION_UMA(secure_origin, "Permissions.Action.DurableStorage", + "Permissions.Action.SecureOrigin.DurableStorage", + "Permissions.Action.InsecureOrigin.DurableStorage", + action); + break; + case PermissionType::AUDIO_CAPTURE: + // Media permissions are disabled on insecure origins, so there's no + // need to record metrics for secure/insecue. + UMA_HISTOGRAM_ENUMERATION("Permissions.Action.AudioCapture", action, + PERMISSION_ACTION_NUM); + break; + case PermissionType::VIDEO_CAPTURE: + UMA_HISTOGRAM_ENUMERATION("Permissions.Action.VideoCapture", action, + PERMISSION_ACTION_NUM); + break; + // The user is not prompted for these permissions, thus there is no + // permission action recorded for them. + case PermissionType::MIDI: + case PermissionType::BACKGROUND_SYNC: + case PermissionType::NUM: + NOTREACHED() << "PERMISSION " + << PermissionUtil::GetPermissionString(permission) + << " not accounted for"; + } + + // Retrieve the name of the RAPPOR metric. Currently, the new metric name is + // the deprecated name with "2" on the end, e.g. + // ContentSettings.PermissionActions_Geolocation.Granted.Url2. For simplicity, + // we retrieve the deprecated name and append the "2" for the new name. + // TODO(dominickn): remove the deprecated metric and replace it solely with + // the new one in GetRapporMetric - crbug.com/605836. + const std::string deprecated_metric = GetRapporMetric(permission, action); + rappor::RapporService* rappor_service = g_browser_process->rappor_service(); + if (!deprecated_metric.empty() && rappor_service) { + rappor::SampleDomainAndRegistryFromGURL(rappor_service, deprecated_metric, + requesting_origin); + + std::string rappor_metric = deprecated_metric + "2"; + rappor_service->RecordSample( + rappor_metric, rappor::LOW_FREQUENCY_ETLD_PLUS_ONE_RAPPOR_TYPE, + rappor::GetDomainAndRegistrySampleFromGURL(requesting_origin)); + } +}
diff --git a/chrome/browser/permissions/permission_uma_util.h b/chrome/browser/permissions/permission_uma_util.h index f1636173..0d7c771 100644 --- a/chrome/browser/permissions/permission_uma_util.h +++ b/chrome/browser/permissions/permission_uma_util.h
@@ -51,15 +51,20 @@ const GURL& embedding_origin, Profile* profile); static void PermissionGranted(content::PermissionType permission, - const GURL& requesting_origin); + const GURL& requesting_origin, + Profile* profile); static void PermissionDenied(content::PermissionType permission, - const GURL& requesting_origin); + const GURL& requesting_origin, + Profile* profile); static void PermissionDismissed(content::PermissionType permission, - const GURL& requesting_origin); + const GURL& requesting_origin, + Profile* profile); static void PermissionIgnored(content::PermissionType permission, - const GURL& requesting_origin); + const GURL& requesting_origin, + Profile* profile); static void PermissionRevoked(content::PermissionType permission, - const GURL& revoked_origin); + const GURL& revoked_origin, + Profile* profile); // UMA specifically for when permission prompts are shown. This should be // roughly equivalent to the metrics above, however it is @@ -86,7 +91,16 @@ const std::vector<PermissionBubbleRequest*>& requests); private: + friend class PermissionUmaUtilTest; + DISALLOW_IMPLICIT_CONSTRUCTORS(PermissionUmaUtil); + + static bool IsOptedIntoPermissionActionReporting(Profile* profile); + + static void RecordPermissionAction(content::PermissionType permission, + PermissionAction action, + const GURL& requesting_origin, + Profile* profile); }; #endif // CHROME_BROWSER_PERMISSIONS_PERMISSION_UMA_UTIL_H_
diff --git a/chrome/browser/permissions/permission_uma_util_unittest.cc b/chrome/browser/permissions/permission_uma_util_unittest.cc new file mode 100644 index 0000000..4921fceb --- /dev/null +++ b/chrome/browser/permissions/permission_uma_util_unittest.cc
@@ -0,0 +1,161 @@ +// 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/permissions/permission_uma_util.h" + +#include "base/command_line.h" +#include "chrome/browser/signin/fake_signin_manager_builder.h" +#include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/base/testing_profile.h" +#include "components/browser_sync/browser/profile_sync_service.h" +#include "components/browser_sync/common/browser_sync_switches.h" +#include "components/prefs/pref_service.h" +#include "components/sync_driver/glue/sync_backend_host_mock.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "sync/internal_api/public/base/model_type.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { +const char* kTestingGaiaId = "gaia_id"; +const char* kTestingUsername = "fake_username"; +} // namespace + +class PermissionUmaUtilTest : public testing::Test { + protected: + PermissionUmaUtilTest() : profile_(new TestingProfile()) {} + + static bool IsOptedIntoPermissionActionReporting(Profile* profile) { + return PermissionUmaUtil::IsOptedIntoPermissionActionReporting(profile); + } + + void SetUp() override { + profile_.reset(new TestingProfile()); + ResetCommandLine(); + } + + void FakeSignIn() { + SigninManagerBase* signin_manager = + static_cast<FakeSigninManagerForTesting*>( + SigninManagerFactory::GetForProfile(profile())); + signin_manager->SetAuthenticatedAccountInfo(kTestingGaiaId, + kTestingUsername); + // Attach a sync backend to the profile sync service. + GetProfileSyncService()->backend_.reset( + new browser_sync::SyncBackendHostMock()); + GetProfileSyncService()->backend_initialized_ = true; + } + + void ResetCommandLine() { + base::CommandLine::Reset(); + base::CommandLine::Init(0, NULL); + } + + void SetKeepEverythingSynced(bool flag) { + GetProfileSyncService()->sync_prefs_.SetKeepEverythingSynced(flag); + } + + void SetSafeBrowsing(bool enabled) { + PrefService* preferences = profile_->GetPrefs(); + preferences->SetBoolean(prefs::kSafeBrowsingEnabled, enabled); + } + + ProfileSyncService* GetProfileSyncService() { + return ProfileSyncServiceFactory::GetForProfile(profile()); + } + + Profile* profile() { return profile_.get(); } + + private: + content::TestBrowserThreadBundle thread_bundle_; + std::unique_ptr<Profile> profile_; +}; + +// Test that PermissionUmaUtil::IsOptedIntoPermissionActionReporting returns +// true if Safe Browsing is enabled, Permission Action Reporting flag is +// enabled, not in incognito mode and signed in with default sync preferences. +TEST_F(PermissionUmaUtilTest, IsOptedIntoPermissionActionReportingSignInCheck) { + SetSafeBrowsing(true); + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnablePermissionActionReporting); + EXPECT_FALSE(IsOptedIntoPermissionActionReporting(profile())); + + FakeSignIn(); + EXPECT_FALSE(IsOptedIntoPermissionActionReporting( + profile()->GetOffTheRecordProfile())); + EXPECT_TRUE(IsOptedIntoPermissionActionReporting(profile())); +} + +// Test that PermissionUmaUtil::IsOptedIntoPermissionActionReporting returns +// false if Permission Action Reporting is not enabled. +TEST_F(PermissionUmaUtilTest, IsOptedIntoPermissionActionReportingFlagCheck) { + SetSafeBrowsing(true); + FakeSignIn(); + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnablePermissionActionReporting); + EXPECT_TRUE(IsOptedIntoPermissionActionReporting(profile())); + + ResetCommandLine(); + EXPECT_FALSE(IsOptedIntoPermissionActionReporting(profile())); + + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kDisablePermissionActionReporting); + EXPECT_FALSE(IsOptedIntoPermissionActionReporting(profile())); +} + +// Test that PermissionUmaUtil::IsOptedIntoPermissionActionReporting returns +// false if Safe Browsing is disabled. +TEST_F(PermissionUmaUtilTest, + IsOptedIntoPermissionActionReportingSafeBrowsingCheck) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnablePermissionActionReporting); + FakeSignIn(); + SetSafeBrowsing(true); + EXPECT_TRUE(IsOptedIntoPermissionActionReporting(profile())); + + SetSafeBrowsing(false); + EXPECT_FALSE(IsOptedIntoPermissionActionReporting(profile())); +} + +// Test that PermissionUmaUtil::IsOptedIntoPermissionActionReporting returns +// false if Sync is disabled. +TEST_F(PermissionUmaUtilTest, + IsOptedIntoPermissionActionReportingProfileSyncServiceCheck) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnablePermissionActionReporting); + SetSafeBrowsing(true); + FakeSignIn(); + EXPECT_TRUE(IsOptedIntoPermissionActionReporting(profile())); + + base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kDisableSync); + EXPECT_FALSE(IsOptedIntoPermissionActionReporting(profile())); +} + +// Test that PermissionUmaUtil::IsOptedIntoPermissionActionReporting returns +// false if Tab Sync and Pref Sync are not both enabled. +TEST_F(PermissionUmaUtilTest, + IsOptedIntoPermissionActionReportingSyncPreferenceCheck) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnablePermissionActionReporting); + SetSafeBrowsing(true); + FakeSignIn(); + EXPECT_TRUE(IsOptedIntoPermissionActionReporting(profile())); + + SetKeepEverythingSynced(false); + GetProfileSyncService()->ChangePreferredDataTypes( + syncer::ModelTypeSet(syncer::PROXY_TABS)); + EXPECT_FALSE(IsOptedIntoPermissionActionReporting(profile())); + + SetKeepEverythingSynced(false); + GetProfileSyncService()->ChangePreferredDataTypes( + syncer::ModelTypeSet(syncer::PRIORITY_PREFERENCES)); + EXPECT_FALSE(IsOptedIntoPermissionActionReporting(profile())); + + SetKeepEverythingSynced(true); + GetProfileSyncService()->ChangePreferredDataTypes( + syncer::ModelTypeSet(syncer::PROXY_TABS, syncer::PREFERENCES)); + EXPECT_TRUE(IsOptedIntoPermissionActionReporting(profile())); +}
diff --git a/chrome/browser/permissions/permission_util.cc b/chrome/browser/permissions/permission_util.cc index 8749ac4..78271a2c5 100644 --- a/chrome/browser/permissions/permission_util.cc +++ b/chrome/browser/permissions/permission_util.cc
@@ -100,7 +100,8 @@ final_value != CONTENT_SETTING_ALLOW) { PermissionType permission_type; if (PermissionUtil::GetPermissionType(content_type, &permission_type)) { - PermissionUmaUtil::PermissionRevoked(permission_type, primary_url); + PermissionUmaUtil::PermissionRevoked(permission_type, primary_url, + profile); } } }
diff --git a/chrome/browser/plugins/plugin_power_saver_browsertest.cc b/chrome/browser/plugins/plugin_power_saver_browsertest.cc index 4c60ad01..3ecbfd4e 100644 --- a/chrome/browser/plugins/plugin_power_saver_browsertest.cc +++ b/chrome/browser/plugins/plugin_power_saver_browsertest.cc
@@ -308,6 +308,28 @@ GetActiveWebContents()->GetMainFrame())); } + // Returns the background WebContents. + content::WebContents* LoadHTMLInBackgroundTab(const std::string& html) { + embedded_test_server()->RegisterRequestHandler( + base::Bind(&RespondWithHTML, html)); + ui_test_utils::NavigateToURLWithDisposition( + browser(), embedded_test_server()->base_url(), NEW_BACKGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); + + int index = browser()->tab_strip_model()->GetIndexOfLastWebContentsOpenedBy( + GetActiveWebContents(), 0 /* start_index */); + content::WebContents* contents = + browser()->tab_strip_model()->GetWebContentsAt(index); + EXPECT_TRUE(content::WaitForRenderFrameReady(contents->GetMainFrame())); + return contents; + } + + void ActivateTab(content::WebContents* contents) { + browser()->tab_strip_model()->ActivateTabAt( + browser()->tab_strip_model()->GetIndexOfWebContents(contents), + true /* user_gesture */); + } + content::WebContents* GetActiveWebContents() { return browser()->tab_strip_model()->GetActiveWebContents(); } @@ -619,35 +641,19 @@ } IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, BackgroundTabPlugins) { - std::string html = + content::WebContents* background_contents = LoadHTMLInBackgroundTab( "<object id='same_origin' data='fake.swf' " " type='application/x-ppapi-tests'></object>" "<object id='small_cross_origin' data='http://otherorigin.com/fake1.swf' " - " type='application/x-ppapi-tests' width='400' height='100'></object>"; - embedded_test_server()->RegisterRequestHandler( - base::Bind(&RespondWithHTML, html)); - ui_test_utils::NavigateToURLWithDisposition( - browser(), embedded_test_server()->base_url(), NEW_BACKGROUND_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); - - ASSERT_EQ(2, browser()->tab_strip_model()->count()); - content::WebContents* background_contents = - browser()->tab_strip_model()->GetWebContentsAt(1); - EXPECT_TRUE( - content::WaitForRenderFrameReady(background_contents->GetMainFrame())); + " type='application/x-ppapi-tests' width='400' height='80'></object>"); EXPECT_FALSE(PluginLoaded(background_contents, "same_origin")); EXPECT_FALSE(PluginLoaded(background_contents, "small_cross_origin")); - browser()->tab_strip_model()->SelectNextTab(); - EXPECT_EQ(background_contents, GetActiveWebContents()); + ActivateTab(background_contents); VerifyPluginMarkedEssential(background_contents, "same_origin"); VerifyPluginIsThrottled(background_contents, "small_cross_origin"); - - // TODO(groby): We need to cover the edge case of tiny plugin on a a - // background tab here. If blocking of tiny content is enabled - // this should be IsThrotthled, not IsPlaceholderOnly. } IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, ZoomIndependent) { @@ -670,8 +676,7 @@ base::FeatureList::ClearInstanceForTesting(); PluginPowerSaverBrowserTest::SetUp(); } - void SetUpInProcessBrowserTestFixture() override { BlockTinyPlugins(); } - void BlockTinyPlugins() { + void SetUpInProcessBrowserTestFixture() override { base::FeatureList::ClearInstanceForTesting(); std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); feature_list->InitializeFromCommandLine(features::kBlockSmallContent.name, @@ -682,12 +687,6 @@ IN_PROC_BROWSER_TEST_F(PluginPowerSaverBlockTinyBrowserTest, BlockTinyPlugins) { LoadHTML( - "<object id='large_same_origin' data='fake.swf' " - " type='application/x-ppapi-tests' width='500' height='500'>" - "</object>" - "<object id='small_same_origin' data='fake.swf' " - " type='application/x-ppapi-tests' width='500' height='500'>" - "</object>" "<object id='tiny_same_origin' data='fake.swf' " " type='application/x-ppapi-tests' width='3' height='3'>" "</object>" @@ -698,9 +697,41 @@ " type='application/x-ppapi-tests' width='1' height='1'>" "</object>"); - VerifyPluginMarkedEssential(GetActiveWebContents(), "large_same_origin"); - VerifyPluginMarkedEssential(GetActiveWebContents(), "small_same_origin"); VerifyPluginMarkedEssential(GetActiveWebContents(), "tiny_same_origin"); VerifyPluginIsPlaceholderOnly("tiny_cross_origin_1"); VerifyPluginIsPlaceholderOnly("tiny_cross_origin_2"); } + +IN_PROC_BROWSER_TEST_F(PluginPowerSaverBlockTinyBrowserTest, + BackgroundTabTinyPlugins) { + content::WebContents* background_contents = LoadHTMLInBackgroundTab( + "<object id='tiny' data='http://a.com/fake.swf' " + " type='application/x-ppapi-tests' width='3' height='3'>" + "</object>"); + EXPECT_FALSE(PluginLoaded(background_contents, "tiny")); + + ActivateTab(background_contents); + VerifyPluginIsPlaceholderOnly("tiny"); +} + +IN_PROC_BROWSER_TEST_F(PluginPowerSaverBlockTinyBrowserTest, + ExpandingTinyPlugins) { + LoadHTML( + "<object id='expand_to_peripheral' data='http://a.com/fake.swf' " + " type='application/x-ppapi-tests' width='4' height='4'></object>" + "<object id='expand_to_essential' data='http://b.com/fake.swf' " + " type='application/x-ppapi-tests' width='4' height='4'></object>"); + + VerifyPluginIsPlaceholderOnly("expand_to_peripheral"); + VerifyPluginIsPlaceholderOnly("expand_to_essential"); + + std::string script = + "window.document.getElementById('expand_to_peripheral').height = 200;" + "window.document.getElementById('expand_to_peripheral').width = 200;" + "window.document.getElementById('expand_to_essential').height = 400;" + "window.document.getElementById('expand_to_essential').width = 400;"; + ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), script)); + + VerifyPluginIsThrottled(GetActiveWebContents(), "expand_to_peripheral"); + VerifyPluginMarkedEssential(GetActiveWebContents(), "expand_to_essential"); +}
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index f4d108818..968217e1 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc
@@ -87,7 +87,6 @@ #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension_constants.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" @@ -166,6 +165,7 @@ #include "extensions/common/constants.h" #include "extensions/common/extension.h" #include "extensions/common/extension_set.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/manifest_handlers/shared_module_info.h" #include "net/base/net_errors.h" #include "net/base/url_util.h"
diff --git a/chrome/browser/prefs/chrome_pref_service_factory.cc b/chrome/browser/prefs/chrome_pref_service_factory.cc index 0c7a9f5..9d95bbd 100644 --- a/chrome/browser/prefs/chrome_pref_service_factory.cc +++ b/chrome/browser/prefs/chrome_pref_service_factory.cc
@@ -429,9 +429,7 @@ if (supervised_user_settings) { scoped_refptr<PrefStore> supervised_user_prefs = make_scoped_refptr( new SupervisedUserPrefStore(supervised_user_settings)); - // TODO(bauerb): Temporary CHECK while investigating - // https://crbug.com/425785. Remove when that bug is fixed. - CHECK(async || supervised_user_prefs->IsInitializationComplete()); + DCHECK(async || supervised_user_prefs->IsInitializationComplete()); factory->set_supervised_user_prefs(supervised_user_prefs); } #endif
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc index becbd9c..c70aead 100644 --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc
@@ -1492,9 +1492,8 @@ bool ProfileManager::ShouldGoOffTheRecord(Profile* profile) { #if defined(OS_CHROMEOS) - if (profile->GetPath().BaseName().value() == chrome::kInitialProfile) { + if (chromeos::ProfileHelper::IsSigninProfile(profile)) return true; - } #endif return profile->IsGuestSession() || profile->IsSystemProfile(); }
diff --git a/chrome/browser/profiles/profile_window_browsertest.cc b/chrome/browser/profiles/profile_window_browsertest.cc index f722e54a..d1233ae5 100644 --- a/chrome/browser/profiles/profile_window_browsertest.cc +++ b/chrome/browser/profiles/profile_window_browsertest.cc
@@ -87,7 +87,7 @@ public: // Don't handle accelerators. bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override { + ui::Accelerator* accelerator) const override { return false; } };
diff --git a/chrome/browser/push_messaging/push_messaging_browsertest.cc b/chrome/browser/push_messaging/push_messaging_browsertest.cc index de9d4eb..550e4a4 100644 --- a/chrome/browser/push_messaging/push_messaging_browsertest.cc +++ b/chrome/browser/push_messaging/push_messaging_browsertest.cc
@@ -29,6 +29,7 @@ #include "chrome/browser/notifications/message_center_display_service.h" #include "chrome/browser/notifications/notification_test_util.h" #include "chrome/browser/notifications/platform_notification_service_impl.h" +#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/push_messaging/push_messaging_app_identifier.h" #include "chrome/browser/push_messaging/push_messaging_constants.h" @@ -38,7 +39,6 @@ #include "chrome/browser/services/gcm/gcm_profile_service_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/features.h" #include "chrome/test/base/in_process_browser_test.h" @@ -207,8 +207,8 @@ kPushMessagingAppIdentifierPrefix); } - PermissionBubbleManager* GetPermissionBubbleManager() { - return PermissionBubbleManager::FromWebContents( + PermissionRequestManager* GetPermissionRequestManager() { + return PermissionRequestManager::FromWebContents( GetBrowser()->tab_strip_model()->GetActiveWebContents()); } @@ -296,16 +296,16 @@ void PushMessagingBrowserTest::RequestAndAcceptPermission() { std::string script_result; - GetPermissionBubbleManager()->set_auto_response_for_test( - PermissionBubbleManager::ACCEPT_ALL); + GetPermissionRequestManager()->set_auto_response_for_test( + PermissionRequestManager::ACCEPT_ALL); EXPECT_TRUE(RunScript("requestNotificationPermission();", &script_result)); EXPECT_EQ("permission status - granted", script_result); } void PushMessagingBrowserTest::RequestAndDenyPermission() { std::string script_result; - GetPermissionBubbleManager()->set_auto_response_for_test( - PermissionBubbleManager::DENY_ALL); + GetPermissionRequestManager()->set_auto_response_for_test( + PermissionRequestManager::DENY_ALL); EXPECT_TRUE(RunScript("requestNotificationPermission();", &script_result)); EXPECT_EQ("permission status - denied", script_result); } @@ -383,8 +383,8 @@ ASSERT_TRUE(RunScript("registerServiceWorker()", &script_result)); ASSERT_EQ("ok - service worker registered", script_result); - GetPermissionBubbleManager()->set_auto_response_for_test( - PermissionBubbleManager::ACCEPT_ALL); + GetPermissionRequestManager()->set_auto_response_for_test( + PermissionRequestManager::ACCEPT_ALL); ASSERT_TRUE(RunScript("documentSubscribePush()", &script_result)); EXPECT_EQ(GetEndpointForSubscriptionId("1-0"), script_result);
diff --git a/chrome/browser/push_messaging/push_messaging_permission_context.cc b/chrome/browser/push_messaging/push_messaging_permission_context.cc index a7a786f1..c7ae175 100644 --- a/chrome/browser/push_messaging/push_messaging_permission_context.cc +++ b/chrome/browser/push_messaging/push_messaging_permission_context.cc
@@ -118,7 +118,8 @@ if (push_content_setting == CONTENT_SETTING_BLOCK) { DVLOG(1) << "Push permission was explicitly blocked."; - PermissionUmaUtil::PermissionDenied(permission_type(), requesting_origin); + PermissionUmaUtil::PermissionDenied(permission_type(), requesting_origin, + profile_); NotifyPermissionSet(id, requesting_origin, embedding_origin, callback, true /* persist */, CONTENT_SETTING_BLOCK); return; @@ -131,7 +132,8 @@ return; } - PermissionUmaUtil::PermissionGranted(permission_type(), requesting_origin); + PermissionUmaUtil::PermissionGranted(permission_type(), requesting_origin, + profile_); NotifyPermissionSet(id, requesting_origin, embedding_origin, callback, true /* persist */, CONTENT_SETTING_ALLOW); }
diff --git a/chrome/browser/renderer_context_menu/mock_render_view_context_menu.cc b/chrome/browser/renderer_context_menu/mock_render_view_context_menu.cc index 71239482..c78af76 100644 --- a/chrome/browser/renderer_context_menu/mock_render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/mock_render_view_context_menu.cc
@@ -53,7 +53,7 @@ bool MockRenderViewContextMenu::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; }
diff --git a/chrome/browser/renderer_context_menu/mock_render_view_context_menu.h b/chrome/browser/renderer_context_menu/mock_render_view_context_menu.h index 133ca40..d286cdb 100644 --- a/chrome/browser/renderer_context_menu/mock_render_view_context_menu.h +++ b/chrome/browser/renderer_context_menu/mock_render_view_context_menu.h
@@ -52,7 +52,7 @@ void MenuWillShow(ui::SimpleMenuModel* source) override; void MenuClosed(ui::SimpleMenuModel* source) override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; // RenderViewContextMenuProxy implementation. void AddMenuItem(int command_id, const base::string16& title) override;
diff --git a/chrome/browser/renderer_context_menu/open_with_menu_factory_ash.cc b/chrome/browser/renderer_context_menu/open_with_menu_factory_ash.cc index 2909bd22..c4494b2 100644 --- a/chrome/browser/renderer_context_menu/open_with_menu_factory_ash.cc +++ b/chrome/browser/renderer_context_menu/open_with_menu_factory_ash.cc
@@ -37,7 +37,7 @@ bool OpenWithMenuObserver::SubMenuDelegate::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; }
diff --git a/chrome/browser/renderer_context_menu/open_with_menu_factory_ash.h b/chrome/browser/renderer_context_menu/open_with_menu_factory_ash.h index b6e7348..e801f2e 100644 --- a/chrome/browser/renderer_context_menu/open_with_menu_factory_ash.h +++ b/chrome/browser/renderer_context_menu/open_with_menu_factory_ash.h
@@ -36,8 +36,9 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; - bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + bool GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; private:
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc index a0da432c..40de50b 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.cc
@@ -37,7 +37,7 @@ bool TestRenderViewContextMenu::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { // None of our commands have accelerators, so always return false. return false; }
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h index 391f5ec..0d2249a 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h
@@ -42,7 +42,7 @@ // Implementation of pure virtuals in RenderViewContextMenu. bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; // Returns true if the command specified by |command_id| is present // in the menu.
diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc index acad9e3..11bc778 100644 --- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc +++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
@@ -714,8 +714,7 @@ void ChromeResourceDispatcherHostDelegate::OnResponseStarted( net::URLRequest* request, content::ResourceContext* resource_context, - content::ResourceResponse* response, - IPC::Sender* sender) { + content::ResourceResponse* response) { const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h index 5afcfd5..dd211f29 100644 --- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h +++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h
@@ -84,8 +84,7 @@ std::unique_ptr<content::StreamInfo> stream) override; void OnResponseStarted(net::URLRequest* request, content::ResourceContext* resource_context, - content::ResourceResponse* response, - IPC::Sender* sender) override; + content::ResourceResponse* response) override; void OnRequestRedirected(const GURL& redirect_url, net::URLRequest* request, content::ResourceContext* resource_context,
diff --git a/chrome/browser/resources/PRESUBMIT.py b/chrome/browser/resources/PRESUBMIT.py index 6d60a3a..9dac919 100644 --- a/chrome/browser/resources/PRESUBMIT.py +++ b/chrome/browser/resources/PRESUBMIT.py
@@ -105,7 +105,8 @@ existing_bots = (change.CQ_INCLUDE_TRYBOTS or '').split(';') clean_bots = set(filter(None, map(lambda s: s.strip(), existing_bots))) - new_bots = clean_bots | set(['tryserver.chromium.linux:closure_compilation']) + new_bots = clean_bots | set( + ['master.tryserver.chromium.linux:closure_compilation']) new_tag = 'CQ_INCLUDE_TRYBOTS=%s' % ';'.join(new_bots) if clean_bots:
diff --git a/chrome/browser/resources/bookmark_manager/js/main.js b/chrome/browser/resources/bookmark_manager/js/main.js index 48e74f2..319397ec 100644 --- a/chrome/browser/resources/bookmark_manager/js/main.js +++ b/chrome/browser/resources/bookmark_manager/js/main.js
@@ -77,24 +77,24 @@ var commandShortcutMap = cr.isMac ? { 'edit': 'Enter', // On Mac we also allow Meta+Backspace. - 'delete': 'U+007F U+0008 Meta-U+0008', - 'open-in-background-tab': 'Meta-Enter', - 'open-in-new-tab': 'Shift-Meta-Enter', - 'open-in-same-window': 'Meta-Down', - 'open-in-new-window': 'Shift-Enter', + 'delete': 'Delete Backspace Meta|Backspace', + 'open-in-background-tab': 'Meta|Enter', + 'open-in-new-tab': 'Shift|Meta|Enter', + 'open-in-same-window': 'Meta|Down', + 'open-in-new-window': 'Shift|Enter', 'rename-folder': 'Enter', // Global undo is Command-Z. It is not in any menu. - 'undo': 'Meta-U+005A', + 'undo': 'Meta|z', } : { 'edit': 'F2', - 'delete': 'U+007F', - 'open-in-background-tab': 'Ctrl-Enter', - 'open-in-new-tab': 'Shift-Ctrl-Enter', + 'delete': 'Delete', + 'open-in-background-tab': 'Ctrl|Enter', + 'open-in-new-tab': 'Shift|Ctrl|Enter', 'open-in-same-window': 'Enter', - 'open-in-new-window': 'Shift-Enter', + 'open-in-new-window': 'Shift|Enter', 'rename-folder': 'F2', // Global undo is Ctrl-Z. It is not in any menu. - 'undo': 'Ctrl-U+005A', + 'undo': 'Ctrl|z', }; /**
diff --git a/chrome/browser/resources/chromeos/arc_support/background.js b/chrome/browser/resources/chromeos/arc_support/background.js index 41a744e6..e6acea59 100644 --- a/chrome/browser/resources/chromeos/arc_support/background.js +++ b/chrome/browser/resources/chromeos/arc_support/background.js
@@ -66,6 +66,19 @@ var termsAccepted = false; /** + * Host window inner default width. + * @const {number} + */ +var INNER_WIDTH = 960; + +/** + * Host window inner default height. + * @const {number} + */ +var INNER_HEIGHT = 688; + + +/** * Closes current window in response to request from native code. This does not * issue 'cancelAuthCode' message to native code. */ @@ -207,6 +220,8 @@ closeWindowInternally(); } else if (message.action == 'showPage') { showPageWithStatus(message.page, message.status); + } else if (message.action == 'setWindowBounds') { + setWindowBounds(); } } @@ -307,10 +322,46 @@ termsView.src = 'https://play.google.com/about/play-terms.html'; } +function setWindowBounds() { + if (!appWindow) { + return; + } + + var decorationWidth = appWindow.outerBounds.width - + appWindow.innerBounds.width; + var decorationHeight = appWindow.outerBounds.height - + appWindow.innerBounds.height; + + var outerWidth = INNER_WIDTH + decorationWidth; + var outerHeight = INNER_HEIGHT + decorationHeight; + if (outerWidth > screen.availWidth) { + outerWidth = screen.availWidth; + } + if (outerHeight > screen.availHeight) { + outerHeight = screen.availHeight; + } + if (appWindow.outerBounds.width == outerWidth && + appWindow.outerBounds.height == outerHeight) { + return; + } + + appWindow.outerBounds.width = outerWidth; + appWindow.outerBounds.height = outerHeight; + appWindow.outerBounds.left = Math.ceil((screen.availWidth - outerWidth) / 2); + appWindow.outerBounds.top = + Math.ceil((screen.availHeight - outerHeight) / 2); +} + chrome.app.runtime.onLaunched.addListener(function() { var onAppContentLoad = function() { var doc = appWindow.contentWindow.document; lsoView = doc.getElementById('arc-support'); + lsoView.addContentScripts([ + { name: 'postProcess', + matches: ['https://accounts.google.com/*'], + css: { files: ['lso.css'] }, + run_at: 'document_end' + }]); var isApprovalResponse = function(url) { var resultUrlPrefix = 'https://accounts.google.com/o/oauth2/approval?'; @@ -340,6 +391,10 @@ if (!isApprovalResponse(lsoView.src)) { // Show LSO page when its content is ready. showPage('lso'); + // We have fixed width for LSO page in css file in order to prevent + // unwanted webview resize animation when it is shown first time. Now + // it safe to make it up to window width. + lsoView.style.width = '100%'; return; } @@ -457,6 +512,8 @@ appWindow = createdWindow; appWindow.contentWindow.onload = onAppContentLoad; createdWindow.onClosed.addListener(onWindowClosed); + + setWindowBounds(); }; var onWindowClosed = function() { @@ -472,6 +529,7 @@ }; windowClosedInternally = false; + var options = { 'id': 'play_store_wnd', 'resizable': false, @@ -481,8 +539,8 @@ color: '#ffffff' }, 'innerBounds': { - 'width': 960, - 'height': 688 + 'width': INNER_WIDTH, + 'height': INNER_HEIGHT } }; chrome.app.window.create('main.html', options, onWindowCreated);
diff --git a/chrome/browser/resources/chromeos/arc_support/lso.css b/chrome/browser/resources/chromeos/arc_support/lso.css new file mode 100644 index 0000000..3e5556544 --- /dev/null +++ b/chrome/browser/resources/chromeos/arc_support/lso.css
@@ -0,0 +1,20 @@ +/** + * 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. + */ + +::-webkit-scrollbar { + background: transparent; + height: 4px; + width: 4px; +} + +::-webkit-scrollbar-thumb { + background: rgba(0, 0, 0, 0.3); + height: 16px; +} + +::-webkit-scrollbar-thumb:hover { + background: rgba(0, 0, 0, 0.2); +}
diff --git a/chrome/browser/resources/chromeos/arc_support/main.css b/chrome/browser/resources/chromeos/arc_support/main.css index 1ca1369a..a71d6563 100644 --- a/chrome/browser/resources/chromeos/arc_support/main.css +++ b/chrome/browser/resources/chromeos/arc_support/main.css
@@ -15,7 +15,24 @@ width: 100%; } +::-webkit-scrollbar { + background: transparent; + height: 4px; + width: 4px; +} + +::-webkit-scrollbar-thumb { + background: rgba(0, 0, 0, 0.3); + height: 16px; +} + +::-webkit-scrollbar-thumb:hover { + background: rgba(0, 0, 0, 0.2); +} + #arc-support { + flex: auto; + overflow: hidden; width: 960px; } @@ -34,6 +51,13 @@ width: 16px; } +.content { + /* Default window inner height (688px) minus image caption height (300px) */ + height: 388px; + margin: 0; + padding: 0; +} + .image-header { display: block; height: 300px; @@ -41,7 +65,16 @@ width: 960px; } +.scrollable { + flex: auto; + margin: 0; + overflow: auto; + padding: 0; +} + .section { + display: flex; + flex-direction: column; text-align: center; } @@ -54,7 +87,6 @@ .section-flex { display: flex; flex-direction: column; - height: 688px; } .section-checkbox-container {
diff --git a/chrome/browser/resources/chromeos/arc_support/main.html b/chrome/browser/resources/chromeos/arc_support/main.html index 4cd3b6d..c9dd9b23 100644 --- a/chrome/browser/resources/chromeos/arc_support/main.html +++ b/chrome/browser/resources/chromeos/arc_support/main.html
@@ -44,40 +44,55 @@ <body> <div id="terms-loading" class="section"> <img class="image-header" src="images/header.png"> - <p class="text-title" i18n-content="greetingHeader"></p> - <p class="text-desc" i18n-content="greetingDescription"></p> - <paper-progress class="blue" indeterminate></paper-progress> + <div class="scrollable"> + <div class="content"> + <p class="text-title" i18n-content="greetingHeader"></p> + <p class="text-desc" i18n-content="greetingDescription"></p> + <paper-progress class="blue" indeterminate></paper-progress> + </div> + </div> </div> - <div id="terms" class="section section-flex" hidden> + <div id="terms" class="section" hidden> <img class="image-header" src="images/header.png"> - <p class="text-title" i18n-content="greetingHeader"></p> - <p class="text-desc" i18n-content="greetingDescription"></p> - <p class="text-terms-title" i18n-content="termsOfService"></p> - <div class="section-terms" id ="terms-container"> - <webview id="terms-view" partition="persist:arc_support"></webview> - </div> - <div class="layout horizontal section-checkbox-container"> - <input type="checkbox" class="checkbox-option" id="enable-metrics" hidden> - <p class="checkbox-text" id="text-metrics"></p> - </div> - <div id="section-backup-restore" class="layout horizontal - section-checkbox-container"> - <input type="checkbox" class="checkbox-option" id="enable-backup-restore"> - <p class="checkbox-text" id="text-backup-restore"></p> - </div> - <div class="layout horizontal end-justified section-buttons"> - <paper-button class="white" id="button-cancel" - i18n-content="buttonCancel"> - </paper-button> - <div class="button-separator"></div> - <paper-button class="blue" id="button-agree" i18n-content="buttonAgree"> - </paper-button> + <div class="scrollable" > + <div class="content section-flex"> + <p class="text-title" i18n-content="greetingHeader"></p> + <p class="text-desc" i18n-content="greetingDescription"></p> + <p class="text-terms-title" i18n-content="termsOfService"></p> + <div class="section-terms" id ="terms-container"> + <webview id="terms-view" partition="persist:arc_support"></webview> + </div> + <div class="layout horizontal section-checkbox-container"> + <input type="checkbox" class="checkbox-option" id="enable-metrics" + hidden> + <p class="checkbox-text" id="text-metrics"></p> + </div> + <div id="section-backup-restore" class="layout horizontal + section-checkbox-container"> + <input type="checkbox" class="checkbox-option" + id="enable-backup-restore"> + <p class="checkbox-text" id="text-backup-restore"></p> + </div> + <div class="layout horizontal end-justified section-buttons"> + <paper-button class="white" id="button-cancel" + i18n-content="buttonCancel"> + </paper-button> + <div class="button-separator"></div> + <paper-button class="blue" id="button-agree" + i18n-content="buttonAgree"> + </paper-button> + </div> + </div> </div> </div> <div id="lso-loading" class="section" hidden> <img class="image-header" src="images/header.png"> - <paper-progress class="blue" indeterminate></paper-progress> - <p class="text-status" i18n-content=progressLsoLoading></p> + <div class="scrollable"> + <div class="content"> + <paper-progress class="blue" indeterminate></paper-progress> + <p class="text-status" i18n-content=progressLsoLoading></p> + </div> + </div> </div> <div id="lso" class="section" hidden> <img class="image-header" src="images/header.png"> @@ -85,18 +100,26 @@ </div> <div id="arc-loading" class="section" hidden> <img class="image-header" src="images/header.png"> - <paper-progress class="blue" indeterminate></paper-progress> - <p class="text-status" i18n-content="progressAndroidLoading"></p> + <div class="scrollable"> + <div class="content"> + <paper-progress class="blue" indeterminate></paper-progress> + <p class="text-status" i18n-content="progressAndroidLoading"></p> + </div> + </div> </div> <div id="error" class="section" hidden> <img class="image-header" src="images/header.png"> - <paper-progress class="red" value="100" max="100" ></paper-progress> - <p class="text-status" id="error-message"></p> - <paper-button class="blue" id="button-send-feedback" - i18n-content="buttonSendFeedback"> - </paper-button> - <paper-button class="blue" id="button-retry" i18n-content="buttonRetry"> - </paper-button> + <div class="scrollable"> + <div class="content"> + <paper-progress class="red" value="100" max="100" ></paper-progress> + <p class="text-status" id="error-message"></p> + <paper-button class="blue" id="button-send-feedback" + i18n-content="buttonSendFeedback"> + </paper-button> + <paper-button class="blue" id="button-retry" i18n-content="buttonRetry"> + </paper-button> + </div> + </div> </div> </body> </html>
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd index 8cd5d2958..22d61ef 100644 --- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd +++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
@@ -1,6 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> -<grit base_dir="." current_release="1" enc_check="möl" latest_public_release="0" source_lang_id="en"> +<grit base_dir="." current_release="1" latest_public_release="0" + output_all_resource_defines="false" enc_check="möl" source_lang_id="en"> <outputs> <output filename="_locales/am/messages.json" type="chrome_messages_json" lang="am"/> <output filename="_locales/ar/messages.json" type="chrome_messages_json" lang="ar"/>
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_oobe.html b/chrome/browser/resources/chromeos/login/custom_elements_oobe.html index 40599cd77..69db270 100644 --- a/chrome/browser/resources/chromeos/login/custom_elements_oobe.html +++ b/chrome/browser/resources/chromeos/login/custom_elements_oobe.html
@@ -16,6 +16,7 @@ <include src="navigation_bar.html"> <include src="oobe_buttons.html"> <include src="oobe_card.html"> +<include src="oobe_dialog.html"> <include src="oobe_welcome.html"> <script src="chrome://oobe/custom_elements.js"></script>
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_oobe.js b/chrome/browser/resources/chromeos/login/custom_elements_oobe.js index bbef3bc4..347df431 100644 --- a/chrome/browser/resources/chromeos/login/custom_elements_oobe.js +++ b/chrome/browser/resources/chromeos/login/custom_elements_oobe.js
@@ -23,4 +23,5 @@ <include src="navigation_bar.js"> <include src="oobe_buttons.js"> <include src="oobe_card.js"> +<include src="oobe_dialog.js"> <include src="oobe_welcome.js">
diff --git a/chrome/browser/resources/chromeos/login/login_non_lock_shared.html b/chrome/browser/resources/chromeos/login/login_non_lock_shared.html index 4badc40..10ac9cdd 100644 --- a/chrome/browser/resources/chromeos/login/login_non_lock_shared.html +++ b/chrome/browser/resources/chromeos/login/login_non_lock_shared.html
@@ -35,4 +35,3 @@ <link rel="stylesheet" href="../../options/chromeos/bluetooth.css"> <script src="chrome://oobe/keyboard_utils.js"></script> -<script src="chrome://resources/js/polymer_config.js"></script>
diff --git a/chrome/browser/resources/chromeos/login/login_shared.html b/chrome/browser/resources/chromeos/login/login_shared.html index 144c679..1f9eefc 100644 --- a/chrome/browser/resources/chromeos/login/login_shared.html +++ b/chrome/browser/resources/chromeos/login/login_shared.html
@@ -6,6 +6,8 @@ Any additional include increases the lock screen initialization time. --> +<!-- This must be the first import in all login pages. --> +<link rel="import" href="chrome://resources/html/polymer.html"> <link rel="stylesheet" href="chrome://resources/css/butter_bar.css"> <link rel="stylesheet" href="chrome://resources/css/dialogs.css"> <link rel="stylesheet" href="chrome://resources/css/list.css">
diff --git a/chrome/browser/resources/chromeos/login/oobe_dialog.css b/chrome/browser/resources/chromeos/login/oobe_dialog.css new file mode 100644 index 0000000..4b4e4959 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/oobe_dialog.css
@@ -0,0 +1,74 @@ +/* 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. */ + +:host { + display: flex; + flex-direction: column; + position: relative; +} + +.oobe-icon-div { + --iron-icon-height: 20px; + --iron-icon-width: 20px; + color: var(--google-blue-500); +} + +.oobe-header { + background-color: white; + color: black; + height: 150px; +} + +.oobe-footer { + background-color: white; + position: relative; +} + +.header-container { + padding: 50px 40px 18px; +} + +.footer-container { + padding: 24px 40px 34px; +} + +::content div.oobe-body-text { + margin-bottom: 24px; +} + +::content div.oobe-body-text p { + color: rgba(0, 0, 0, 0.87); + font-size: 14px; + line-height: 20px; + margin: 0; +} + +::content h1.welcome-message { + color: rgba(0, 0, 0, 0.87); + font-size: 20px; + font-weight: normal; + margin-bottom: 0; +} + +::content h1.welcome-message-hint { + color: rgba(0, 0, 0, 0.87); + font-size: 12px; + font-weight: normal; + margin-bottom: 0; +} + +.overlay { + background-color: rgba(0, 0, 0, 0.5); + display: none; + height: 100%; + position: absolute; + right: 0; + top: 0; + width: 100%; + z-index: 11; +} + +:host(.full-disabled) #full-overlay, +:host(.disabled) #bottom-overlay, +
diff --git a/chrome/browser/resources/chromeos/login/oobe_dialog.html b/chrome/browser/resources/chromeos/login/oobe_dialog.html new file mode 100644 index 0000000..80b000c --- /dev/null +++ b/chrome/browser/resources/chromeos/login/oobe_dialog.html
@@ -0,0 +1,45 @@ +<!-- 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. --> + +<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> + +<!-- + Simple OOBE card which should be used for OOBE UI elements. + It has blue header and grey footer. + + Example: + <oobe-dialog> + <iron-icon ... class="oobe-icon"> + <div class="header flex vertical layout end-justified start"> + ... + </div> + <oobe-input-form class="footer" ...> + </oobe-input-form> + </oobe-dialog> + + Add class |header| to all which you want to go inside the header. Similar + with clases |footer| and |oobe-icon|. +--> +<dom-module name="oobe-dialog"> + <link rel="stylesheet" href="oobe_dialog.css"> + <template> + <div class="oobe-header vertical layout relative"> + <div class="header-container flex vertical layout relative"> + <div class="oobe-icon-div"> + <content select=".oobe-icon"></content> + </div> + <content select=".header"></content> + </div> + </div> + <div class="oobe-footer flex vertical layout"> + <div class="footer-container flex vertical layout"> + <content select=".footer"></content> + </div> + <div id="bottom-overlay" class="overlay"></div> + </div> + <div id="full-overlay" class="overlay"></div> + </template> +</dom-module> +
diff --git a/chrome/browser/resources/chromeos/login/oobe_dialog.js b/chrome/browser/resources/chromeos/login/oobe_dialog.js new file mode 100644 index 0000000..8dd5bc3 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/oobe_dialog.js
@@ -0,0 +1,5 @@ +// 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. + +Polymer({is: 'oobe-dialog'});
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.html b/chrome/browser/resources/chromeos/login/oobe_welcome.html index a666a05..d4a2e85a 100644 --- a/chrome/browser/resources/chromeos/login/oobe_welcome.html +++ b/chrome/browser/resources/chromeos/login/oobe_welcome.html
@@ -2,12 +2,26 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> +<link rel="import" href="chrome://resources/cr_elements/network/cr_network_icon.html"> +<link rel="import" href="chrome://resources/cr_elements/network/cr_network_select.html"> +<link rel="import" href="chrome://resources/cr_elements/network/cr_onc_types.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/classes/iron-flex-layout.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html"> + +<iron-iconset-svg name="oobe-welcome" size="24"> + <svg> + <defs> + <g id="add"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"></path></g> + <g id="wifi"><path d="M1 9l2 2c4.97-4.97 13.03-4.97 18 0l2-2C16.93 2.93 7.08 2.93 1 9zm8 8l3 3 3-3c-1.65-1.66-4.34-1.66-6 0zm-4-4l2 2c2.76-2.76 7.24-2.76 10 0l2-2C15.14 9.14 8.87 9.14 5 13z"></path></g> + </defs> + </svg> +</iron-iconset-svg> <dom-module name="oobe-welcome-md"> <link rel="stylesheet" href="oobe_welcome.css"> <template> - <oobe-card class="fit"> + <oobe-card id="welcomeSection" class="fit" hidden="[[networkSelectionScreenShown]]"> <div class="header flex vertical layout end-justified start"> <h1 class="welcome-message" i18n-content="networkScreenGreeting"></h1> </div> @@ -27,6 +41,22 @@ </div> </div> </oobe-card> + <oobe-dialog id="networkSection" class="fit" hidden="[[!networkSelectionScreenShown]]"> + <iron-icon icon="oobe-welcome:wifi" class="oobe-icon"></iron-icon> + <div class="header flex vertical layout end-justified start"> + <h1 class="welcome-message" i18n-content="networkSectionTitle"></h1> + <h1 class="welcome-message-hint" i18n-content="networkSectionHint"></h1> + </div> + <div class="footer flex vertical layout justified"> + <cr-network-select id="networkSelect" + on-network-connected="onNetworkConnected_" + on-network-item-selected="onNetworkListNetworkItemSelected_" + on-custom-item-selected="onNetworkListCustomItemSelected_" + custom-items="[[_getNetworkCustomItems()]]" + max-height="280"> + </cr-network-select> + </div> + </oobe-dialog> </template> </dom-module>
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.js b/chrome/browser/resources/chromeos/login/oobe_welcome.js index 3500dcd..5b48931 100644 --- a/chrome/browser/resources/chromeos/login/oobe_welcome.js +++ b/chrome/browser/resources/chromeos/login/oobe_welcome.js
@@ -2,30 +2,187 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +/** + * @fileoverview Polymer element for displaying material design OOBE. + */ + Polymer({ is: 'oobe-welcome-md', properties: { - disabled: { - type: Boolean, - value: false, - }, + /** + * Currently selected system language. + */ currentLanguage: { type: String, value: 'English (US)', }, + + /** + * Flag that switches Welcome screen to Network Selection screen. + */ + networkSelectionScreenShown: { + type: Boolean, + value: false, + }, }, + /** + * GUID of the user-selected network. It is remembered after user taps on + * network entry. After we receive event "connected" on this network, + * OOBE will proceed. + */ + networkLastSelectedGuid_: '', + + /** + * Sets proper focus. + */ focus: function() { this.$.welcomeNextButton.focus(); }, + /** + * Handles "visible" event. + * @private + */ onAnimationFinish_: function() { this.focus(); }, + /** + * Returns custom items for network selector. + */ + _getNetworkCustomItems: function() { + var self = this; + return [ + { + customItemName: 'proxySettingsMenuName', + polymerIcon: 'oobe-welcome:add', + customData: { + onTap: function() { self.OpenProxySettingsDialog_(); }, + }, + }, + { + customItemName: 'addWiFiNetworkMenuName', + polymerIcon: 'oobe-welcome:add', + customData: { + onTap: function() { self.OpenAddWiFiNetworkDialog_(); }, + }, + }, + { + customItemName: 'addMobileNetworkMenuName', + polymerIcon: 'oobe-welcome:add', + customData: { + onTap: function() { self.OpenAddWiFiNetworkDialog_(); }, + }, + }, + ]; + }, + + /** + * Handle "Next" button for "Welcome" screen. + * + * @private + */ onWelcomeNextButtonClicked_: function() { + this.networkSelectionScreenShown = true; + }, + + /** + * Handle Networwork Setup screen "Proxy settings" button. + * + * @private + */ + OpenProxySettingsDialog_: function(item) { + chrome.send('launchProxySettingsDialog'); + }, + + /** + * Handle Networwork Setup screen "Add WiFi network" button. + * + * @private + */ + OpenAddWiFiNetworkDialog_: function(item) { + chrome.send('launchAddWiFiNetworkDialog'); + }, + + /** + * Handle Networwork Setup screen "Add cellular network" button. + * + * @private + */ + OpenAddMobileNetworkDialog_: function(item) { + chrome.send('launchAddMobileNetworkDialog'); + }, + + /** + * This is called when network setup is done. + * + * @private + */ + onSelectedNetworkConnected_: function() { $('oobe-connect').hidden = false; $('oobe-welcome-md').hidden = true; - } + }, + + /** + * This gets called when a network enters the 'Connected' state. + * + * @param {!{detail: !CrOnc.NetworkStateProperties}} event + * @private + */ + onNetworkConnected_: function(event) { + var state = event.detail; + if (state.GUID != this.networkLastSelectedGuid_) + return; + + this.onSelectedNetworkConnected_(); + }, + + /** + * This is called when user taps on network entry in networks list. + * + * @param {!{detail: !CrOnc.NetworkStateProperties}} event + * @private + */ + onNetworkListNetworkItemSelected_: function(event) { + var state = event.detail; + // If user has not previously made a selection and selected network + // is already connected, just continue to the next screen. + if (this.networkLastSelectedGuid_ == '' && + state.ConnectionState == CrOnc.ConnectionState.CONNECTED) { + this.onSelectedNetworkConnected_(); + } + + // If user has previously selected another network, there + // is pending connection attempt. So even if new selection is currently + // connected, it may get disconnected at any time. + // So just send one more connection request to cancel current attempts. + this.networkLastSelectedGuid_ = state.GUID; + + var self = this; + var networkStateCopy = Object.assign({}, state); + + chrome.networkingPrivate.startConnect(state.GUID, function() { + var lastError = chrome.runtime.lastError; + if (!lastError) + return; + + if (lastError.message == 'connected') { + self.onNetworkConnected_({'detail': networkStateCopy}); + return; + } + + if (lastError.message != 'connecting') + console.error('networkingPrivate.startConnect error: ' + lastError); + }); + }, + + /** + * @param {!Event} event + */ + onNetworkListCustomItemSelected_: function(e) { + var itemState = e.detail; + itemState.customData.onTap(); + }, });
diff --git a/chrome/browser/resources/chromeos/quick_unlock/compiled_resources2.gyp b/chrome/browser/resources/chromeos/quick_unlock/compiled_resources2.gyp index 3de88518..0c166bf 100644 --- a/chrome/browser/resources/chromeos/quick_unlock/compiled_resources2.gyp +++ b/chrome/browser/resources/chromeos/quick_unlock/compiled_resources2.gyp
@@ -7,7 +7,8 @@ 'target_name': 'pin_keyboard', 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', - ], + '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-button/compiled_resources2.gyp:paper-button-extracted', + ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], }, ],
diff --git a/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js b/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js index f9f5873..90b32bb1 100644 --- a/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js +++ b/chrome/browser/resources/chromeos/quick_unlock/pin_keyboard.js
@@ -69,10 +69,21 @@ this.$$('#pin-input').focus(); }, - /** Called when a keypad number has been tapped. */ + /** + * Called when a keypad number has been tapped. + * @param {!{target: !PaperButtonElement}} event + * @private + */ onNumberTap_: function(event, detail) { var numberValue = event.target.getAttribute('value'); this.value += numberValue; + + // If a number button is clicked, we do not want to switch focus to the + // button, therefore we transfer focus back to the input, but if a number + // button is tabbed into, it should keep focus, so users can use tab and + // spacebar/return to enter their PIN. + if (!event.target.receivedFocusFromKeyboard) + this.focus(); }, /** Fires a submit event with the current PIN value. */
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd index e87619cf..1910b1c 100644 --- a/chrome/browser/resources/component_extension_resources.grd +++ b/chrome/browser/resources/component_extension_resources.grd
@@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- This comment is only here because changes to resources are not picked up without changes to the corresponding grd file. --> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/component_extension_resources.h" type="rc_header"> <emit emit_type='prepend'></emit> @@ -146,15 +146,13 @@ <include name="IDR_FIRST_RUN_DIALOG_ICON_256" file="chromeos/first_run/app/icon/256.png" type="BINDATA" /> <include name="IDR_ARC_SUPPORT_BACKGROUND_JS" file="chromeos/arc_support/background.js" flattenhtml="true" type="BINDATA" /> <include name="IDR_ARC_SUPPORT_MAIN_CSS" file="chromeos/arc_support/main.css" type="BINDATA" /> + <include name="IDR_ARC_SUPPORT_LSO_CSS" file="chromeos/arc_support/lso.css" type="BINDATA" /> <include name="IDR_ARC_SUPPORT_PLAYSTORE_CSS" file="chromeos/arc_support/playstore.css" type="BINDATA" /> <include name="IDR_ARC_SUPPORT_PLAYSTORE_JS" file="chromeos/arc_support/playstore.js" type="BINDATA" /> <include name="IDR_ARC_SUPPORT_MAIN" file="chromeos/arc_support/main.html" allowexternalscript="true" type="BINDATA" /> <include name="IDR_ARC_SUPPORT_ICON" file="chromeos/arc_support/icon/48.png" type="BINDATA" /> <include name="IDR_ARC_SUPPORT_ICON_HEADER" file="chromeos/arc_support/images/header.png" type="BINDATA" /> </if> - <if expr="enable_settings_app"> - <include name="IDR_SETTINGS_APP_JS" file="settings_app/settings_app.js" type="BINDATA" /> - </if> <if expr="enable_plugins"> <include name="IDR_PDF_INDEX_CSS" file="pdf/index.css" allowexternalscript="true" type="BINDATA" /> <include name="IDR_PDF_INDEX_HTML" file="pdf/index.html" allowexternalscript="true" type="BINDATA" />
diff --git a/chrome/browser/resources/help/help_content.css b/chrome/browser/resources/help/help_content.css index b9b7756a..4c47256 100644 --- a/chrome/browser/resources/help/help_content.css +++ b/chrome/browser/resources/help/help_content.css
@@ -108,13 +108,13 @@ } #eol-status-message-container { - -webkit-margin-start: 12px; + -webkit-margin-start: 8px; display: inline-block; vertical-align: middle; } #update-status-message-container { - -webkit-margin-start: 12px; + -webkit-margin-start: 8px; display: inline-block; vertical-align: middle; }
diff --git a/chrome/browser/resources/invalidations_resources.grd b/chrome/browser/resources/invalidations_resources.grd index 2a394a00..8fdd278a 100644 --- a/chrome/browser/resources/invalidations_resources.grd +++ b/chrome/browser/resources/invalidations_resources.grd
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/invalidations_resources.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/resources/local_ntp/most_visited_single.js b/chrome/browser/resources/local_ntp/most_visited_single.js index 817fd76..89b6adfd 100644 --- a/chrome/browser/resources/local_ntp/most_visited_single.js +++ b/chrome/browser/resources/local_ntp/most_visited_single.js
@@ -23,8 +23,8 @@ // Indicates a tile was rendered, no matter if it's a thumbnail, a gray tile // or an external tile. NTP_TILE: 2, - // A NTP Tile has finished loading (successfully or failing). - NTP_TILE_LOADED: 10, + // All NTP Tiles have finished loading (successfully or failing). + NTP_ALL_TILES_LOADED: 11, }; @@ -133,7 +133,7 @@ loadedCounter -= 1; if (loadedCounter <= 0) { showTiles(); - logEvent(LOG_TYPE.NTP_TILE_LOADED); + logEvent(LOG_TYPE.NTP_ALL_TILES_LOADED); window.parent.postMessage({cmd: 'loaded'}, DOMAIN_ORIGIN); loadedCounter = 1; }
diff --git a/chrome/browser/resources/md_extensions/item.js b/chrome/browser/resources/md_extensions/item.js index d2910d97..6f043c66 100644 --- a/chrome/browser/resources/md_extensions/item.js +++ b/chrome/browser/resources/md_extensions/item.js
@@ -62,6 +62,8 @@ var Item = Polymer({ is: 'extensions-item', + behaviors: [I18nBehavior], + properties: { // The item's delegate, or null. delegate: { @@ -74,23 +76,20 @@ value: false, }, - // Whether or not the expanded view of the item is shown. - showingDetails_: { - type: Boolean, - value: false, - }, - // The underlying ExtensionInfo itself. Public for use in declarative // bindings. /** @type {chrome.developerPrivate.ExtensionInfo} */ data: { type: Object, }, - }, - behaviors: [ - I18nBehavior, - ], + // Whether or not the expanded view of the item is shown. + /** @private */ + showingDetails_: { + type: Boolean, + value: false, + }, + }, observers: [ 'observeIdVisibility_(inDevMode, showingDetails_, data.id)',
diff --git a/chrome/browser/resources/md_extensions/manager.js b/chrome/browser/resources/md_extensions/manager.js index b39275e..4f0596e 100644 --- a/chrome/browser/resources/md_extensions/manager.js +++ b/chrome/browser/resources/md_extensions/manager.js
@@ -43,6 +43,8 @@ var Manager = Polymer({ is: 'extensions-manager', + behaviors: [I18nBehavior], + properties: { /** @type {extensions.Sidebar} */ sidebar: Object, @@ -73,10 +75,6 @@ }, }, - behaviors: [ - I18nBehavior, - ], - listeners: { 'items-list.extension-item-show-details': 'showItemDetails_', },
diff --git a/chrome/browser/resources/md_extensions/shortcut_input.js b/chrome/browser/resources/md_extensions/shortcut_input.js index e32cc6e2..6e54fb5 100644 --- a/chrome/browser/resources/md_extensions/shortcut_input.js +++ b/chrome/browser/resources/md_extensions/shortcut_input.js
@@ -9,6 +9,8 @@ var ShortcutInput = Polymer({ is: 'extensions-shortcut-input', + behaviors: [I18nBehavior], + properties: { item: { type: String, @@ -34,8 +36,6 @@ }, }, - behaviors: [I18nBehavior], - ready: function() { var node = this.$['input']; node.addEventListener('mouseup', this.startCapture_.bind(this));
diff --git a/chrome/browser/resources/md_extensions/sidebar.js b/chrome/browser/resources/md_extensions/sidebar.js index 7eab9465..55e62fa 100644 --- a/chrome/browser/resources/md_extensions/sidebar.js +++ b/chrome/browser/resources/md_extensions/sidebar.js
@@ -49,6 +49,8 @@ var Sidebar = Polymer({ is: 'extensions-sidebar', + behaviors: [I18nBehavior], + properties: { inDevMode: { type: Boolean, @@ -56,8 +58,6 @@ }, }, - behaviors: [I18nBehavior], - /** @param {extensions.SidebarDelegate} delegate */ setDelegate: function(delegate) { /** @private {extensions.SidebarDelegate} */
diff --git a/chrome/browser/resources/md_history/app.html b/chrome/browser/resources/md_history/app.html index a3da52df..fb4c2ee1 100644 --- a/chrome/browser/resources/md_history/app.html +++ b/chrome/browser/resources/md_history/app.html
@@ -52,7 +52,7 @@ <div id="main-container"> <iron-pages id="content" attr-for-selected="id" selected="[[selectedPage_]]"> - <history-list-container id="history" query-state="[[queryState_]]" + <history-list-container id="history" query-state="{{queryState_}}" query-result="[[queryResult_]]" grouped="[[grouped_]]"> </history-list-container> <template is="dom-if" if="[[syncedTabsSelected_(selectedPage_)]]">
diff --git a/chrome/browser/resources/md_history/browser_service.js b/chrome/browser/resources/md_history/browser_service.js index 4fa10ac..e8790aae 100644 --- a/chrome/browser/resources/md_history/browser_service.js +++ b/chrome/browser/resources/md_history/browser_service.js
@@ -49,6 +49,10 @@ chrome.send('removeBookmark', [url]); }, + openClearBrowsingData: function() { + chrome.send('clearBrowsingData'); + }, + /** * @param {boolean} successful * @private
diff --git a/chrome/browser/resources/md_history/compiled_resources2.gyp b/chrome/browser/resources/md_history/compiled_resources2.gyp index cfc189a..52673654 100644 --- a/chrome/browser/resources/md_history/compiled_resources2.gyp +++ b/chrome/browser/resources/md_history/compiled_resources2.gyp
@@ -106,6 +106,7 @@ 'dependencies': [ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/app-layout/app-drawer/compiled_resources2.gyp:app-drawer-extracted', '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-selector/compiled_resources2.gyp:iron-selector-extracted', + 'browser_service', ], 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], },
diff --git a/chrome/browser/resources/md_history/side_bar.html b/chrome/browser/resources/md_history/side_bar.html index 9468875..37bdc02 100644 --- a/chrome/browser/resources/md_history/side_bar.html +++ b/chrome/browser/resources/md_history/side_bar.html
@@ -3,6 +3,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-selector/iron-selector.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> +<link rel="import" href="chrome://history/browser_service.html"> <link rel="import" href="chrome://history/shared_style.html"> <dom-module id="history-side-bar">
diff --git a/chrome/browser/resources/md_history/side_bar.js b/chrome/browser/resources/md_history/side_bar.js index 46291206..46cedad3 100644 --- a/chrome/browser/resources/md_history/side_bar.js +++ b/chrome/browser/resources/md_history/side_bar.js
@@ -36,6 +36,6 @@ * @private */ onClearBrowsingDataTap_: function() { - window.location.href = 'chrome://settings/clearBrowserData'; + md_history.BrowserService.getInstance().openClearBrowsingData(); }, });
diff --git a/chrome/browser/resources/md_policy/policy_resources.grd b/chrome/browser/resources/md_policy/policy_resources.grd index 50c9bcc..dc76f52 100644 --- a/chrome/browser/resources/md_policy/policy_resources.grd +++ b/chrome/browser/resources/md_policy/policy_resources.grd
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/policy_resources.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/resources/net_internals_resources.grd b/chrome/browser/resources/net_internals_resources.grd index 6b3aefe..5a00818 100644 --- a/chrome/browser/resources/net_internals_resources.grd +++ b/chrome/browser/resources/net_internals_resources.grd
@@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- This comment is only here because changes to resources are not picked up without changes to the corresponding grd file. --> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/net_internals_resources.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/resources/offline_pages/offline_internals.html b/chrome/browser/resources/offline_pages/offline_internals.html index 6bf82b1..9045a8ee 100644 --- a/chrome/browser/resources/offline_pages/offline_internals.html +++ b/chrome/browser/resources/offline_pages/offline_internals.html
@@ -50,6 +50,7 @@ <th>URL</th> <th>Namespace</th> <th>Size (Kb)</th> + <th>Expired</th> </tr> </thead> <tbody id="stored-pages"> </tbody>
diff --git a/chrome/browser/resources/offline_pages/offline_internals.js b/chrome/browser/resources/offline_pages/offline_internals.js index b4690eec4..3bfde97 100644 --- a/chrome/browser/resources/offline_pages/offline_internals.js +++ b/chrome/browser/resources/offline_pages/offline_internals.js
@@ -48,6 +48,10 @@ cell.textContent = Math.round(pages[i].size / 1024); row.appendChild(cell); + cell = document.createElement('td'); + cell.textContent = pages[i].isExpired; + row.appendChild(cell); + storedPagesTable.appendChild(row); } offlinePages = pages;
diff --git a/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js b/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js index 3649c55..f3312fb 100644 --- a/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js +++ b/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js
@@ -11,7 +11,8 @@ * size: string, * filePath: string, * lastAccessTime: number, - * accessCount: number + * accessCount: number, + * isExpired: string * }} */ var OfflinePage;
diff --git a/chrome/browser/resources/options/browser_options.html b/chrome/browser/resources/options/browser_options.html index f86d32e..553ccef 100644 --- a/chrome/browser/resources/options/browser_options.html +++ b/chrome/browser/resources/options/browser_options.html
@@ -277,11 +277,6 @@ </if> <div id="profiles-buttons"> <button id="profiles-create" i18n-content="profilesCreate"></button> -<if expr="enable_settings_app"> - <button id="profiles-app-list-switch" - i18n-content="profilesAppListSwitch" hidden> - </button> -</if> <button id="profiles-manage" i18n-content="profilesManage" disabled> </button> <button id="profiles-delete" i18n-content="profilesDelete"></button>
diff --git a/chrome/browser/resources/options/browser_options.js b/chrome/browser/resources/options/browser_options.js index 8d9e0320..1fdaa55 100644 --- a/chrome/browser/resources/options/browser_options.js +++ b/chrome/browser/resources/options/browser_options.js
@@ -389,12 +389,6 @@ ['Options_ShowCreateProfileDlg']); ManageProfileOverlay.showCreateDialog(); }; - if (OptionsPage.isSettingsApp()) { - $('profiles-app-list-switch').onclick = function(event) { - var selectedProfile = self.getSelectedProfileItem_(); - chrome.send('switchAppListProfile', [selectedProfile.filePath]); - }; - } $('profiles-manage').onclick = function(event) { chrome.send('metricsHandler:recordAction', ['Options_ShowEditProfileDlg']); @@ -483,7 +477,6 @@ PageManager.showPageByName('clearBrowserData'); chrome.send('coreOptionsUserMetricsAction', ['Options_ClearData']); }; - $('privacyClearDataButton').hidden = OptionsPage.isSettingsApp(); if ($('metrics-reporting-enabled')) { $('metrics-reporting-enabled').checked = @@ -1527,10 +1520,6 @@ $('profiles-manage').title = ''; $('profiles-delete').disabled = !profilesList.canDeleteItems || !hasSelection; - if (OptionsPage.isSettingsApp()) { - $('profiles-app-list-switch').disabled = !hasSelection || - selectedProfile.isCurrentProfile; - } var importData = $('import-data'); if (importData) { importData.disabled = $('import-data').disabled = hasSelection && @@ -1550,13 +1539,10 @@ var showSingleProfileView = !usingNewProfilesUI && numProfiles == 1; $('profiles-list').hidden = showSingleProfileView; $('profiles-single-message').hidden = !showSingleProfileView; - $('profiles-manage').hidden = - showSingleProfileView || OptionsPage.isSettingsApp(); + $('profiles-manage').hidden = showSingleProfileView; $('profiles-delete').textContent = showSingleProfileView ? loadTimeData.getString('profilesDeleteSingle') : loadTimeData.getString('profilesDelete'); - if (OptionsPage.isSettingsApp()) - $('profiles-app-list-switch').hidden = showSingleProfileView; }, /**
diff --git a/chrome/browser/resources/options/options.html b/chrome/browser/resources/options/options.html index 9318c51..026c99c 100644 --- a/chrome/browser/resources/options/options.html +++ b/chrome/browser/resources/options/options.html
@@ -71,9 +71,6 @@ <link rel="stylesheet" href="certificate_manager.css"> <link rel="stylesheet" href="certificate_tree.css"> </if> -<if expr="enable_settings_app"> -<link rel="stylesheet" href="options_settings_app.css"> -</if> <script src="chrome://resources/js/action_link.js"></script> <script src="chrome://resources/js/cr.js"></script> <script src="chrome://resources/js/event_tracker.js"></script>
diff --git a/chrome/browser/resources/options/options_bundle.js b/chrome/browser/resources/options/options_bundle.js index d6a330c..0c340bc 100644 --- a/chrome/browser/resources/options/options_bundle.js +++ b/chrome/browser/resources/options/options_bundle.js
@@ -129,6 +129,3 @@ <include src="../uber/uber_page_manager_observer.js"> <include src="../uber/uber_utils.js"> <include src="options.js"> -<if expr="enable_settings_app"> -<include src="options_settings_app.js"> -</if>
diff --git a/chrome/browser/resources/options/options_page.js b/chrome/browser/resources/options/options_page.js index ecff736..9700c74 100644 --- a/chrome/browser/resources/options/options_page.js +++ b/chrome/browser/resources/options/options_page.js
@@ -85,24 +85,6 @@ 'enablePepperFlashSettings'); } }, - - /** - * Sets whether Settings is shown as a standalone page in a window for the - * app launcher settings "app". - * @param {boolean} isSettingsApp Whether this page is shown standalone. - */ - setIsSettingsApp: function(isSettingsApp) { - document.documentElement.classList.toggle('settings-app', isSettingsApp); - }, - - /** - * Returns true if Settings is shown as an "app" (in a window by itself) - * for the app launcher settings "app". - * @return {boolean} Whether this page is shown standalone. - */ - isSettingsApp: function() { - return document.documentElement.classList.contains('settings-app'); - }, }; // Export
diff --git a/chrome/browser/resources/options/options_settings_app.css b/chrome/browser/resources/options/options_settings_app.css deleted file mode 100644 index e1bd6580..0000000 --- a/chrome/browser/resources/options/options_settings_app.css +++ /dev/null
@@ -1,47 +0,0 @@ -/* Copyright 2012 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. */ - -/* Don't use the large margin used for the navigation bar. Settings App uses a - * 20px margin for headings + 18px for sections. - */ -html.settings-app body.uber-frame { - -webkit-margin-start: 38px; -} - -/* There is a tweak in uber_shared.css to improve touch events around the - * navigation bar (which is not used for the settings app) in reaction to a - * webkit bug (wk95204). We need to reset back to the original style. - */ -@media(pointer:coarse) { - html.settings-app body.uber-frame section { - -webkit-padding-start: 18px; - } - html.settings-app body.uber-frame section > h3 { - -webkit-margin-start: -18px; - } -} - -html.settings-app body.uber-frame header { - left: 20px; - min-width: 400px; -} - -html.settings-app #content-settings-page .content-area { - -webkit-margin-start: 18px; -} - -/* Settings App is narrower due to no navigation margin, so the roomy language - * overlay needs to be trimmed down. 25% is taken off the original height and - * the width is trimmed proportional to (half) the reduction due to the removal - * of the left margin. - */ -html.settings-app .language-options-left { - height: 300px; - width: 228px; -} - -html.settings-app .language-options-right { - height: 300px; - width: 288px; -}
diff --git a/chrome/browser/resources/options/options_settings_app.js b/chrome/browser/resources/options/options_settings_app.js deleted file mode 100644 index 72d2928..0000000 --- a/chrome/browser/resources/options/options_settings_app.js +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2012 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. - -(function() { - if (document.location != 'chrome://settings-frame/options_settings_app.html') - return; - - OptionsPage.setIsSettingsApp(true); - - // Override the offset in the options page. - PageManager.horizontalOffset = 38; - - document.addEventListener('DOMContentLoaded', function() { - // Hide everything by default. - var sections = document.querySelectorAll('section'); - for (var i = 0; i < sections.length; i++) - sections[i].hidden = true; - - var whitelistedSections = [ - 'advanced-settings', - 'downloads-section', - 'handlers-section', - 'languages-section', - 'network-section', - 'notifications-section', - 'sync-section' - ]; - - for (var i = 0; i < whitelistedSections.length; i++) - $(whitelistedSections[i]).hidden = false; - - // Avoid showing an empty Users section on ash. Note that profiles-section - // is actually a div element, rather than section, so is not hidden after - // the querySelectorAll(), above. - $('sync-users-section').hidden = $('profiles-section').hidden; - - // Hide Import bookmarks and settings button. - $('import-data').hidden = true; - - // Hide create / edit / delete profile buttons. - $('profiles-create').hidden = true; - $('profiles-delete').hidden = true; - $('profiles-manage').hidden = true; - - // Remove the 'X'es on profiles in the profile list. - $('profiles-list').canDeleteItems = false; - }); - - loadTimeData.overrideValues(/** @type {!Object} */( - loadTimeData.getValue('settingsApp'))); -}());
diff --git a/chrome/browser/resources/options_resources.grd b/chrome/browser/resources/options_resources.grd index be34501..f517c41 100644 --- a/chrome/browser/resources/options_resources.grd +++ b/chrome/browser/resources/options_resources.grd
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/options_resources.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/resources/options_test_resources.grd b/chrome/browser/resources/options_test_resources.grd index 9e79550..a9220f9f 100644 --- a/chrome/browser/resources/options_test_resources.grd +++ b/chrome/browser/resources/options_test_resources.grd
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/options_test_resources.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/resources/password_manager_internals_resources.grd b/chrome/browser/resources/password_manager_internals_resources.grd index 367acb9..ed63cbb 100644 --- a/chrome/browser/resources/password_manager_internals_resources.grd +++ b/chrome/browser/resources/password_manager_internals_resources.grd
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/password_manager_internals_resources.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/resources/quota_internals_resources.grd b/chrome/browser/resources/quota_internals_resources.grd index c81a1c1..d077fc8f 100644 --- a/chrome/browser/resources/quota_internals_resources.grd +++ b/chrome/browser/resources/quota_internals_resources.grd
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/quota_internals_resources.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/resources/settings/about_page/about_page.html b/chrome/browser/resources/settings/about_page/about_page.html index 03a0025..10d4a34 100644 --- a/chrome/browser/resources/settings/about_page/about_page.html +++ b/chrome/browser/resources/settings/about_page/about_page.html
@@ -24,6 +24,10 @@ <dom-module id="settings-about-page"> <template> <style include="settings-shared settings-page-styles"> + .copyable { + -webkit-user-select: text; + } + .product-title { font-size: 20px; margin-bottom: auto; @@ -98,7 +102,7 @@ $i18n{learnMore} </a> </span> - <div class="secondary">$i18n{aboutBrowserVersion}</div> + <div class="secondary copyable">$i18n{aboutBrowserVersion}</div> </div> <span class="secondary-action"> <paper-button id="relaunch" class="secondary-button" @@ -140,11 +144,10 @@ <if expr="chromeos"> <div class="settings-box" on-tap="onDetailedBuildInfoTap_" actionable> - <!-- TODO(dpapad): Localize string. --> - Detailed build info + $i18n{aboutDetailedBuildInfo} </div> </if> - <div class="settings-box product-info"> + <div class="settings-box product-info copyable"> <div class="info-section"> <div class="secondary">$i18n{aboutProductTitle}</div> <div class="secondary">$i18n{aboutProductCopyright}</div> @@ -169,7 +172,7 @@ </neon-animatable> <if expr="chromeos"> <template is="dom-if" name="detailed-build-info"> - <settings-subpage page-title="Detailed build information"> + <settings-subpage page-title="$i18n{aboutDetailedBuildInfo}"> <settings-detailed-build-info></settings-detailed-build-info> </settings-subpage> </template>
diff --git a/chrome/browser/resources/settings/about_page/detailed_build_info.html b/chrome/browser/resources/settings/about_page/detailed_build_info.html index e31872c..6e87415 100644 --- a/chrome/browser/resources/settings/about_page/detailed_build_info.html +++ b/chrome/browser/resources/settings/about_page/detailed_build_info.html
@@ -10,26 +10,27 @@ <dom-module id="settings-detailed-build-info"> <template> - <style include="settings-shared"></style> + <style include="settings-shared"> + .secondary { + -webkit-user-select: text; + } + </style> <div class="settings-box two-line"> <div class="start"> - <!-- TODO(dpapad): Localize string --> - <div>Platform</div> + <div>$i18n{aboutPlatformLabel}</div> <div class="secondary" id="osVersion">[[versionInfo_.osVersion]]</div> </div> </div> <div class="settings-box two-line" hidden$="[[!shouldShowVersion_(versionInfo_.osFirmware)]]"> <div class="start"> - <!-- TODO(dpapad): Localize string --> - <div>Firmware</div> + <div>$i18n{aboutFirmwareLabel}</div> <div class="secondary" id="osFirmware">[[versionInfo_.osFirmware]]</div> </div> </div> <div class="settings-box two-line"> <div class="start"> - <!-- TODO(dpapad): Localize string --> - <div>Channel</div> + <div>$i18n{aboutChannelLabel}</div> <div class="secondary">[[currentlyOnChannelText_]]</div> </div> <div class="secondary-action"> @@ -46,15 +47,13 @@ <div class="settings-box two-line" hidden$="[[!shouldShowVersion_(versionInfo_.arcVersion)]]"> <div class="start"> - <!-- TODO(dpapad): Localize string --> - <div>ARC Version</div> + <div>$i18n{aboutArcVersionLabel}</div> <div class="secondary" id="arcVersion">[[versionInfo_.arcVersion]]</div> </div> </div> <div class="settings-box two-line"> <div class="start"> - <!-- TODO(dpapad): Localize string --> - <div>Blink</div> + <div>Blink</div><!-- No need to localize. --> <div class="secondary">$i18n{aboutBlinkVersion}</div> </div> </div> @@ -66,22 +65,19 @@ </div> <div class="settings-box two-line"> <div class="start"> - <!-- TODO(dpapad): Localize string --> - <div>User agent</div> + <div>$i18n{aboutUserAgentLabel}</div> <div class="secondary">$i18n{aboutUserAgent}</div> </div> </div> <div class="settings-box two-line"> <div class="start"> - <!-- TODO(dpapad): Localize string --> - <div>Command line</div> + <div>$i18n{aboutCommandLineLabel}</div> <div class="secondary">$i18n{aboutCommandLine}</div> </div> </div> <div class="settings-box two-line"> <div class="start"> - <!-- TODO(dpapad): Localize string --> - <div>Build date</div> + <div>$i18n{aboutBuildDateLabel}</div> <div class="secondary">$i18n{aboutBuildDate}</div> </div> </div>
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.html b/chrome/browser/resources/settings/appearance_page/appearance_page.html index 699cf79b..33a89ab1 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_page.html +++ b/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -5,7 +5,6 @@ <link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-button/paper-radio-button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> <link rel="import" href="/appearance_page/appearance_browser_proxy.html"> <link rel="import" href="/controls/settings_dropdown_menu.html"> <link rel="import" href="/controls/settings_input.html">
diff --git a/chrome/browser/resources/settings/compiled_resources2.gyp b/chrome/browser/resources/settings/compiled_resources2.gyp index ba6aece..bb021c6 100644 --- a/chrome/browser/resources/settings/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/compiled_resources2.gyp
@@ -58,6 +58,13 @@ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], }, { + 'target_name': 'route', + 'dependencies': [ + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + ], + 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { 'target_name': 'search_settings', 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
diff --git a/chrome/browser/resources/settings/controls/settings_dropdown_menu.html b/chrome/browser/resources/settings/controls/settings_dropdown_menu.html index 89654d1..3e9e3e5 100644 --- a/chrome/browser/resources/settings/controls/settings_dropdown_menu.html +++ b/chrome/browser/resources/settings/controls/settings_dropdown_menu.html
@@ -16,17 +16,16 @@ <paper-listbox class="dropdown-content" selected="{{selected_}}" attr-for-selected="data-value"> <template is="dom-repeat" items="[[menuOptions]]" initial-count="5"> - <!--TODO(dpapad): Use <button class="paper-item">..</button> once it - lands in paper-item-shared-styles.html--> - <div class="dropdown-item" role="option" data-value$="[[item.value]]"> + <button class="dropdown-item" role="option" + data-value$="[[item.value]]"> [[item.name]] - </div> + </button> </template> - <div class="dropdown-item" role="option" + <button class="dropdown-item" role="option" data-value$="[[notFoundValue_]]" hidden$="[[!isSelectedNotFound_(selected_)]]"> $i18n{custom} - </div> + </button> </paper-listbox> </paper-dropdown-menu> </template>
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.html b/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.html new file mode 100644 index 0000000..0853be3 --- /dev/null +++ b/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.html
@@ -0,0 +1,92 @@ +<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> +<link rel="import" href="chrome://resources/html/cr.html"> +<link rel="import" href="chrome://resources/html/i18n_behavior.html"> +<link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-dropdown-menu/paper-dropdown-menu.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-textarea.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-listbox/paper-listbox.html"> +<link rel="import" href="/settings_shared_css.html"> + +<dom-module id="settings-address-edit-dialog"> + <style include="settings-shared"> + .address-row { + display: flex; + } + + .address-column { + -webkit-margin-end: 16px; + margin-bottom: 8px; + width: calc((var(--paper-input-max-width) - 16px) / 2); + } + + .long { + width: var(--paper-input-max-width); + } + + #saveButton { + -webkit-margin-start: 8px; + } + </style> + <template> + <cr-dialog id="dialog"> + <div class="title">[[title_]]</div> + <div class="body"> + <template is="dom-repeat" items="[[addressWrapper_]]"> + <div class="address-row"> + <template is="dom-repeat" items="[[item]]"> + <template is="dom-if" if="[[item.isTextArea]]"> + <paper-textarea label="[[item.component.fieldName]]" + value="{{item.value}}" on-value-changed="updateCanSave_" + class$="address-column [[long_(item)]]" always-float-label> + </paper-textarea> + </template> + <template is="dom-if" if="[[!item.isTextArea]]"> + <paper-input type="text" label="[[item.component.fieldName]]" + always-float-label value="{{item.value}}" + on-value-changed="updateCanSave_" + class$="address-column [[long_(item)]]"></paper-input> + </template> + </template> + </div> + </template> + <div class="address-row"> + <paper-dropdown-menu class="country-dropdown address-column long" + on-value-changed="updateCanSave_" label="$i18n{addressCountry}" + always-float-label> + <paper-listbox id="countryList" class="dropdown-content" + selected="{{countryCode_}}" attr-for-selected="code"> + <template is="dom-repeat" items="[[countries_]]"> + <paper-item code="[[getCode_(item)]]" + disabled="[[isDivision_(item)]]"> + [[getName_(item)]] + </paper-item> + </template> + </paper-listbox> + </paper-dropdown-menu> + </div> + <div class="address-row"> + <paper-input id="phoneInput" type="text" label="$i18n{addressPhone}" + always-float-label class="address-column" + on-value-changed="updateCanSave_" value="{{phoneNumber_}}"> + </paper-input> + <paper-input id="emailInput" type="text" label="$i18n{addressEmail}" + on-value-changed="updateCanSave_" always-float-label + class="address-column long" value="{{email_}}"> + </paper-input> + </div> + </div> + <div class="button-container"> + <paper-button id="cancelButton" dialog-dismiss> + $i18n{cancel} + </paper-button> + <paper-button id="saveButton" class="action-button" + disabled="[[!canSave_]]" on-tap="onSaveButtonTap_"> + $i18n{save} + </paper-button> + </div> + </cr-dialog> + </template> + <script src="/passwords_and_forms_page/address_edit_dialog.js"></script> +</dom-module>
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.js b/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.js new file mode 100644 index 0000000..94556a7 --- /dev/null +++ b/chrome/browser/resources/settings/passwords_and_forms_page/address_edit_dialog.js
@@ -0,0 +1,373 @@ +// 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. + +/** + * @fileoverview 'password-edit-dialog' is the dialog that allows showing a + * saved password. + */ +(function() { +'use strict'; + +Polymer({ + is: 'settings-address-edit-dialog', + + behaviors: [ + I18nBehavior, + ], + + properties: { + /** @private {!chrome.autofillPrivate.AddressEntry} */ + address_: Object, + + /** @private */ + title_: String, + + /** @private {!Array<!chrome.autofillPrivate.CountryEntry>} */ + countries_: Array, + + /** @private {string|undefined} */ + countryCode_: { + type: String, + observer: 'onUpdateCountryCode_', + }, + + /** @private {!Array<!Array<!settings.address.AddressComponentUI>>} */ + addressWrapper_: Object, + + /** @private */ + phoneNumber_: { + type: String, + observer: 'onUpdatePhoneNumber_', + }, + + /** @private */ + email_: { + type: String, + observer: 'onUpdateEmail_', + }, + + /** @private */ + canSave_: Boolean, + }, + + /** @override */ + ready: function() { + this.countryInfo = + settings.address.CountryDetailManagerImpl.getInstance(); + + this.countryInfo.getCountryList().then(function(countryList) { + this.countries_ = countryList; + }.bind(this)); + }, + + /** + * Opens the dialog to edit |address| + * @param {!chrome.autofillPrivate.AddressEntry} address + */ + open: function(address) { + this.title_ = + this.i18n(address.guid ? 'editAddressTitle' : 'addAddressTitle'); + this.address_ = address; + + // |phoneNumbers| and |emailAddresses| are a single item array. + // See crbug.com/497934 for details. + this.phoneNumber_ = address.phoneNumbers ? address.phoneNumbers[0] : ''; + this.email_ = address.emailAddresses ? address.emailAddresses[0] : ''; + + if (this.countryCode_ == address.countryCode) + this.updateAddressWrapper_(); + else + this.countryCode_ = address.countryCode; // Updates the address wrapper. + + // Open is called on the dialog after the address wrapper has been updated. + }, + + /** + * Returns a class to denote how long this entry is. + * @param {settings.address.AddressComponentUI} setting + * @return {string} + */ + long_: function(setting) { + return setting.component.isLongField ? 'long' : ''; + }, + + /** + * Updates the wrapper that represents this address in the country's format. + * @private + */ + updateAddressWrapper_: function() { + var self = this; + + // Default to the last country used if no country code is provided. + var countryCode = self.countryCode_ || self.countries_[0].countryCode; + self.countryInfo.getAddressFormat(countryCode).then(function(format) { + /** @type {!Array<!Array<!settings.address.AddressComponentUI>>} */ + var wrapper = []; + format.components.forEach(function(component) { + /** @type {!Array<!settings.address.AddressComponentUI>} */ + var components = []; + wrapper.push(components); + + component.row.forEach(function(component) { + components.push(new settings.address.AddressComponentUI( + self.address_, component)); + }); + }); + self.addressWrapper_ = wrapper; + + // Flush dom before resize and savability updates. + Polymer.dom.flush(); + +/** + * TODO(hcarmona): Fix closure compiler to better understand |SettingsDialog|. + * @suppress {missingProperties} + */ +(function() { + self.$.dialog.notifyResize(); + + self.updateCanSave_(); + + self.fire('on-update-address-wrapper'); // For easier testing. + + if (!self.$.dialog.opened) + self.$.dialog.open(); +})(); + }); + }, + + updateCanSave_: function() { + var inputs = this.$.dialog.querySelectorAll('.address-column'); + + for (var i = 0; i < inputs.length; ++i) { + if (inputs[i].value) { + this.canSave_ = true; + this.fire('on-update-can-save'); // For easier testing. + return; + } + } + + this.canSave_ = false; + this.fire('on-update-can-save'); // For easier testing. + }, + + /** + * @param {!chrome.autofillPrivate.CountryEntry} country + * @return {string} + * @private + */ + getCode_: function(country) { + return country.countryCode || 'SPACER'; + }, + + /** + * @param {!chrome.autofillPrivate.CountryEntry} country + * @return {string} + * @private + */ + getName_: function(country) { + return country.name || '------'; + }, + + /** + * @param {!chrome.autofillPrivate.CountryEntry} country + * @return {boolean} + * @private + */ + isDivision_: function(country) { + return !country.countryCode; + }, + + /** + * Handler for tapping the save button. + * @private + */ + onSaveButtonTap_: function() { + // Set a default country if none is set. + if (!this.address_.countryCode) + this.address_.countryCode = this.countries_[0].countryCode; + + this.fire('save-address', this.address_); + this.$.dialog.close(); + }, + + /** + * Syncs the country code back to the address and rebuilds the address wrapper + * for the new location. + * @param {string|undefined} countryCode + * @private + */ + onUpdateCountryCode_: function(countryCode) { + this.address_.countryCode = countryCode; + this.updateAddressWrapper_(); + }, + + /** + * Syncs the phone number back to the address. An address can have only one + * phone number. Variants are deprecated. + * @param {string} phoneNumber + */ + onUpdatePhoneNumber_: function(phoneNumber) { + if (this.address_) + this.address_.phoneNumbers = [phoneNumber]; + }, + + /** + * Syncs the email back to the address. An address can have only one email. + * Variants are deprecated. + * @param {string} email + */ + onUpdateEmail_: function(email) { + if (this.address_) + this.address_.emailAddresses = [email]; + }, +}); +})(); + +cr.define('settings.address', function() { + /** + * Creates a wrapper against a single data member for an address. + * @param {!chrome.autofillPrivate.AddressEntry} address + * @param {!chrome.autofillPrivate.AddressComponent} component + * @constructor + */ + function AddressComponentUI(address, component) { + Object.defineProperty(this, 'value', { + get: function() { + return this.getValue_(); + }, + set: function(newValue) { + this.setValue_(newValue); + }, + }); + this.address_ = address; + this.component = component; + this.isTextArea = + component.field == chrome.autofillPrivate.AddressField.ADDRESS_LINES; + } + + AddressComponentUI.prototype = { + /** + * Gets the value from the address that's associated with this component. + * @return {string|undefined} + * @private + */ + getValue_: function() { + var address = this.address_; + switch (this.component.field) { + case chrome.autofillPrivate.AddressField.FULL_NAME: + // |fullNames| is a single item array. See crbug.com/497934 for + // details. + return address.fullNames ? address.fullNames[0] : undefined; + case chrome.autofillPrivate.AddressField.COMPANY_NAME: + return address.companyName; + case chrome.autofillPrivate.AddressField.ADDRESS_LINES: + return address.addressLines; + case chrome.autofillPrivate.AddressField.ADDRESS_LEVEL_1: + return address.addressLevel1; + case chrome.autofillPrivate.AddressField.ADDRESS_LEVEL_2: + return address.addressLevel2; + case chrome.autofillPrivate.AddressField.ADDRESS_LEVEL_3: + return address.addressLevel3; + case chrome.autofillPrivate.AddressField.POSTAL_CODE: + return address.postalCode; + case chrome.autofillPrivate.AddressField.SORTING_CODE: + return address.sortingCode; + case chrome.autofillPrivate.AddressField.COUNTRY_CODE: + return address.countryCode; + default: + assertNotReached(); + } + }, + + /** + * Sets the value in the address that's associated with this component. + * @param {string} value + * @private + */ + setValue_: function(value) { + var address = this.address_; + switch (this.component.field) { + case chrome.autofillPrivate.AddressField.FULL_NAME: + address.fullNames = [value]; + break; + case chrome.autofillPrivate.AddressField.COMPANY_NAME: + address.companyName = value; + break; + case chrome.autofillPrivate.AddressField.ADDRESS_LINES: + address.addressLines = value; + break; + case chrome.autofillPrivate.AddressField.ADDRESS_LEVEL_1: + address.addressLevel1 = value; + break; + case chrome.autofillPrivate.AddressField.ADDRESS_LEVEL_2: + address.addressLevel2 = value; + break; + case chrome.autofillPrivate.AddressField.ADDRESS_LEVEL_3: + address.addressLevel3 = value; + break; + case chrome.autofillPrivate.AddressField.POSTAL_CODE: + address.postalCode = value; + break; + case chrome.autofillPrivate.AddressField.SORTING_CODE: + address.sortingCode = value; + break; + case chrome.autofillPrivate.AddressField.COUNTRY_CODE: + address.countryCode = value; + break; + default: + assertNotReached(); + } + }, + }; + + /** @interface */ + function CountryDetailManager() {} + CountryDetailManager.prototype = { + /** + * Gets the list of available countries. + * The default country will be first, followed by a separator, followed by + * an alphabetized list of countries available. + * @return {!Promise<!Array<!chrome.autofillPrivate.CountryEntry>>} + */ + getCountryList: assertNotReached, + + /** + * Gets the address format for a given country code. + * @param {string} countryCode + * @return {!Promise<!chrome.autofillPrivate.AddressComponents>} + */ + getAddressFormat: assertNotReached, + }; + + /** + * Default implementation. Override for testing. + * @implements {settings.address.CountryDetailManager} + * @constructor + */ + function CountryDetailManagerImpl() {} + cr.addSingletonGetter(CountryDetailManagerImpl); + CountryDetailManagerImpl.prototype = { + __proto__: CountryDetailManager, + + /** @override */ + getCountryList: function() { + return new Promise(function(callback) { + chrome.autofillPrivate.getCountryList(callback); + }); + }, + + /** @override */ + getAddressFormat: function(countryCode) { + return new Promise(function(callback) { + chrome.autofillPrivate.getAddressComponents(countryCode, callback); + }); + }, + }; + + return { + AddressComponentUI: AddressComponentUI, + CountryDetailManager: CountryDetailManager, + CountryDetailManagerImpl: CountryDetailManagerImpl, + }; +});
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html b/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html index 730dd9e..138a0da1 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html +++ b/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.html
@@ -3,6 +3,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html"> +<link rel="import" href="/passwords_and_forms_page/address_edit_dialog.html"> <link rel="import" href="/passwords_and_forms_page/credit_card_edit_dialog.html"> <link rel="import" href="/passwords_and_forms_page/passwords_shared_css.html"> <link rel="import" href="/settings_shared_css.html"> @@ -67,6 +68,8 @@ <div id="menuRemoveAddress" class="list-item menu-item" on-tap="onMenuRemoveAddressTap_">$i18n{removeAddress}</div> </cr-shared-menu> + <settings-address-edit-dialog id="addressEditDialog"> + </settings-address-edit-dialog> <div class="heading">$i18n{creditCards}</div> <div class="item-list"> <div class="list-item column-header">
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js b/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js index 001cc0dd..6ba5811 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js +++ b/chrome/browser/resources/settings/passwords_and_forms_page/autofill_section.js
@@ -75,8 +75,8 @@ * @private */ onAddAddressTap_: function(e) { - // TODO(hcarmona): implement adding an address. e.preventDefault(); + this.$.addressEditDialog.open({}); }, /** @@ -88,9 +88,9 @@ /** @type {chrome.autofillPrivate.AddressEntry} */ var address = menu.itemData; - // TODO(hcarmona): implement editing a local address. - - if (!address.metadata.isLocal) + if (address.metadata.isLocal) + this.$.addressEditDialog.open(address); + else window.open(this.i18n('manageAddressesUrl')); menu.closeMenu();
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/compiled_resources2.gyp b/chrome/browser/resources/settings/passwords_and_forms_page/compiled_resources2.gyp index 6668e15..a61272a 100644 --- a/chrome/browser/resources/settings/passwords_and_forms_page/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/passwords_and_forms_page/compiled_resources2.gyp
@@ -22,11 +22,21 @@ 'dependencies': [ '<(DEPTH)/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources2.gyp:cr_shared_menu', '<(EXTERNS_GYP):autofill_private', + 'address_edit_dialog', 'credit_card_edit_dialog', ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], }, { + 'target_name': 'address_edit_dialog', + 'dependencies': [ + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', + '<(EXTERNS_GYP):autofill_private', + ], + 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { 'target_name': 'credit_card_edit_dialog', 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
diff --git a/chrome/browser/resources/settings/people_page/compiled_resources2.gyp b/chrome/browser/resources/settings/people_page/compiled_resources2.gyp index 34ce2e5..963e0bd5 100644 --- a/chrome/browser/resources/settings/people_page/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/people_page/compiled_resources2.gyp
@@ -86,6 +86,48 @@ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], }, { + 'target_name': 'quick_unlock_authenticate', + 'dependencies': [ + 'quick_unlock_routing_behavior', + '<(EXTERNS_GYP):quick_unlock_private', + ], + 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { + 'target_name': 'quick_unlock_choose_method', + 'dependencies': [ + 'quick_unlock_password_detect_behavior', + '../prefs/compiled_resources2.gyp:prefs_types', + '../prefs/compiled_resources2.gyp:prefs_behavior', + '<(EXTERNS_GYP):quick_unlock_private', + ], + 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { + 'target_name': 'quick_unlock_routing_behavior', + 'dependencies': [ + '../settings_page/compiled_resources2.gyp:settings_router', + ], + 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { + 'target_name': 'quick_unlock_password_detect_behavior', + 'dependencies': [ + 'quick_unlock_routing_behavior', + ], + 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { + 'target_name': 'quick_unlock_setup_pin', + 'dependencies': [ + 'quick_unlock_password_detect_behavior', + '../settings_page/compiled_resources2.gyp:settings_router', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior', + '<(EXTERNS_GYP):quick_unlock_private', + ], + 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { 'target_name': 'sync_page', 'dependencies': [ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', @@ -130,17 +172,5 @@ ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], }, - { - 'target_name': 'quick_unlock_routing_behavior', - 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], - }, - { - 'target_name': 'quick_unlock_authenticate', - 'dependencies': [ - 'quick_unlock_routing_behavior', - '<(EXTERNS_GYP):quick_unlock_private', - ], - 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], - }, ], }
diff --git a/chrome/browser/resources/settings/people_page/people_page.html b/chrome/browser/resources/settings/people_page/people_page.html index 8605081..d46ff15 100644 --- a/chrome/browser/resources/settings/people_page/people_page.html +++ b/chrome/browser/resources/settings/people_page/people_page.html
@@ -18,6 +18,8 @@ <link rel="import" href="/people_page/easy_unlock_browser_proxy.html"> <link rel="import" href="/people_page/easy_unlock_turn_off_dialog.html"> <link rel="import" href="/people_page/quick_unlock_authenticate.html"> +<link rel="import" href="/people_page/quick_unlock_choose_method.html"> +<link rel="import" href="/people_page/quick_unlock_setup_pin.html"> <link rel="import" href="/people_page/users_page.html"> </if> <if expr="not chromeos"> @@ -242,12 +244,29 @@ <template is="dom-if" name="quick-unlock-authenticate"> <settings-subpage page-title="$i18n{quickUnlockTitle}"> <settings-quick-unlock-authenticate - account-password="{{quickUnlockAccountPassword}}" + set-modes="{{quickUnlockSetModes}}" current-route="{{currentRoute}}" profile-name="[[profileName_]]"> </settings-quick-unlock-authenticate> </settings-subpage> </template> + <template is="dom-if" name="quick-unlock-choose-method"> + <settings-subpage page-title="$i18n{quickUnlockTitle}"> + <settings-quick-unlock-choose-method + set-modes="[[quickUnlockSetModes]]" + current-route="{{currentRoute}}" + prefs="{{prefs}}"> + </settings-quick-unlock-choose-method> + </settings-subpage> + </template> + <template is="dom-if" name="quick-unlock-setup-pin"> + <settings-subpage page-title="$i18n{quickUnlockTitle}"> + <settings-quick-unlock-setup-pin + set-modes="[[quickUnlockSetModes]]" + current-route="{{currentRoute}}"> + </settings-quick-unlock-setup-pin> + </settings-subpage> + </template> <template is="dom-if" name="users"> <settings-subpage page-title="$i18n{usersPageTitle}"> <settings-users-page prefs="{{prefs}}"></settings-users-page>
diff --git a/chrome/browser/resources/settings/people_page/quick_unlock_choose_method.html b/chrome/browser/resources/settings/people_page/quick_unlock_choose_method.html new file mode 100644 index 0000000..bff939b --- /dev/null +++ b/chrome/browser/resources/settings/people_page/quick_unlock_choose_method.html
@@ -0,0 +1,63 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html"> +<link rel="import" href="/people_page/pin_keyboard.html"> +<link rel="import" href="/people_page/quick_unlock_routing_behavior.html"> +<link rel="import" href="/people_page/quick_unlock_password_detect_behavior.html"> +<link rel="import" href="/prefs/prefs_behavior.html"> +<link rel="import" href="/settings_page/settings_section.html"> +<link rel="import" href="/settings_shared_css.html"> + + +<dom-module id="settings-quick-unlock-choose-method"> + <template> + <style include="settings-shared"></style> + <style> + #warning-message { + color: var(--paper-grey-500); + font-style: italic; + } + + .align-end { + justify-content: flex-end; + } + </style> + + <div> + <div class="settings-box"> + $i18n{quickUnlockChooseUnlockMethod} + </div> + + <div class="list-frame"> + <paper-radio-group selected="{{selectedUnlockType_}}"> + <paper-radio-button name="password"> + $i18n{quickUnlockUnlockMethodPassword} + </paper-radio-button> + <paper-radio-button name="pin+password"> + $i18n{quickUnlockUnlockMethodPinAndPassword} + </paper-radio-button> + <paper-radio-button name="none"> + $i18n{quickUnlockUnlockMethodNone} + </paper-radio-button> + </paper-radio-group> + </div> + + <div class="step" hidden$="[[!showSetupPin_(selectedUnlockType_)]]"> + <div class="settings-box continuation"> + <!-- TODO(jdufault): i18n once this string is finalized. --> + <span id="warning-message"> + Warning about how PIN is weaker than a password. + </span> + </div> + + <div class="align-end settings-box"> + <paper-button class="action-button" on-tap="onConfigurePin_"> + $i18n{quickUnlockConfigurePinButton} + </paper-button> + </div> + </div> + </div> + </template> + + <script src="quick_unlock_choose_method.js"></script> +</dom-module>
diff --git a/chrome/browser/resources/settings/people_page/quick_unlock_choose_method.js b/chrome/browser/resources/settings/people_page/quick_unlock_choose_method.js new file mode 100644 index 0000000..db0a579 --- /dev/null +++ b/chrome/browser/resources/settings/people_page/quick_unlock_choose_method.js
@@ -0,0 +1,183 @@ +// 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. + +/** + * @fileoverview + * 'settings-quick-unlock-choose-method' allows the user to change how they + * unlock their device. Note that setting up the unlock method is delegated + * to other elements. + * + * Example: + * + * <settings-quick-unlock-choose-method + * set-modes="[[quickUnlockSetModes]]" + * current-route="{{currentRoute}}" + * prefs="{{prefs}}"> + * </settings-quick-unlock-choose-method> + */ + +(function() { +'use strict'; + +/** @const */ var ENABLE_LOCK_SCREEN_PREF = 'settings.enable_screen_lock'; + +/** @enum {string} */ +var QuickUnlockUnlockType = { + VALUE_PENDING: 'value_pending', + NONE: 'none', + PASSWORD: 'password', + PIN_PASSWORD: 'pin+password' +}; + +Polymer({ + is: 'settings-quick-unlock-choose-method', + + behaviors: [ + PrefsBehavior, QuickUnlockPasswordDetectBehavior + ], + + properties: { + /** Preferences state. */ + prefs: { + type: Object, + notify: true, + }, + + /** + * The currently selected unlock type. + * @type {!QuickUnlockUnlockType} + * @private + */ + selectedUnlockType_: { + type: String, + notify: true, + value: QuickUnlockUnlockType.VALUE_PENDING, + observer: 'selectedUnlockTypeChanged_' + } + }, + + observers: [ + 'onRouteChanged_(currentRoute)', + 'onSetModesChanged_(setModes)' + ], + + /** @override */ + attached: function() { + CrSettingsPrefs.initialized.then(this.updateUnlockType_.bind(this)); + + this.boundOnPrefsChanged_ = function(prefs) { + for (var i = 0; i < prefs.length; ++i) { + if (prefs[i].key == ENABLE_LOCK_SCREEN_PREF) + this.updateUnlockType_(); + } + }.bind(this); + this.boundOnActiveModesChanged_ = this.updateUnlockType_.bind(this); + + chrome.settingsPrivate.onPrefsChanged.addListener( + this.boundOnPrefsChanged_); + chrome.quickUnlockPrivate.onActiveModesChanged.addListener( + this.boundOnActiveModesChanged_); + + this.askForPasswordIfUnset(); + }, + + /** @override */ + detached: function() { + chrome.settingsPrivate.onPrefsChanged.removeListener( + this.boundOnPrefsChanged_); + chrome.quickUnlockPrivate.onActiveModesChanged.removeListener( + this.boundOnActiveModesChanged_); + }, + + /** @private */ + onRouteChanged_: function() { + if (this.isScreenActive(QuickUnlockScreen.CHOOSE_METHOD)) + this.askForPasswordIfUnset(); + }, + + /** @private */ + onSetModesChanged_: function() { + if (this.isScreenActive(QuickUnlockScreen.CHOOSE_METHOD)) + this.askForPasswordIfUnset(); + }, + + /** + * Updates the selected unlock type radio group. This function will get called + * after preferences are initialized, after the quick unlock mode has been + * changed, and after the lockscreen preference has changed. + * + * @private + */ + updateUnlockType_: function() { + // The quickUnlockPrivate.onActiveModesChanged event could trigger this + // function before CrSettingsPrefs is initialized if another settings page + // changes the quick unlock state. + if (!CrSettingsPrefs.isInitialized) + return; + + if (!this.getPref(ENABLE_LOCK_SCREEN_PREF).value) { + this.selectedUnlockType_ = QuickUnlockUnlockType.NONE; + return; + } + + chrome.quickUnlockPrivate.getActiveModes(function(modes) { + if (modes.includes(chrome.quickUnlockPrivate.QuickUnlockMode.PIN)) { + this.selectedUnlockType_ = QuickUnlockUnlockType.PIN_PASSWORD; + } else if (this.selectedUnlockType_ != + QuickUnlockUnlockType.PIN_PASSWORD) { + // We don't want to clobber an existing PIN+PASSWORD state because the + // user needs to configure that option before actually using it. + // + // Specifically, this check is needed because this function gets called + // by the pref system after changing the unlock type from NONE to + // PIN+PASSWORD. Without the conditional assignment, this function would + // change the PIN+PASSWORD lock type to PASSWORD because the PIN hasn't + // been configured yet. + this.selectedUnlockType_ = QuickUnlockUnlockType.PASSWORD; + } + }.bind(this)); + }, + + /** + * Called when the unlock type has changed. + * @param {!string} selected The current unlock type. + * @param {?string} previous The old unlock type. undefined if not present. + * @private + */ + selectedUnlockTypeChanged_: function(selected, previous) { + // This method gets invoked when setting the initial value from the existing + // state. In that case, we don't need to bother updating the prefs. + if (!previous) + return; + + this.setPrefValue(ENABLE_LOCK_SCREEN_PREF, + selected != QuickUnlockUnlockType.NONE); + if (selected != QuickUnlockUnlockType.PIN_PASSWORD && this.setModes) { + this.setModes.call(null, [], [], function(didSet) { + assert(didSet, 'Failed to clear quick unlock modes'); + }); + } + }, + + /** + * Retruns true if the setup pin section should be shown. + * @param {!string} selectedUnlockType The current unlock type. Used to let + * polymer know about the dependency. + * @private + */ + showSetupPin_: function(selectedUnlockType) { + return selectedUnlockType === QuickUnlockUnlockType.PIN_PASSWORD; + }, + + /** @private */ + onConfigurePin_: function() { + this.currentRoute = { + page: 'basic', + section: 'people', + subpage: [QuickUnlockScreen.CHOOSE_METHOD, QuickUnlockScreen.SETUP_PIN] + }; + }, +}); + +})();
diff --git a/chrome/browser/resources/settings/people_page/quick_unlock_password_detect_behavior.html b/chrome/browser/resources/settings/people_page/quick_unlock_password_detect_behavior.html new file mode 100644 index 0000000..046bf74 --- /dev/null +++ b/chrome/browser/resources/settings/people_page/quick_unlock_password_detect_behavior.html
@@ -0,0 +1,2 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> +<script src="/people_page/quick_unlock_password_detect_behavior.js"></script>
diff --git a/chrome/browser/resources/settings/people_page/quick_unlock_password_detect_behavior.js b/chrome/browser/resources/settings/people_page/quick_unlock_password_detect_behavior.js new file mode 100644 index 0000000..3b67d36 --- /dev/null +++ b/chrome/browser/resources/settings/people_page/quick_unlock_password_detect_behavior.js
@@ -0,0 +1,30 @@ +// 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. + +/** + * @fileoverview + * Contains utilities for verifying the user has entered an account password. + */ + +/** @polymerBehavior */ +var QuickUnlockPasswordDetectBehavior = [QuickUnlockRoutingBehavior, { + properties: { + setModes: Object + }, + + /** + * Verifies that there is an account password available for the + * chrome.quickUnlockPrivate.setModes call. If there is no password, this will + * redirect to the authenticate screen. + */ + askForPasswordIfUnset: function() { + if (!this.setModes) { + this.currentRoute = { + page: 'basic', + section: 'people', + subpage: [QuickUnlockScreen.AUTHENTICATE] + }; + } + } +}];
diff --git a/chrome/browser/resources/settings/people_page/quick_unlock_routing_behavior.js b/chrome/browser/resources/settings/people_page/quick_unlock_routing_behavior.js index 7f5e23b..e1dcb421 100644 --- a/chrome/browser/resources/settings/people_page/quick_unlock_routing_behavior.js +++ b/chrome/browser/resources/settings/people_page/quick_unlock_routing_behavior.js
@@ -12,6 +12,7 @@ /** @polymerBehavior */ var QuickUnlockRoutingBehavior = { properties: { + /** @type {SettingsRoute} */ currentRoute: { type: Object, notify: true,
diff --git a/chrome/browser/resources/settings/people_page/quick_unlock_setup_pin.html b/chrome/browser/resources/settings/people_page/quick_unlock_setup_pin.html new file mode 100644 index 0000000..f5e2d487 --- /dev/null +++ b/chrome/browser/resources/settings/people_page/quick_unlock_setup_pin.html
@@ -0,0 +1,78 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> +<link rel="import" href="chrome://resources/html/i18n_behavior.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> +<link rel="import" href="/people_page/pin_keyboard.html"> +<link rel="import" href="/people_page/quick_unlock_password_detect_behavior.html"> +<link rel="import" href="/people_page/quick_unlock_routing_behavior.html"> +<link rel="import" href="/settings_page/settings_section.html"> +<link rel="import" href="/settings_shared_css.html"> + +<dom-module id="settings-quick-unlock-setup-pin"> + <template> + <style include="settings-shared"></style> + <style> + iron-icon { + -webkit-margin-end: var(--iron-icon-spacing); + } + + .warning { + color: var(--paper-grey-500); + } + + .warning > iron-icon { + --iron-icon-fill-color: var(--paper-grey-500); + } + + .error { + color: var(--paper-red-500); + } + + .error > iron-icon { + --iron-icon-fill-color: var(--paper-red-500); + } + + .align-center { + justify-content: center; + } + + .align-end { + justify-content: flex-end; + } + </style> + + <div> + <!-- Title; only shown if warning/error is hidden. --> + <div class="settings-box" hidden$="[[hasProblem_(problemMessage_)]]"> + <span>[[getTitleMessage_(isConfirmStep_)]]</span> + </div> + + <!-- Warning/error; only shown if title is hidden. --> + <div class$="[[problemClass_]] settings-box" + hidden$="[[!hasProblem_(problemMessage_)]]"> + <iron-icon icon="icons:warning"></iron-icon> + <span>[[problemMessage_]]</span> + </div> + + <!-- Pin keyboard --> + <div class="align-center settings-box continuation"> + <pin-keyboard on-pin-change="onPinChange_" on-submit="onPinSubmit_" + value="{{pinKeyboardValue_}}"></pin-keyboard> + </div> + + <div class="align-end settings-box"> + <paper-button class="cancel-button" on-tap="resetState_" + hidden$="[[!isConfirmStep_]]"> + $i18n{quickUnlockConfigurePinBackButton} + </paper-button> + + <paper-button class="action-button" on-tap="onPinSubmit_" + disabled$="[[!enableSubmit_]]"> + <span>[[getContinueMessage_(isConfirmStep_)]]</span> + </paper-button> + </div> + + </div> + </template> + + <script src="quick_unlock_setup_pin.js"></script> +</dom-module>
diff --git a/chrome/browser/resources/settings/people_page/quick_unlock_setup_pin.js b/chrome/browser/resources/settings/people_page/quick_unlock_setup_pin.js new file mode 100644 index 0000000..0d47e63 --- /dev/null +++ b/chrome/browser/resources/settings/people_page/quick_unlock_setup_pin.js
@@ -0,0 +1,300 @@ +// 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. + +/** + * @fileoverview + * 'settings-quick-unlock-setup-pin' is the settings page for choosing a PIN. + * + * Example: + * + * <settings-quick-unlock-setup-pin + * set-modes="[[quickUnlockSetModes]]" + * current-route="{{currentRoute}}"> + * </settings-quick-unlock-setup-pin> + */ + +(function() { +'use strict'; + +/** + * Metainformation about a problem message to pass to showProblem. |class| is + * the css class to show the problem message with. |messageId| is the i18n + * string id to use. + * @const + */ +var ProblemInfo = { + TOO_SHORT: { + messageId: 'quickUnlockConfigurePinChoosePinTooShort', + class: 'error' + }, + WEAK: { + messageId: 'quickUnlockConfigurePinChoosePinWeakPinWarning', + class: 'warning' + }, + MISMATCHED: { + messageId: 'quickUnlockConfigurePinMismatchedPins', + class: 'error' + } +}; + +/** + * A list of the top-10 most commmonly used PINs. This list is taken from + * www.datagenetics.com/blog/september32012/. + * @const + */ +var WEAK_PINS = [ + '1234', '1111', '0000', '1212', '7777', '1004', '2000', '4444', '2222', + '6969' +]; + +Polymer({ + is: 'settings-quick-unlock-setup-pin', + + behaviors: [ + QuickUnlockPasswordDetectBehavior, + I18nBehavior + ], + + properties: { + /** + * The current PIN keyboard value. + * @private + */ + pinKeyboardValue_: String, + + /** + * Stores the initial PIN value so it can be confirmed. + * @private + */ + initialPin_: String, + + /** + * The actual problem message to display. + * @private + */ + problemMessage_: String, + + /** + * The type of problem class to show (warning or error). + */ + problemClass_: String, + + /** + * Should the step-specific submit button be displayed? + * @private + */ + enableSubmit_: Boolean, + + /** + * The current step/subpage we are on. + * @private + */ + isConfirmStep_: { + type: Boolean, + value: false + }, + }, + + observers: [ + 'onRouteChanged_(currentRoute)', + 'onSetModesChanged_(setModes)' + ], + + /** @override */ + attached: function() { + this.resetState_(); + this.askForPasswordIfUnset(); + }, + + /** + * @param {!SettingsRoute} currentRoute + * @private + */ + onRouteChanged_: function(currentRoute) { + if (this.isScreenActive(QuickUnlockScreen.SETUP_PIN)) { + this.askForPasswordIfUnset(); + } else { + // If the user hits the back button, they can leave the element + // half-completed; therefore, reset state if the element is not active. + this.resetState_(); + } + }, + + /** @private */ + onSetModesChanged_: function() { + if (this.isScreenActive(QuickUnlockScreen.SETUP_PIN)) + this.askForPasswordIfUnset(); + }, + + /** + * Resets the element to the initial state. + * @private + */ + resetState_: function() { + this.initialPin_ = ''; + this.pinKeyboardValue_ = ''; + this.enableSubmit_ = false; + this.isConfirmStep_ = false; + this.onPinChange_(); + }, + + /** + * Returns true if the given PIN is likely easy to guess. + * @private + * @param {string} pin + * @return {boolean} + */ + isPinWeak_: function(pin) { + // Warn if it's a top-10 pin. + if (WEAK_PINS.includes(pin)) + return true; + + // Warn if the PIN is consecutive digits. + var delta = 0; + for (var i = 1; i < pin.length; ++i) { + var prev = Number(pin[i - 1]); + var num = Number(pin[i]); + if (Number.isNaN(prev) || Number.isNaN(num)) + return false; + delta = Math.max(delta, Math.abs(num - prev)); + } + + return delta <= 1; + }, + + /** + * Returns true if the given PIN matches PIN requirements, such as minimum + * length. + * @private + * @param {string|undefined} pin + * @return {boolean} + */ + isPinLongEnough_: function(pin) { + return !!pin && pin.length >= 4; + }, + + /** + * Returns true if the PIN is ready to be changed to a new value. + * @private + * @return {boolean} + */ + canSubmit_: function() { + return this.isPinLongEnough_(this.pinKeyboardValue_) && + this.initialPin_ == this.pinKeyboardValue_; + }, + + /** + * Notify the user about a problem. + * @private + * @param {!{messageId: string, class: string}} problemInfo + */ + showProblem_: function(problemInfo) { + this.problemMessage_ = this.i18n(problemInfo.messageId); + this.problemClass_ = problemInfo.class; + this.updateStyles(); + }, + + /** @private */ + hideProblem_: function() { + this.problemMessage_ = ''; + this.problemClass_ = ''; + }, + + /** @private */ + onPinChange_: function() { + if (!this.isConfirmStep_) { + var isPinLongEnough = this.isPinLongEnough_(this.pinKeyboardValue_); + var isWeak = isPinLongEnough && this.isPinWeak_(this.pinKeyboardValue_); + + if (!isPinLongEnough && this.pinKeyboardValue_) + this.showProblem_(ProblemInfo.TOO_SHORT); + else if (isWeak) + this.showProblem_(ProblemInfo.WEAK); + else + this.hideProblem_(); + + this.enableSubmit_ = isPinLongEnough; + + } else { + var canSubmit = this.canSubmit_(); + + if (!canSubmit && this.pinKeyboardValue_) + this.showProblem_(ProblemInfo.MISMATCHED); + else + this.hideProblem_(); + + this.enableSubmit_ = canSubmit; + } + }, + + /** @private */ + onPinSubmit_: function() { + if (!this.isConfirmStep_) { + if (this.isPinLongEnough_(this.pinKeyboardValue_)) { + this.initialPin_ = this.pinKeyboardValue_; + this.pinKeyboardValue_ = ''; + this.isConfirmStep_ = true; + this.onPinChange_(); + } + } else { + // onPinSubmit_ gets called if the user hits enter on the PIN keyboard. + // The PIN is not guaranteed to be valid in that case. + if (!this.canSubmit_()) + return; + + function onSetModesCompleted(didSet) { + if (!didSet) { + console.error('Failed to update pin'); + return; + } + + this.resetState_(); + this.currentRoute = { + page: 'basic', + section: 'people', + subpage: [QuickUnlockScreen.CHOOSE_METHOD] + }; + } + + this.setModes.call( + null, + [chrome.quickUnlockPrivate.QuickUnlockMode.PIN], + [this.pinKeyboardValue_], + onSetModesCompleted.bind(this)); + } + }, + + /** + * @private + * @param {string} problemMessage + * @return {boolean} + */ + hasProblem_: function(problemMessage) { + return !!problemMessage; + }, + + /** + * @private + * @param {boolean} isConfirmStep + * @return {string} + */ + getTitleMessage_: function(isConfirmStep) { + if (!isConfirmStep) + return this.i18n('quickUnlockConfigurePinChoosePinTitle'); + return this.i18n('quickUnlockConfigurePinConfirmPinTitle'); + }, + + /** + * @private + * @param {boolean} isConfirmStep + * @return {string} + */ + getContinueMessage_: function(isConfirmStep) { + if (!isConfirmStep) + return this.i18n('quickUnlockConfigurePinContinueButton'); + return this.i18n('save'); + }, +}); + +})();
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html index fbd2986..2efb345 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page.html +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -11,6 +11,7 @@ <link rel="import" href="/site_settings/all_sites.html"> <link rel="import" href="/site_settings/constants.html"> <link rel="import" href="/site_settings/media_picker.html"> +<link rel="import" href="/site_settings/protocol_handlers.html"> <link rel="import" href="/site_settings/site_data.html"> <link rel="import" href="/site_settings_page/site_settings_page.html"> @@ -202,6 +203,11 @@ </site-settings-category> </settings-subpage> </template> + <template is="dom-if" name="protocol-handlers"> + <settings-subpage page-title="$i18n{siteSettingsCategoryHandlers}"> + <protocol-handlers></protocol-handlers> + </settings-subpage> + </template> <template is="dom-if" name="site-settings-category-javascript"> <settings-subpage page-title="$i18n{siteSettingsCategoryJavascript}">
diff --git a/chrome/browser/resources/settings/route.html b/chrome/browser/resources/settings/route.html new file mode 100644 index 0000000..102248ea --- /dev/null +++ b/chrome/browser/resources/settings/route.html
@@ -0,0 +1,3 @@ +<link rel="import" href="chrome://resources/html/cr.html"> + +<script src="route.js"></script>
diff --git a/chrome/browser/resources/settings/route.js b/chrome/browser/resources/settings/route.js new file mode 100644 index 0000000..d6b184c --- /dev/null +++ b/chrome/browser/resources/settings/route.js
@@ -0,0 +1,77 @@ +// 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. + +cr.define('settings', function() { + /** + * Class for navigable routes. May only be instantiated within this file. + * @constructor + * @param {string} url + * @private + */ + var Route = function(url) { + this.url = url; + + /** @private {?settings.Route} */ + this.parent_ = null; + + // Below are all legacy properties to provide compatibility with the old + // routing system. TODO(tommycli): Remove once routing refactor complete. + this.page = ''; + this.section = ''; + /** @type {!Array<string>} */ this.subpage = []; + this.dialog = false; + }; + + Route.prototype = { + /** + * Returns a new Route instance that's a child of this route. + * @param {string} url + * @param {string=} opt_subpageName + * @return {!settings.Route} + * @private + */ + createChild: function(url, opt_subpageName) { + var route = new Route(url); + route.parent_ = this; + route.page = this.page; + route.section = this.section; + route.subpage = this.subpage.slice(); // Shallow copy. + + if (opt_subpageName) + route.subpage.push(opt_subpageName); + + return route; + }, + + /** + * Returns a new Route instance that's a child dialog of this route. + * @param {string} url + * @return {!settings.Route} + * @private + */ + createDialog: function(url) { + var route = this.createChild(url); + route.dialog = true; + return route; + }, + + /** + * Returns true if this route is a descendant of the parameter. + * @param {!settings.Route} route + * @return {boolean} + */ + isDescendantOf: function(route) { + for (var parent = this.parent_; parent != null; parent = parent.parent_) { + if (route == parent) + return true; + } + + return false; + }, + }; + + return { + Route: Route, + }; +});
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.js b/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.js index ae28c04..eb272e5 100644 --- a/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.js +++ b/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.js
@@ -57,7 +57,7 @@ this.actionButtonText_ = loadTimeData.getString('save'); // If editing an existing search engine, pre-populate the input fields. - this.searchEngine_ = this.model.displayName; + this.searchEngine_ = this.model.name; this.keyword_ = this.model.keyword; this.queryUrl_ = this.model.url; } else {
diff --git a/chrome/browser/resources/settings/search_settings.js b/chrome/browser/resources/settings/search_settings.js index 53d5d22..1b95ac9 100644 --- a/chrome/browser/resources/settings/search_settings.js +++ b/chrome/browser/resources/settings/search_settings.js
@@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +/** @typedef {{id: number, rawQuery: ?string, regExp: ?RegExp}} */ +var SearchContext; + cr.define('settings', function() { /** @const {string} */ var WRAPPER_CSS_CLASS = 'search-highlight-wrapper'; @@ -9,9 +12,6 @@ /** @const {string} */ var HIT_CSS_CLASS = 'search-highlight-hit'; - /** @const {!RegExp} */ - var SANITIZE_REGEX = /[-[\]{}()*+?.,\\^$|#\s]/g; - /** * List of elements types that should not be searched at all. * The only DOM-MODULE node is in <body> which is not searched, therefore @@ -40,6 +40,7 @@ /** * Finds all previous highlighted nodes under |node| (both within self and * children's Shadow DOM) and removes the highlight (yellow rectangle). + * TODO(dpapad): Consider making this a private method of TopLevelSearchTask. * @param {!Node} node * @private */ @@ -97,19 +98,41 @@ } /** + * Checks whether the given |node| requires force rendering. + * + * @param {!SearchContext} context + * @param {!Node} node + * @return {boolean} Whether a forced rendering task was scheduled. + * @private + */ + function forceRenderNeeded_(context, node) { + if (node.nodeName != 'TEMPLATE' || !node.hasAttribute('name') || node.if) + return false; + + // TODO(dpapad): Temporarily ignore site-settings because it throws an + // assertion error during force-rendering. + return node.getAttribute('name').indexOf('site-') != 0; + } + + /** * Traverses the entire DOM (including Shadow DOM), finds text nodes that * match the given regular expression and applies the highlight UI. It also * ensures that <settings-section> instances become visible if any matches * occurred under their subtree. * - * @param {!Element} page The page to be searched, should be either - * <settings-basic-page> or <settings-advanced-page>. - * @param {!RegExp} regExp The regular expression to detect matches. + * @param {!SearchContext} context + * @param {!Node} root The root of the sub-tree to be searched * @private */ - function findAndHighlightMatches_(page, regExp) { + function findAndHighlightMatches_(context, root) { function doSearch(node) { - if (IGNORED_ELEMENTS.has(node.tagName)) + if (forceRenderNeeded_(context, node)) { + SearchManager.getInstance().queue_.addRenderTask( + new RenderTask(context, node)); + return; + } + + if (IGNORED_ELEMENTS.has(node.nodeName)) return; if (node.nodeType == Node.TEXT_NODE) { @@ -117,9 +140,9 @@ if (textContent.length == 0) return; - if (regExp.test(textContent)) { + if (context.regExp.test(textContent)) { revealParentSection_(node); - highlight_(node, textContent.split(regExp)); + highlight_(node, textContent.split(context.regExp)); } // Returning early since TEXT_NODE nodes never have children. return; @@ -139,7 +162,7 @@ doSearch(shadowRoot); } - doSearch(page); + doSearch(root); } /** @@ -149,7 +172,7 @@ function revealParentSection_(node) { // Find corresponding SETTINGS-SECTION parent and make it visible. var parent = node; - while (parent && parent.tagName !== 'SETTINGS-SECTION') { + while (parent && parent.nodeName !== 'SETTINGS-SECTION') { parent = parent.nodeType == Node.DOCUMENT_FRAGMENT_NODE ? parent.host : parent.parentNode; } @@ -158,35 +181,255 @@ } /** - * @param {!Element} page - * @param {boolean} visible - * @private + * @constructor + * + * @param {!SearchContext} context + * @param {!Node} node */ - function setSectionsVisibility_(page, visible) { - var sections = Polymer.dom(page.root).querySelectorAll('settings-section'); - for (var i = 0; i < sections.length; i++) - sections[i].hidden = !visible; + function Task(context, node) { + /** @protected {!SearchContext} */ + this.context = context; + + /** @protected {!Node} */ + this.node = node; } + Task.prototype = { + /** + * @abstract + * @return {!Promise} + */ + exec: function() {}, + }; + /** - * Performs hierarchical search, starting at the given page element. + * A task that takes a <template is="dom-if">...</template> node corresponding + * to a setting subpage and renders it. A SearchAndHighlightTask is posted for + * the newly rendered subtree, once rendering is done. + * @constructor + * @extends {Task} + * + * @param {!SearchContext} context + * @param {!Node} node + */ + function RenderTask(context, node) { + Task.call(this, context, node); + } + + RenderTask.prototype = { + /** @override */ + exec: function() { + var subpageTemplate = + this.node['_content'].querySelector('settings-subpage'); + subpageTemplate.id = subpageTemplate.id || this.node.getAttribute('name'); + assert(!this.node.if); + this.node.if = true; + + return new Promise(function(resolve, reject) { + var parent = this.node.parentNode; + parent.async(function() { + var renderedNode = parent.querySelector('#' + subpageTemplate.id); + // Register a SearchAndHighlightTask for the part of the DOM that was + // just rendered. + SearchManager.getInstance().queue_.addSearchAndHighlightTask( + new SearchAndHighlightTask(this.context, assert(renderedNode))); + resolve(); + }.bind(this)); + }.bind(this)); + }, + }; + + /** + * @constructor + * @extends {Task} + * + * @param {!SearchContext} context + * @param {!Node} node + */ + function SearchAndHighlightTask(context, node) { + Task.call(this, context, node); + } + + SearchAndHighlightTask.prototype = { + /** @override */ + exec: function() { + findAndHighlightMatches_(this.context, this.node); + return Promise.resolve(); + }, + }; + + /** + * @constructor + * @extends {Task} + * + * @param {!SearchContext} context + * @param {!Node} page + */ + function TopLevelSearchTask(context, page) { + Task.call(this, context, page); + } + + TopLevelSearchTask.prototype = { + /** @override */ + exec: function() { + findAndRemoveHighlights_(this.node); + + var shouldSearch = this.context.regExp !== null; + this.setSectionsVisibility_(!shouldSearch); + if (shouldSearch) + findAndHighlightMatches_(this.context, this.node); + + return Promise.resolve(); + }, + + /** + * @param {boolean} visible + * @private + */ + setSectionsVisibility_: function(visible) { + var sections = Polymer.dom( + this.node.root).querySelectorAll('settings-section'); + for (var i = 0; i < sections.length; i++) + sections[i].hidden = !visible; + }, + }; + + /** + * @constructor + */ + function TaskQueue() { + /** + * @private {{ + * high: !Array<!Task>, + * middle: !Array<!Task>, + * low: !Array<!Task> + * }} + */ + this.queues_; + this.reset(); + + /** + * Whether a task is currently running. + * @private {boolean} + */ + this.running_ = false; + } + + TaskQueue.prototype = { + /** Drops all tasks. */ + reset: function() { + this.queues_ = {high: [], middle: [], low: []}; + }, + + /** @param {!TopLevelSearchTask} task */ + addTopLevelSearchTask: function(task) { + this.queues_.high.push(task); + this.consumePending_(); + }, + + /** @param {!SearchAndHighlightTask} task */ + addSearchAndHighlightTask: function(task) { + this.queues_.middle.push(task); + this.consumePending_(); + }, + + /** @param {!RenderTask} task */ + addRenderTask: function(task) { + this.queues_.low.push(task); + this.consumePending_(); + }, + + /** + * @return {!Task|undefined} + * @private + */ + popNextTask_: function() { + return this.queues_.high.shift() || + this.queues_.middle.shift() || + this.queues_.low.shift(); + }, + + /** @private */ + consumePending_: function() { + if (this.running_) + return; + + while (1) { + var task = this.popNextTask_(); + if (!task) { + this.running_ = false; + return; + } + + window.requestIdleCallback(function() { + function startNextTask() { + this.running_ = false; + this.consumePending_(); + } + if (task.context.id == + SearchManager.getInstance().activeContext_.id) { + task.exec().then(startNextTask.bind(this)); + } else { + // Dropping this task without ever executing it, since a new search + // has been issued since this task was queued. + startNextTask.call(this); + } + }.bind(this)); + return; + } + }, + }; + + /** + * @constructor + */ + var SearchManager = function() { + /** @private {!TaskQueue} */ + this.queue_ = new TaskQueue(); + + /** @private {!SearchContext} */ + this.activeContext_ = {id: 0, rawQuery: null, regExp: null}; + }; + cr.addSingletonGetter(SearchManager); + + /** @private @const {!RegExp} */ + SearchManager.SANITIZE_REGEX_ = /[-[\]{}()*+?.,\\^$|#\s]/g; + + SearchManager.prototype = { + /** + * @param {string} text The text to search for. + * @param {!Node} page + */ + search: function(text, page) { + if (this.activeContext_.rawQuery != text) { + var newId = this.activeContext_.id + 1; + + var regExp = null; + // Generate search text by escaping any characters that would be + // problematic for regular expressions. + var searchText = text.trim().replace( + SearchManager.SANITIZE_REGEX_, '\\$&'); + if (searchText.length > 0) + regExp = new RegExp('(' + searchText + ')', 'i'); + + this.activeContext_ = {id: newId, rawQuery: text, regExp: regExp}; + + // Drop all previously scheduled tasks, since a new search was just + // issued. + this.queue_.reset(); + } + + this.queue_.addTopLevelSearchTask( + new TopLevelSearchTask(this.activeContext_, page)); + }, + }; + + /** * @param {string} text - * @param {!Element} page Must be either <settings-basic-page> or - * <settings-advanced-page>. + * @param {!Node} page */ function search(text, page) { - findAndRemoveHighlights_(page); - - // Generate search text by escaping any characters that would be problematic - // for regular expressions. - var searchText = text.trim().replace(SANITIZE_REGEX, '\\$&'); - if (searchText.length == 0) { - setSectionsVisibility_(page, true); - return; - } - - setSectionsVisibility_(page, false); - findAndHighlightMatches_(page, new RegExp('(' + searchText + ')', 'i')); + SearchManager.getInstance().search(text, page); } return {
diff --git a/chrome/browser/resources/settings/settings_page/settings_router.js b/chrome/browser/resources/settings/settings_page/settings_router.js index cf98772..dde4efb 100644 --- a/chrome/browser/resources/settings/settings_page/settings_router.js +++ b/chrome/browser/resources/settings/settings_page/settings_router.js
@@ -215,6 +215,18 @@ subpage: ['quick-unlock-authenticate'], }, { + url: '/quickUnlock/chooseMethod', + page: 'basic', + section: 'people', + subpage: ['quick-unlock-choose-method'], + }, + { + url: '/quickUnlock/setupPin', + page: 'basic', + section: 'people', + subpage: ['quick-unlock-choose-method', 'quick-unlock-setup-pin'], + }, + { url: '/accounts', page: 'basic', section: 'people', @@ -283,6 +295,18 @@ subpage: ['site-settings', 'site-settings-category-images'], }, { + url: '/siteSettings/handlers', + page: 'advanced', + section: 'privacy', + subpage: ['site-settings', 'protocol-handlers'], + }, + { + url: '/siteSettings/javascript', + page: 'advanced', + section: 'privacy', + subpage: ['site-settings', 'site-settings-category-javascript'], + }, + { url: '/siteSettings/keygen', page: 'advanced', section: 'privacy', @@ -295,12 +319,6 @@ subpage: ['site-settings', 'site-settings-category-location'], }, { - url: '/siteSettings/javascript', - page: 'advanced', - section: 'privacy', - subpage: ['site-settings', 'site-settings-category-javascript'], - }, - { url: '/siteSettings/microphone', page: 'advanced', section: 'privacy', @@ -380,6 +398,13 @@ 'site-details'], }, { + url: '/siteSettings/javascript/details', + page: 'advanced', + section: 'privacy', + subpage: ['site-settings', 'site-settings-category-javascript', + 'site-details'], + }, + { url: '/siteSettings/keygen/details', page: 'advanced', section: 'privacy', @@ -394,13 +419,6 @@ 'site-details'], }, { - url: '/siteSettings/javascript/details', - page: 'advanced', - section: 'privacy', - subpage: ['site-settings', 'site-settings-category-javascript', - 'site-details'], - }, - { url: '/siteSettings/microphone/details', page: 'advanced', section: 'privacy',
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd index 38fb84a9..f08d1c8e 100644 --- a/chrome/browser/resources/settings/settings_resources.grd +++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/settings_resources.h" type="rc_header"> <emit emit_type='prepend'></emit> @@ -548,6 +548,12 @@ <structure name="IDR_SETTINGS_AUTOFILL_SECTION_JS" file="passwords_and_forms_page/autofill_section.js" type="chrome_html" /> + <structure name="IDR_SETTINGS_ADDRESS_EDIT_DIALOG_HTML" + file="passwords_and_forms_page/address_edit_dialog.html" + type="chrome_html" /> + <structure name="IDR_SETTINGS_ADDRESS_EDIT_DIALOG_JS" + file="passwords_and_forms_page/address_edit_dialog.js" + type="chrome_html" /> <structure name="IDR_SETTINGS_PASSWORDS_SECTION_HTML" file="passwords_and_forms_page/passwords_section.html" type="chrome_html" /> @@ -647,6 +653,18 @@ file="privacy_page/privacy_page_browser_proxy.js" type="chrome_html" /> </if> + <structure name="IDR_SETTINGS_PROTOCOL_HANDLERS_HTML" + file="site_settings/protocol_handlers.html" + type="chrome_html" /> + <structure name="IDR_SETTINGS_PROTOCOL_HANDLERS_JS" + file="site_settings/protocol_handlers.js" + type="chrome_html" /> + <structure name="IDR_SETTINGS_ROUTE_HTML" + file="route.html" + type="chrome_html" /> + <structure name="IDR_SETTINGS_ROUTE_JS" + file="route.js" + type="chrome_html" /> <structure name="IDR_SETTINGS_CR_SETTINGS_ROUTER_HTML" file="settings_page/settings_router.html" type="chrome_html" /> @@ -965,6 +983,22 @@ type="chrome_html" flattenhtml="true" allowexternalscript="true" /> + <structure name="IDR_SETTINGS_QUICK_UNLOCK_CHOOSE_METHOD_JS" + file="people_page/quick_unlock_choose_method.js" + type="chrome_html" /> + <structure name="IDR_SETTINGS_QUICK_UNLOCK_CHOOSE_METHOD_HTML" + file="people_page/quick_unlock_choose_method.html" + type="chrome_html" + flattenhtml="true" + allowexternalscript="true" /> + <structure name="IDR_SETTINGS_QUICK_UNLOCK_SETUP_PIN_JS" + file="people_page/quick_unlock_setup_pin.js" + type="chrome_html" /> + <structure name="IDR_SETTINGS_QUICK_UNLOCK_SETUP_PIN_HTML" + file="people_page/quick_unlock_setup_pin.html" + type="chrome_html" + flattenhtml="true" + allowexternalscript="true" /> <structure name="IDR_SETTINGS_QUICK_UNLOCK_ROUTING_BEHAVIOR_JS" file="people_page/quick_unlock_routing_behavior.js" type="chrome_html" /> @@ -973,6 +1007,14 @@ type="chrome_html" flattenhtml="true" allowexternalscript="true" /> + <structure name="IDR_SETTINGS_QUICK_UNLOCK_PASSWORD_DETECT_BEHAVIOR_JS" + file="people_page/quick_unlock_password_detect_behavior.js" + type="chrome_html" /> + <structure name="IDR_SETTINGS_QUICK_UNLOCK_PASSWORD_DETECT_BEHAVIOR_HTML" + file="people_page/quick_unlock_password_detect_behavior.html" + type="chrome_html" + flattenhtml="true" + allowexternalscript="true" /> <structure name="IDR_SETTINGS_KEYBOARD_PIN_JS" file="people_page/pin_keyboard.js" type="chrome_html"
diff --git a/chrome/browser/resources/settings/settings_shared_css.html b/chrome/browser/resources/settings/settings_shared_css.html index 859c59a3..bdcfcec 100644 --- a/chrome/browser/resources/settings/settings_shared_css.html +++ b/chrome/browser/resources/settings/settings_shared_css.html
@@ -27,6 +27,10 @@ background-color: var(--paper-grey-300); } + paper-toggle-button { + @apply(--settings-actionable); + } + paper-dropdown-menu { --iron-icon-fill-color: var(--paper-grey-600); --paper-font-subhead: { @@ -39,11 +43,14 @@ paper-dropdown-menu .dropdown-item { align-items: center; + background: none; + border: none; color: var(--paper-grey-800); display: flex; - font-size: inherit; + font: inherit; min-height: 48px; padding: 0 16px; + width: 100%; } paper-dropdown-menu .dropdown-item.iron-selected {
diff --git a/chrome/browser/resources/settings/site_settings/constants.js b/chrome/browser/resources/settings/site_settings/constants.js index 27a10838..f32a531 100644 --- a/chrome/browser/resources/settings/site_settings/constants.js +++ b/chrome/browser/resources/settings/site_settings/constants.js
@@ -22,6 +22,7 @@ FULLSCREEN: 'fullscreen', MIC: 'media-stream-mic', CAMERA: 'media-stream-camera', + PROTOCOL_HANDLERS: 'register-protocol-handler', UNSANDBOXED_PLUGINS: 'ppapi-broker', AUTOMATIC_DOWNLOADS: 'multiple-automatic-downloads', KEYGEN: 'keygen',
diff --git a/chrome/browser/resources/settings/site_settings/protocol_handlers.html b/chrome/browser/resources/settings/site_settings/protocol_handlers.html new file mode 100644 index 0000000..4e6a31e8 --- /dev/null +++ b/chrome/browser/resources/settings/site_settings/protocol_handlers.html
@@ -0,0 +1,73 @@ +<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/polymer/v1_0/paper-icon-button/paper-icon-button.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-item/paper-item.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-menu/paper-menu.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-menu-button/paper-menu-button.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html"> +<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> +<link rel="import" href="/i18n_setup.html"> +<link rel="import" href="/settings_shared_css.html"> +<link rel="import" href="/site_settings/site_settings_behavior.html"> +<link rel="import" href="/site_settings/site_settings_prefs_browser_proxy.html"> + +<dom-module id="protocol-handlers"> + <template> + <style include="settings-shared"> + :host { + display: block; + } + + .protocol { + -webkit-margin-start: 20px; + margin-bottom: 15px; + margin-top: 15px; + } + </style> + <div class="settings-box first two-line"> + <div class="start secondary"> + [[computeHandlersDescription_(categoryEnabled)]] + </div> + <paper-toggle-button id="toggle" checked="{{categoryEnabled}}" + on-change="onToggleChange_"></paper-toggle-button> + </div> + + <template is="dom-repeat" items="[[protocols]]" as="protocol"> + <div class="protocol">[[protocol.protocol]]</div> + + <div class="list-frame menu-content vertical-list"> + <template is="dom-repeat" items="[[protocol.handlers]]"> + + <div class="list-item underscore"> + <div class="middle" > + <div>[[item.host]]</div> + <div class="secondary" + hidden$="[[!isDefault_(index, protocol.default_handler)]]"> + $i18n{handlerIsDefault} + </div> + </div> + + <paper-menu-button> + <paper-icon-button icon="cr:more-vert" + class="dropdown-trigger"> + </paper-icon-button> + <paper-menu id="actionMenu" class="dropdown-content" + on-iron-activate="onActionMenuIronActivate_" + attr-for-selected="menu-value"> + <paper-item menu-value$="[[menuActions_.SET_DEFAULT]]" + hidden$="[[isDefault_(index, protocol.default_handler)]]"> + $i18n{handlerSetDefault} + </paper-item> + <paper-item menu-value$="[[menuActions_.REMOVE]]"> + $i18n{handlerRemove} + </paper-item> + </paper-menu> + </paper-menu-button> + </div> + + </template> + </div> + </template> + </template> + <script src="protocol_handlers.js"></script> +</dom-module>
diff --git a/chrome/browser/resources/settings/site_settings/protocol_handlers.js b/chrome/browser/resources/settings/site_settings/protocol_handlers.js new file mode 100644 index 0000000..2f37b29 --- /dev/null +++ b/chrome/browser/resources/settings/site_settings/protocol_handlers.js
@@ -0,0 +1,142 @@ +// 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. + +/** + * @fileoverview + * 'protocol-handlers' is the polymer element for showing the + * protocol handlers category under Site Settings. + */ + +var MenuActions = { + SET_DEFAULT: 'SetDefault', + REMOVE: 'Remove', +}; + +/** + * @typedef {{host: string, + * protocol: string, + * spec: string}} + */ +var HandlerEntry; + +/** + * @typedef {{default_handler: number, + * handlers: !Array<!HandlerEntry>, + * has_policy_recommendations: boolean, + * is_default_handler_set_by_user: boolean, + * protocol: string}} + */ +var ProtocolEntry; + +Polymer({ + is: 'protocol-handlers', + + behaviors: [SiteSettingsBehavior, WebUIListenerBehavior], + + properties: { + /** + * Represents the state of the main toggle shown for the category. + */ + categoryEnabled: Boolean, + + /** + * Array of protocols and their handlers. + * @type {!Array<!ProtocolEntry>} + */ + protocols: Array, + + /** + * The possible menu actions. + * @type {MenuActions} + */ + menuActions_: { + type: Object, + value: MenuActions, + readOnly: true, + }, + }, + + ready: function() { + this.addWebUIListener('setHandlersEnabled', + this.setHandlersEnabled_.bind(this)); + this.addWebUIListener('setProtocolHandlers', + this.setProtocolHandlers_.bind(this)); + this.addWebUIListener('setIgnoredProtocolHandlers', + this.setIgnoredProtocolHandlers_.bind(this)); + this.browserProxy.initializeProtocolHandlerList(); + }, + + /** + * Obtains the description for the main toggle. + * @param {number} categoryEnabled Whether the main toggle is enabled. + * @return {string} The description to use. + * @private + */ + computeHandlersDescription_: function(categoryEnabled) { + return this.computeCategoryDesc( + settings.ContentSettingsTypes.PROTOCOL_HANDLERS, categoryEnabled, true); + }, + + /** + * Returns whether the given index matches the default handler. + * @param {number} index The index to evaluate. + * @param {number} defaultHandler The default handler index. + * @return {boolean} Whether the item is default. + * @private + */ + isDefault_: function(index, defaultHandler) { + return defaultHandler == index; + }, + + /** + * Updates the main toggle to set it enabled/disabled. + * @param {boolean} enabled The state to set. + * @private + */ + setHandlersEnabled_: function(enabled) { + this.categoryEnabled = enabled; + }, + + /** + * Updates the list of protocol handlers. + * @param {!Array<!ProtocolEntry>} protocols The new protocol handler list. + * @private + */ + setProtocolHandlers_: function(protocols) { + this.protocols = protocols; + }, + + /** + * Updates the list of ignored protocol handlers. + * @param {!Array<!ProtocolEntry>} args The new (ignored) protocol handler + * list. + * @private + */ + setIgnoredProtocolHandlers_: function(args) { + // TODO(finnur): Figure this out. Have yet to be able to trigger the C++ + // side to send this. + }, + + /** + * A handler when the toggle is flipped. + * @private + */ + onToggleChange_: function(event) { + this.browserProxy.setProtocolHandlerDefault(this.categoryEnabled); + }, + + /** + * A handler when an action is selected in the action menu. + * @private + */ + onActionMenuIronActivate_: function(event) { + var protocol = event.model.item.protocol; + var url = event.model.item.spec; + if (event.detail.selected == MenuActions.SET_DEFAULT) { + this.browserProxy.setProtocolDefault(protocol, url); + } else if (event.detail.selected == MenuActions.REMOVE) { + this.browserProxy.removeProtocolHandler(protocol, url); + } + }, +});
diff --git a/chrome/browser/resources/settings/site_settings/site_list.js b/chrome/browser/resources/settings/site_settings/site_list.js index 4c249642..3020f519 100644 --- a/chrome/browser/resources/settings/site_settings/site_list.js +++ b/chrome/browser/resources/settings/site_settings/site_list.js
@@ -243,6 +243,13 @@ getAllSitesList_: function() { var promiseList = []; for (var type in settings.ContentSettingsTypes) { + if (settings.ContentSettingsTypes[type] == + settings.ContentSettingsTypes.PROTOCOL_HANDLERS) { + // Protocol handlers don't have data stored the way all the other + // categories do. + continue; + } + promiseList.push( this.browserProxy_.getExceptionList( settings.ContentSettingsTypes[type]));
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_behavior.js b/chrome/browser/resources/settings/site_settings/site_settings_behavior.js index 86ee14b3..7b05396 100644 --- a/chrome/browser/resources/settings/site_settings/site_settings_behavior.js +++ b/chrome/browser/resources/settings/site_settings/site_settings_behavior.js
@@ -96,6 +96,8 @@ return 'plugins'; case settings.ContentSettingsTypes.POPUPS: return 'popups'; + case settings.ContentSettingsTypes.PROTOCOL_HANDLERS: + return 'handlers'; case settings.ContentSettingsTypes.UNSANDBOXED_PLUGINS: return 'unsandboxed-plugins'; default: @@ -139,6 +141,8 @@ return 'cr:extension'; case settings.ContentSettingsTypes.POPUPS: return 'settings:open-in-new'; + case settings.ContentSettingsTypes.PROTOCOL_HANDLERS: + return 'settings:open-with'; case settings.ContentSettingsTypes.UNSANDBOXED_PLUGINS: return 'cr:extension'; default: @@ -183,6 +187,8 @@ return loadTimeData.getString('siteSettingsPlugins'); case settings.ContentSettingsTypes.POPUPS: return loadTimeData.getString('siteSettingsPopups'); + case settings.ContentSettingsTypes.PROTOCOL_HANDLERS: + return loadTimeData.getString('siteSettingsHandlers'); case settings.ContentSettingsTypes.UNSANDBOXED_PLUGINS: return loadTimeData.getString('siteSettingsUnsandboxedPlugins'); default: @@ -245,6 +251,14 @@ return showRecommendation ? loadTimeData.getString('siteSettingsCookiesAllowedRecommended') : loadTimeData.getString('siteSettingsCookiesAllowed'); + case settings.ContentSettingsTypes.PROTOCOL_HANDLERS: + // "Allow sites to ask to become default handlers" vs "Blocked". + if (!categoryEnabled) { + return loadTimeData.getString('siteSettingsHandlersBlocked'); + } + return showRecommendation ? + loadTimeData.getString('siteSettingsHandlersAskRecommended') : + loadTimeData.getString('siteSettingsHandlersAsk'); case settings.ContentSettingsTypes.IMAGES: if (!categoryEnabled) { return loadTimeData.getString('siteSettingsDontShowImages');
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_category.js b/chrome/browser/resources/settings/site_settings/site_settings_category.js index 9012e4a..81672e8e 100644 --- a/chrome/browser/resources/settings/site_settings/site_settings_category.js +++ b/chrome/browser/resources/settings/site_settings/site_settings_category.js
@@ -77,6 +77,7 @@ case settings.ContentSettingsTypes.JAVASCRIPT: case settings.ContentSettingsTypes.KEYGEN: case settings.ContentSettingsTypes.POPUPS: + case settings.ContentSettingsTypes.PROTOCOL_HANDLERS: // "Allowed" vs "Blocked". this.browserProxy.setDefaultValueForContentType( this.category, @@ -85,8 +86,8 @@ settings.PermissionValues.BLOCK); break; case settings.ContentSettingsTypes.AUTOMATIC_DOWNLOADS: - case settings.ContentSettingsTypes.GEOLOCATION: case settings.ContentSettingsTypes.CAMERA: + case settings.ContentSettingsTypes.GEOLOCATION: case settings.ContentSettingsTypes.MIC: case settings.ContentSettingsTypes.NOTIFICATIONS: case settings.ContentSettingsTypes.UNSANDBOXED_PLUGINS:
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js b/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js index 99af3cd..c944ccdc 100644 --- a/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js +++ b/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js
@@ -127,6 +127,33 @@ * @param {string} path The path to the parent cookie. */ removeCookie: function(path) {}, + + /** + * Initializes the protocol handler list. List is returned through JS calls + * to setHandlersEnabled, setProtocolHandlers & setIgnoredProtocolHandlers. + */ + initializeProtocolHandlerList: function() {}, + + /** + * Enables or disables the ability for sites to ask to become the default + * protocol handlers. + * @param {boolean} enabled Whether sites can ask to become default. + */ + setProtocolHandlerDefault: function(enabled) {}, + + /** + * Sets a certain url as default for a given protocol handler. + * @param {string} protocol The protocol to set a default for. + * @param {string} url The url to use as the default. + */ + setProtocolDefault: function(protocol, url) {}, + + /** + * Deletes a certain protocol handler by url. + * @param {string} protocol The protocol to delete the url from. + * @param {string} url The url to delete. + */ + removeProtocolHandler: function(protocol, url) {}, }; /** @@ -197,7 +224,26 @@ /** @override */ removeCookie: function(path) { chrome.send('removeCookie', [path]); - } + }, + + initializeProtocolHandlerList: function() { + chrome.send('initializeProtocolHandlerList'); + }, + + /** @override */ + setProtocolHandlerDefault: function(enabled) { + chrome.send('setHandlersEnabled', [enabled]); + }, + + /** @override */ + setProtocolDefault: function(protocol, url) { + chrome.send('setDefault', [[protocol, url]]); + }, + + /** @override */ + removeProtocolHandler: function(protocol, url) { + chrome.send('removeHandler', [[protocol, url]]); + }, }; return {
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.html b/chrome/browser/resources/settings/site_settings_page/site_settings_page.html index 16afa796..fc3e621 100644 --- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.html +++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
@@ -147,6 +147,17 @@ <div id="unsandboxedPlugins" class="secondary"></div> </div> </div> + <div class="settings-box two-line" + category$="[[ContentSettingsTypes.PROTOCOL_HANDLERS]]" + on-tap="onTapCategory"> + <iron-icon icon="[[computeIconForContentCategory( + ContentSettingsTypes.PROTOCOL_HANDLERS)]]" item-icon=""></iron-icon> + <div class="middle"> + [[computeTitleForContentCategory( + ContentSettingsTypes.PROTOCOL_HANDLERS)]] + <div id="handlers" class="secondary"></div> + </div> + </div> </template> <script src="site_settings_page.js"></script> </dom-module>
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.js b/chrome/browser/resources/settings/site_settings_page/site_settings_page.js index a757f08..f44f0b3 100644 --- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.js +++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.js
@@ -52,6 +52,8 @@ '#notifications'); this.setDefaultValue_(this.ContentSettingsTypes.PLUGINS, '#plugins'); this.setDefaultValue_(this.ContentSettingsTypes.POPUPS, '#popups'); + this.setDefaultValue_(this.ContentSettingsTypes.PROTOCOL_HANDLERS, + '#handlers'); this.setDefaultValue_(this.ContentSettingsTypes.UNSANDBOXED_PLUGINS, '#unsandboxedPlugins'); }, @@ -77,6 +79,12 @@ section: 'privacy', subpage: ['site-settings', 'all-sites'], }; + } else if (category == this.ContentSettingsTypes.PROTOCOL_HANDLERS) { + this.currentRoute = { + page: this.currentRoute.page, + section: 'privacy', + subpage: ['site-settings', 'protocol-handlers'], + }; } else { this.categorySelected = this.computeCategoryTextId(category); this.currentRoute = {
diff --git a/chrome/browser/resources/settings_app/manifest.json b/chrome/browser/resources/settings_app/manifest.json deleted file mode 100644 index b382801..0000000 --- a/chrome/browser/resources/settings_app/manifest.json +++ /dev/null
@@ -1,24 +0,0 @@ -{ - //chrome-extension://ennkphjdgehloodpbhlhldgbnhmacadg - "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDoVDPGX6fvKPVVgc+gnkYlGqHuuapgFDyKhsy4z7UzRLO/95zXPv8h8e5EacqbAQJLUbP6DERH5jowyNEYVxq9GJyntJMwP1ejvoz/52hnY3CCGGCmttmKzzpp5zwLuq3iZf8bslwywfflNUYtaCFSDa0TtrBZz0aOPrAAd/AhNwIDAQAB", - "name": "Settings", - "version": "0.2", - "manifest_version": 2, - "description": "Settings", - - "icons": { - "16": "settings_app_icon_16.png", - "32": "settings_app_icon_32.png", - "48": "settings_app_icon_48.png", - "128": "settings_app_icon_128.png" - }, - "app": { - "background": { - "scripts": [ "settings_app.js" ] - } - }, - "permissions": [ - "chrome://settings-frame/" - ], - "display_in_launcher": false -}
diff --git a/chrome/browser/resources/settings_app/settings_app.js b/chrome/browser/resources/settings_app/settings_app.js deleted file mode 100644 index 8b82ec4..0000000 --- a/chrome/browser/resources/settings_app/settings_app.js +++ /dev/null
@@ -1,9 +0,0 @@ -// Copyright 2012 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. - -chrome.app.runtime.onLaunched.addListener(function() { - chrome.app.window.create( - 'chrome://settings-frame/options_settings_app.html', - {'id': 'settings_app', 'height': 550, 'width': 750}); -});
diff --git a/chrome/browser/resources/snippets_internals.html b/chrome/browser/resources/snippets_internals.html index 0f8fdfc..8affa6f 100644 --- a/chrome/browser/resources/snippets_internals.html +++ b/chrome/browser/resources/snippets_internals.html
@@ -37,11 +37,13 @@ </div> <div id="snippets"> - <h2>Snippets <span class="detail">(click for details)</span></h2> + <h2>Snippets directly from NTPSnippetsService + <span class="detail">(click for details)</span> + </h2> <table class="section-details"> <tr jsselect="list" style="display:none"> <td class="title-link"> - <span class="snippet-title" jsvalues="snippet-id:id"> + <span class="snippet-title" jsvalues="hidden-id:id"> <span jscontent="title"></span>>></span> <div jsvalues="id:id" class="snippet-detail hidden"> <table> @@ -106,7 +108,7 @@ <table class="section-details"> <tr jsselect="list" style="display:none"> <td class="title-link"> - <span class="discarded-snippet-title" jsvalues="snippet-id:id"> + <span class="discarded-snippet-title" jsvalues="hidden-id:id"> <span jscontent="title"></span> >></span> <div jsvalues="id:id" class="snippet-detail hidden"> <table> @@ -149,4 +151,59 @@ </table> <div class="detail" id="hosts-empty"></div> </div> + + <div id="content-suggestions"> + <h2>Content suggestions by category + <span class="detail">(click for details)</span> + </h2> + <div jsselect="list" style="display:none"> + <h3> + <span jscontent="name"></span> + <span class="detail"> + (<span jscontent="status"></span>) + </span> + </h3> + + <table class="section-details"> + <tr jsselect="suggestions" style="display:none"> + <td class="title-link"> + <span class="content-suggestion-title" + jsvalues="hidden-id:id"> + <span jscontent="title"></span>>> + </span> + <div jsvalues="id:id" class="content-suggestion-detail hidden"> + <table> + <tr> + <td>ID + <td jscontent="suggestionId"> + <tr> + <td>URL + <td><a class="url" jsvalues="href:url" jscontent="url"></a> + <tr> + <td>AMP URL + <td> + <a class="amp-url" jsvalues="href:ampUrl" + jscontent="ampUrl"></a> + <tr> + <td>Snippet text + <td jscontent="snippetText"> + <tr> + <td>Publish date + <td class="expiry"> + <span class="date" jscontent="publishDate"></span> + <tr> + <td>Publisher name + <td jscontent="publisherName"> + </table> + </div> + </table> + </div> + <div class="detail" id="content-suggestions-empty"></div> + <div class="forms"> + <input id="submit-clear-cached-suggestions" type="submit" + value="Clear cached suggestions"> + <input id="submit-clear-discarded-suggestions" type="submit" + value="Clear discarded suggestions"> + </div> + </div> </div>
diff --git a/chrome/browser/resources/snippets_internals.js b/chrome/browser/resources/snippets_internals.js index b44905c2..0969dc4 100644 --- a/chrome/browser/resources/snippets_internals.js +++ b/chrome/browser/resources/snippets_internals.js
@@ -38,6 +38,18 @@ event.preventDefault(); }); + $('submit-clear-cached-suggestions') + .addEventListener('click', function(event) { + chrome.send('clearCachedSuggestions'); + event.preventDefault(); + }); + + $('submit-clear-discarded-suggestions') + .addEventListener('click', function(event) { + chrome.send('clearDiscardedSuggestions'); + event.preventDefault(); + }); + chrome.send('loaded'); } @@ -69,6 +81,11 @@ 'discarded-snippet-title'); } + function receiveContentSuggestions(categoriesList) { + displayList(categoriesList, 'content-suggestions', + 'content-suggestion-title'); + } + function receiveJson(json) { var trimmed = json.trim(); var hasContent = (trimmed && trimmed != '{}'); @@ -91,6 +108,11 @@ link.click(); } + function toggleHidden(event) { + var id = event.currentTarget.getAttribute('hidden-id'); + $(id).classList.toggle('hidden'); + } + function displayList(object, domId, titleClass) { jstProcess(new JsEvalContext(object), $(domId)); @@ -110,10 +132,7 @@ var links = document.getElementsByClassName(titleClass); for (var link of links) { - link.addEventListener('click', function(event) { - var id = event.currentTarget.getAttribute('snippet-id'); - $(id).classList.toggle('hidden'); - }); + link.addEventListener('click', toggleHidden); } } @@ -125,6 +144,7 @@ receiveHosts: receiveHosts, receiveSnippets: receiveSnippets, receiveDiscardedSnippets: receiveDiscardedSnippets, + receiveContentSuggestions: receiveContentSuggestions, receiveJson: receiveJson, }; });
diff --git a/chrome/browser/resources/sync_file_system_internals_resources.grd b/chrome/browser/resources/sync_file_system_internals_resources.grd index 62f685d6..6c730ce 100644 --- a/chrome/browser/resources/sync_file_system_internals_resources.grd +++ b/chrome/browser/resources/sync_file_system_internals_resources.grd
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/sync_file_system_internals_resources.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/resources/translate_internals_resources.grd b/chrome/browser/resources/translate_internals_resources.grd index 1ad9abf3d..02cc177 100644 --- a/chrome/browser/resources/translate_internals_resources.grd +++ b/chrome/browser/resources/translate_internals_resources.grd
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/translate_internals_resources.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/browser/safe_browsing/download_feedback.cc b/chrome/browser/safe_browsing/download_feedback.cc index 2356900..501f6a40f 100644 --- a/chrome/browser/safe_browsing/download_feedback.cc +++ b/chrome/browser/safe_browsing/download_feedback.cc
@@ -7,9 +7,11 @@ #include "base/bind.h" #include "base/files/file_util_proxy.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/metrics/histogram.h" #include "base/task_runner.h" #include "chrome/common/safe_browsing/csd.pb.h" +#include "content/public/browser/browser_thread.h" #include "net/base/net_errors.h" namespace safe_browsing { @@ -89,12 +91,13 @@ file_size_(-1), ping_request_(ping_request), ping_response_(ping_response) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DVLOG(1) << "DownloadFeedback constructed " << this << " for " << file_path.AsUTF8Unsafe(); } DownloadFeedbackImpl::~DownloadFeedbackImpl() { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DVLOG(1) << "DownloadFeedback destructed " << this; if (uploader_) { @@ -110,7 +113,7 @@ } void DownloadFeedbackImpl::Start(const base::Closure& finish_callback) { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(!uploader_); ClientDownloadReport report_metadata; @@ -126,16 +129,12 @@ std::string metadata_string; bool ok = report_metadata.SerializeToString(&metadata_string); DCHECK(ok); - uploader_.reset( - TwoPhaseUploader::Create(request_context_getter_.get(), - file_task_runner_.get(), - GURL(kSbFeedbackURL), - metadata_string, - file_path_, - TwoPhaseUploader::ProgressCallback(), - base::Bind(&DownloadFeedbackImpl::FinishedUpload, - base::Unretained(this), - finish_callback))); + uploader_ = TwoPhaseUploader::Create( + request_context_getter_.get(), file_task_runner_.get(), + GURL(kSbFeedbackURL), metadata_string, file_path_, + TwoPhaseUploader::ProgressCallback(), + base::Bind(&DownloadFeedbackImpl::FinishedUpload, base::Unretained(this), + finish_callback)); uploader_->Start(); } @@ -144,33 +143,31 @@ int net_error, int response_code, const std::string& response_data) { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DVLOG(1) << __FUNCTION__ << " " << state << " rlen=" << response_data.size(); switch (state) { case TwoPhaseUploader::STATE_SUCCESS: { ClientUploadResponse response; if (!response.ParseFromString(response_data) || - response.status() != ClientUploadResponse::SUCCESS) + response.status() != ClientUploadResponse::SUCCESS) { RecordUploadResult(UPLOAD_COMPLETE_RESPONSE_ERROR); - else + } else { RecordUploadResult(UPLOAD_SUCCESS); + } break; } case TwoPhaseUploader::UPLOAD_FILE: - if (net_error != net::OK) - RecordUploadResult(UPLOAD_FILE_NET_ERROR); - else - RecordUploadResult(UPLOAD_FILE_RESPONSE_ERROR); + RecordUploadResult(net_error != net::OK ? UPLOAD_FILE_NET_ERROR + : UPLOAD_FILE_RESPONSE_ERROR); break; case TwoPhaseUploader::UPLOAD_METADATA: - if (net_error != net::OK) - RecordUploadResult(UPLOAD_METADATA_NET_ERROR); - else - RecordUploadResult(UPLOAD_METADATA_RESPONSE_ERROR); + RecordUploadResult(net_error != net::OK ? UPLOAD_METADATA_NET_ERROR + : UPLOAD_METADATA_RESPONSE_ERROR); break; default: NOTREACHED(); + break; } uploader_.reset(); @@ -180,12 +177,13 @@ } void DownloadFeedbackImpl::RecordUploadResult(UploadResultType result) { - if (result == UPLOAD_SUCCESS) + if (result == UPLOAD_SUCCESS) { UMA_HISTOGRAM_CUSTOM_COUNTS( "SBDownloadFeedback.SizeSuccess", file_size_, 1, kMaxUploadSize, 50); - else + } else { UMA_HISTOGRAM_CUSTOM_COUNTS( "SBDownloadFeedback.SizeFailure", file_size_, 1, kMaxUploadSize, 50); + } UMA_HISTOGRAM_ENUMERATION( "SBDownloadFeedback.UploadResult", result, UPLOAD_RESULT_MAX); } @@ -200,19 +198,20 @@ "https://safebrowsing.google.com/safebrowsing/uploads/chrome"; // static -DownloadFeedbackFactory* DownloadFeedback::factory_ = NULL; +DownloadFeedbackFactory* DownloadFeedback::factory_ = nullptr; // static -DownloadFeedback* DownloadFeedback::Create( +std::unique_ptr<DownloadFeedback> DownloadFeedback::Create( net::URLRequestContextGetter* request_context_getter, base::TaskRunner* file_task_runner, const base::FilePath& file_path, const std::string& ping_request, const std::string& ping_response) { - if (!DownloadFeedback::factory_) - return new DownloadFeedbackImpl( - request_context_getter, file_task_runner, file_path, ping_request, - ping_response); + if (!factory_) { + return base::WrapUnique( + new DownloadFeedbackImpl(request_context_getter, file_task_runner, + file_path, ping_request, ping_response)); + } return DownloadFeedback::factory_->CreateDownloadFeedback( request_context_getter, file_task_runner, file_path, ping_request, ping_response);
diff --git a/chrome/browser/safe_browsing/download_feedback.h b/chrome/browser/safe_browsing/download_feedback.h index 90734eb..cd8adf5e 100644 --- a/chrome/browser/safe_browsing/download_feedback.h +++ b/chrome/browser/safe_browsing/download_feedback.h
@@ -14,10 +14,6 @@ #include "base/threading/non_thread_safe.h" #include "chrome/browser/safe_browsing/two_phase_uploader.h" -namespace content { -class DownloadItem; -} - namespace safe_browsing { class DownloadFeedbackFactory; @@ -28,7 +24,7 @@ public: // Takes ownership of the file pointed to be |file_path|, it will be deleted // when the DownloadFeedback is destructed. - static DownloadFeedback* Create( + static std::unique_ptr<DownloadFeedback> Create( net::URLRequestContextGetter* request_context_getter, base::TaskRunner* file_task_runner, const base::FilePath& file_path, @@ -70,7 +66,7 @@ public: virtual ~DownloadFeedbackFactory() {} - virtual DownloadFeedback* CreateDownloadFeedback( + virtual std::unique_ptr<DownloadFeedback> CreateDownloadFeedback( net::URLRequestContextGetter* request_context_getter, base::TaskRunner* file_task_runner, const base::FilePath& file_path,
diff --git a/chrome/browser/safe_browsing/download_feedback_service.cc b/chrome/browser/safe_browsing/download_feedback_service.cc index 9eb9b09..ca50fd24 100644 --- a/chrome/browser/safe_browsing/download_feedback_service.cc +++ b/chrome/browser/safe_browsing/download_feedback_service.cc
@@ -81,10 +81,11 @@ : request_context_getter_(request_context_getter), file_task_runner_(file_task_runner), weak_ptr_factory_(this) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } DownloadFeedbackService::~DownloadFeedbackService() { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } // static @@ -142,7 +143,7 @@ void DownloadFeedbackService::BeginFeedbackForDownload( content::DownloadItem* download) { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); UMA_HISTOGRAM_ENUMERATION("SBDownloadFeedback.Activations", download->GetDangerType(), @@ -186,11 +187,11 @@ const std::string& ping_request, const std::string& ping_response, const base::FilePath& path) { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); std::unique_ptr<DownloadFeedback> feedback(DownloadFeedback::Create( request_context_getter_.get(), file_task_runner_.get(), path, ping_request, ping_response)); - active_feedback_.push_back(std::move(feedback)); + active_feedback_.push(std::move(feedback)); UMA_HISTOGRAM_COUNTS_100("SBDownloadFeedback.ActiveFeedbacks", active_feedback_.size()); @@ -200,9 +201,9 @@ void DownloadFeedbackService::FeedbackComplete() { DVLOG(1) << __FUNCTION__; - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(!active_feedback_.empty()); - active_feedback_.erase(active_feedback_.begin()); + active_feedback_.pop(); if (!active_feedback_.empty()) StartPendingFeedback(); }
diff --git a/chrome/browser/safe_browsing/download_feedback_service.h b/chrome/browser/safe_browsing/download_feedback_service.h index 35058ea..48b1ee8 100644 --- a/chrome/browser/safe_browsing/download_feedback_service.h +++ b/chrome/browser/safe_browsing/download_feedback_service.h
@@ -6,12 +6,11 @@ #define CHROME_BROWSER_SAFE_BROWSING_DOWNLOAD_FEEDBACK_SERVICE_H_ #include <memory> +#include <queue> #include <string> -#include <vector> #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/threading/non_thread_safe.h" #include "chrome/browser/safe_browsing/download_protection_service.h" #include "content/public/browser/download_danger_type.h" @@ -33,7 +32,8 @@ // Tracks active DownloadFeedback objects, provides interface for storing ping // data for malicious downloads. -class DownloadFeedbackService : public base::NonThreadSafe { +// Lives on the UI thread. +class DownloadFeedbackService { public: DownloadFeedbackService(net::URLRequestContextGetter* request_context_getter, base::TaskRunner* file_task_runner); @@ -86,7 +86,7 @@ // Currently active & pending uploads. The first item is active, remaining // items are pending. - std::vector<std::unique_ptr<DownloadFeedback>> active_feedback_; + std::queue<std::unique_ptr<DownloadFeedback>> active_feedback_; base::WeakPtrFactory<DownloadFeedbackService> weak_ptr_factory_;
diff --git a/chrome/browser/safe_browsing/download_feedback_service_unittest.cc b/chrome/browser/safe_browsing/download_feedback_service_unittest.cc index 5bb379f..1c11e93 100644 --- a/chrome/browser/safe_browsing/download_feedback_service_unittest.cc +++ b/chrome/browser/safe_browsing/download_feedback_service_unittest.cc
@@ -11,6 +11,7 @@ #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/strings/string_number_conversions.h" #include "chrome/browser/safe_browsing/download_feedback.h" @@ -82,7 +83,7 @@ public: ~FakeDownloadFeedbackFactory() override {} - DownloadFeedback* CreateDownloadFeedback( + std::unique_ptr<DownloadFeedback> CreateDownloadFeedback( net::URLRequestContextGetter* request_context_getter, base::TaskRunner* file_task_runner, const base::FilePath& file_path, @@ -98,12 +99,10 @@ base::Unretained(this), feedbacks_.size())); feedbacks_.push_back(feedback); - return feedback; + return base::WrapUnique(feedback); } - void DownloadFeedbackDeleted(size_t n) { - feedbacks_[n] = NULL; - } + void DownloadFeedbackDeleted(size_t n) { feedbacks_[n] = nullptr; } FakeDownloadFeedback* feedback(size_t n) const { return feedbacks_[n]; @@ -144,7 +143,7 @@ DownloadFeedback::RegisterFactory(&download_feedback_factory_); } - void TearDown() override { DownloadFeedback::RegisterFactory(NULL); } + void TearDown() override { DownloadFeedback::RegisterFactory(nullptr); } base::FilePath CreateTestFile(int n) const { base::FilePath upload_file_path( @@ -235,14 +234,14 @@ TEST_F(DownloadFeedbackServiceTest, MultiplePendingFeedbackComplete) { const std::string ping_request = "ping"; const std::string ping_response = "resp"; - const size_t num_downloads = 3; + const size_t kNumDownloads = 3; content::DownloadItem::AcquireFileCallback - download_discarded_callback[num_downloads]; + download_discarded_callback[kNumDownloads]; - base::FilePath file_path[num_downloads]; - content::MockDownloadItem item[num_downloads]; - for (size_t i = 0; i < num_downloads; ++i) { + base::FilePath file_path[kNumDownloads]; + content::MockDownloadItem item[kNumDownloads]; + for (size_t i = 0; i < kNumDownloads; ++i) { file_path[i] = CreateTestFile(i); EXPECT_CALL(item[i], GetDangerType()) .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT)); @@ -258,14 +257,14 @@ { DownloadFeedbackService service(request_context_getter_.get(), file_task_runner_.get()); - for (size_t i = 0; i < num_downloads; ++i) { + for (size_t i = 0; i < kNumDownloads; ++i) { SCOPED_TRACE(i); service.BeginFeedbackForDownload(&item[i]); ASSERT_FALSE(download_discarded_callback[i].is_null()); } EXPECT_EQ(0U, num_feedbacks()); - for (size_t i = 0; i < num_downloads; ++i) { + for (size_t i = 0; i < kNumDownloads; ++i) { download_discarded_callback[i].Run(file_path[i]); } @@ -304,14 +303,14 @@ TEST_F(DownloadFeedbackServiceTest, MultiFeedbackWithIncomplete) { const std::string ping_request = "ping"; const std::string ping_response = "resp"; - const size_t num_downloads = 3; + const size_t kNumDownloads = 3; content::DownloadItem::AcquireFileCallback - download_discarded_callback[num_downloads]; + download_discarded_callback[kNumDownloads]; - base::FilePath file_path[num_downloads]; - content::MockDownloadItem item[num_downloads]; - for (size_t i = 0; i < num_downloads; ++i) { + base::FilePath file_path[kNumDownloads]; + content::MockDownloadItem item[kNumDownloads]; + for (size_t i = 0; i < kNumDownloads; ++i) { file_path[i] = CreateTestFile(i); EXPECT_CALL(item[i], GetDangerType()) .WillRepeatedly(Return(content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT)); @@ -327,7 +326,7 @@ { DownloadFeedbackService service(request_context_getter_.get(), file_task_runner_.get()); - for (size_t i = 0; i < num_downloads; ++i) { + for (size_t i = 0; i < kNumDownloads; ++i) { SCOPED_TRACE(i); service.BeginFeedbackForDownload(&item[i]); ASSERT_FALSE(download_discarded_callback[i].is_null());
diff --git a/chrome/browser/safe_browsing/download_feedback_unittest.cc b/chrome/browser/safe_browsing/download_feedback_unittest.cc index 2ce8b49..6c7979ff 100644 --- a/chrome/browser/safe_browsing/download_feedback_unittest.cc +++ b/chrome/browser/safe_browsing/download_feedback_unittest.cc
@@ -6,6 +6,7 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" +#include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" @@ -64,10 +65,10 @@ class FakeUploaderFactory : public TwoPhaseUploaderFactory { public: - FakeUploaderFactory() : uploader_(NULL) {} + FakeUploaderFactory() : uploader_(nullptr) {} ~FakeUploaderFactory() override {} - TwoPhaseUploader* CreateTwoPhaseUploader( + std::unique_ptr<TwoPhaseUploader> CreateTwoPhaseUploader( net::URLRequestContextGetter* url_request_context_getter, base::TaskRunner* file_task_runner, const GURL& base_url, @@ -79,7 +80,7 @@ FakeUploader* uploader_; }; -TwoPhaseUploader* FakeUploaderFactory::CreateTwoPhaseUploader( +std::unique_ptr<TwoPhaseUploader> FakeUploaderFactory::CreateTwoPhaseUploader( net::URLRequestContextGetter* url_request_context_getter, base::TaskRunner* file_task_runner, const GURL& base_url, @@ -92,7 +93,7 @@ uploader_ = new FakeUploader(url_request_context_getter, file_task_runner, base_url, metadata, file_path, progress_callback, finish_callback); - return uploader_; + return base::WrapUnique(uploader_); } } // namespace @@ -120,16 +121,15 @@ TwoPhaseUploader::RegisterFactory(&two_phase_uploader_factory_); } - void TearDown() override { TwoPhaseUploader::RegisterFactory(NULL); } + void TearDown() override { TwoPhaseUploader::RegisterFactory(nullptr); } FakeUploader* uploader() const { return two_phase_uploader_factory_.uploader_; } - void FinishCallback(DownloadFeedback* feedback) { + void FinishCallback() { EXPECT_FALSE(feedback_finish_called_); feedback_finish_called_ = true; - delete feedback; } protected: @@ -147,11 +147,10 @@ TEST_F(DownloadFeedbackTest, CompleteUpload) { ClientDownloadReport expected_report_metadata; - expected_report_metadata.mutable_download_request()->set_url("http://test"); - expected_report_metadata.mutable_download_request()->set_length( - upload_file_data_.size()); - expected_report_metadata.mutable_download_request()->mutable_digests( - )->set_sha1("hi"); + auto* request = expected_report_metadata.mutable_download_request(); + request->set_url("http://test"); + request->set_length(upload_file_data_.size()); + request->mutable_digests()->set_sha1("hi"); expected_report_metadata.mutable_download_response()->set_verdict( ClientDownloadResponse::DANGEROUS_HOST); std::string ping_request( @@ -159,17 +158,13 @@ std::string ping_response( expected_report_metadata.download_response().SerializeAsString()); - DownloadFeedback* feedback = - DownloadFeedback::Create(url_request_context_getter_.get(), - file_task_runner_.get(), - upload_file_path_, - ping_request, - ping_response); + std::unique_ptr<DownloadFeedback> feedback = DownloadFeedback::Create( + url_request_context_getter_.get(), file_task_runner_.get(), + upload_file_path_, ping_request, ping_response); EXPECT_FALSE(uploader()); feedback->Start(base::Bind(&DownloadFeedbackTest::FinishCallback, - base::Unretained(this), - feedback)); + base::Unretained(this))); ASSERT_TRUE(uploader()); EXPECT_FALSE(feedback_finish_called_); EXPECT_TRUE(uploader()->start_called_); @@ -188,17 +183,17 @@ uploader()->finish_callback_.Run( TwoPhaseUploader::STATE_SUCCESS, net::OK, 0, ""); EXPECT_TRUE(feedback_finish_called_); + feedback.reset(); base::RunLoop().RunUntilIdle(); EXPECT_FALSE(base::PathExists(upload_file_path_)); } TEST_F(DownloadFeedbackTest, CancelUpload) { ClientDownloadReport expected_report_metadata; - expected_report_metadata.mutable_download_request()->set_url("http://test"); - expected_report_metadata.mutable_download_request()->set_length( - upload_file_data_.size()); - expected_report_metadata.mutable_download_request()->mutable_digests( - )->set_sha1("hi"); + auto* request = expected_report_metadata.mutable_download_request(); + request->set_url("http://test"); + request->set_length(upload_file_data_.size()); + request->mutable_digests()->set_sha1("hi"); expected_report_metadata.mutable_download_response()->set_verdict( ClientDownloadResponse::DANGEROUS_HOST); std::string ping_request( @@ -206,23 +201,19 @@ std::string ping_response( expected_report_metadata.download_response().SerializeAsString()); - DownloadFeedback* feedback = - DownloadFeedback::Create(url_request_context_getter_.get(), - file_task_runner_.get(), - upload_file_path_, - ping_request, - ping_response); + std::unique_ptr<DownloadFeedback> feedback = DownloadFeedback::Create( + url_request_context_getter_.get(), file_task_runner_.get(), + upload_file_path_, ping_request, ping_response); EXPECT_FALSE(uploader()); feedback->Start(base::Bind(&DownloadFeedbackTest::FinishCallback, - base::Unretained(this), - feedback)); + base::Unretained(this))); ASSERT_TRUE(uploader()); EXPECT_FALSE(feedback_finish_called_); EXPECT_TRUE(uploader()->start_called_); EXPECT_TRUE(base::PathExists(upload_file_path_)); - delete feedback; + feedback.reset(); EXPECT_FALSE(feedback_finish_called_); base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.cc b/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.cc index 142da45a..ebc14d2f 100644 --- a/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.cc +++ b/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.h" #include "base/location.h" +#include "content/public/browser/browser_thread.h" namespace safe_browsing { @@ -12,27 +13,29 @@ base::TimeDelta delay, const scoped_refptr<base::TaskRunner>& task_runner) : task_runner_(task_runner), - next_callback_(callbacks_.end()), + has_work_(false), timer_(FROM_HERE, delay, this, &DelayedCallbackRunner::OnTimer) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } DelayedCallbackRunner::~DelayedCallbackRunner() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } void DelayedCallbackRunner::RegisterCallback(const base::Closure& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); - callbacks_.push_back(callback); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + callbacks_.push(callback); } void DelayedCallbackRunner::Start() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Nothing to do if the runner is already running or nothing has been added. - if (next_callback_ != callbacks_.end() || callbacks_.empty()) + if (has_work_ || callbacks_.empty()) return; // Prime the system with the first callback. - next_callback_ = callbacks_.begin(); + has_work_ = true; // Point the starter pistol in the air and pull the trigger. timer_.Reset(); @@ -40,11 +43,13 @@ void DelayedCallbackRunner::OnTimer() { // Run the next callback on the task runner. - task_runner_->PostTask(FROM_HERE, *next_callback_); + auto callback = callbacks_.front(); + callbacks_.pop(); + task_runner_->PostTask(FROM_HERE, callback); // Remove this callback and get ready for the next if there is one. - next_callback_ = callbacks_.erase(next_callback_); - if (next_callback_ != callbacks_.end()) + has_work_ = !callbacks_.empty(); + if (has_work_) timer_.Reset(); }
diff --git a/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.h b/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.h index 19e3f6c1..db95bc55e 100644 --- a/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.h +++ b/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner.h
@@ -5,13 +5,12 @@ #ifndef CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_DELAYED_CALLBACK_RUNNER_H_ #define CHROME_BROWSER_SAFE_BROWSING_INCIDENT_REPORTING_DELAYED_CALLBACK_RUNNER_H_ -#include <list> +#include <queue> #include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/task_runner.h" -#include "base/threading/thread_checker.h" #include "base/time/time.h" #include "base/timer/timer.h" @@ -22,6 +21,7 @@ // the first callback will be run some time after Start() is invoked). Callbacks // are deleted after they are run. Start() is idempotent: calling it while the // runner is doing its job has no effect. +// Lives on the UI thread. class DelayedCallbackRunner { public: // Constructs an instance that runs tasks on |callback_runner|, waiting for @@ -38,22 +38,20 @@ void Start(); private: - typedef std::list<base::Closure> CallbackList; + using CallbackList = std::queue<base::Closure>; // A callback invoked by the timer to run the next callback. The timer is // restarted to process the next callback if there is one. void OnTimer(); - base::ThreadChecker thread_checker_; - // The runner on which callbacks are to be run. scoped_refptr<base::TaskRunner> task_runner_; // The list of callbacks to run. Callbacks are removed when run. CallbackList callbacks_; - // callbacks_.end() when no work is being done. Any other value otherwise. - CallbackList::iterator next_callback_; + // Whethere there is work to be done from |callbacks_|. + bool has_work_; // A timer upon the firing of which the next callback will be run. base::DelayTimer timer_;
diff --git a/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner_unittest.cc index 863b599..2d284dd 100644 --- a/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/delayed_callback_runner_unittest.cc
@@ -11,8 +11,10 @@ #include "base/callback.h" #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "base/test/test_simple_task_runner.h" +#include "base/run_loop.h" #include "base/threading/thread_task_runner_handle.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -45,14 +47,11 @@ } protected: - DelayedCallbackRunnerTest() - : task_runner_(new base::TestSimpleTaskRunner), - thread_task_runner_handle_(task_runner_) {} + DelayedCallbackRunnerTest() {} void SetUp() override { instance_.reset(new safe_browsing::DelayedCallbackRunner( - base::TimeDelta::FromMilliseconds(1), // ignored by simple runner. - task_runner_)); + base::TimeDelta(), base::ThreadTaskRunnerHandle::Get())); } void TearDown() override { instance_.reset(); } @@ -90,8 +89,7 @@ return callbacks_[name].deleted; } - scoped_refptr<base::TestSimpleTaskRunner> task_runner_; - base::ThreadTaskRunnerHandle thread_task_runner_handle_; + content::TestBrowserThreadBundle thread_bundle_; std::unique_ptr<safe_browsing::DelayedCallbackRunner> instance_; private: @@ -118,7 +116,7 @@ const std::string name("one"); RegisterTestCallback(name); instance_->Start(); - task_runner_->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(CallbackWasRun(name)); EXPECT_TRUE(CallbackWasDeleted(name)); } @@ -130,15 +128,13 @@ const std::string name2("two"); // Post a task to register a new callback after Start() is called. - task_runner_->PostTask( - FROM_HERE, - base::Bind(&DelayedCallbackRunnerTest::RegisterTestCallback, - base::Unretained(this), - name2)); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&DelayedCallbackRunnerTest::RegisterTestCallback, + base::Unretained(this), name2)); RegisterTestCallback(name); instance_->Start(); - task_runner_->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(CallbackWasRun(name)); EXPECT_TRUE(CallbackWasDeleted(name)); EXPECT_TRUE(CallbackWasRun(name2)); @@ -151,13 +147,13 @@ RegisterTestCallback(name); instance_->Start(); - task_runner_->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(CallbackWasRun(name)); EXPECT_TRUE(CallbackWasDeleted(name)); RegisterTestCallback(name2); instance_->Start(); - task_runner_->RunUntilIdle(); + base::RunLoop().RunUntilIdle(); EXPECT_TRUE(CallbackWasRun(name2)); EXPECT_TRUE(CallbackWasDeleted(name2)); }
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc index 4e30cf3..2de8eb7 100644 --- a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc +++ b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc
@@ -241,7 +241,7 @@ void IncidentReportingService::Receiver::AddIncidentForProfile( Profile* profile, std::unique_ptr<Incident> incident) { - DCHECK(thread_runner_->BelongsToCurrentThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(profile); AddIncidentOnMainThread(service_, profile, std::move(incident)); } @@ -361,6 +361,7 @@ download_metadata_manager_(content::BrowserThread::GetBlockingPool()), receiver_weak_ptr_factory_(this), weak_ptr_factory_(this) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED, content::NotificationService::AllSources()); @@ -368,9 +369,9 @@ chrome::NOTIFICATION_PROFILE_DESTROYED, content::NotificationService::AllSources()); DownloadProtectionService* download_protection_service = - (safe_browsing_service ? - safe_browsing_service->download_protection_service() : - NULL); + (safe_browsing_service + ? safe_browsing_service->download_protection_service() + : nullptr); if (download_protection_service) { client_download_request_subscription_ = download_protection_service->RegisterClientDownloadRequestCallback( @@ -382,7 +383,7 @@ } IncidentReportingService::~IncidentReportingService() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); CancelIncidentCollection(); // Cancel all internal asynchronous tasks. @@ -403,7 +404,7 @@ std::unique_ptr<TrackedPreferenceValidationDelegate> IncidentReportingService::CreatePreferenceValidationDelegate(Profile* profile) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (profile->IsOffTheRecord()) return std::unique_ptr<TrackedPreferenceValidationDelegate>(); @@ -413,7 +414,7 @@ void IncidentReportingService::RegisterDelayedAnalysisCallback( const DelayedAnalysisCallback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // |callback| will be run on the blocking pool. The receiver will bounce back // to the origin thread if needed. @@ -430,7 +431,7 @@ void IncidentReportingService:: RegisterExtendedReportingOnlyDelayedAnalysisCallback( const DelayedAnalysisCallback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // |callback| will be run on the blocking pool. The receiver will bounce back // to the origin thread if needed. @@ -460,7 +461,7 @@ const scoped_refptr<base::TaskRunner>& delayed_task_runner) : database_manager_(safe_browsing_service ? safe_browsing_service->database_manager() - : NULL), + : nullptr), url_request_context_getter_(request_context_getter), collect_environment_data_fn_(&CollectEnvironmentData), environment_collection_task_runner_( @@ -508,7 +509,7 @@ } void IncidentReportingService::OnProfileAdded(Profile* profile) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Track the addition of all profiles even when no report is being assembled // so that the service can determine whether or not it can evaluate a @@ -584,13 +585,13 @@ } bool IncidentReportingService::IsProcessingReport() const { - return report_ != NULL; + return report_ != nullptr; } IncidentReportingService::ProfileContext* IncidentReportingService::GetOrCreateProfileContext(Profile* profile) { ProfileContextCollection::iterator it = - profiles_.insert(ProfileContextCollection::value_type(profile, NULL)) + profiles_.insert(ProfileContextCollection::value_type(profile, nullptr)) .first; if (!it->second) it->second = new ProfileContext(); @@ -600,11 +601,11 @@ IncidentReportingService::ProfileContext* IncidentReportingService::GetProfileContext(Profile* profile) { ProfileContextCollection::iterator it = profiles_.find(profile); - return it == profiles_.end() ? NULL : it->second; + return it != profiles_.end() ? it->second : nullptr; } void IncidentReportingService::OnProfileDestroyed(Profile* profile) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ProfileContextCollection::iterator it = profiles_.find(profile); if (it == profiles_.end()) @@ -626,7 +627,7 @@ } Profile* IncidentReportingService::FindEligibleProfile() const { - Profile* candidate = NULL; + Profile* candidate = nullptr; for (ProfileContextCollection::const_iterator scan = profiles_.begin(); scan != profiles_.end(); ++scan) { @@ -654,7 +655,7 @@ void IncidentReportingService::AddIncident(Profile* profile, std::unique_ptr<Incident> incident) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Ignore incidents from off-the-record profiles. if (profile && profile->IsOffTheRecord()) @@ -705,7 +706,7 @@ } void IncidentReportingService::BeginReportProcessing() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Creates a new report if needed. if (!report_) @@ -734,7 +735,7 @@ } void IncidentReportingService::OnCollationTimeout() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Exit early if collection was cancelled. if (!collation_timeout_pending_) @@ -756,7 +757,7 @@ } void IncidentReportingService::BeginEnvironmentCollection() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(report_); // Nothing to do if environment collection is pending or has already // completed, if there are no incidents to process, or if there is no eligible @@ -794,7 +795,7 @@ void IncidentReportingService::OnEnvironmentDataCollected( std::unique_ptr<ClientIncidentReport_EnvironmentData> environment_data) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(environment_collection_pending_); DCHECK(report_ && !report_->has_environment()); environment_collection_pending_ = false; @@ -816,7 +817,7 @@ } void IncidentReportingService::BeginDownloadCollection() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(report_); // Nothing to do if a search for the most recent download is already pending, // if one has already been found, or if there are no incidents to process. @@ -870,7 +871,7 @@ std::unique_ptr<ClientIncidentReport_DownloadDetails> last_binary_download, std::unique_ptr<ClientIncidentReport_NonBinaryDownloadDetails> last_non_binary_download) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(report_); UMA_HISTOGRAM_TIMES("SBIRS.FindDownloadedBinaryTime", @@ -923,7 +924,7 @@ // Associate process-wide incidents with the profile that benefits from the // strongest safe browsing protections. If there is no such profile, drop the // incidents. - ProfileContext* null_context = GetProfileContext(NULL); + ProfileContext* null_context = GetProfileContext(nullptr); if (null_context && null_context->HasIncidents()) { if (eligible_profile) { ProfileContext* eligible_context = GetProfileContext(eligible_profile); @@ -1063,7 +1064,7 @@ } #endif - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!is_killswitch_on) { // Initiate the upload. context->uploader = StartReportUpload( @@ -1095,7 +1096,7 @@ UploadContext* context, IncidentReportUploader::Result result, std::unique_ptr<ClientIncidentResponse> response) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); UMA_HISTOGRAM_ENUMERATION( "SBIRS.UploadResult", result, IncidentReportUploader::NUM_UPLOAD_RESULTS);
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.h b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.h index c692814..38e6d16 100644 --- a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.h +++ b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.h
@@ -16,7 +16,6 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" -#include "base/threading/thread_checker.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "chrome/browser/safe_browsing/download_protection_service.h" @@ -74,6 +73,7 @@ // a bit. Additional incidents that arrive during this time are collated with // the initial incident. Finally, already-reported incidents are pruned and any // remaining are uploaded in an incident report. +// Lives on the UI thread. class IncidentReportingService : public content::NotificationObserver { public: explicit IncidentReportingService(SafeBrowsingService* safe_browsing_service); @@ -277,8 +277,6 @@ const content::NotificationSource& source, const content::NotificationDetails& details) override; - base::ThreadChecker thread_checker_; - // The safe browsing database manager, through which the whitelist killswitch // is checked. scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc index 3ed7947..6f6c229 100644 --- a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service_unittest.cc
@@ -35,6 +35,7 @@ #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/syncable_prefs/testing_pref_service_syncable.h" +#include "content/public/test/test_browser_thread.h" #include "extensions/browser/quota_service.h" #include "net/url_request/url_request_context_getter.h" #include "testing/gtest/include/gtest/gtest.h" @@ -53,22 +54,20 @@ class TestIncidentReportingService : public safe_browsing::IncidentReportingService { public: - typedef base::Callback<void(Profile*)> PreProfileAddCallback; + using PreProfileAddCallback = base::Callback<void(Profile*)>; - typedef base::Callback< - void(safe_browsing::ClientIncidentReport_EnvironmentData*)> - CollectEnvironmentCallback; + using CollectEnvironmentCallback = base::Callback<void( + safe_browsing::ClientIncidentReport_EnvironmentData*)>; - typedef base::Callback<std::unique_ptr<safe_browsing::LastDownloadFinder>( - const safe_browsing::LastDownloadFinder::LastDownloadCallback& - callback)> - CreateDownloadFinderCallback; + using CreateDownloadFinderCallback = + base::Callback<std::unique_ptr<safe_browsing::LastDownloadFinder>( + const safe_browsing::LastDownloadFinder::LastDownloadCallback& + callback)>; - typedef base::Callback< - std::unique_ptr<safe_browsing::IncidentReportUploader>( + using StartUploadCallback = + base::Callback<std::unique_ptr<safe_browsing::IncidentReportUploader>( const safe_browsing::IncidentReportUploader::OnResultCallback&, - const safe_browsing::ClientIncidentReport& report)> - StartUploadCallback; + const safe_browsing::ClientIncidentReport& report)>; TestIncidentReportingService( const scoped_refptr<base::TaskRunner>& task_runner, @@ -76,8 +75,8 @@ const CollectEnvironmentCallback& collect_environment_callback, const CreateDownloadFinderCallback& create_download_finder_callback, const StartUploadCallback& start_upload_callback) - : IncidentReportingService(NULL, - NULL, + : IncidentReportingService(nullptr, + nullptr, base::TimeDelta::FromMilliseconds(5), task_runner), pre_profile_add_callback_(pre_profile_add_callback), @@ -89,7 +88,9 @@ test_instance_.Get().Set(this); } - ~TestIncidentReportingService() override { test_instance_.Get().Set(NULL); } + ~TestIncidentReportingService() override { + test_instance_.Get().Set(nullptr); + } bool IsProcessingReport() const { return IncidentReportingService::IsProcessingReport(); @@ -195,6 +196,7 @@ IncidentReportingServiceTest() : task_runner_(new base::TestSimpleTaskRunner), thread_task_runner_handle_(task_runner_), + ui_thread_(content::BrowserThread::UI), profile_manager_(TestingBrowserProcess::GetGlobal()), on_create_download_finder_action_( ON_CREATE_DOWNLOAD_FINDER_DOWNLOADS_FOUND), @@ -344,6 +346,7 @@ disable_purge_for_testing_; scoped_refptr<base::TestSimpleTaskRunner> task_runner_; base::ThreadTaskRunnerHandle thread_task_runner_handle_; + content::TestBrowserThread ui_thread_; TestingProfileManager profile_manager_; std::unique_ptr<TestIncidentReportingService> instance_; base::Closure on_start_upload_callback_; @@ -508,9 +511,7 @@ // operation. void CollectEnvironmentData( safe_browsing::ClientIncidentReport_EnvironmentData* data) { - ASSERT_NE( - static_cast<safe_browsing::ClientIncidentReport_EnvironmentData*>(NULL), - data); + ASSERT_TRUE(data); data->mutable_os()->set_os_name(kFakeOsName); environment_collected_ = true; } @@ -1069,7 +1070,7 @@ TEST_F(IncidentReportingServiceTest, ProcessWideNoProfileNoUpload) { SetFieldTrialAndCreateService(true); // Add the test incident. - AddTestIncident(NULL); + AddTestIncident(nullptr); // Let all tasks run. task_runner_->RunUntilIdle(); @@ -1090,7 +1091,7 @@ ON_PROFILE_ADDITION_NO_ACTION, nullptr); // Add the test incident. - AddTestIncident(NULL); + AddTestIncident(nullptr); // Let all tasks run. task_runner_->RunUntilIdle(); @@ -1099,7 +1100,7 @@ ExpectTestIncidentUploadWithBinaryDownload(1); // Add the incident to the service again. - AddTestIncident(NULL); + AddTestIncident(nullptr); // Let all tasks run. task_runner_->RunUntilIdle(); @@ -1148,7 +1149,7 @@ TEST_F(IncidentReportingServiceTest, ProcessWideNoUploadAfterProfile) { SetFieldTrialAndCreateService(false); // Add the test incident. - AddTestIncident(NULL); + AddTestIncident(nullptr); // Let all tasks run. task_runner_->RunUntilIdle(); @@ -1294,7 +1295,7 @@ ExpectTestIncidentUploadWithBinaryDownload(1); // Add the incident to the service again. - AddTestIncident(NULL); + AddTestIncident(nullptr); // Let all tasks run. task_runner_->RunUntilIdle();
diff --git a/chrome/browser/safe_browsing/local_database_manager.cc b/chrome/browser/safe_browsing/local_database_manager.cc index e2430a7..2ec9325 100644 --- a/chrome/browser/safe_browsing/local_database_manager.cc +++ b/chrome/browser/safe_browsing/local_database_manager.cc
@@ -804,7 +804,7 @@ return database_; const base::TimeTicks before = base::TimeTicks::Now(); - SafeBrowsingDatabase* database = SafeBrowsingDatabase::Create( + std::unique_ptr<SafeBrowsingDatabase> database = SafeBrowsingDatabase::Create( safe_browsing_task_runner_, enable_download_protection_, enable_csd_whitelist_, enable_download_whitelist_, enable_extension_blacklist_, enable_ip_blacklist_, @@ -815,7 +815,7 @@ // Acquiring the lock here guarantees correct ordering between the writes to // the new database object above, and the setting of |database_| below. base::AutoLock lock(database_lock_); - database_ = database; + database_ = database.release(); } BrowserThread::PostTask(
diff --git a/chrome/browser/safe_browsing/ping_manager.cc b/chrome/browser/safe_browsing/ping_manager.cc index f24cf859..f75ed23e 100644 --- a/chrome/browser/safe_browsing/ping_manager.cc +++ b/chrome/browser/safe_browsing/ping_manager.cc
@@ -7,9 +7,11 @@ #include <utility> #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "chrome/browser/safe_browsing/permission_reporter.h" #include "components/certificate_reporting/error_reporter.h" #include "content/public/browser/browser_thread.h" #include "google_apis/google_api_keys.h" @@ -38,11 +40,12 @@ // SafeBrowsingPingManager implementation ---------------------------------- // static -SafeBrowsingPingManager* SafeBrowsingPingManager::Create( +std::unique_ptr<SafeBrowsingPingManager> SafeBrowsingPingManager::Create( net::URLRequestContextGetter* request_context_getter, const SafeBrowsingProtocolConfig& config) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - return new SafeBrowsingPingManager(request_context_getter, config); + return base::WrapUnique( + new SafeBrowsingPingManager(request_context_getter, config)); } SafeBrowsingPingManager::SafeBrowsingPingManager( @@ -62,6 +65,9 @@ certificate_error_reporter_.reset(new certificate_reporting::ErrorReporter( request_context_getter->GetURLRequestContext(), certificate_upload_url, cookies_preference)); + + permission_reporter_.reset( + new PermissionReporter(request_context_getter->GetURLRequestContext())); } version_ = SafeBrowsingProtocolManagerHelper::Version(); @@ -129,6 +135,13 @@ certificate_error_reporter_ = std::move(certificate_error_reporter); } +void SafeBrowsingPingManager::ReportPermissionAction( + const GURL& origin, + content::PermissionType permission, + PermissionAction action) { + permission_reporter_->SendReport(origin, permission, action); +} + GURL SafeBrowsingPingManager::SafeBrowsingHitUrl( const safe_browsing::HitReport& hit_report) const { DCHECK(hit_report.threat_type == SB_THREAT_TYPE_URL_MALWARE ||
diff --git a/chrome/browser/safe_browsing/ping_manager.h b/chrome/browser/safe_browsing/ping_manager.h index f8730ba..f07252c 100644 --- a/chrome/browser/safe_browsing/ping_manager.h +++ b/chrome/browser/safe_browsing/ping_manager.h
@@ -14,9 +14,11 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" +#include "chrome/browser/permissions/permission_uma_util.h" #include "chrome/browser/safe_browsing/protocol_manager_helper.h" #include "components/safe_browsing_db/hit_report.h" #include "components/safe_browsing_db/util.h" +#include "content/public/browser/permission_type.h" #include "net/url_request/url_fetcher_delegate.h" #include "url/gurl.h" @@ -31,12 +33,14 @@ namespace safe_browsing { +class PermissionReporter; + class SafeBrowsingPingManager : public net::URLFetcherDelegate { public: ~SafeBrowsingPingManager() override; // Create an instance of the safe browsing ping manager. - static SafeBrowsingPingManager* Create( + static std::unique_ptr<SafeBrowsingPingManager> Create( net::URLRequestContextGetter* request_context_getter, const SafeBrowsingProtocolConfig& config); @@ -60,6 +64,11 @@ std::unique_ptr<certificate_reporting::ErrorReporter> certificate_error_reporter); + // Report permission action to SafeBrowsing servers. + void ReportPermissionAction(const GURL& origin, + content::PermissionType permission, + PermissionAction action); + private: FRIEND_TEST_ALL_PREFIXES(SafeBrowsingPingManagerTest, TestSafeBrowsingHitUrl); @@ -100,6 +109,9 @@ std::unique_ptr<certificate_reporting::ErrorReporter> certificate_error_reporter_; + // Sends reports of permission actions. + std::unique_ptr<PermissionReporter> permission_reporter_; + DISALLOW_COPY_AND_ASSIGN(SafeBrowsingPingManager); };
diff --git a/chrome/browser/safe_browsing/protocol_manager.cc b/chrome/browser/safe_browsing/protocol_manager.cc index e9c561a..5ba83b1 100644 --- a/chrome/browser/safe_browsing/protocol_manager.cc +++ b/chrome/browser/safe_browsing/protocol_manager.cc
@@ -9,6 +9,7 @@ #include "base/environment.h" #include "base/logging.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/sparse_histogram.h" #include "base/profiler/scoped_tracker.h" @@ -22,6 +23,7 @@ #include "chrome/common/env_vars.h" #include "components/safe_browsing_db/util.h" #include "components/variations/variations_associated_data.h" +#include "content/public/browser/browser_thread.h" #include "google_apis/google_api_keys.h" #include "net/base/escape.h" #include "net/base/load_flags.h" @@ -98,12 +100,13 @@ public: SBProtocolManagerFactoryImpl() {} ~SBProtocolManagerFactoryImpl() override {} - SafeBrowsingProtocolManager* CreateProtocolManager( + + std::unique_ptr<SafeBrowsingProtocolManager> CreateProtocolManager( SafeBrowsingProtocolManagerDelegate* delegate, net::URLRequestContextGetter* request_context_getter, const SafeBrowsingProtocolConfig& config) override { - return new SafeBrowsingProtocolManager(delegate, request_context_getter, - config); + return base::WrapUnique(new SafeBrowsingProtocolManager( + delegate, request_context_getter, config)); } private: @@ -113,17 +116,14 @@ // SafeBrowsingProtocolManager implementation ---------------------------------- // static -SBProtocolManagerFactory* SafeBrowsingProtocolManager::factory_ = NULL; +SBProtocolManagerFactory* SafeBrowsingProtocolManager::factory_ = nullptr; // static -SafeBrowsingProtocolManager* SafeBrowsingProtocolManager::Create( +std::unique_ptr<SafeBrowsingProtocolManager> +SafeBrowsingProtocolManager::Create( SafeBrowsingProtocolManagerDelegate* delegate, net::URLRequestContextGetter* request_context_getter, const SafeBrowsingProtocolConfig& config) { - // TODO(cbentzel): Remove ScopedTracker below once crbug.com/483689 is fixed. - tracked_objects::ScopedTracker tracking_profile( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "483689 SafeBrowsingProtocolManager::Create")); if (!factory_) factory_ = new SBProtocolManagerFactoryImpl(); return factory_->CreateProtocolManager(delegate, request_context_getter, @@ -206,7 +206,7 @@ FullHashCallback callback, bool is_download, bool is_extended_reporting) { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); // If we are in GetHash backoff, we need to check if we're past the next // allowed time. If we are, we can proceed with the request. If not, we are // required to return empty results (i.e. treat the page as safe). @@ -232,7 +232,7 @@ } void SafeBrowsingProtocolManager::GetNextUpdate() { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (request_.get() || request_type_ != NO_REQUEST) return; @@ -251,7 +251,7 @@ // required, the SafeBrowsing servers will tell us to get it again. void SafeBrowsingProtocolManager::OnURLFetchComplete( const net::URLFetcher* source) { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); std::unique_ptr<const net::URLFetcher> fetcher; HashRequests::iterator it = hash_requests_.find(source); @@ -409,7 +409,7 @@ bool SafeBrowsingProtocolManager::HandleServiceResponse(const GURL& url, const char* data, size_t length) { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); switch (request_type_) { case UPDATE_REQUEST: @@ -490,11 +490,7 @@ } void SafeBrowsingProtocolManager::Initialize() { - DCHECK(CalledOnValidThread()); - // TODO(cbentzel): Remove ScopedTracker below once crbug.com/483689 is fixed. - tracked_objects::ScopedTracker tracking_profile( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "483689 SafeBrowsingProtocolManager::Initialize")); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); // Don't want to hit the safe browsing servers on build/chrome bots. std::unique_ptr<base::Environment> env(base::Environment::Create()); if (env->HasVar(env_vars::kHeadless)) @@ -503,7 +499,7 @@ } void SafeBrowsingProtocolManager::ScheduleNextUpdate(bool back_off) { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (disable_auto_update_) { // Unschedule any current timer. update_timer_.Stop(); @@ -516,7 +512,7 @@ void SafeBrowsingProtocolManager::ForceScheduleNextUpdate( base::TimeDelta interval) { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK(interval >= base::TimeDelta()); // Unschedule any current timer. update_timer_.Stop(); @@ -529,7 +525,7 @@ // when we receive a response from the SafeBrowsing service. base::TimeDelta SafeBrowsingProtocolManager::GetNextUpdateInterval( bool back_off) { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK(next_update_interval_ > base::TimeDelta()); base::TimeDelta next = next_update_interval_; if (back_off) { @@ -545,7 +541,7 @@ base::TimeDelta SafeBrowsingProtocolManager::GetNextBackOffInterval( size_t* error_count, size_t* multiplier) const { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK(multiplier && error_count); (*error_count)++; if (*error_count > 1 && *error_count < 6) { @@ -569,7 +565,7 @@ // otherhand, this request will only occur ~20-30 minutes so there // isn't that much overhead. Measure! void SafeBrowsingProtocolManager::IssueUpdateRequest() { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); request_type_ = UPDATE_REQUEST; delegate_->UpdateStarted(); delegate_->GetChunks( @@ -581,7 +577,7 @@ // retrieved from the DB. bool SafeBrowsingProtocolManager::IssueBackupUpdateRequest( BackupUpdateReason backup_update_reason) { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK_EQ(request_type_, UPDATE_REQUEST); DCHECK(backup_update_reason >= 0 && backup_update_reason < BACKUP_UPDATE_REASON_MAX); @@ -607,7 +603,7 @@ } void SafeBrowsingProtocolManager::IssueChunkRequest() { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); // We are only allowed to have one request outstanding at any time. Also, // don't get the next url until the previous one has been written to disk so // that we don't use too much memory. @@ -630,7 +626,7 @@ const std::vector<SBListChunkRanges>& lists, bool database_error, bool is_extended_reporting) { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK_EQ(request_type_, UPDATE_REQUEST); DCHECK(update_list_data_.empty()); if (database_error) { @@ -685,7 +681,7 @@ // If we haven't heard back from the server with an update response, this method // will run. Close the current update session and schedule another update. void SafeBrowsingProtocolManager::UpdateResponseTimeout() { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK(request_type_ == UPDATE_REQUEST || request_type_ == BACKUP_UPDATE_REQUEST); request_.reset(); @@ -697,7 +693,7 @@ } void SafeBrowsingProtocolManager::OnAddChunksComplete() { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); chunk_pending_to_write_ = false; if (chunk_request_urls_.empty()) { @@ -709,7 +705,7 @@ } void SafeBrowsingProtocolManager::HandleGetHashError(const Time& now) { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); base::TimeDelta next = GetNextBackOffInterval(&gethash_error_count_, &gethash_back_off_mult_); next_gethash_time_ = now + next; @@ -720,7 +716,7 @@ } void SafeBrowsingProtocolManager::UpdateFinished(bool success, bool back_off) { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); UMA_HISTOGRAM_COUNTS("SB2.UpdateSize", update_size_); update_size_ = 0; bool update_success = success || request_type_ == CHUNK_REQUEST; @@ -766,7 +762,7 @@ } GURL SafeBrowsingProtocolManager::NextChunkUrl(const std::string& url) const { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); std::string next_url; if (!base::StartsWith(url, "http://", base::CompareCase::INSENSITIVE_ASCII) && !base::StartsWith(url, "https://",
diff --git a/chrome/browser/safe_browsing/protocol_manager.h b/chrome/browser/safe_browsing/protocol_manager.h index aecf832..d1f8f50 100644 --- a/chrome/browser/safe_browsing/protocol_manager.h +++ b/chrome/browser/safe_browsing/protocol_manager.h
@@ -24,7 +24,6 @@ #include "base/containers/hash_tables.h" #include "base/gtest_prod_util.h" #include "base/macros.h" -#include "base/threading/non_thread_safe.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "chrome/browser/safe_browsing/chunk_range.h" @@ -47,8 +46,8 @@ class SBProtocolManagerFactory; class SafeBrowsingProtocolManagerDelegate; -class SafeBrowsingProtocolManager : public net::URLFetcherDelegate, - public base::NonThreadSafe { +// Lives on the IO thread. +class SafeBrowsingProtocolManager : public net::URLFetcherDelegate { public: // FullHashCallback is invoked when GetFullHash completes. // Parameters: @@ -56,8 +55,9 @@ // were no matches, and that the resource is safe. // - The cache lifetime of the result. A lifetime of 0 indicates the results // should not be cached. - typedef base::Callback<void(const std::vector<SBFullHashResult>&, - const base::TimeDelta&)> FullHashCallback; + using FullHashCallback = + base::Callback<void(const std::vector<SBFullHashResult>&, + const base::TimeDelta&)>; ~SafeBrowsingProtocolManager() override; @@ -68,7 +68,7 @@ } // Create an instance of the safe browsing protocol manager. - static SafeBrowsingProtocolManager* Create( + static std::unique_ptr<SafeBrowsingProtocolManager> Create( SafeBrowsingProtocolManagerDelegate* delegate, net::URLRequestContextGetter* request_context_getter, const SafeBrowsingProtocolConfig& config); @@ -290,7 +290,7 @@ FullHashCallback callback; bool is_download; }; - typedef base::hash_map<const net::URLFetcher*, FullHashDetails> HashRequests; + using HashRequests = base::hash_map<const net::URLFetcher*, FullHashDetails>; // The factory that controls the creation of SafeBrowsingProtocolManager. // This is used by tests. @@ -392,10 +392,12 @@ public: SBProtocolManagerFactory() {} virtual ~SBProtocolManagerFactory() {} - virtual SafeBrowsingProtocolManager* CreateProtocolManager( + + virtual std::unique_ptr<SafeBrowsingProtocolManager> CreateProtocolManager( SafeBrowsingProtocolManagerDelegate* delegate, net::URLRequestContextGetter* request_context_getter, const SafeBrowsingProtocolConfig& config) = 0; + private: DISALLOW_COPY_AND_ASSIGN(SBProtocolManagerFactory); }; @@ -403,12 +405,11 @@ // Delegate interface for the SafeBrowsingProtocolManager. class SafeBrowsingProtocolManagerDelegate { public: - typedef base::Callback<void( + using GetChunksCallback = base::Callback<void( const std::vector<SBListChunkRanges>&, /* List of chunks */ bool, /* database_error */ - bool /* is_extended_reporting */ - )> GetChunksCallback; - typedef base::Callback<void(void)> AddChunksCallback; + bool /* is_extended_reporting */)>; + using AddChunksCallback = base::Closure; virtual ~SafeBrowsingProtocolManagerDelegate();
diff --git a/chrome/browser/safe_browsing/protocol_manager_unittest.cc b/chrome/browser/safe_browsing/protocol_manager_unittest.cc index 70e240b..b08d01a9 100644 --- a/chrome/browser/safe_browsing/protocol_manager_unittest.cc +++ b/chrome/browser/safe_browsing/protocol_manager_unittest.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/safe_browsing/chunk.pb.h" #include "components/safe_browsing_db/safebrowsing.pb.h" #include "components/safe_browsing_db/util.h" +#include "content/public/test/test_browser_thread.h" #include "google_apis/google_api_keys.h" #include "net/base/escape.h" #include "net/base/load_flags.h" @@ -70,7 +71,12 @@ class SafeBrowsingProtocolManagerTest : public testing::Test { protected: - std::string key_param_; + SafeBrowsingProtocolManagerTest() + : runner_(new base::TestSimpleTaskRunner), + runner_handler_(runner_), + io_thread_(content::BrowserThread::IO) {} + + ~SafeBrowsingProtocolManagerTest() override {} void SetUp() override { std::string key = google_apis::GetAPIKey(); @@ -91,7 +97,7 @@ config.backup_network_error_url_prefix = kBackupNetworkUrlPrefix; config.version = kAppVer; return std::unique_ptr<SafeBrowsingProtocolManager>( - SafeBrowsingProtocolManager::Create(delegate, NULL, config)); + SafeBrowsingProtocolManager::Create(delegate, nullptr, config)); } void ValidateUpdateFetcherRequest(const net::TestURLFetcher* url_fetcher, @@ -121,11 +127,17 @@ EXPECT_EQ("", url_fetcher->upload_data()); EXPECT_EQ(GURL(expected_url), url_fetcher->GetOriginalURL()); } + + scoped_refptr<base::TestSimpleTaskRunner> runner_; + base::ThreadTaskRunnerHandle runner_handler_; + content::TestBrowserThread io_thread_; + std::string key_param_; }; // Ensure that we respect section 5 of the SafeBrowsing protocol specification. TEST_F(SafeBrowsingProtocolManagerTest, TestBackOffTimes) { - std::unique_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL)); + std::unique_ptr<SafeBrowsingProtocolManager> pm( + CreateProtocolManager(nullptr)); pm->next_update_interval_ = TimeDelta::FromSeconds(1800); ASSERT_TRUE(pm->back_off_fuzz_ >= 0.0 && pm->back_off_fuzz_ <= 1.0); @@ -174,7 +186,8 @@ } TEST_F(SafeBrowsingProtocolManagerTest, TestChunkStrings) { - std::unique_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL)); + std::unique_ptr<SafeBrowsingProtocolManager> pm( + CreateProtocolManager(nullptr)); // Add and Sub chunks. SBListChunkRanges phish(kDefaultPhishList); @@ -202,7 +215,8 @@ } TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashBackOffTimes) { - std::unique_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL)); + std::unique_ptr<SafeBrowsingProtocolManager> pm( + CreateProtocolManager(nullptr)); // No errors or back off time yet. EXPECT_EQ(0U, pm->gethash_error_count_); @@ -254,7 +268,8 @@ } TEST_F(SafeBrowsingProtocolManagerTest, TestGetHashUrl) { - std::unique_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL)); + std::unique_ptr<SafeBrowsingProtocolManager> pm( + CreateProtocolManager(nullptr)); EXPECT_EQ( "https://prefix.com/foo/gethash?client=unittest&appver=1.0&" @@ -271,7 +286,8 @@ } TEST_F(SafeBrowsingProtocolManagerTest, TestUpdateUrl) { - std::unique_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL)); + std::unique_ptr<SafeBrowsingProtocolManager> pm( + CreateProtocolManager(nullptr)); EXPECT_EQ( "https://prefix.com/foo/downloads?client=unittest&appver=1.0&" @@ -288,7 +304,8 @@ } TEST_F(SafeBrowsingProtocolManagerTest, TestNextChunkUrl) { - std::unique_ptr<SafeBrowsingProtocolManager> pm(CreateProtocolManager(NULL)); + std::unique_ptr<SafeBrowsingProtocolManager> pm( + CreateProtocolManager(nullptr)); std::string url_partial = "localhost:1234/foo/bar?foo"; std::string url_http_full = "http://localhost:1234/foo/bar?foo"; @@ -381,10 +398,6 @@ // Tests that the Update protocol will be skipped if there are problems // accessing the database. TEST_F(SafeBrowsingProtocolManagerTest, ProblemAccessingDatabase) { - scoped_refptr<base::TestSimpleTaskRunner> runner( - new base::TestSimpleTaskRunner()); - base::ThreadTaskRunnerHandle runner_handler(runner); - testing::StrictMock<MockProtocolDelegate> test_delegate; EXPECT_CALL(test_delegate, UpdateStarted()).Times(1); EXPECT_CALL(test_delegate, GetChunks(_)).WillOnce( @@ -397,7 +410,7 @@ CreateProtocolManager(&test_delegate)); pm->ForceScheduleNextUpdate(TimeDelta()); - runner->RunPendingTasks(); + runner_->RunPendingTasks(); EXPECT_TRUE(pm->IsUpdateScheduled()); } @@ -406,9 +419,6 @@ // local database. This is not exhaustive, as the actual list formatting // is covered by SafeBrowsingProtocolManagerTest.TestChunkStrings. TEST_F(SafeBrowsingProtocolManagerTest, ExistingDatabase) { - scoped_refptr<base::TestSimpleTaskRunner> runner( - new base::TestSimpleTaskRunner()); - base::ThreadTaskRunnerHandle runner_handler(runner); net::TestURLFetcherFactory url_fetcher_factory; std::vector<SBListChunkRanges> ranges; @@ -435,7 +445,7 @@ // Kick off initialization. This returns chunks from the DB synchronously. pm->ForceScheduleNextUpdate(TimeDelta()); - runner->RunPendingTasks(); + runner_->RunPendingTasks(); // We should have an URLFetcher at this point in time. net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0); @@ -460,9 +470,6 @@ } TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseBadBodyBackupSuccess) { - scoped_refptr<base::TestSimpleTaskRunner> runner( - new base::TestSimpleTaskRunner()); - base::ThreadTaskRunnerHandle runner_handler(runner); net::TestURLFetcherFactory url_fetcher_factory; testing::StrictMock<MockProtocolDelegate> test_delegate; @@ -478,7 +485,7 @@ // Kick off initialization. This returns chunks from the DB synchronously. pm->ForceScheduleNextUpdate(TimeDelta()); - runner->RunPendingTasks(); + runner_->RunPendingTasks(); // We should have an URLFetcher at this point in time. net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0); @@ -507,9 +514,6 @@ // Tests what happens when there is an HTTP error response to the update // request, as well as an error response to the backup update request. TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupError) { - scoped_refptr<base::TestSimpleTaskRunner> runner( - new base::TestSimpleTaskRunner()); - base::ThreadTaskRunnerHandle runner_handler(runner); net::TestURLFetcherFactory url_fetcher_factory; testing::StrictMock<MockProtocolDelegate> test_delegate; @@ -525,7 +529,7 @@ // Kick off initialization. This returns chunks from the DB synchronously. pm->ForceScheduleNextUpdate(TimeDelta()); - runner->RunPendingTasks(); + runner_->RunPendingTasks(); // We should have an URLFetcher at this point in time. net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0); @@ -554,9 +558,6 @@ // Tests what happens when there is an HTTP error response to the update // request, followed by a successful response to the backup update request. TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupSuccess) { - scoped_refptr<base::TestSimpleTaskRunner> runner( - new base::TestSimpleTaskRunner()); - base::ThreadTaskRunnerHandle runner_handler(runner); net::TestURLFetcherFactory url_fetcher_factory; testing::StrictMock<MockProtocolDelegate> test_delegate; @@ -572,7 +573,7 @@ // Kick off initialization. This returns chunks from the DB synchronously. pm->ForceScheduleNextUpdate(TimeDelta()); - runner->RunPendingTasks(); + runner_->RunPendingTasks(); // We should have an URLFetcher at this point in time. net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0); @@ -601,9 +602,6 @@ // Tests what happens when there is an HTTP error response to the update // request, and a timeout on the backup update request. TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseHttpErrorBackupTimeout) { - scoped_refptr<base::TestSimpleTaskRunner> runner( - new base::TestSimpleTaskRunner()); - base::ThreadTaskRunnerHandle runner_handler(runner); net::TestURLFetcherFactory url_fetcher_factory; testing::StrictMock<MockProtocolDelegate> test_delegate; @@ -619,7 +617,7 @@ // Kick off initialization. This returns chunks from the DB synchronously. pm->ForceScheduleNextUpdate(TimeDelta()); - runner->RunPendingTasks(); + runner_->RunPendingTasks(); // We should have an URLFetcher at this point in time. net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0); @@ -642,9 +640,9 @@ // call the timeout task from the backup request, or schedule another task // to run that in the future. // TODO(cbentzel): Less fragile approach. - runner->RunPendingTasks(); + runner_->RunPendingTasks(); if (!pm->IsUpdateScheduled()) - runner->RunPendingTasks(); + runner_->RunPendingTasks(); EXPECT_TRUE(pm->IsUpdateScheduled()); } @@ -652,9 +650,6 @@ // request, and an error with the backup update request. TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseConnectionErrorBackupError) { - scoped_refptr<base::TestSimpleTaskRunner> runner( - new base::TestSimpleTaskRunner()); - base::ThreadTaskRunnerHandle runner_handler(runner); net::TestURLFetcherFactory url_fetcher_factory; testing::StrictMock<MockProtocolDelegate> test_delegate; @@ -670,7 +665,7 @@ // Kick off initialization. This returns chunks from the DB synchronously. pm->ForceScheduleNextUpdate(TimeDelta()); - runner->RunPendingTasks(); + runner_->RunPendingTasks(); // We should have an URLFetcher at this point in time. net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0); @@ -699,9 +694,6 @@ // request, and a successful response to the backup update request. TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseConnectionErrorBackupSuccess) { - scoped_refptr<base::TestSimpleTaskRunner> runner( - new base::TestSimpleTaskRunner()); - base::ThreadTaskRunnerHandle runner_handler(runner); net::TestURLFetcherFactory url_fetcher_factory; testing::StrictMock<MockProtocolDelegate> test_delegate; @@ -717,7 +709,7 @@ // Kick off initialization. This returns chunks from the DB synchronously. pm->ForceScheduleNextUpdate(TimeDelta()); - runner->RunPendingTasks(); + runner_->RunPendingTasks(); // We should have an URLFetcher at this point in time. net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0); @@ -745,9 +737,6 @@ // update request, and an error with the backup update request. TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseNetworkErrorBackupError) { - scoped_refptr<base::TestSimpleTaskRunner> runner( - new base::TestSimpleTaskRunner()); - base::ThreadTaskRunnerHandle runner_handler(runner); net::TestURLFetcherFactory url_fetcher_factory; testing::StrictMock<MockProtocolDelegate> test_delegate; @@ -763,7 +752,7 @@ // Kick off initialization. This returns chunks from the DB synchronously. pm->ForceScheduleNextUpdate(TimeDelta()); - runner->RunPendingTasks(); + runner_->RunPendingTasks(); // We should have an URLFetcher at this point in time. net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0); @@ -793,9 +782,6 @@ // update request, and a successful response to the backup update request. TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseNetworkErrorBackupSuccess) { - scoped_refptr<base::TestSimpleTaskRunner> runner( - new base::TestSimpleTaskRunner()); - base::ThreadTaskRunnerHandle runner_handler(runner); net::TestURLFetcherFactory url_fetcher_factory; testing::StrictMock<MockProtocolDelegate> test_delegate; @@ -811,7 +797,7 @@ // Kick off initialization. This returns chunks from the DB synchronously. pm->ForceScheduleNextUpdate(TimeDelta()); - runner->RunPendingTasks(); + runner_->RunPendingTasks(); // We should have an URLFetcher at this point in time. net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0); @@ -839,9 +825,6 @@ // Tests what happens when there is a timeout before an update response. TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseTimeoutBackupSuccess) { - scoped_refptr<base::TestSimpleTaskRunner> runner( - new base::TestSimpleTaskRunner()); - base::ThreadTaskRunnerHandle runner_handler(runner); net::TestURLFetcherFactory url_fetcher_factory; testing::StrictMock<MockProtocolDelegate> test_delegate; @@ -857,7 +840,7 @@ // Kick off initialization. This returns chunks from the DB synchronously. pm->ForceScheduleNextUpdate(TimeDelta()); - runner->RunPendingTasks(); + runner_->RunPendingTasks(); // We should have an URLFetcher at this point in time. net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0); @@ -865,7 +848,7 @@ // The first time RunPendingTasks is called above, the update timeout timer is // not handled. This call of RunPendingTasks will handle the update. - runner->RunPendingTasks(); + runner_->RunPendingTasks(); // There should be a backup URLFetcher now. net::TestURLFetcher* backup_url_fetcher = @@ -883,9 +866,6 @@ // Tests what happens when there is a reset command in the response. TEST_F(SafeBrowsingProtocolManagerTest, UpdateResponseReset) { - scoped_refptr<base::TestSimpleTaskRunner> runner( - new base::TestSimpleTaskRunner()); - base::ThreadTaskRunnerHandle runner_handler(runner); net::TestURLFetcherFactory url_fetcher_factory; testing::StrictMock<MockProtocolDelegate> test_delegate; @@ -902,7 +882,7 @@ // Kick off initialization. This returns chunks from the DB synchronously. pm->ForceScheduleNextUpdate(TimeDelta()); - runner->RunPendingTasks(); + runner_->RunPendingTasks(); net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0); ValidateUpdateFetcherRequest(url_fetcher); @@ -919,9 +899,6 @@ // Tests a single valid update response, followed by a single redirect response // that has an valid, but empty body. TEST_F(SafeBrowsingProtocolManagerTest, EmptyRedirectResponse) { - scoped_refptr<base::TestSimpleTaskRunner> runner( - new base::TestSimpleTaskRunner()); - base::ThreadTaskRunnerHandle runner_handler(runner); net::TestURLFetcherFactory url_fetcher_factory; testing::StrictMock<MockProtocolDelegate> test_delegate; @@ -937,7 +914,7 @@ // Kick off initialization. This returns chunks from the DB synchronously. pm->ForceScheduleNextUpdate(TimeDelta()); - runner->RunPendingTasks(); + runner_->RunPendingTasks(); // The update response contains a single redirect command. net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0); @@ -966,9 +943,6 @@ // Tests a single valid update response, followed by a single redirect response // that has an invalid body. TEST_F(SafeBrowsingProtocolManagerTest, InvalidRedirectResponse) { - scoped_refptr<base::TestSimpleTaskRunner> runner( - new base::TestSimpleTaskRunner()); - base::ThreadTaskRunnerHandle runner_handler(runner); net::TestURLFetcherFactory url_fetcher_factory; testing::StrictMock<MockProtocolDelegate> test_delegate; @@ -984,7 +958,7 @@ // Kick off initialization. This returns chunks from the DB synchronously. pm->ForceScheduleNextUpdate(TimeDelta()); - runner->RunPendingTasks(); + runner_->RunPendingTasks(); // The update response contains a single redirect command. net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0); @@ -1013,9 +987,6 @@ // Tests a single valid update response, followed by a single redirect response // containing chunks. TEST_F(SafeBrowsingProtocolManagerTest, SingleRedirectResponseWithChunks) { - scoped_refptr<base::TestSimpleTaskRunner> runner( - new base::TestSimpleTaskRunner()); - base::ThreadTaskRunnerHandle runner_handler(runner); net::TestURLFetcherFactory url_fetcher_factory; testing::StrictMock<MockProtocolDelegate> test_delegate; @@ -1033,7 +1004,7 @@ // Kick off initialization. This returns chunks from the DB synchronously. pm->ForceScheduleNextUpdate(TimeDelta()); - runner->RunPendingTasks(); + runner_->RunPendingTasks(); // The update response contains a single redirect command. net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0); @@ -1059,7 +1030,7 @@ EXPECT_FALSE(pm->IsUpdateScheduled()); // The AddChunksCallback needs to be invoked. - runner->RunPendingTasks(); + runner_->RunPendingTasks(); EXPECT_TRUE(pm->IsUpdateScheduled()); } @@ -1067,9 +1038,6 @@ // Tests a single valid update response, followed by multiple redirect responses // containing chunks. TEST_F(SafeBrowsingProtocolManagerTest, MultipleRedirectResponsesWithChunks) { - scoped_refptr<base::TestSimpleTaskRunner> runner( - new base::TestSimpleTaskRunner()); - base::ThreadTaskRunnerHandle runner_handler(runner); net::TestURLFetcherFactory url_fetcher_factory; testing::StrictMock<MockProtocolDelegate> test_delegate; @@ -1087,7 +1055,7 @@ // Kick off initialization. This returns chunks from the DB synchronously. pm->ForceScheduleNextUpdate(TimeDelta()); - runner->RunPendingTasks(); + runner_->RunPendingTasks(); // The update response contains multiple redirect commands. net::TestURLFetcher* url_fetcher = url_fetcher_factory.GetFetcherByID(0); @@ -1113,7 +1081,7 @@ first_chunk_url_fetcher); // Invoke the AddChunksCallback to trigger the second request. - runner->RunPendingTasks(); + runner_->RunPendingTasks(); EXPECT_FALSE(pm->IsUpdateScheduled()); @@ -1131,7 +1099,7 @@ EXPECT_FALSE(pm->IsUpdateScheduled()); // Invoke the AddChunksCallback to finish the update. - runner->RunPendingTasks(); + runner_->RunPendingTasks(); EXPECT_TRUE(pm->IsUpdateScheduled()); }
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.cc b/chrome/browser/safe_browsing/safe_browsing_database.cc index d1bc5486..a824223 100644 --- a/chrome/browser/safe_browsing/safe_browsing_database.cc +++ b/chrome/browser/safe_browsing/safe_browsing_database.cc
@@ -280,7 +280,7 @@ // The default SafeBrowsingDatabaseFactory. class SafeBrowsingDatabaseFactoryImpl : public SafeBrowsingDatabaseFactory { public: - SafeBrowsingDatabase* CreateSafeBrowsingDatabase( + std::unique_ptr<SafeBrowsingDatabase> CreateSafeBrowsingDatabase( const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, bool enable_download_protection, bool enable_client_side_whitelist, @@ -289,7 +289,7 @@ bool enable_ip_blacklist, bool enable_unwanted_software_list, bool enable_module_whitelist) override { - return new SafeBrowsingDatabaseNew( + return base::WrapUnique(new SafeBrowsingDatabaseNew( db_task_runner, CreateStore(true, db_task_runner), // browse_store CreateStore(enable_download_protection, db_task_runner), CreateStore(enable_client_side_whitelist, db_task_runner), @@ -298,7 +298,7 @@ CreateStore(enable_ip_blacklist, db_task_runner), CreateStore(enable_unwanted_software_list, db_task_runner), CreateStore(enable_module_whitelist, db_task_runner), - CreateStore(true, db_task_runner)); // resource_blacklist_store + CreateStore(true, db_task_runner))); // resource_blacklist_store } SafeBrowsingDatabaseFactoryImpl() {} @@ -315,7 +315,7 @@ // TODO(shess): There's no need for a factory any longer. Convert // SafeBrowsingDatabaseNew to SafeBrowsingDatabase, and have Create() // callers just construct things directly. -SafeBrowsingDatabase* SafeBrowsingDatabase::Create( +std::unique_ptr<SafeBrowsingDatabase> SafeBrowsingDatabase::Create( const scoped_refptr<base::SequencedTaskRunner>& current_task_runner, bool enable_download_protection, bool enable_client_side_whitelist,
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.h b/chrome/browser/safe_browsing/safe_browsing_database.h index 9b1d7ff..67f75b39 100644 --- a/chrome/browser/safe_browsing/safe_browsing_database.h +++ b/chrome/browser/safe_browsing/safe_browsing_database.h
@@ -36,7 +36,7 @@ public: SafeBrowsingDatabaseFactory() { } virtual ~SafeBrowsingDatabaseFactory() { } - virtual SafeBrowsingDatabase* CreateSafeBrowsingDatabase( + virtual std::unique_ptr<SafeBrowsingDatabase> CreateSafeBrowsingDatabase( const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, bool enable_download_protection, bool enable_client_side_whitelist, @@ -68,7 +68,7 @@ // It is not thread safe. // The browse list and off-domain inclusion whitelist are always on; // availability of other lists is controlled by the flags on this method. - static SafeBrowsingDatabase* Create( + static std::unique_ptr<SafeBrowsingDatabase> Create( const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, bool enable_download_protection, bool enable_client_side_whitelist,
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc index ae689f3..19158a2a7 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -281,8 +281,6 @@ SafeBrowsingService::SafeBrowsingService() : services_delegate_(ServicesDelegate::Create(this)), - protocol_manager_(nullptr), - ping_manager_(nullptr), enabled_(false), enabled_by_prefs_(false) {} @@ -390,12 +388,16 @@ SafeBrowsingProtocolManager* SafeBrowsingService::protocol_manager() const { DCHECK_CURRENTLY_ON(BrowserThread::IO); - return protocol_manager_; +#if defined(SAFE_BROWSING_DB_LOCAL) + return protocol_manager_.get(); +#else + return nullptr; +#endif } SafeBrowsingPingManager* SafeBrowsingService::ping_manager() const { DCHECK_CURRENTLY_ON(BrowserThread::IO); - return ping_manager_; + return ping_manager_.get(); } std::unique_ptr<TrackedPreferenceValidationDelegate> @@ -569,11 +571,9 @@ // This cancels all in-flight GetHash requests. Note that // |database_manager_| relies on |protocol_manager_| so if the latter is // destroyed, the former must be stopped. - delete protocol_manager_; - protocol_manager_ = nullptr; + protocol_manager_.reset(); #endif - delete ping_manager_; - ping_manager_ = NULL; + ping_manager_.reset(); } }
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.h b/chrome/browser/safe_browsing/safe_browsing_service.h index 0d85341..0ac36a33 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.h +++ b/chrome/browser/safe_browsing/safe_browsing_service.h
@@ -244,11 +244,13 @@ scoped_refptr<SafeBrowsingURLRequestContextGetter> url_request_context_getter_; +#if defined(SAFE_BROWSING_DB_LOCAL) // Handles interaction with SafeBrowsing servers. Accessed on IO thread. - SafeBrowsingProtocolManager* protocol_manager_; + std::unique_ptr<SafeBrowsingProtocolManager> protocol_manager_; +#endif // Provides phishing and malware statistics. Accessed on IO thread. - SafeBrowsingPingManager* ping_manager_; + std::unique_ptr<SafeBrowsingPingManager> ping_manager_; // Whether the service is running. 'enabled_' is used by SafeBrowsingService // on the IO thread during normal operations.
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc index e24a4a5..5a041c2 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -345,10 +345,10 @@ // Factory that creates TestSafeBrowsingDatabase instances. class TestSafeBrowsingDatabaseFactory : public SafeBrowsingDatabaseFactory { public: - TestSafeBrowsingDatabaseFactory() : db_(NULL) {} + TestSafeBrowsingDatabaseFactory() : db_(nullptr) {} ~TestSafeBrowsingDatabaseFactory() override {} - SafeBrowsingDatabase* CreateSafeBrowsingDatabase( + std::unique_ptr<SafeBrowsingDatabase> CreateSafeBrowsingDatabase( const scoped_refptr<base::SequencedTaskRunner>& db_task_runner, bool enable_download_protection, bool enable_client_side_whitelist, @@ -358,7 +358,7 @@ bool enabled_unwanted_software_list, bool enable_module_whitelist) override { db_ = new TestSafeBrowsingDatabase(); - return db_; + return base::WrapUnique(db_); } TestSafeBrowsingDatabase* GetDb() { return db_; } @@ -420,15 +420,15 @@ // Factory that creates TestProtocolManager instances. class TestSBProtocolManagerFactory : public SBProtocolManagerFactory { public: - TestSBProtocolManagerFactory() : pm_(NULL) {} + TestSBProtocolManagerFactory() : pm_(nullptr) {} ~TestSBProtocolManagerFactory() override {} - SafeBrowsingProtocolManager* CreateProtocolManager( + std::unique_ptr<SafeBrowsingProtocolManager> CreateProtocolManager( SafeBrowsingProtocolManagerDelegate* delegate, net::URLRequestContextGetter* request_context_getter, const SafeBrowsingProtocolConfig& config) override { pm_ = new TestProtocolManager(delegate, request_context_getter, config); - return pm_; + return base::WrapUnique(pm_); } TestProtocolManager* GetProtocolManager() { return pm_; } @@ -484,7 +484,7 @@ SBFullHashResult* full_hash) { std::string host; std::string path; - CanonicalizeUrl(url, &host, &path, NULL); + CanonicalizeUrl(url, &host, &path, nullptr); full_hash->hash = SBFullHashForString(host + path); full_hash->list_id = list_id; } @@ -516,9 +516,9 @@ // Unregister test factories after InProcessBrowserTest::TearDown // (which destructs SafeBrowsingService). - SafeBrowsingDatabase::RegisterFactory(NULL); - SafeBrowsingProtocolManager::RegisterFactory(NULL); - SafeBrowsingService::RegisterFactory(NULL); + SafeBrowsingDatabase::RegisterFactory(nullptr); + SafeBrowsingProtocolManager::RegisterFactory(nullptr); + SafeBrowsingService::RegisterFactory(nullptr); } void SetUpCommandLine(base::CommandLine* command_line) override { @@ -573,7 +573,7 @@ WebContents* contents = browser()->tab_strip_model()->GetActiveWebContents(); InterstitialPage* interstitial_page = contents->GetInterstitialPage(); - return interstitial_page != NULL; + return interstitial_page != nullptr; } void IntroduceGetHashDelay(const base::TimeDelta& delay) { @@ -1473,9 +1473,9 @@ sb_service->safe_browsing_detection_service(); PrefService* pref_service = browser()->profile()->GetPrefs(); - ASSERT_TRUE(sb_service != NULL); - ASSERT_TRUE(csd_service != NULL); - ASSERT_TRUE(pref_service != NULL); + ASSERT_TRUE(sb_service); + ASSERT_TRUE(csd_service); + ASSERT_TRUE(pref_service); EXPECT_TRUE(pref_service->GetBoolean(prefs::kSafeBrowsingEnabled)); @@ -1487,8 +1487,8 @@ // Add a new Profile. SBS should keep running. ASSERT_TRUE(temp_profile_dir_.CreateUniqueTempDir()); std::unique_ptr<Profile> profile2(Profile::CreateProfile( - temp_profile_dir_.path(), NULL, Profile::CREATE_MODE_SYNCHRONOUS)); - ASSERT_TRUE(profile2.get() != NULL); + temp_profile_dir_.path(), nullptr, Profile::CREATE_MODE_SYNCHRONOUS)); + ASSERT_TRUE(profile2); StartupTaskRunnerServiceFactory::GetForProfile(profile2.get())-> StartDeferredTaskRunners(); PrefService* pref_service2 = profile2->GetPrefs(); @@ -1530,7 +1530,7 @@ EXPECT_TRUE(csd_service->enabled()); // Delete the Profile. SBS stops again. - pref_service2 = NULL; + pref_service2 = nullptr; profile2.reset(); EXPECT_FALSE(sb_service->enabled_by_prefs()); WaitForIOAndCheckEnabled(sb_service, false); @@ -1570,9 +1570,9 @@ sb_service->safe_browsing_detection_service(); PrefService* pref_service = browser()->profile()->GetPrefs(); - ASSERT_TRUE(sb_service != NULL); - ASSERT_TRUE(csd_service != NULL); - ASSERT_TRUE(pref_service != NULL); + ASSERT_TRUE(sb_service); + ASSERT_TRUE(csd_service); + ASSERT_TRUE(pref_service); EXPECT_TRUE(pref_service->GetBoolean(prefs::kSafeBrowsingEnabled)); @@ -1629,7 +1629,7 @@ void TearDown() override { InProcessBrowserTest::TearDown(); - SafeBrowsingService::RegisterFactory(NULL); + SafeBrowsingService::RegisterFactory(nullptr); } bool SetUpUserDataDirectory() override { @@ -1743,6 +1743,7 @@ return std::move(http_response); } + private: DISALLOW_COPY_AND_ASSIGN(SafeBrowsingDatabaseManagerCookieTest); };
diff --git a/chrome/browser/safe_browsing/srt_fetcher_win.cc b/chrome/browser/safe_browsing/srt_fetcher_win.cc index ccba9a6c..62996ec1 100644 --- a/chrome/browser/safe_browsing/srt_fetcher_win.cc +++ b/chrome/browser/safe_browsing/srt_fetcher_win.cc
@@ -22,7 +22,6 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/task_runner_util.h" -#include "base/threading/thread_checker.h" #include "base/time/time.h" #include "base/win/registry.h" #include "chrome/browser/browser_process.h" @@ -472,7 +471,7 @@ const scoped_refptr<base::TaskRunner>& blocking_task_runner) { if (!instance_) instance_ = new ReporterRunner; - DCHECK(instance_->thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // There's nothing to do if the path and version of the reporter has not // changed, we just keep running the tasks that are running now. if (instance_->exe_path_ == exe_path && instance_->version_.IsValid() && @@ -497,7 +496,7 @@ void OnBrowserSetLastActive(Browser* browser) override {} void OnBrowserRemoved(Browser* browser) override {} void OnBrowserAdded(Browser* browser) override { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(browser); MaybeFetchSRT(browser, version_); BrowserList::RemoveObserver(this); @@ -509,7 +508,7 @@ void ReporterDone(const base::Time& reporter_start_time, const base::Version& version, int exit_code) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(BrowserThread::UI); base::TimeDelta reporter_running_time = base::Time::Now() - reporter_start_time; @@ -565,7 +564,7 @@ } void TryToRun() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CURRENTLY_ON(BrowserThread::UI); PrefService* local_state = g_browser_process->local_state(); if (!version_.IsValid() || !local_state) { DCHECK(exe_path_.empty()); @@ -622,7 +621,6 @@ // A single leaky instance. static ReporterRunner* instance_; - base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(ReporterRunner); };
diff --git a/chrome/browser/safe_browsing/two_phase_uploader.cc b/chrome/browser/safe_browsing/two_phase_uploader.cc index eaabab9..242326d7 100644 --- a/chrome/browser/safe_browsing/two_phase_uploader.cc +++ b/chrome/browser/safe_browsing/two_phase_uploader.cc
@@ -10,7 +10,9 @@ #include "base/bind.h" #include "base/macros.h" +#include "base/memory/ptr_util.h" #include "base/task_runner.h" +#include "content/public/browser/browser_thread.h" #include "net/base/net_errors.h" #include "net/http/http_response_headers.h" #include "net/url_request/url_fetcher.h" @@ -20,12 +22,12 @@ namespace { // Header sent on initial request to start the two phase upload process. -const char* kStartHeader = "x-goog-resumable: start"; +const char kStartHeader[] = "x-goog-resumable: start"; // Header returned on initial response with URL to use for the second phase. -const char* kLocationHeader = "Location"; +const char kLocationHeader[] = "Location"; -const char* kUploadContentType = "application/octet-stream"; +const char kUploadContentType[] = "application/octet-stream"; class TwoPhaseUploaderImpl : public net::URLFetcherDelegate, public TwoPhaseUploader { @@ -84,21 +86,22 @@ file_path_(file_path), progress_callback_(progress_callback), finish_callback_(finish_callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } TwoPhaseUploaderImpl::~TwoPhaseUploaderImpl() { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } void TwoPhaseUploaderImpl::Start() { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(STATE_NONE, state_); UploadMetadata(); } void TwoPhaseUploaderImpl::OnURLFetchComplete(const net::URLFetcher* source) { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); net::URLRequestStatus status = source->GetStatus(); int response_code = source->GetResponseCode(); @@ -126,7 +129,7 @@ } std::string location; if (!source->GetResponseHeaders()->EnumerateHeader( - NULL, kLocationHeader, &location)) { + nullptr, kLocationHeader, &location)) { LOG(ERROR) << "no location header"; Finish(net::OK, response_code, std::string()); return; @@ -154,7 +157,7 @@ const net::URLFetcher* source, int64_t current, int64_t total) { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DVLOG(3) << __FUNCTION__ << " " << source->GetURL().spec() << " " << current << "/" << total; if (state_ == UPLOAD_FILE && !progress_callback_.is_null()) @@ -162,7 +165,7 @@ } void TwoPhaseUploaderImpl::UploadMetadata() { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); state_ = UPLOAD_METADATA; url_fetcher_ = net::URLFetcher::Create(base_url_, net::URLFetcher::POST, this); @@ -173,7 +176,7 @@ } void TwoPhaseUploaderImpl::UploadFile() { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); state_ = UPLOAD_FILE; url_fetcher_ = @@ -188,17 +191,17 @@ void TwoPhaseUploaderImpl::Finish(int net_error, int response_code, const std::string& response) { - DCHECK(CalledOnValidThread()); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); finish_callback_.Run(state_, net_error, response_code, response); } } // namespace // static -TwoPhaseUploaderFactory* TwoPhaseUploader::factory_ = NULL; +TwoPhaseUploaderFactory* TwoPhaseUploader::factory_ = nullptr; // static -TwoPhaseUploader* TwoPhaseUploader::Create( +std::unique_ptr<TwoPhaseUploader> TwoPhaseUploader::Create( net::URLRequestContextGetter* url_request_context_getter, base::TaskRunner* file_task_runner, const GURL& base_url, @@ -206,10 +209,11 @@ const base::FilePath& file_path, const ProgressCallback& progress_callback, const FinishCallback& finish_callback) { - if (!TwoPhaseUploader::factory_) - return new TwoPhaseUploaderImpl( + if (!factory_) { + return base::WrapUnique(new TwoPhaseUploaderImpl( url_request_context_getter, file_task_runner, base_url, metadata, - file_path, progress_callback, finish_callback); + file_path, progress_callback, finish_callback)); + } return TwoPhaseUploader::factory_->CreateTwoPhaseUploader( url_request_context_getter, file_task_runner, base_url, metadata, file_path, progress_callback, finish_callback);
diff --git a/chrome/browser/safe_browsing/two_phase_uploader.h b/chrome/browser/safe_browsing/two_phase_uploader.h index f7c2d5f..12325003 100644 --- a/chrome/browser/safe_browsing/two_phase_uploader.h +++ b/chrome/browser/safe_browsing/two_phase_uploader.h
@@ -12,7 +12,6 @@ #include "base/callback.h" #include "base/files/file_path.h" -#include "base/threading/non_thread_safe.h" #include "net/url_request/url_request_context_getter.h" #include "url/gurl.h" @@ -33,7 +32,8 @@ // supports sending metadata in the POST request body. We also do not need the // api-version and authorization headers. // TODO(mattm): support retry / resume. -class TwoPhaseUploader : public base::NonThreadSafe { +// Lives on the UI thread. +class TwoPhaseUploader { public: enum State { STATE_NONE, @@ -41,11 +41,11 @@ UPLOAD_FILE, STATE_SUCCESS, }; - typedef base::Callback<void(int64_t sent, int64_t total)> ProgressCallback; - typedef base::Callback<void(State state, - int net_error, - int response_code, - const std::string& response_data)> FinishCallback; + using ProgressCallback = base::Callback<void(int64_t sent, int64_t total)>; + using FinishCallback = base::Callback<void(State state, + int net_error, + int response_code, + const std::string& response_data)>; virtual ~TwoPhaseUploader() {} @@ -62,7 +62,7 @@ // response_data will specify information about the error. |finish_callback| // will not be called if the upload is cancelled by destructing the // TwoPhaseUploader object before completion. - static TwoPhaseUploader* Create( + static std::unique_ptr<TwoPhaseUploader> Create( net::URLRequestContextGetter* url_request_context_getter, base::TaskRunner* file_task_runner, const GURL& base_url, @@ -90,7 +90,7 @@ public: virtual ~TwoPhaseUploaderFactory() {} - virtual TwoPhaseUploader* CreateTwoPhaseUploader( + virtual std::unique_ptr<TwoPhaseUploader> CreateTwoPhaseUploader( net::URLRequestContextGetter* url_request_context_getter, base::TaskRunner* file_task_runner, const GURL& base_url,
diff --git a/chrome/browser/safe_browsing/two_phase_uploader_unittest.cc b/chrome/browser/safe_browsing/two_phase_uploader_unittest.cc index dbb22b0..f845a173 100644 --- a/chrome/browser/safe_browsing/two_phase_uploader_unittest.cc +++ b/chrome/browser/safe_browsing/two_phase_uploader_unittest.cc
@@ -51,10 +51,10 @@ base::FilePath GetTestFilePath() { base::FilePath file_path; PathService::Get(base::DIR_SOURCE_ROOT, &file_path); - file_path = file_path.Append(FILE_PATH_LITERAL("net")); - file_path = file_path.Append(FILE_PATH_LITERAL("data")); - file_path = file_path.Append(FILE_PATH_LITERAL("url_request_unittest")); - file_path = file_path.Append(FILE_PATH_LITERAL("BullRunSpeech.txt")); + file_path = file_path.AppendASCII("net"); + file_path = file_path.AppendASCII("data"); + file_path = file_path.AppendASCII("url_request_unittest"); + file_path = file_path.AppendASCII("BullRunSpeech.txt"); return file_path; }
diff --git a/chrome/browser/safe_browsing/ui_manager.cc b/chrome/browser/safe_browsing/ui_manager.cc index 8543c38..ab4769e 100644 --- a/chrome/browser/safe_browsing/ui_manager.cc +++ b/chrome/browser/safe_browsing/ui_manager.cc
@@ -280,6 +280,17 @@ callback); } +void SafeBrowsingUIManager::ReportPermissionAction( + const GURL& origin, + content::PermissionType permission, + PermissionAction action) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&SafeBrowsingUIManager::ReportPermissionActionOnIOThread, this, + origin, permission, action)); +} + void SafeBrowsingUIManager::AddObserver(Observer* observer) { DCHECK_CURRENTLY_ON(BrowserThread::UI); observer_list_.AddObserver(observer); @@ -302,6 +313,21 @@ sb_service_->ping_manager()->ReportInvalidCertificateChain(serialized_report); } +void SafeBrowsingUIManager::ReportPermissionActionOnIOThread( + const GURL& origin, + content::PermissionType permission, + PermissionAction action) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + // The service may delete the ping manager (i.e. when user disabling service, + // etc). This happens on the IO thread. + if (!sb_service_ || !sb_service_->ping_manager()) + return; + + sb_service_->ping_manager()->ReportPermissionAction(origin, permission, + action); +} + // If the user had opted-in to send ThreatDetails, this gets called // when the report is ready. void SafeBrowsingUIManager::SendSerializedThreatDetails(
diff --git a/chrome/browser/safe_browsing/ui_manager.h b/chrome/browser/safe_browsing/ui_manager.h index b9b7e528..4b39b65 100644 --- a/chrome/browser/safe_browsing/ui_manager.h +++ b/chrome/browser/safe_browsing/ui_manager.h
@@ -16,9 +16,11 @@ #include "base/memory/ref_counted.h" #include "base/observer_list.h" #include "base/time/time.h" +#include "chrome/browser/permissions/permission_uma_util.h" #include "components/safe_browsing_db/hit_report.h" #include "components/safe_browsing_db/util.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/permission_type.h" #include "url/gurl.h" namespace base { @@ -148,6 +150,12 @@ void ReportInvalidCertificateChain(const std::string& serialized_report, const base::Closure& callback); + // Report permission action to SafeBrowsing servers. Can only be called on UI + // thread. + void ReportPermissionAction(const GURL& origin, + content::PermissionType permission, + PermissionAction action); + // Add and remove observers. These methods must be invoked on the UI thread. void AddObserver(Observer* observer); void RemoveObserver(Observer* remove); @@ -168,6 +176,11 @@ void ReportInvalidCertificateChainOnIOThread( const std::string& serialized_report); + // Report permission action to SafeBrowsing servers. + void ReportPermissionActionOnIOThread(const GURL& origin, + content::PermissionType permission, + PermissionAction action); + // Updates the whitelist state. Called on the UI thread. void AddToWhitelist(const UnsafeResource& resource);
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc index c54ae62..70a21ab 100644 --- a/chrome/browser/search/local_ntp_source.cc +++ b/chrome/browser/search/local_ntp_source.cc
@@ -148,8 +148,7 @@ // Returns a JS dictionary of configuration data for the local NTP. std::string GetConfigData(Profile* profile) { base::DictionaryValue config_data; - bool is_google = DefaultSearchProviderIsGoogle(profile) && - search::ShouldShowGoogleLocalNTP(); + bool is_google = DefaultSearchProviderIsGoogle(profile); config_data.Set("translatedStrings", GetTranslatedStrings(is_google).release()); config_data.SetBoolean("isGooglePage", is_google);
diff --git a/chrome/browser/search/search.cc b/chrome/browser/search/search.cc index 60f2cd3..c2ac4fe 100644 --- a/chrome/browser/search/search.cc +++ b/chrome/browser/search/search.cc
@@ -61,8 +61,6 @@ const char kAltInstantURLPath[] = "search"; const char kAltInstantURLQueryParams[] = "&qbp=1"; -const char kShouldShowGoogleLocalNTPFlagName[] = "google_local_ntp"; - // Status of the New Tab URL for the default Search provider. NOTE: Used in a // UMA histogram so values should only be added at the end and not reordered. enum NewTabURLState { @@ -502,12 +500,6 @@ kPrerenderInstantUrlOnOmniboxFocus, false, flags); } -bool ShouldShowGoogleLocalNTP() { - FieldTrialFlags flags; - return !GetFieldTrialInfo(&flags) || GetBoolValueForFlagWithDefault( - kShouldShowGoogleLocalNTPFlagName, true, flags); -} - GURL GetEffectiveURLForInstant(const GURL& url, Profile* profile) { CHECK(ShouldAssignURLToInstantRenderer(url, profile)) << "Error granting Instant access.";
diff --git a/chrome/browser/search/search.h b/chrome/browser/search/search.h index 2b33dbb..4466ef2 100644 --- a/chrome/browser/search/search.h +++ b/chrome/browser/search/search.h
@@ -134,10 +134,6 @@ // focused. bool ShouldPrerenderInstantUrlOnOmniboxFocus(); -// Returns true if the local new tab page should show a Google logo and search -// box for users whose default search provider is Google, or false if not. -bool ShouldShowGoogleLocalNTP(); - // Transforms the input |url| into its "effective URL". The returned URL // facilitates grouping process-per-site. The |url| is transformed, for // example, from
diff --git a/chrome/browser/search/search_unittest.cc b/chrome/browser/search/search_unittest.cc index baa19152..72b12f4a 100644 --- a/chrome/browser/search/search_unittest.cc +++ b/chrome/browser/search/search_unittest.cc
@@ -596,23 +596,6 @@ } -TEST_F(SearchTest, ShouldShowGoogleLocalNTP_Default) { - EXPECT_TRUE(ShouldShowGoogleLocalNTP()); -} - -TEST_F(SearchTest, ShouldShowGoogleLocalNTP_EnabledViaFinch) { - ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( - "EmbeddedSearch", "Group1 espv:2 google_local_ntp:1")); - EXPECT_TRUE(ShouldShowGoogleLocalNTP()); -} - -TEST_F(SearchTest, ShouldShowGoogleLocalNTP_DisabledViaFinch) { - ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( - "EmbeddedSearch", "Group1 espv:2 google_local_ntp:0")); - EXPECT_FALSE(ShouldShowGoogleLocalNTP()); -} - - TEST_F(SearchTest, IsNTPURL) { GURL invalid_url; GURL ntp_url(chrome::kChromeUINewTabURL);
diff --git a/chrome/browser/shell_integration_linux.cc b/chrome/browser/shell_integration_linux.cc index 555b2d21..b1035007 100644 --- a/chrome/browser/shell_integration_linux.cc +++ b/chrome/browser/shell_integration_linux.cc
@@ -202,7 +202,9 @@ } // Allow any reply that starts with "yes". - return (reply.find("yes") == 0) ? IS_DEFAULT : NOT_DEFAULT; + return base::StartsWith(reply, "yes", base::CompareCase::SENSITIVE) + ? IS_DEFAULT + : NOT_DEFAULT; #endif }
diff --git a/chrome/browser/site_per_process_interactive_browsertest.cc b/chrome/browser/site_per_process_interactive_browsertest.cc index c063ef8..9c105d7 100644 --- a/chrome/browser/site_per_process_interactive_browsertest.cc +++ b/chrome/browser/site_per_process_interactive_browsertest.cc
@@ -741,3 +741,32 @@ EXPECT_FALSE(ElementHasFullscreenStyle(c_middle, "child-0")); } +// Test that deleting a RenderWidgetHost that holds the mouse lock won't cause a +// crash. https://crbug.com/619571. +IN_PROC_BROWSER_TEST_F(SitePerProcessInteractiveBrowserTest, + RenderWidgetHostDeletedWhileMouseLocked) { + GURL main_url(embedded_test_server()->GetURL( + "a.com", "/cross_site_iframe_factory.html?a(b)")); + ui_test_utils::NavigateToURL(browser(), main_url); + + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + content::RenderFrameHost* main_frame = web_contents->GetMainFrame(); + content::RenderFrameHost* child = ChildFrameAt(main_frame, 0); + + EXPECT_TRUE(ExecuteScript(child, "document.body.requestPointerLock()")); + bool mouse_locked = false; + EXPECT_TRUE(ExecuteScriptAndExtractBool(child, + "window.domAutomationController.send(" + "document.body == " + "document.pointerLockElement)", + &mouse_locked)); + EXPECT_TRUE(mouse_locked); + EXPECT_TRUE(main_frame->GetView()->IsMouseLocked()); + + EXPECT_TRUE(ExecuteScript(main_frame, + "document.querySelector('iframe').parentNode." + "removeChild(document.querySelector('iframe'))")); + EXPECT_FALSE(main_frame->GetView()->IsMouseLocked()); +}
diff --git a/chrome/browser/status_icons/status_icon_menu_model.cc b/chrome/browser/status_icons/status_icon_menu_model.cc index eee644e..5f36040 100644 --- a/chrome/browser/status_icons/status_icon_menu_model.cc +++ b/chrome/browser/status_icons/status_icon_menu_model.cc
@@ -113,7 +113,7 @@ } bool StatusIconMenuModel::GetAcceleratorForCommandId( - int command_id, ui::Accelerator* accelerator) { + int command_id, ui::Accelerator* accelerator) const { ItemStateMap::const_iterator iter = item_states_.find(command_id); if (iter != item_states_.end() && iter->second.accelerator.key_code() != ui::VKEY_UNKNOWN) {
diff --git a/chrome/browser/status_icons/status_icon_menu_model.h b/chrome/browser/status_icons/status_icon_menu_model.h index 57967a5..672ff35d 100644 --- a/chrome/browser/status_icons/status_icon_menu_model.h +++ b/chrome/browser/status_icons/status_icon_menu_model.h
@@ -82,7 +82,7 @@ bool IsCommandIdEnabled(int command_id) const override; bool IsCommandIdVisible(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; bool IsItemForCommandIdDynamic(int command_id) const override; base::string16 GetLabelForCommandId(int command_id) const override; base::string16 GetSublabelForCommandId(int command_id) const override;
diff --git a/chrome/browser/supervised_user/supervised_user_pref_store.cc b/chrome/browser/supervised_user/supervised_user_pref_store.cc index 921fbe13..3f144a4 100644 --- a/chrome/browser/supervised_user/supervised_user_pref_store.cc +++ b/chrome/browser/supervised_user/supervised_user_pref_store.cc
@@ -76,7 +76,7 @@ // TODO(peconn): Remove this once SupervisedUserPrefStore is (partially at // least) a KeyedService. The user_settings_subscription_ must be reset or // destroyed before the SupervisedUserSettingsService is. - if (supervised_user_settings_service->GetProfile() != nullptr){ + if (supervised_user_settings_service->GetProfile()) { unsubscriber_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, content::Source<Profile>( supervised_user_settings_service->GetProfile())); @@ -85,10 +85,6 @@ bool SupervisedUserPrefStore::GetValue(const std::string& key, const base::Value** value) const { - // TODO(bauerb): Temporary CHECK to force a clean crash while investigating - // https://crbug.com/425785. Remove (or change back to DCHECK) once the bug - // is fixed. - CHECK(prefs_); return prefs_->GetValue(key, value); }
diff --git a/chrome/browser/supervised_user/supervised_user_service_unittest.cc b/chrome/browser/supervised_user/supervised_user_service_unittest.cc index ac4e24ea..5be56ec 100644 --- a/chrome/browser/supervised_user/supervised_user_service_unittest.cc +++ b/chrome/browser/supervised_user/supervised_user_service_unittest.cc
@@ -44,9 +44,9 @@ #include "chrome/browser/extensions/extension_service_test_base.h" #include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/unpacked_installer.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/manifest_constants.h" using extensions::Extension;
diff --git a/chrome/browser/supervised_user/supervised_user_settings_service.cc b/chrome/browser/supervised_user/supervised_user_settings_service.cc index cf8dc89..6561085 100644 --- a/chrome/browser/supervised_user/supervised_user_settings_service.cc +++ b/chrome/browser/supervised_user/supervised_user_settings_service.cc
@@ -75,9 +75,8 @@ Init(store); if (load_synchronously) { store_->ReadPrefs(); - // TODO(bauerb): Temporary CHECK while investigating - // https://crbug.com/425785. Remove (or change to DCHECK) once the bug - // is fixed. + // This should be a DCHECK, but it is triggering in the wild. + // https://crbug.com/627031 CHECK(store_->IsInitializationComplete()); } else { store_->ReadPrefsAsync(nullptr); @@ -102,7 +101,7 @@ return callback_list_.Add(callback); } -Profile* SupervisedUserSettingsService::GetProfile(){ +Profile* SupervisedUserSettingsService::GetProfile() { return profile_; } @@ -111,7 +110,7 @@ InformSubscribers(); } -bool SupervisedUserSettingsService::IsReady() { +bool SupervisedUserSettingsService::IsReady() const { // Initialization cannot be complete but have failed at the same time. DCHECK(!(store_->IsInitializationComplete() && initialization_failed_)); return initialization_failed_ || store_->IsInitializationComplete(); @@ -404,9 +403,7 @@ initialization_failed_ = true; } - // TODO(bauerb): Temporary CHECK while investigating https://crbug.com/425785. - // Remove (or change back to DCHECK) once the bug is fixed. - CHECK(IsReady()); + DCHECK(IsReady()); InformSubscribers(); }
diff --git a/chrome/browser/supervised_user/supervised_user_settings_service.h b/chrome/browser/supervised_user/supervised_user_settings_service.h index fc0a06b..6903fd4 100644 --- a/chrome/browser/supervised_user/supervised_user_settings_service.h +++ b/chrome/browser/supervised_user/supervised_user_settings_service.h
@@ -95,7 +95,7 @@ void SetActive(bool active); // Whether supervised user settings are available. - bool IsReady(); + bool IsReady() const; // Clears all supervised user settings and items. void Clear(); @@ -172,7 +172,7 @@ // directly hooked up to the PrefService. scoped_refptr<PersistentPrefStore> store_; - Profile* profile_; + Profile* const profile_; bool active_;
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc index 047674ab..62685f0 100644 --- a/chrome/browser/sync/test/integration/sync_test.cc +++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -145,7 +145,8 @@ source->GetResponseAsString(&data); running_ = (source->GetStatus().status() == net::URLRequestStatus::SUCCESS && - source->GetResponseCode() == 200 && data.find("ok") == 0); + source->GetResponseCode() == 200 && + base::StartsWith(data, "ok", base::CompareCase::SENSITIVE)); base::MessageLoop::current()->QuitWhenIdle(); }
diff --git a/chrome/browser/task_management/providers/arc/arc_process_task.cc b/chrome/browser/task_management/providers/arc/arc_process_task.cc index 8f179109..435eee3 100644 --- a/chrome/browser/task_management/providers/arc/arc_process_task.cc +++ b/chrome/browser/task_management/providers/arc/arc_process_task.cc
@@ -42,10 +42,8 @@ default: break; } - base::string16 title = - l10n_util::GetStringFUTF16( - name_template, - base::UTF8ToUTF16(process_name)); + base::string16 title = l10n_util::GetStringFUTF16( + name_template, base::UTF8ToUTF16(process_name)); base::i18n::AdjustStringForLocaleDirection(&title); return title; } @@ -69,8 +67,10 @@ const std::string& process_name, arc::mojom::ProcessState process_state, const std::vector<std::string>& packages) - : Task(MakeTitle(process_name, process_state), process_name, - nullptr /* icon */, pid), + : Task(MakeTitle(process_name, process_state), + process_name, + nullptr /* icon */, + pid), nspid_(nspid), process_name_(process_name), process_state_(process_state), @@ -103,12 +103,12 @@ if (result == arc::ActivityIconLoader::GetResult::FAILED_ARC_NOT_READY) { // Need to retry loading the icon. - arc::ArcBridgeService::Get()->AddObserver(this); + arc::ArcBridgeService::Get()->intent_helper()->AddObserver(this); } } ArcProcessTask::~ArcProcessTask() { - arc::ArcBridgeService::Get()->RemoveObserver(this); + arc::ArcBridgeService::Get()->intent_helper()->RemoveObserver(this); } Task::Type ArcProcessTask::GetType() const { @@ -127,25 +127,25 @@ void ArcProcessTask::Kill() { arc::mojom::ProcessInstance* arc_process_instance = - arc::ArcBridgeService::Get()->process_instance(); + arc::ArcBridgeService::Get()->process()->instance(); if (!arc_process_instance) { LOG(ERROR) << "ARC process instance is not ready."; return; } - if (arc::ArcBridgeService::Get()->process_version() < 1) { + if (arc::ArcBridgeService::Get()->process()->version() < 1) { LOG(ERROR) << "ARC KillProcess IPC is unavailable."; return; } - arc_process_instance->KillProcess( - nspid_, "Killed manually from Task Manager"); + arc_process_instance->KillProcess(nspid_, + "Killed manually from Task Manager"); } -void ArcProcessTask::OnIntentHelperInstanceReady() { +void ArcProcessTask::OnInstanceReady() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); VLOG(2) << "intent_helper instance is ready. Fetching the icon for " << package_name_; - arc::ArcBridgeService::Get()->RemoveObserver(this); + arc::ArcBridgeService::Get()->intent_helper()->RemoveObserver(this); // Instead of calling into StartIconLoading() directly, return to the main // loop first to make sure other ArcBridgeService observers are notified.
diff --git a/chrome/browser/task_management/providers/arc/arc_process_task.h b/chrome/browser/task_management/providers/arc/arc_process_task.h index 9cae4d86..3edf6538 100644 --- a/chrome/browser/task_management/providers/arc/arc_process_task.h +++ b/chrome/browser/task_management/providers/arc/arc_process_task.h
@@ -14,12 +14,15 @@ #include "chrome/browser/task_management/providers/task.h" #include "components/arc/arc_bridge_service.h" #include "components/arc/common/process.mojom.h" +#include "components/arc/instance_holder.h" #include "components/arc/intent_helper/activity_icon_loader.h" namespace task_management { // Defines a task that represents an ARC process. -class ArcProcessTask : public Task, public arc::ArcBridgeService::Observer { +class ArcProcessTask + : public Task, + public arc::InstanceHolder<arc::mojom::IntentHelperInstance>::Observer { public: ArcProcessTask(base::ProcessId pid, base::ProcessId nspid, @@ -34,8 +37,8 @@ bool IsKillable() override; void Kill() override; - // arc::ArcBridgeService::Observer: - void OnIntentHelperInstanceReady() override; + // arc::InstanceHolder<arc::mojom::IntentHelperInstance>::Observer: + void OnInstanceReady() override; void SetProcessState(arc::mojom::ProcessState process_state);
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index a982d5b9..031d9ae 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -484,7 +484,6 @@ "//ui/views/controls/webview", ] deps += [ - "//chrome/installer/util:strings", "//components/search_engines", "//google_update", "//third_party/iaccessible2",
diff --git a/chrome/browser/ui/app_list/app_context_menu.cc b/chrome/browser/ui/app_list/app_context_menu.cc index 5836e8c..5e85a6e 100644 --- a/chrome/browser/ui/app_list/app_context_menu.cc +++ b/chrome/browser/ui/app_list/app_context_menu.cc
@@ -84,8 +84,9 @@ return true; } -bool AppContextMenu::GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) { +bool AppContextMenu::GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const { return false; }
diff --git a/chrome/browser/ui/app_list/app_context_menu.h b/chrome/browser/ui/app_list/app_context_menu.h index 4d80cd2..aea36ff1 100644 --- a/chrome/browser/ui/app_list/app_context_menu.h +++ b/chrome/browser/ui/app_list/app_context_menu.h
@@ -52,7 +52,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; protected:
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.cc b/chrome/browser/ui/app_list/app_list_view_delegate.cc index 814fddb..37188e3ea 100644 --- a/chrome/browser/ui/app_list/app_list_view_delegate.cc +++ b/chrome/browser/ui/app_list/app_list_view_delegate.cc
@@ -567,18 +567,6 @@ } } -void AppListViewDelegate::OpenSettings() { - const extensions::Extension* extension = - extensions::ExtensionRegistry::Get(profile_)->GetExtensionById( - extension_misc::kSettingsAppId, - extensions::ExtensionRegistry::EVERYTHING); - DCHECK(extension); - controller_->ActivateApp(profile_, - extension, - AppListControllerDelegate::LAUNCH_FROM_UNKNOWN, - 0); -} - void AppListViewDelegate::OpenHelp() { chrome::ScopedTabbedBrowserDisplayer displayer(profile_); content::OpenURLParams params(GURL(chrome::kAppLauncherHelpURL),
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.h b/chrome/browser/ui/app_list/app_list_view_delegate.h index a1d4d2e1..3346029 100644 --- a/chrome/browser/ui/app_list/app_list_view_delegate.h +++ b/chrome/browser/ui/app_list/app_list_view_delegate.h
@@ -101,7 +101,6 @@ void ViewInitialized() override; void Dismiss() override; void ViewClosing() override; - void OpenSettings() override; void OpenHelp() override; void OpenFeedback() override; void StartSpeechRecognition() override;
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc index fa58150..7ab5c3b 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -108,9 +108,9 @@ base::CreateDirectory(icon_path.DirName()); - int wrote = base::WriteFile(icon_path, - reinterpret_cast<const char*>(&content_png[0]), - content_png.size()); + int wrote = + base::WriteFile(icon_path, reinterpret_cast<const char*>(&content_png[0]), + content_png.size()); if (wrote != static_cast<int>(content_png.size())) { VLOG(2) << "Failed to write ARC icon file: " << icon_path.MaybeAsASCII() << "."; @@ -234,15 +234,18 @@ arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get(); DCHECK(bridge_service); + bridge_service->app()->AddObserver(this); bridge_service->AddObserver(this); if (!bridge_service->ready()) - OnBridgeStopped(); + OnBridgeStopped(arc::ArcBridgeService::StopReason::SHUTDOWN); } ArcAppListPrefs::~ArcAppListPrefs() { arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get(); - if (bridge_service) + if (bridge_service) { bridge_service->RemoveObserver(this); + bridge_service->app()->RemoveObserver(this); + } arc::ArcAuthService* auth_service = arc::ArcAuthService::Get(); if (auth_service) @@ -258,35 +261,34 @@ ui::ScaleFactor scale_factor) const { const base::FilePath app_path = GetAppPath(app_id); switch (scale_factor) { - case ui::SCALE_FACTOR_100P: - return app_path.AppendASCII("icon_100p.png"); - case ui::SCALE_FACTOR_125P: - return app_path.AppendASCII("icon_125p.png"); - case ui::SCALE_FACTOR_133P: - return app_path.AppendASCII("icon_133p.png"); - case ui::SCALE_FACTOR_140P: - return app_path.AppendASCII("icon_140p.png"); - case ui::SCALE_FACTOR_150P: - return app_path.AppendASCII("icon_150p.png"); - case ui::SCALE_FACTOR_180P: - return app_path.AppendASCII("icon_180p.png"); - case ui::SCALE_FACTOR_200P: - return app_path.AppendASCII("icon_200p.png"); - case ui::SCALE_FACTOR_250P: - return app_path.AppendASCII("icon_250p.png"); - case ui::SCALE_FACTOR_300P: - return app_path.AppendASCII("icon_300p.png"); - default: - NOTREACHED(); - return base::FilePath(); + case ui::SCALE_FACTOR_100P: + return app_path.AppendASCII("icon_100p.png"); + case ui::SCALE_FACTOR_125P: + return app_path.AppendASCII("icon_125p.png"); + case ui::SCALE_FACTOR_133P: + return app_path.AppendASCII("icon_133p.png"); + case ui::SCALE_FACTOR_140P: + return app_path.AppendASCII("icon_140p.png"); + case ui::SCALE_FACTOR_150P: + return app_path.AppendASCII("icon_150p.png"); + case ui::SCALE_FACTOR_180P: + return app_path.AppendASCII("icon_180p.png"); + case ui::SCALE_FACTOR_200P: + return app_path.AppendASCII("icon_200p.png"); + case ui::SCALE_FACTOR_250P: + return app_path.AppendASCII("icon_250p.png"); + case ui::SCALE_FACTOR_300P: + return app_path.AppendASCII("icon_300p.png"); + default: + NOTREACHED(); + return base::FilePath(); } } void ArcAppListPrefs::RequestIcon(const std::string& app_id, ui::ScaleFactor scale_factor) { if (!IsRegistered(app_id)) { - VLOG(2) << "Request to load icon for non-registered app: " - << app_id << "."; + VLOG(2) << "Request to load icon for non-registered app: " << app_id << "."; return; } @@ -302,7 +304,7 @@ NOTREACHED(); return; } - arc::mojom::AppInstance* app_instance = bridge_service->app_instance(); + arc::mojom::AppInstance* app_instance = bridge_service->app()->instance(); if (!app_instance) { // AppInstance should be ready since we have app_id in ready_apps_. NOTREACHED(); @@ -311,7 +313,7 @@ std::unique_ptr<AppInfo> app_info = GetApp(app_id); if (!app_info) { - VLOG(2) << "Failed to get app info: " << app_id << "."; + VLOG(2) << "Failed to get app info: " << app_id << "."; return; } @@ -345,9 +347,9 @@ // In case app is not ready, defer this request. if (!ready_apps_.count(app_id)) { SetNotificationsEnabledDeferred(prefs_).Put(app_id, enabled); - FOR_EACH_OBSERVER(Observer, observer_list_, - OnNotificationsEnabledChanged( - app_info->package_name, enabled)); + FOR_EACH_OBSERVER( + Observer, observer_list_, + OnNotificationsEnabledChanged(app_info->package_name, enabled)); return; } @@ -357,14 +359,14 @@ return; } - arc::mojom::AppInstance* app_instance = bridge_service->app_instance(); + arc::mojom::AppInstance* app_instance = bridge_service->app()->instance(); if (!app_instance) { // AppInstance should be ready since we have app_id in ready_apps_. NOTREACHED(); return; } - if (bridge_service->app_version() < kSetNotificationsEnabledMinVersion) { + if (bridge_service->app()->version() < kSetNotificationsEnabledMinVersion) { VLOG(2) << "app version is too small to set notifications enabled."; return; } @@ -425,8 +427,8 @@ // crx_file::id_util is de-facto utility for id generation. const base::DictionaryValue* apps = prefs_->GetDictionary(prefs::kArcApps); - for (base::DictionaryValue::Iterator app_id(*apps); - !app_id.IsAtEnd(); app_id.Advance()) { + for (base::DictionaryValue::Iterator app_id(*apps); !app_id.IsAtEnd(); + app_id.Advance()) { if (!crx_file::id_util::IdIsValid(app_id.key())) continue; @@ -524,8 +526,7 @@ std::set<std::string> old_ready_apps; old_ready_apps.swap(ready_apps_); for (auto& app_id : old_ready_apps) { - FOR_EACH_OBSERVER(Observer, - observer_list_, + FOR_EACH_OBSERVER(Observer, observer_list_, OnAppReadyChanged(app_id, false)); } } @@ -542,8 +543,7 @@ NOTREACHED(); continue; } - FOR_EACH_OBSERVER(Observer, - observer_list_, + FOR_EACH_OBSERVER(Observer, observer_list_, OnAppRegistered(app_id, *app_info)); } @@ -563,17 +563,18 @@ RemoveAllApps(); } -void ArcAppListPrefs::OnBridgeStopped() { +void ArcAppListPrefs::OnBridgeStopped( + arc::ArcBridgeService::StopReason reason) { DisableAllApps(); } -void ArcAppListPrefs::OnAppInstanceReady() { +void ArcAppListPrefs::OnInstanceReady() { arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get(); if (!bridge_service) { NOTREACHED(); return; } - arc::mojom::AppInstance* app_instance = bridge_service->app_instance(); + arc::mojom::AppInstance* app_instance = bridge_service->app()->instance(); if (!app_instance) { VLOG(2) << "Request to refresh app list when bridge service is not ready."; return; @@ -583,7 +584,7 @@ app_instance->RefreshAppList(); } -void ArcAppListPrefs::OnAppInstanceClosed() { +void ArcAppListPrefs::OnInstanceClosed() { ready_apps_.clear(); } @@ -626,8 +627,7 @@ ready_apps_.insert(app_id); if (was_registered) { - FOR_EACH_OBSERVER(Observer, - observer_list_, + FOR_EACH_OBSERVER(Observer, observer_list_, OnAppReadyChanged(app_id, true)); } else { AppInfo app_info(name, package_name, activity, intent_uri, icon_resource_id, @@ -674,14 +674,11 @@ // app_id may be released by observers, get the path first. const base::FilePath app_path = GetAppPath(app_id); - FOR_EACH_OBSERVER(Observer, - observer_list_, - OnAppRemoved(app_id)); + FOR_EACH_OBSERVER(Observer, observer_list_, OnAppRemoved(app_id)); // Remove local data on file system. content::BrowserThread::GetBlockingPool()->PostTask( - FROM_HERE, - base::Bind(&DeleteAppFolderFromFileThread, app_path)); + FROM_HERE, base::Bind(&DeleteAppFolderFromFileThread, app_path)); } void ArcAppListPrefs::OnAppListRefreshed( @@ -755,8 +752,8 @@ void ArcAppListPrefs::OnPackageRemoved(const mojo::String& package_name) { const base::DictionaryValue* apps = prefs_->GetDictionary(prefs::kArcApps); std::vector<std::string> apps_to_remove; - for (base::DictionaryValue::Iterator app_it(*apps); - !app_it.IsAtEnd(); app_it.Advance()) { + for (base::DictionaryValue::Iterator app_it(*apps); !app_it.IsAtEnd(); + app_it.Advance()) { const base::Value* value = &app_it.value(); const base::DictionaryValue* app; if (!value->GetAsDictionary(&app)) { @@ -817,8 +814,7 @@ void ArcAppListPrefs::OnTaskCreated(int32_t task_id, const mojo::String& package_name, const mojo::String& activity) { - FOR_EACH_OBSERVER(Observer, - observer_list_, + FOR_EACH_OBSERVER(Observer, observer_list_, OnTaskCreated(task_id, package_name, activity)); } @@ -831,10 +827,11 @@ } void ArcAppListPrefs::OnNotificationsEnabledChanged( - const mojo::String& package_name, bool enabled) { + const mojo::String& package_name, + bool enabled) { const base::DictionaryValue* apps = prefs_->GetDictionary(prefs::kArcApps); - for (base::DictionaryValue::Iterator app(*apps); - !app.IsAtEnd(); app.Advance()) { + for (base::DictionaryValue::Iterator app(*apps); !app.IsAtEnd(); + app.Advance()) { const base::DictionaryValue* app_dict; std::string app_package_name; if (!app.value().GetAsDictionary(&app_dict) || @@ -902,17 +899,12 @@ ui::ScaleFactor scale_factor, const std::vector<uint8_t>& content_png) { base::FilePath icon_path = GetIconPath(app_id, scale_factor); - base::PostTaskAndReplyWithResult(content::BrowserThread::GetBlockingPool(), - FROM_HERE, - base::Bind(&InstallIconFromFileThread, - app_id, - scale_factor, - icon_path, - content_png), - base::Bind(&ArcAppListPrefs::OnIconInstalled, - weak_ptr_factory_.GetWeakPtr(), - app_id, - scale_factor)); + base::PostTaskAndReplyWithResult( + content::BrowserThread::GetBlockingPool(), FROM_HERE, + base::Bind(&InstallIconFromFileThread, app_id, scale_factor, icon_path, + content_png), + base::Bind(&ArcAppListPrefs::OnIconInstalled, + weak_ptr_factory_.GetWeakPtr(), app_id, scale_factor)); } void ArcAppListPrefs::OnIconInstalled(const std::string& app_id, @@ -922,8 +914,7 @@ if (!install_succeed) return; - FOR_EACH_OBSERVER(Observer, - observer_list_, + FOR_EACH_OBSERVER(Observer, observer_list_, OnAppIconUpdated(app_id, scale_factor)); }
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h index 173843c5..907fa513 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h +++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.h
@@ -21,6 +21,7 @@ #include "chrome/browser/chromeos/arc/arc_auth_service.h" #include "components/arc/arc_bridge_service.h" #include "components/arc/common/app.mojom.h" +#include "components/arc/instance_holder.h" #include "components/keyed_service/core/keyed_service.h" #include "mojo/public/cpp/bindings/binding.h" #include "ui/base/layout.h" @@ -44,10 +45,12 @@ // information is used to pre-create non-ready app items while ARC bridge // service is not ready to provide information about available ARC apps. // NOTE: ArcAppListPrefs is only created for the primary user. -class ArcAppListPrefs : public KeyedService, - public arc::mojom::AppHost, - public arc::ArcBridgeService::Observer, - public arc::ArcAuthService::Observer { +class ArcAppListPrefs + : public KeyedService, + public arc::mojom::AppHost, + public arc::ArcBridgeService::Observer, + public arc::InstanceHolder<arc::mojom::AppInstance>::Observer, + public arc::ArcAuthService::Observer { public: struct AppInfo { AppInfo(const std::string& name, @@ -206,9 +209,11 @@ ArcAppListPrefs(const base::FilePath& base_path, PrefService* prefs); // arc::ArcBridgeService::Observer: - void OnBridgeStopped() override; - void OnAppInstanceReady() override; - void OnAppInstanceClosed() override; + void OnBridgeStopped(arc::ArcBridgeService::StopReason reason) override; + + // arc::InstanceHolder<arc::mojom::AppInstance>::Observer: + void OnInstanceReady() override; + void OnInstanceClosed() override; // arc::mojom::AppHost: void OnAppListRefreshed(mojo::Array<arc::mojom::AppInfoPtr> apps) override;
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.cc b/chrome/browser/ui/app_list/arc/arc_app_utils.cc index 273c104..651bbb8 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_utils.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
@@ -53,14 +53,14 @@ return nullptr; } - arc::mojom::AppInstance* app_instance = bridge_service->app_instance(); + arc::mojom::AppInstance* app_instance = bridge_service->app()->instance(); if (!app_instance) { VLOG(2) << "Request to " << service_name << " when mojom::app_instance is not ready."; return nullptr; } - int bridge_version = bridge_service->app_version(); + int bridge_version = bridge_service->app()->version(); if (bridge_version < required_version) { VLOG(2) << "Request to " << service_name << " when Arc version " << bridge_version << " does not support it."; @@ -109,10 +109,8 @@ public: LaunchAppWithoutSize(content::BrowserContext* context, const std::string& app_id, - bool landscape_mode) : - context_(context), - app_id_(app_id), - landscape_mode_(landscape_mode) {} + bool landscape_mode) + : context_(context), app_id_(app_id), landscape_mode_(landscape_mode) {} // This will launch the request and after the return the creator does not // need to delete the object anymore. @@ -130,7 +128,8 @@ // capability flags like [PHONE/TABLET]_[LANDSCAPE/PORTRAIT] and which // might also return the used DP->PIX conversion constant to do better // size calculations. - bool result = CanHandleResolution(context_, app_id_, landscape_, + bool result = CanHandleResolution( + context_, app_id_, landscape_, base::Bind(&LaunchAppWithoutSize::Callback, base::Unretained(this))); if (!result) delete this; @@ -200,9 +199,8 @@ } bool LaunchAndroidSettingsApp(content::BrowserContext* context) { - return arc::LaunchApp(context, - kSettingsAppId, - true); // landscape_layout + constexpr bool kUseLandscapeLayout = true; + return arc::LaunchApp(context, kSettingsAppId, kUseLandscapeLayout); } bool LaunchApp(content::BrowserContext* context, const std::string& app_id) { @@ -225,15 +223,14 @@ return true; } - return (new LaunchAppWithoutSize(context, - app_id, - landscape_layout))->LaunchAndRelease(); + return (new LaunchAppWithoutSize(context, app_id, landscape_layout)) + ->LaunchAndRelease(); } bool CanHandleResolution(content::BrowserContext* context, - const std::string& app_id, - const gfx::Rect& rect, - const CanHandleResolutionCallback& callback) { + const std::string& app_id, + const gfx::Rect& rect, + const CanHandleResolutionCallback& callback) { const ArcAppListPrefs* prefs = ArcAppListPrefs::Get(context); DCHECK(prefs); std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(app_id);
diff --git a/chrome/browser/ui/app_list/search/search_controller_factory.cc b/chrome/browser/ui/app_list/search/search_controller_factory.cc index 3776d469..bbe518c 100644 --- a/chrome/browser/ui/app_list/search/search_controller_factory.cc +++ b/chrome/browser/ui/app_list/search/search_controller_factory.cc
@@ -34,7 +34,6 @@ // Maximum number of results to show in each mixer group. const size_t kMaxAppsGroupResults = 4; -// Ignored unless AppListMixer field trial is "Blended". const size_t kMaxOmniboxResults = 4; const size_t kMaxWebstoreResults = 2; const size_t kMaxSuggestionsResults = 6; @@ -67,18 +66,12 @@ HistoryFactory::GetForBrowserContext(profile))); // Add mixer groups. There are three main groups: apps, webstore and - // omnibox. The behaviour depends on the AppListMixer field trial: - // - If default: The apps and webstore groups each have a fixed - // maximum number of results. The omnibox group fills the remaining slots - // (with a minimum of one result). - // - If "Blended": Each group has a "soft" maximum number of results. However, - // if a query turns up very few results, the mixer may take more than this - // maximum from a particular group. - size_t apps_group_id = controller->AddGroup(kMaxAppsGroupResults, 3.0, 1.0); - size_t omnibox_group_id = - controller->AddOmniboxGroup(kMaxOmniboxResults, 2.0, 1.0); - size_t webstore_group_id = - controller->AddGroup(kMaxWebstoreResults, 1.0, 0.4); + // omnibox. Each group has a "soft" maximum number of results. However, if + // a query turns up very few results, the mixer may take more than this + // maximum from a particular group. + size_t apps_group_id = controller->AddGroup(kMaxAppsGroupResults, 1.0); + size_t omnibox_group_id = controller->AddGroup(kMaxOmniboxResults, 1.0); + size_t webstore_group_id = controller->AddGroup(kMaxWebstoreResults, 0.4); // Add search providers. controller->AddProvider( @@ -94,7 +87,7 @@ new WebstoreProvider(profile, list_controller))); if (IsSuggestionsSearchProviderEnabled()) { size_t suggestions_group_id = - controller->AddGroup(kMaxSuggestionsResults, 3.0, 1.0); + controller->AddGroup(kMaxSuggestionsResults, 1.0); controller->AddProvider( suggestions_group_id, std::unique_ptr<SearchProvider>( @@ -107,7 +100,7 @@ if (app_list::switches::IsDriveSearchInChromeLauncherEnabled() && !profile->IsGuestSession()) { size_t search_api_group_id = - controller->AddGroup(kMaxLauncherSearchResults, 0.0, 1.0); + controller->AddGroup(kMaxLauncherSearchResults, 1.0); controller->AddProvider( search_api_group_id, std::unique_ptr<SearchProvider>(new LauncherSearchProvider(profile)));
diff --git a/chrome/browser/ui/apps/chrome_app_window_client.cc b/chrome/browser/ui/apps/chrome_app_window_client.cc index 1fa807fc..3349e24 100644 --- a/chrome/browser/ui/apps/chrome_app_window_client.cc +++ b/chrome/browser/ui/apps/chrome_app_window_client.cc
@@ -7,11 +7,11 @@ #include "base/memory/singleton.h" #include "build/build_config.h" #include "chrome/browser/devtools/devtools_window.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "components/version_info/version_info.h" #include "content/public/browser/devtools_agent_host.h" #include "extensions/browser/app_window/app_window.h" #include "extensions/common/extension.h" +#include "extensions/common/features/feature_channel.h" // TODO(jamescook): We probably shouldn't compile this class at all on Android. // See http://crbug.com/343612
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc index 264b5f7..eb20851 100644 --- a/chrome/browser/ui/ash/chrome_shell_delegate.cc +++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -76,6 +76,8 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" +using chromeos::AccessibilityManager; + namespace { const char kKeyboardShortcutHelpPageUrl[] = @@ -101,34 +103,32 @@ class AccessibilityDelegateImpl : public ash::AccessibilityDelegate { public: AccessibilityDelegateImpl() { - ash::WmShell::Get()->AddShellObserver( - chromeos::AccessibilityManager::Get()); + ash::WmShell::Get()->AddShellObserver(AccessibilityManager::Get()); } ~AccessibilityDelegateImpl() override { - ash::WmShell::Get()->RemoveShellObserver( - chromeos::AccessibilityManager::Get()); + ash::WmShell::Get()->RemoveShellObserver(AccessibilityManager::Get()); } void ToggleHighContrast() override { - DCHECK(chromeos::AccessibilityManager::Get()); - chromeos::AccessibilityManager::Get()->EnableHighContrast( - !chromeos::AccessibilityManager::Get()->IsHighContrastEnabled()); + DCHECK(AccessibilityManager::Get()); + AccessibilityManager::Get()->EnableHighContrast( + !AccessibilityManager::Get()->IsHighContrastEnabled()); } bool IsSpokenFeedbackEnabled() const override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->IsSpokenFeedbackEnabled(); + DCHECK(AccessibilityManager::Get()); + return AccessibilityManager::Get()->IsSpokenFeedbackEnabled(); } void ToggleSpokenFeedback( ash::AccessibilityNotificationVisibility notify) override { - DCHECK(chromeos::AccessibilityManager::Get()); - chromeos::AccessibilityManager::Get()->ToggleSpokenFeedback(notify); + DCHECK(AccessibilityManager::Get()); + AccessibilityManager::Get()->ToggleSpokenFeedback(notify); } bool IsHighContrastEnabled() const override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->IsHighContrastEnabled(); + DCHECK(AccessibilityManager::Get()); + return AccessibilityManager::Get()->IsHighContrastEnabled(); } void SetMagnifierEnabled(bool enabled) override { @@ -152,104 +152,103 @@ } void SetLargeCursorEnabled(bool enabled) override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->EnableLargeCursor(enabled); + DCHECK(AccessibilityManager::Get()); + return AccessibilityManager::Get()->EnableLargeCursor(enabled); } bool IsLargeCursorEnabled() const override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->IsLargeCursorEnabled(); + DCHECK(AccessibilityManager::Get()); + return AccessibilityManager::Get()->IsLargeCursorEnabled(); } void SetAutoclickEnabled(bool enabled) override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->EnableAutoclick(enabled); + DCHECK(AccessibilityManager::Get()); + return AccessibilityManager::Get()->EnableAutoclick(enabled); } bool IsAutoclickEnabled() const override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->IsAutoclickEnabled(); + DCHECK(AccessibilityManager::Get()); + return AccessibilityManager::Get()->IsAutoclickEnabled(); } void SetVirtualKeyboardEnabled(bool enabled) override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->EnableVirtualKeyboard( - enabled); + DCHECK(AccessibilityManager::Get()); + return AccessibilityManager::Get()->EnableVirtualKeyboard(enabled); } bool IsVirtualKeyboardEnabled() const override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->IsVirtualKeyboardEnabled(); + DCHECK(AccessibilityManager::Get()); + return AccessibilityManager::Get()->IsVirtualKeyboardEnabled(); } void SetMonoAudioEnabled(bool enabled) override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->EnableMonoAudio(enabled); + DCHECK(AccessibilityManager::Get()); + return AccessibilityManager::Get()->EnableMonoAudio(enabled); } bool IsMonoAudioEnabled() const override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->IsMonoAudioEnabled(); + DCHECK(AccessibilityManager::Get()); + return AccessibilityManager::Get()->IsMonoAudioEnabled(); } void SetCaretHighlightEnabled(bool enabled) override { - DCHECK(chromeos::AccessibilityManager::Get()); - chromeos::AccessibilityManager::Get()->SetCaretHighlightEnabled(enabled); + DCHECK(AccessibilityManager::Get()); + AccessibilityManager::Get()->SetCaretHighlightEnabled(enabled); } bool IsCaretHighlightEnabled() const override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->IsCaretHighlightEnabled(); + DCHECK(AccessibilityManager::Get()); + return AccessibilityManager::Get()->IsCaretHighlightEnabled(); } void SetCursorHighlightEnabled(bool enabled) override { - DCHECK(chromeos::AccessibilityManager::Get()); - chromeos::AccessibilityManager::Get()->SetCursorHighlightEnabled(enabled); + DCHECK(AccessibilityManager::Get()); + AccessibilityManager::Get()->SetCursorHighlightEnabled(enabled); } bool IsCursorHighlightEnabled() const override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->IsCursorHighlightEnabled(); + DCHECK(AccessibilityManager::Get()); + return AccessibilityManager::Get()->IsCursorHighlightEnabled(); } void SetFocusHighlightEnabled(bool enabled) override { - DCHECK(chromeos::AccessibilityManager::Get()); - chromeos::AccessibilityManager::Get()->SetFocusHighlightEnabled(enabled); + DCHECK(AccessibilityManager::Get()); + AccessibilityManager::Get()->SetFocusHighlightEnabled(enabled); } bool IsFocusHighlightEnabled() const override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->IsFocusHighlightEnabled(); + DCHECK(AccessibilityManager::Get()); + return AccessibilityManager::Get()->IsFocusHighlightEnabled(); } void SetSelectToSpeakEnabled(bool enabled) override { - DCHECK(chromeos::AccessibilityManager::Get()); - chromeos::AccessibilityManager::Get()->SetSelectToSpeakEnabled(enabled); + DCHECK(AccessibilityManager::Get()); + AccessibilityManager::Get()->SetSelectToSpeakEnabled(enabled); } bool IsSelectToSpeakEnabled() const override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->IsSelectToSpeakEnabled(); + DCHECK(AccessibilityManager::Get()); + return AccessibilityManager::Get()->IsSelectToSpeakEnabled(); } void SetSwitchAccessEnabled(bool enabled) override { - DCHECK(chromeos::AccessibilityManager::Get()); - chromeos::AccessibilityManager::Get()->SetSwitchAccessEnabled(enabled); + DCHECK(AccessibilityManager::Get()); + AccessibilityManager::Get()->SetSwitchAccessEnabled(enabled); } bool IsSwitchAccessEnabled() const override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->IsSwitchAccessEnabled(); + DCHECK(AccessibilityManager::Get()); + return AccessibilityManager::Get()->IsSwitchAccessEnabled(); } bool ShouldShowAccessibilityMenu() const override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->ShouldShowAccessibilityMenu(); + DCHECK(AccessibilityManager::Get()); + return AccessibilityManager::Get()->ShouldShowAccessibilityMenu(); } bool IsBrailleDisplayConnected() const override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->IsBrailleDisplayConnected(); + DCHECK(AccessibilityManager::Get()); + return AccessibilityManager::Get()->IsBrailleDisplayConnected(); } void SilenceSpokenFeedback() const override { @@ -295,16 +294,17 @@ } void PlayEarcon(int sound_key) override { - DCHECK(chromeos::AccessibilityManager::Get()); - return chromeos::AccessibilityManager::Get()->PlayEarcon(sound_key); + DCHECK(AccessibilityManager::Get()); + AccessibilityManager::Get()->PlayEarcon( + sound_key, chromeos::PlaySoundOption::SPOKEN_FEEDBACK_ENABLED); } base::TimeDelta PlayShutdownSound() const override { - return chromeos::AccessibilityManager::Get()->PlayShutdownSound(); + return AccessibilityManager::Get()->PlayShutdownSound(); } void HandleAccessibilityGesture(ui::AXGesture gesture) override { - chromeos::AccessibilityManager::Get()->HandleAccessibilityGesture(gesture); + AccessibilityManager::Get()->HandleAccessibilityGesture(gesture); } private: @@ -352,7 +352,7 @@ } bool ChromeShellDelegate::IsIncognitoAllowed() const { - return chromeos::AccessibilityManager::Get()->IsIncognitoAllowed(); + return AccessibilityManager::Get()->IsIncognitoAllowed(); } bool ChromeShellDelegate::IsRunningInForcedAppMode() const {
diff --git a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc index cf5a14a7..8d8f328 100644 --- a/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc +++ b/chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.cc
@@ -3,8 +3,11 @@ // found in the LICENSE file. #include "chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.h" +#include <string> + #include "ash/common/wm/maximize_mode/maximize_mode_controller.h" #include "ash/common/wm/window_state.h" +#include "ash/common/wm_lookup.h" #include "ash/common/wm_shell.h" #include "ash/display/display_manager.h" #include "ash/display/screen_orientation_controller_chromeos.h" @@ -211,15 +214,15 @@ arc::mojom::AppInstance* GetAppInstance() { arc::ArcBridgeService* bridge_service = arc::ArcBridgeService::Get(); arc::mojom::AppInstance* app_instance = - bridge_service ? bridge_service->app_instance() : nullptr; + bridge_service ? bridge_service->app()->instance() : nullptr; if (!app_instance) { VLOG(2) << "Arc Bridge is not available."; return nullptr; } - if (bridge_service->app_version() < 3) { + if (bridge_service->app()->version() < 3) { VLOG(2) << "Arc Bridge has old version for apps." - << bridge_service->app_version(); + << bridge_service->app()->version(); return nullptr; } return app_instance; @@ -354,8 +357,6 @@ if (app_window) { app_window->set_widget(views::Widget::GetWidgetForNativeWindow(window)); ash::SetShelfIDForWindow(app_window->shelf_id(), window); - if (app_window->controller()) - window->SetTitle(app_window->controller()->GetTitle()); chrome::MultiUserWindowManager::GetInstance()->SetWindowOwner( window, user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId()); @@ -580,8 +581,8 @@ void ArcAppWindowLauncherController::SetOrientationLockForAppWindow( AppWindow* app_window) { - ash::Shell* shell = ash::Shell::GetInstance(); - aura::Window* window = app_window->widget()->GetNativeWindow(); + ash::WmWindow* window = + ash::WmLookup::Get()->GetWindowForWidget(app_window->widget()); if (!window) return; arc::mojom::OrientationLock orientation_lock; @@ -602,6 +603,7 @@ app_window->set_requested_orientation_lock(orientation_lock); } + ash::Shell* shell = ash::Shell::GetInstance(); shell->screen_orientation_controller()->LockOrientationForWindow( window, BlinkOrientationLockFromMojom(orientation_lock)); }
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc index 929bc24..984adf5 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_impl.cc
@@ -1669,7 +1669,12 @@ // ash::WindowTreeHostManager::Observer: void ChromeLauncherControllerImpl::OnDisplayConfigurationChanged() { - SetShelfBehaviorsFromPrefs(); + // In BOTTOM_LOCKED state, ignore the call of SetShelfBehaviorsFromPrefs. + // Because it might be called by some operations, like crbug.com/627040 + // rotating screen. + ash::Shelf* shelf = ash::Shelf::ForPrimaryDisplay(); + if (!shelf || shelf->alignment() != ash::SHELF_ALIGNMENT_BOTTOM_LOCKED) + SetShelfBehaviorsFromPrefs(); } ///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.cc b/chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.cc index dbc2535..7f89b3a 100644 --- a/chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.cc +++ b/chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.cc
@@ -48,7 +48,7 @@ bool LauncherApplicationMenuItemModel::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; }
diff --git a/chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h b/chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h index ba9b533..583554b 100644 --- a/chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h +++ b/chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h
@@ -33,7 +33,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; private:
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc index f050a3b5..388f3aa 100644 --- a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc +++ b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
@@ -109,8 +109,8 @@ } bool LauncherContextMenu::GetAcceleratorForCommandId( - int command_id, - ui::Accelerator* accelerator) { + int command_id, + ui::Accelerator* accelerator) const { return false; }
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu.h b/chrome/browser/ui/ash/launcher/launcher_context_menu.h index 773ddeb..8a380db9 100644 --- a/chrome/browser/ui/ash/launcher/launcher_context_menu.h +++ b/chrome/browser/ui/ash/launcher/launcher_context_menu.h
@@ -36,7 +36,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; protected:
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos.cc b/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos.cc index 702517f..df2cbebc 100644 --- a/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos.cc +++ b/chrome/browser/ui/ash/multi_user/multi_user_context_menu_chromeos.cc
@@ -41,7 +41,7 @@ bool IsCommandIdChecked(int command_id) const override { return false; } bool IsCommandIdEnabled(int command_id) const override { return true; } bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override { + ui::Accelerator* accelerator) const override { return false; } void ExecuteCommand(int command_id, int event_flags) override;
diff --git a/chrome/browser/ui/ash/multi_user/user_switch_util.cc b/chrome/browser/ui/ash/multi_user/user_switch_util.cc new file mode 100644 index 0000000..d21e826 --- /dev/null +++ b/chrome/browser/ui/ash/multi_user/user_switch_util.cc
@@ -0,0 +1,195 @@ +// 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. + +#include "chrome/browser/ui/ash/multi_user/user_switch_util.h" + +#include "ash/common/system/chromeos/screen_security/screen_tray_item.h" +#include "ash/common/system/tray/system_tray.h" +#include "ash/shell.h" +#include "ash/strings/grit/ash_strings.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/views/controls/label.h" +#include "ui/views/layout/grid_layout.h" +#include "ui/views/widget/widget.h" +#include "ui/views/window/dialog_delegate.h" + +namespace { + +// Default width/height of the dialog. +const int kDefaultWidth = 500; +const int kDefaultHeight = 150; + +const int kPaddingToMessage = 30; +const int kInset = 40; +const int kTopInset = 10; + +//////////////////////////////////////////////////////////////////////////////// +// Dialog for multi-profiles desktop casting warning. +class DesktopCastingWarningView : public views::DialogDelegateView { + public: + explicit DesktopCastingWarningView(base::Callback<void()> on_accept); + ~DesktopCastingWarningView() override; + + static void ShowDialog(const base::Callback<void()> on_accept); + + // views::DialogDelegate overrides. + bool Accept() override; + base::string16 GetDialogButtonLabel(ui::DialogButton button) const override; + bool IsDialogButtonEnabled(ui::DialogButton button) const override; + int GetDefaultDialogButton() const override; + + // views::WidgetDelegate overrides. + ui::ModalType GetModalType() const override; + + // views::View overrides. + gfx::Size GetPreferredSize() const override; + + private: + void InitDialog(); + + const base::Callback<void()> on_switch_; + + DISALLOW_COPY_AND_ASSIGN(DesktopCastingWarningView); +}; + +// The current instance of the running dialog - or NULL. This is used for +// unittest related functions. +static DesktopCastingWarningView* instance_for_test; + +//////////////////////////////////////////////////////////////////////////////// +// DesktopCastingWarningView implementation. + +DesktopCastingWarningView::DesktopCastingWarningView( + const base::Callback<void()> on_switch) + : on_switch_(on_switch) { + DCHECK(!instance_for_test); + instance_for_test = this; +} + +DesktopCastingWarningView::~DesktopCastingWarningView() { + DCHECK(instance_for_test); + instance_for_test = NULL; +} + +// static +void DesktopCastingWarningView::ShowDialog( + const base::Callback<void()> on_accept) { + DesktopCastingWarningView* dialog_view = + new DesktopCastingWarningView(on_accept); + views::DialogDelegate::CreateDialogWidget( + dialog_view, ash::Shell::GetTargetRootWindow(), NULL); + dialog_view->InitDialog(); + views::Widget* widget = dialog_view->GetWidget(); + DCHECK(widget); + widget->Show(); +} + +bool DesktopCastingWarningView::Accept() { + // Stop screen sharing and capturing. + ash::SystemTray* system_tray = + ash::Shell::GetInstance()->GetPrimarySystemTray(); + if (system_tray->GetScreenShareItem()->is_started()) + system_tray->GetScreenShareItem()->Stop(); + if (system_tray->GetScreenCaptureItem()->is_started()) + system_tray->GetScreenCaptureItem()->Stop(); + + on_switch_.Run(); + return true; +} + +base::string16 DesktopCastingWarningView::GetDialogButtonLabel( + ui::DialogButton button) const { + return l10n_util::GetStringUTF16( + button == ui::DIALOG_BUTTON_OK + ? IDS_DESKTOP_CASTING_ACTIVE_BUTTON_SWITCH_USER + : IDS_DESKTOP_CASTING_ACTIVE_BUTTON_ABORT_USER_SWITCH); +} + +bool DesktopCastingWarningView::IsDialogButtonEnabled( + ui::DialogButton button) const { + return button == ui::DIALOG_BUTTON_OK || button == ui::DIALOG_BUTTON_CANCEL; +} + +int DesktopCastingWarningView::GetDefaultDialogButton() const { + // The default should turn off the casting. + return ui::DIALOG_BUTTON_CANCEL; +} + +ui::ModalType DesktopCastingWarningView::GetModalType() const { + return ui::MODAL_TYPE_SYSTEM; +} + +gfx::Size DesktopCastingWarningView::GetPreferredSize() const { + return gfx::Size(kDefaultWidth, kDefaultHeight); +} + +void DesktopCastingWarningView::InitDialog() { + const gfx::Insets kDialogInsets(kTopInset, kInset, kInset, kInset); + + // Create the views and layout manager and set them up. + views::GridLayout* grid_layout = views::GridLayout::CreatePanel(this); + grid_layout->SetInsets(kDialogInsets); + + views::ColumnSet* column_set = grid_layout->AddColumnSet(0); + column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, + views::GridLayout::USE_PREF, 0, 0); + + // Title + views::Label* title_label_ = new views::Label( + l10n_util::GetStringUTF16(IDS_DESKTOP_CASTING_ACTIVE_TITLE)); + title_label_->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList( + ui::ResourceBundle::MediumBoldFont)); + title_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); + grid_layout->StartRow(0, 0); + grid_layout->AddView(title_label_); + grid_layout->AddPaddingRow(0, kPaddingToMessage); + + // Explanation string + views::Label* label = new views::Label( + l10n_util::GetStringUTF16(IDS_DESKTOP_CASTING_ACTIVE_MESSAGE)); + label->SetFontList(ui::ResourceBundle::GetSharedInstance().GetFontList( + ui::ResourceBundle::MediumFont)); + label->SetMultiLine(true); + label->SetHorizontalAlignment(gfx::ALIGN_LEFT); + label->SetAllowCharacterBreak(true); + grid_layout->StartRow(0, 0); + grid_layout->AddView(label); + + SetLayoutManager(grid_layout); + Layout(); +} + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// Factory function. + +void TrySwitchingActiveUser(const base::Callback<void()> on_switch) { + // Some unit tests do not have a shell. In that case simply execute. + if (!ash::Shell::HasInstance()) { + on_switch.Run(); + return; + } + // If neither screen sharing nor capturing is going on we can immediately + // switch users. + ash::SystemTray* system_tray = + ash::Shell::GetInstance()->GetPrimarySystemTray(); + if (!system_tray->GetScreenShareItem()->is_started() && + !system_tray->GetScreenCaptureItem()->is_started()) { + on_switch.Run(); + return; + } + DesktopCastingWarningView::ShowDialog(on_switch); +} + +bool TestAndTerminateDesktopCastingWarningForTest(bool accept) { + if (!instance_for_test) + return false; + if (accept) + instance_for_test->Accept(); + delete instance_for_test->GetWidget()->GetNativeWindow(); + CHECK(!instance_for_test); + return true; +}
diff --git a/chrome/browser/ui/ash/multi_user/user_switch_util.h b/chrome/browser/ui/ash/multi_user/user_switch_util.h new file mode 100644 index 0000000..aa94d812 --- /dev/null +++ b/chrome/browser/ui/ash/multi_user/user_switch_util.h
@@ -0,0 +1,20 @@ +// 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 CHROME_BROWSER_UI_ASH_MULTI_USER_USER_SWITCH_UTIL_H_ +#define CHROME_BROWSER_UI_ASH_MULTI_USER_USER_SWITCH_UTIL_H_ + +#include "base/callback.h" + +// Tries to switch to a new user by first checking if desktop casting / sharing +// is going on, and let the user decide if he wants to terminate it or not. +// After terminating any desktop sharing operations, the |switch_user| function +// will be called. +void TrySwitchingActiveUser(const base::Callback<void()> switch_user); + +// Terminates the "DesktopCastingWarning" dialog from a unit tests and |accept|s +// it. False will be returned if there was no dialog shown. +bool TestAndTerminateDesktopCastingWarningForTest(bool accept); + +#endif // CHROME_BROWSER_UI_ASH_MULTI_USER_USER_SWITCH_UTIL_H_
diff --git a/chrome/browser/ui/ash/multi_user/user_switch_util_unittest.cc b/chrome/browser/ui/ash/multi_user/user_switch_util_unittest.cc new file mode 100644 index 0000000..4e8fba93 --- /dev/null +++ b/chrome/browser/ui/ash/multi_user/user_switch_util_unittest.cc
@@ -0,0 +1,214 @@ +// 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. + +#include "ash/common/system/chromeos/screen_security/screen_tray_item.h" +#include "ash/common/system/tray/system_tray.h" +#include "ash/test/ash_test_base.h" +#include "chrome/browser/ui/ash/multi_user/user_switch_util.h" + +namespace ash { + +class TrySwitchingUserTest : public ash::test::AshTestBase { + public: + // The action type to perform / check for upon user switching. + enum ActionType { + NO_DIALOG, // No dialog should be shown. + ACCEPT_DIALOG, // A dialog should be shown and we should accept it. + DECLINE_DIALOG, // A dialog should be shown and we do not accept it. + }; + TrySwitchingUserTest() + : capture_item_(NULL), + share_item_(NULL), + stop_capture_callback_hit_count_(0), + stop_share_callback_hit_count_(0), + switch_callback_hit_count_(0) {} + ~TrySwitchingUserTest() override {} + + void SetUp() override { + test::AshTestBase::SetUp(); + TrayItemView::DisableAnimationsForTest(); + SystemTray* system_tray = GetPrimarySystemTray(); + share_item_ = system_tray->GetScreenShareItem(); + capture_item_ = system_tray->GetScreenCaptureItem(); + EXPECT_TRUE(share_item_); + EXPECT_TRUE(capture_item_); + } + + // Accessing the capture session functionality. + // Simulates a screen capture session start. + void StartCaptureSession() { + capture_item_->Start(base::Bind(&TrySwitchingUserTest::StopCaptureCallback, + base::Unretained(this))); + } + + // The callback which gets called when the screen capture gets stopped. + void StopCaptureSession() { capture_item_->Stop(); } + + // Simulates a screen capture session stop. + void StopCaptureCallback() { stop_capture_callback_hit_count_++; } + + // Accessing the share session functionality. + // Simulate a Screen share session start. + void StartShareSession() { + share_item_->Start(base::Bind(&TrySwitchingUserTest::StopShareCallback, + base::Unretained(this))); + } + + // Simulates a screen share session stop. + void StopShareSession() { share_item_->Stop(); } + + // The callback which gets called when the screen share gets stopped. + void StopShareCallback() { stop_share_callback_hit_count_++; } + + // Issuing a switch user call which might or might not create a dialog. + // The passed |action| type parameter defines the outcome (which will be + // checked) and the action the user will choose. + void SwitchUser(ActionType action) { + TrySwitchingActiveUser(base::Bind(&TrySwitchingUserTest::SwitchCallback, + base::Unretained(this))); + switch (action) { + case NO_DIALOG: + EXPECT_TRUE(!TestAndTerminateDesktopCastingWarningForTest(true)); + return; + case ACCEPT_DIALOG: + EXPECT_TRUE(TestAndTerminateDesktopCastingWarningForTest(true)); + return; + case DECLINE_DIALOG: + EXPECT_TRUE(TestAndTerminateDesktopCastingWarningForTest(false)); + return; + } + } + + // Called when the user will get actually switched. + void SwitchCallback() { switch_callback_hit_count_++; } + + // Various counter accessors. + int stop_capture_callback_hit_count() const { + return stop_capture_callback_hit_count_; + } + int stop_share_callback_hit_count() const { + return stop_share_callback_hit_count_; + } + int switch_callback_hit_count() const { return switch_callback_hit_count_; } + + private: + // The two items from the SystemTray for the screen capture / share + // functionality. + ScreenTrayItem* capture_item_; + ScreenTrayItem* share_item_; + + // Various counters to query for. + int stop_capture_callback_hit_count_; + int stop_share_callback_hit_count_; + int switch_callback_hit_count_; + + DISALLOW_COPY_AND_ASSIGN(TrySwitchingUserTest); +}; + +// Test that when there is no screen operation going on the user switch will be +// performed as planned. +TEST_F(TrySwitchingUserTest, NoLock) { + EXPECT_EQ(0, switch_callback_hit_count()); + SwitchUser(TrySwitchingUserTest::NO_DIALOG); + EXPECT_EQ(1, switch_callback_hit_count()); +} + +// Test that with a screen capture operation going on, the user will need to +// confirm. Declining will neither change the running state or switch users. +TEST_F(TrySwitchingUserTest, CaptureActiveDeclined) { + EXPECT_EQ(0, switch_callback_hit_count()); + StartCaptureSession(); + SwitchUser(TrySwitchingUserTest::DECLINE_DIALOG); + EXPECT_EQ(0, switch_callback_hit_count()); + EXPECT_EQ(0, stop_capture_callback_hit_count()); + EXPECT_EQ(0, stop_share_callback_hit_count()); + StopCaptureSession(); + EXPECT_EQ(0, switch_callback_hit_count()); + EXPECT_EQ(1, stop_capture_callback_hit_count()); + EXPECT_EQ(0, stop_share_callback_hit_count()); +} + +// Test that with a screen share operation going on, the user will need to +// confirm. Declining will neither change the running state or switch users. +TEST_F(TrySwitchingUserTest, ShareActiveDeclined) { + EXPECT_EQ(0, switch_callback_hit_count()); + StartShareSession(); + SwitchUser(TrySwitchingUserTest::DECLINE_DIALOG); + EXPECT_EQ(0, switch_callback_hit_count()); + EXPECT_EQ(0, stop_capture_callback_hit_count()); + EXPECT_EQ(0, stop_share_callback_hit_count()); + StopShareSession(); + EXPECT_EQ(0, switch_callback_hit_count()); + EXPECT_EQ(0, stop_capture_callback_hit_count()); + EXPECT_EQ(1, stop_share_callback_hit_count()); +} + +// Test that with both operations going on, the user will need to confirm. +// Declining will neither change the running state or switch users. +TEST_F(TrySwitchingUserTest, BothActiveDeclined) { + EXPECT_EQ(0, switch_callback_hit_count()); + StartShareSession(); + StartCaptureSession(); + SwitchUser(TrySwitchingUserTest::DECLINE_DIALOG); + EXPECT_EQ(0, switch_callback_hit_count()); + EXPECT_EQ(0, stop_capture_callback_hit_count()); + EXPECT_EQ(0, stop_share_callback_hit_count()); + StopShareSession(); + StopCaptureSession(); + EXPECT_EQ(0, switch_callback_hit_count()); + EXPECT_EQ(1, stop_capture_callback_hit_count()); + EXPECT_EQ(1, stop_share_callback_hit_count()); +} + +// Test that with a screen capture operation going on, the user will need to +// confirm. Accepting will change to stopped state and switch users. +TEST_F(TrySwitchingUserTest, CaptureActiveAccepted) { + EXPECT_EQ(0, switch_callback_hit_count()); + StartCaptureSession(); + SwitchUser(TrySwitchingUserTest::ACCEPT_DIALOG); + EXPECT_EQ(1, switch_callback_hit_count()); + EXPECT_EQ(1, stop_capture_callback_hit_count()); + EXPECT_EQ(0, stop_share_callback_hit_count()); + // Another stop should have no effect. + StopCaptureSession(); + EXPECT_EQ(1, switch_callback_hit_count()); + EXPECT_EQ(1, stop_capture_callback_hit_count()); + EXPECT_EQ(0, stop_share_callback_hit_count()); +} + +// Test that with a screen share operation going on, the user will need to +// confirm. Accepting will change to stopped state and switch users. +TEST_F(TrySwitchingUserTest, ShareActiveAccepted) { + EXPECT_EQ(0, switch_callback_hit_count()); + StartShareSession(); + SwitchUser(TrySwitchingUserTest::ACCEPT_DIALOG); + EXPECT_EQ(1, switch_callback_hit_count()); + EXPECT_EQ(0, stop_capture_callback_hit_count()); + EXPECT_EQ(1, stop_share_callback_hit_count()); + // Another stop should have no effect. + StopShareSession(); + EXPECT_EQ(1, switch_callback_hit_count()); + EXPECT_EQ(0, stop_capture_callback_hit_count()); + EXPECT_EQ(1, stop_share_callback_hit_count()); +} + +// Test that with both operations going on, the user will need to confirm. +// Accepting will change to stopped state and switch users. +TEST_F(TrySwitchingUserTest, BothActiveAccepted) { + EXPECT_EQ(0, switch_callback_hit_count()); + StartShareSession(); + StartCaptureSession(); + SwitchUser(TrySwitchingUserTest::ACCEPT_DIALOG); + EXPECT_EQ(1, switch_callback_hit_count()); + EXPECT_EQ(1, stop_capture_callback_hit_count()); + EXPECT_EQ(1, stop_share_callback_hit_count()); + // Another stop should have no effect. + StopShareSession(); + StopCaptureSession(); + EXPECT_EQ(1, switch_callback_hit_count()); + EXPECT_EQ(1, stop_capture_callback_hit_count()); + EXPECT_EQ(1, stop_share_callback_hit_count()); +} + +} // namespace ash
diff --git a/chrome/browser/ui/ash/session_state_delegate_chromeos.cc b/chrome/browser/ui/ash/session_state_delegate_chromeos.cc index 08bd348..686996a3 100644 --- a/chrome/browser/ui/ash/session_state_delegate_chromeos.cc +++ b/chrome/browser/ui/ash/session_state_delegate_chromeos.cc
@@ -7,7 +7,6 @@ #include "ash/aura/wm_window_aura.h" #include "ash/common/session/session_state_observer.h" #include "ash/content/shell_content_state.h" -#include "ash/system/chromeos/multi_user/user_switch_util.h" #include "base/bind.h" #include "base/callback.h" #include "base/command_line.h" @@ -19,6 +18,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" +#include "chrome/browser/ui/ash/multi_user/user_switch_util.h" #include "chrome/browser/ui/ash/session_util.h" #include "chrome/common/pref_names.h" #include "chromeos/chromeos_switches.h" @@ -276,5 +276,5 @@ void SessionStateDelegateChromeos::TryToSwitchUser( const AccountId& account_id) { - ash::TrySwitchingActiveUser(base::Bind(&DoSwitchUser, account_id)); + TrySwitchingActiveUser(base::Bind(&DoSwitchUser, account_id)); }
diff --git a/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc b/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc index 1ba70ed..fa81d50 100644 --- a/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc +++ b/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc
@@ -24,6 +24,7 @@ #include "ash/common/system/chromeos/shutdown_policy_observer.h" #include "ash/common/system/date/clock_observer.h" #include "ash/common/system/ime/ime_observer.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/system_tray_notifier.h" #include "ash/common/system/tray_accessibility.h" @@ -33,7 +34,8 @@ #include "ash/common/wm_shell.h" #include "ash/desktop_background/desktop_background_controller.h" #include "ash/shell.h" -#include "ash/system/tray/system_tray.h" +#include "ash/system/chromeos/rotation/tray_rotation_lock.h" +#include "ash/system/chromeos/tray_display.h" #include "ash/wm/lock_state_controller.h" #include "base/bind_helpers.h" #include "base/callback.h" @@ -850,6 +852,16 @@ return vpn_delegate_.get(); } +std::unique_ptr<ash::SystemTrayItem> +SystemTrayDelegateChromeOS::CreateDisplayTrayItem(ash::SystemTray* tray) { + return base::MakeUnique<ash::TrayDisplay>(tray); +} + +std::unique_ptr<ash::SystemTrayItem> +SystemTrayDelegateChromeOS::CreateRotationLockTrayItem(ash::SystemTray* tray) { + return base::MakeUnique<ash::TrayRotationLock>(tray); +} + void SystemTrayDelegateChromeOS::UserAddedToSession( const user_manager::User* active_user) { }
diff --git a/chrome/browser/ui/ash/system_tray_delegate_chromeos.h b/chrome/browser/ui/ash/system_tray_delegate_chromeos.h index 64ba22a..ceff52b5 100644 --- a/chrome/browser/ui/ash/system_tray_delegate_chromeos.h +++ b/chrome/browser/ui/ash/system_tray_delegate_chromeos.h
@@ -13,8 +13,8 @@ #include "ash/common/accessibility_types.h" #include "ash/common/session/session_state_observer.h" #include "ash/common/system/chromeos/supervised/custodian_info_tray_observer.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" -#include "ash/system/tray/system_tray.h" #include "base/callback_forward.h" #include "base/callback_list.h" #include "base/compiler_specific.h" @@ -152,6 +152,10 @@ void ShouldRebootOnShutdown( const ash::RebootOnShutdownCallback& callback) override; ash::VPNDelegate* GetVPNDelegate() const override; + std::unique_ptr<ash::SystemTrayItem> CreateDisplayTrayItem( + ash::SystemTray* tray) override; + std::unique_ptr<ash::SystemTrayItem> CreateRotationLockTrayItem( + ash::SystemTray* tray) override; // Overridden from user_manager::UserManager::UserSessionStateObserver: void UserAddedToSession(const user_manager::User* active_user) override;
diff --git a/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_chromeos.cc b/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_chromeos.cc index 6eb3c22..46692de 100644 --- a/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_chromeos.cc +++ b/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_chromeos.cc
@@ -3,11 +3,11 @@ // found in the LICENSE file. #include "ash/common/system/cast/tray_cast.h" +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/system/tray/system_tray_item.h" #include "ash/common/wm_shell.h" #include "ash/shell.h" -#include "ash/system/tray/system_tray.h" #include "ash/test/tray_cast_test_api.h" #include "base/macros.h" #include "base/memory/ptr_util.h"
diff --git a/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc b/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc index c8966e8..660f3cb 100644 --- a/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc +++ b/chrome/browser/ui/ash/system_tray_tray_cast_browsertest_media_router_chromeos.cc
@@ -4,10 +4,10 @@ #include <vector> +#include "ash/common/system/tray/system_tray.h" #include "ash/common/system/tray/system_tray_delegate.h" #include "ash/common/wm_shell.h" #include "ash/shell.h" -#include "ash/system/tray/system_tray.h" #include "ash/test/tray_cast_test_api.h" #include "base/macros.h" #include "chrome/browser/media/router/media_routes_observer.h"
diff --git a/chrome/browser/ui/ash/volume_controller_chromeos.cc b/chrome/browser/ui/ash/volume_controller_chromeos.cc index 58e4478c..cdd310b 100644 --- a/chrome/browser/ui/ash/volume_controller_chromeos.cc +++ b/chrome/browser/ui/ash/volume_controller_chromeos.cc
@@ -4,10 +4,10 @@ #include "chrome/browser/ui/ash/volume_controller_chromeos.h" -#include "ash/audio/sounds.h" #include "ash/common/ash_switches.h" #include "base/command_line.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/extensions/api/system_private/system_private_api.h" #include "chromeos/audio/chromeos_sounds.h" #include "chromeos/chromeos_switches.h" @@ -29,8 +29,11 @@ } void PlayVolumeAdjustSound() { - if (VolumeAdjustSoundEnabled()) - ash::PlaySystemSoundIfSpokenFeedback(chromeos::SOUND_VOLUME_ADJUST); + if (VolumeAdjustSoundEnabled()) { + chromeos::AccessibilityManager::Get()->PlayEarcon( + chromeos::SOUND_VOLUME_ADJUST, + chromeos::PlaySoundOption::SPOKEN_FEEDBACK_ENABLED); + } } } // namespace
diff --git a/chrome/browser/ui/autofill/autofill_dialog_models.cc b/chrome/browser/ui/autofill/autofill_dialog_models.cc index 036e5ce..b2fbce6 100644 --- a/chrome/browser/ui/autofill/autofill_dialog_models.cc +++ b/chrome/browser/ui/autofill/autofill_dialog_models.cc
@@ -112,7 +112,7 @@ bool SuggestionsMenuModel::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; }
diff --git a/chrome/browser/ui/autofill/autofill_dialog_models.h b/chrome/browser/ui/autofill/autofill_dialog_models.h index 3b5b33d..101a1743 100644 --- a/chrome/browser/ui/autofill/autofill_dialog_models.h +++ b/chrome/browser/ui/autofill/autofill_dialog_models.h
@@ -85,7 +85,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; private:
diff --git a/chrome/browser/ui/bluetooth/bluetooth_chooser_controller.cc b/chrome/browser/ui/bluetooth/bluetooth_chooser_controller.cc index 447778f1..173fc1884 100644 --- a/chrome/browser/ui/bluetooth/bluetooth_chooser_controller.cc +++ b/chrome/browser/ui/bluetooth/bluetooth_chooser_controller.cc
@@ -29,10 +29,18 @@ BluetoothChooserController::BluetoothChooserController( content::RenderFrameHost* owner, const content::BluetoothChooser::EventHandler& event_handler) - : ChooserController(owner), event_handler_(event_handler) {} + : ChooserController(owner, + IDS_BLUETOOTH_DEVICE_CHOOSER_PROMPT_ORIGIN, + IDS_BLUETOOTH_DEVICE_CHOOSER_PROMPT_EXTENSION_NAME), + event_handler_(event_handler) {} BluetoothChooserController::~BluetoothChooserController() {} +base::string16 BluetoothChooserController::GetOkButtonLabel() const { + return l10n_util::GetStringUTF16( + IDS_BLUETOOTH_DEVICE_CHOOSER_PAIR_BUTTON_TEXT); +} + size_t BluetoothChooserController::NumOptions() const { return device_names_and_ids_.size(); }
diff --git a/chrome/browser/ui/bluetooth/bluetooth_chooser_controller.h b/chrome/browser/ui/bluetooth/bluetooth_chooser_controller.h index 0ec12e9..deb2caa 100644 --- a/chrome/browser/ui/bluetooth/bluetooth_chooser_controller.h +++ b/chrome/browser/ui/bluetooth/bluetooth_chooser_controller.h
@@ -28,6 +28,7 @@ ~BluetoothChooserController() override; // ChooserController: + base::string16 GetOkButtonLabel() const override; size_t NumOptions() const override; base::string16 GetOption(size_t index) const override; void Select(size_t index) override;
diff --git a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc index cb8461f..d05b36e 100644 --- a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc +++ b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.cc
@@ -434,7 +434,7 @@ bool BookmarkContextMenuController::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; }
diff --git a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.h b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.h index 274cdd0..c020f733 100644 --- a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.h +++ b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller.h
@@ -68,7 +68,7 @@ bool IsCommandIdEnabled(int command_id) const override; bool IsCommandIdVisible(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; bool IsItemForCommandIdDynamic(int command_id) const override; base::string16 GetLabelForCommandId(int command_id) const override;
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 0e77ef3b..3951954 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -68,6 +68,7 @@ #include "chrome/browser/memory/tab_manager_web_contents_data.h" #include "chrome/browser/notifications/notification_ui_manager.h" #include "chrome/browser/pepper_broker_infobar_delegate.h" +#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_destroyer.h" @@ -143,7 +144,6 @@ #include "chrome/browser/ui/unload_controller.h" #include "chrome/browser/ui/validation_message_bubble.h" #include "chrome/browser/ui/website_settings/chooser_bubble_delegate.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" #include "chrome/browser/ui/webui/signin/login_ui_service.h" #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" #include "chrome/browser/ui/window_sizer/window_sizer.h" @@ -1763,10 +1763,10 @@ window_->GetLocationBar()->UpdateContentSettingsIcons(); } - PermissionBubbleManager* bubble_manager = - PermissionBubbleManager::FromWebContents(web_contents); - if (bubble_manager) { - bubble_manager->AddRequest( + PermissionRequestManager* permission_request_manager = + PermissionRequestManager::FromWebContents(web_contents); + if (permission_request_manager) { + permission_request_manager->AddRequest( new RegisterProtocolHandlerPermissionRequest(registry, handler, url, user_gesture)); }
diff --git a/chrome/browser/ui/browser_instant_controller.cc b/chrome/browser/ui/browser_instant_controller.cc index 1a95c98..08b8d6f 100644 --- a/chrome/browser/ui/browser_instant_controller.cc +++ b/chrome/browser/ui/browser_instant_controller.cc
@@ -154,8 +154,6 @@ } void BrowserInstantController::TabDeactivated(content::WebContents* contents) { - instant_.TabDeactivated(contents); - InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer(profile()); if (prerenderer)
diff --git a/chrome/browser/ui/browser_ui_prefs.cc b/chrome/browser/ui/browser_ui_prefs.cc index 0d26df60..d583627b 100644 --- a/chrome/browser/ui/browser_ui_prefs.cc +++ b/chrome/browser/ui/browser_ui_prefs.cc
@@ -49,36 +49,28 @@ registry->RegisterBooleanPref(prefs::kShowHomeButton, false, GetHomeButtonAndHomePageIsNewTabPageFlags()); registry->RegisterBooleanPref( - prefs::kDeleteBrowsingHistory, - true, + browsing_data::prefs::kDeleteBrowsingHistory, true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterBooleanPref( - prefs::kDeleteDownloadHistory, - true, + browsing_data::prefs::kDeleteDownloadHistory, true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterBooleanPref( - prefs::kDeleteCache, - true, + browsing_data::prefs::kDeleteCache, true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterBooleanPref( - prefs::kDeleteCookies, - true, + browsing_data::prefs::kDeleteCookies, true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterBooleanPref( - prefs::kDeletePasswords, - false, + browsing_data::prefs::kDeletePasswords, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterBooleanPref( - prefs::kDeleteFormData, - false, + browsing_data::prefs::kDeleteFormData, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterBooleanPref( - prefs::kDeleteHostedAppsData, - false, + browsing_data::prefs::kDeleteHostedAppsData, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterBooleanPref( - prefs::kDeleteMediaLicenses, - false, + browsing_data::prefs::kDeleteMediaLicenses, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterIntegerPref( browsing_data::prefs::kDeleteTimePeriod, 0,
diff --git a/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm b/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm index 36818e2..bc4f35f 100644 --- a/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm +++ b/chrome/browser/ui/cocoa/app_menu/app_menu_controller.mm
@@ -79,8 +79,9 @@ // A C++ delegate that handles the accelerators in the app menu. class AcceleratorDelegate : public ui::AcceleratorProvider { public: - bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* out_accelerator) override { + bool GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* out_accelerator) const override { AcceleratorsCocoa* keymap = AcceleratorsCocoa::GetInstance(); const ui::Accelerator* accelerator = keymap->GetAcceleratorForCommand(command_id);
diff --git a/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.h b/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.h index 850e275..e8dffcb 100644 --- a/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.h +++ b/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.h
@@ -72,7 +72,7 @@ // ui::AcceleratorProvider: bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; // ExclusiveAccessBubbleViewsContext: ExclusiveAccessManager* GetExclusiveAccessManager() override;
diff --git a/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.mm b/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.mm index a3498ae..75f67caf 100644 --- a/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.mm +++ b/chrome/browser/ui/cocoa/browser/exclusive_access_controller_views.mm
@@ -154,7 +154,7 @@ bool ExclusiveAccessController::GetAcceleratorForCommandId( int cmd_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { *accelerator = *AcceleratorsCocoa::GetInstance()->GetAcceleratorForCommand(cmd_id); return true;
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm index 0f9b729..fe57b6095 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -21,6 +21,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/extensions/extension_commands_global_registry.h" +#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/profiles/avatar_menu.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_attributes_storage.h" @@ -77,7 +78,6 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" #include "chrome/browser/ui/translate/translate_bubble_model_impl.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" #include "chrome/browser/ui/window_sizer/window_sizer.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/command.h" @@ -1016,15 +1016,15 @@ - (void)onActiveTabChanged:(content::WebContents*)oldContents to:(content::WebContents*)newContents { // No need to remove previous bubble. It will close itself. - PermissionBubbleManager* manager(nullptr); + PermissionRequestManager* manager(nullptr); if (oldContents) { - manager = PermissionBubbleManager::FromWebContents(oldContents); + manager = PermissionRequestManager::FromWebContents(oldContents); if (manager) manager->HideBubble(); } if (newContents) { - manager = PermissionBubbleManager::FromWebContents(newContents); + manager = PermissionRequestManager::FromWebContents(newContents); if (manager) manager->DisplayPendingRequests(); } @@ -1634,7 +1634,7 @@ } - (void)dismissPermissionBubble { - PermissionBubbleManager* manager = [self permissionBubbleManager]; + PermissionRequestManager* manager = [self permissionRequestManager]; if (manager) manager->HideBubble(); }
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.h b/chrome/browser/ui/cocoa/browser_window_controller_private.h index 61a96e86..d754669 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_private.h +++ b/chrome/browser/ui/cocoa/browser_window_controller_private.h
@@ -10,7 +10,7 @@ #import "chrome/browser/ui/cocoa/fullscreen_toolbar_controller.h" @class BrowserWindowLayout; -class PermissionBubbleManager; +class PermissionRequestManager; namespace content { class WebContents; @@ -176,7 +176,7 @@ - (void)resetCustomAppKitFullscreenVariables; - (content::WebContents*)webContents; -- (PermissionBubbleManager*)permissionBubbleManager; +- (PermissionRequestManager*)permissionRequestManager; // Hides or unhides any displayed modal sheet for fullscreen transition. // Modal sheets should be hidden at the beginning and then shown at the end.
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.mm b/chrome/browser/ui/cocoa/browser_window_controller_private.mm index 0eba308..bc844c8 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller_private.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
@@ -15,6 +15,7 @@ #import "base/mac/sdk_forward_declarations.h" #include "base/metrics/histogram.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_avatar_icon_util.h" #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h" @@ -45,7 +46,6 @@ #import "chrome/browser/ui/cocoa/website_settings/permission_bubble_cocoa.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" #include "chrome/common/chrome_switches.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" @@ -268,7 +268,7 @@ // Will update the location of the permission bubble when showing/hiding the // top level toolbar in fullscreen. - PermissionBubbleManager* manager = [self permissionBubbleManager]; + PermissionRequestManager* manager = [self permissionRequestManager]; if (manager) manager->UpdateAnchorPosition(); @@ -421,7 +421,7 @@ statusBubble_->SwitchParentWindow(destWindow); // Updates the bubble position. - PermissionBubbleManager* manager = [self permissionBubbleManager]; + PermissionRequestManager* manager = [self permissionRequestManager]; if (manager) manager->UpdateAnchorPosition(); @@ -468,7 +468,7 @@ BOOL showDropdown = !fullscreenForTab && !kioskMode && ([self floatingBarHasFocus]); - PermissionBubbleManager* manager = [self permissionBubbleManager]; + PermissionRequestManager* manager = [self permissionRequestManager]; if (manager && manager->IsBubbleVisible()) { NSWindow* bubbleWindow = manager->GetBubbleWindow(); DCHECK(bubbleWindow); @@ -815,7 +815,7 @@ [self resetCustomAppKitFullscreenVariables]; // Ensures that the permission bubble shows up properly at the front. - PermissionBubbleManager* manager = [self permissionBubbleManager]; + PermissionRequestManager* manager = [self permissionRequestManager]; if (manager && manager->IsBubbleVisible()) { NSWindow* bubbleWindow = manager->GetBubbleWindow(); DCHECK(bubbleWindow); @@ -1274,9 +1274,9 @@ return browser_->tab_strip_model()->GetActiveWebContents(); } -- (PermissionBubbleManager*)permissionBubbleManager { +- (PermissionRequestManager*)permissionRequestManager { if (WebContents* contents = [self webContents]) - return PermissionBubbleManager::FromWebContents(contents); + return PermissionRequestManager::FromWebContents(contents); return nil; }
diff --git a/chrome/browser/ui/cocoa/chooser_content_view_cocoa.mm b/chrome/browser/ui/cocoa/chooser_content_view_cocoa.mm index 73a7379f..d97c3ef 100644 --- a/chrome/browser/ui/cocoa/chooser_content_view_cocoa.mm +++ b/chrome/browser/ui/cocoa/chooser_content_view_cocoa.mm
@@ -264,7 +264,7 @@ - (base::scoped_nsobject<NSButton>)createConnectButton { NSString* connectTitle = - l10n_util::GetNSString(IDS_DEVICE_CHOOSER_CONNECT_BUTTON_TEXT); + base::SysUTF16ToNSString(chooserController_->GetOkButtonLabel()); return [self createButtonWithTitle:connectTitle]; }
diff --git a/chrome/browser/ui/cocoa/extensions/chooser_dialog_cocoa_controller.mm b/chrome/browser/ui/cocoa/extensions/chooser_dialog_cocoa_controller.mm index 668929e1..0ef8a21 100644 --- a/chrome/browser/ui/cocoa/extensions/chooser_dialog_cocoa_controller.mm +++ b/chrome/browser/ui/cocoa/extensions/chooser_dialog_cocoa_controller.mm
@@ -5,17 +5,9 @@ #import "chrome/browser/ui/cocoa/extensions/chooser_dialog_cocoa_controller.h" #include "base/strings/sys_string_conversions.h" -#include "base/strings/utf_string_conversions.h" #include "chrome/browser/chooser_controller/chooser_controller.h" #import "chrome/browser/ui/cocoa/chooser_content_view_cocoa.h" #import "chrome/browser/ui/cocoa/extensions/chooser_dialog_cocoa.h" -#include "chrome/grit/generated_resources.h" -#include "components/url_formatter/elide_url.h" -#include "content/public/browser/web_contents.h" -#include "extensions/browser/extension_registry.h" -#import "ui/base/l10n/l10n_util_mac.h" -#include "url/gurl.h" -#include "url/origin.h" @implementation ChooserDialogCocoaController @@ -28,28 +20,9 @@ if ((self = [super init])) chooserDialogCocoa_ = chooserDialogCocoa; - base::string16 chooserTitle; - url::Origin origin = chooserController->GetOrigin(); - content::WebContents* web_contents = chooserDialogCocoa_->web_contents(); - content::BrowserContext* browser_context = web_contents->GetBrowserContext(); - extensions::ExtensionRegistry* extension_registry = - extensions::ExtensionRegistry::Get(browser_context); - if (extension_registry) { - const extensions::Extension* extension = - extension_registry->enabled_extensions().GetExtensionOrAppByURL( - GURL(origin.Serialize())); - if (extension) - chooserTitle = base::UTF8ToUTF16(extension->name()); - } - - if (chooserTitle.empty()) { - chooserTitle = url_formatter::FormatOriginForSecurityDisplay( - origin, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC); - } - + base::string16 chooserTitle = chooserController->GetTitle(); chooserContentView_.reset([[ChooserContentViewCocoa alloc] - initWithChooserTitle:l10n_util::GetNSStringF(IDS_DEVICE_CHOOSER_PROMPT, - chooserTitle) + initWithChooserTitle:base::SysUTF16ToNSString(chooserTitle) chooserController:std::move(chooserController)]); tableView_ = [chooserContentView_ tableView];
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm index 2090139a..4738732 100644 --- a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm +++ b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
@@ -93,178 +93,6 @@ } // namespace -// A temporary class that draws hardcoded HTTP graphic icons for Material -// design. This class will be removed once the Material icons are available -// in M53. -@interface LocationBarImageRep : NSCustomImageRep -@property(assign, nonatomic) gfx::VectorIconId iconId; -@property(retain, nonatomic) NSColor* fillColor; - -+ (NSImage*)imageForId:(gfx::VectorIconId)vectorIconId - color:(SkColor)vectorIconColor; - -// NSCustomImageRep delegate method that performs the drawing. -+ (void)drawLocationBarIcon:(LocationBarImageRep*)imageRep; - -@end - -@implementation LocationBarImageRep - -@synthesize iconId = iconId_; -@synthesize fillColor = fillColor_; - -- (void)dealloc { - [fillColor_ release]; - [super dealloc]; -} - -+ (NSImage*)imageForId:(gfx::VectorIconId)vectorIconId - color:(SkColor)vectorIconColor { - if (vectorIconId != gfx::VectorIconId::LOCATION_BAR_HTTP && - vectorIconId != gfx::VectorIconId::LOCATION_BAR_HTTPS_INVALID && - vectorIconId != gfx::VectorIconId::LOCATION_BAR_HTTPS_VALID) { - return NSImageFromImageSkiaWithColorSpace( - gfx::CreateVectorIcon(vectorIconId, kDefaultIconSize, vectorIconColor), - base::mac::GetSRGBColorSpace()); - } - - base::scoped_nsobject<LocationBarImageRep> imageRep( - [[LocationBarImageRep alloc] - initWithDrawSelector:@selector(drawLocationBarIcon:) - delegate:[LocationBarImageRep class]]); - [imageRep setIconId:vectorIconId]; - [imageRep setFillColor:skia::SkColorToSRGBNSColor(vectorIconColor)]; - - // Create the image from the image rep. - const NSSize kImageSize = NSMakeSize(kDefaultIconSize, kDefaultIconSize); - NSImage* locationBarImage = - [[[NSImage alloc] initWithSize:kImageSize] autorelease]; - [locationBarImage setCacheMode:NSImageCacheAlways]; - [locationBarImage addRepresentation:imageRep]; - - return locationBarImage; -} - -+ (void)drawLocationBarIcon:(LocationBarImageRep*)imageRep { - [[imageRep fillColor] set]; - - // Determine the scale factor. - CGContextRef context = static_cast<CGContextRef>( - [[NSGraphicsContext currentContext] graphicsPort]); - CGRect unitRect = CGRectMake(0.0, 0.0, 1.0, 1.0); - CGRect deviceRect = CGContextConvertRectToDeviceSpace(context, unitRect); - int scaleFactor = deviceRect.size.height; - - switch ([imageRep iconId]) { - case gfx::VectorIconId::LOCATION_BAR_HTTP: - [self drawLocationBarIconHTTPForScale:scaleFactor]; - break; - case gfx::VectorIconId::LOCATION_BAR_HTTPS_INVALID: - [self drawLocationBarIconHTTPSInvalidForScale:scaleFactor]; - break; - case gfx::VectorIconId::LOCATION_BAR_HTTPS_VALID: - [self drawLocationBarIconHTTPSValidForScale:scaleFactor]; - break; - default: - // Make it obvious that there's a problem. - [[NSColor redColor] set]; - NSRectFill(NSMakeRect(0, 0, kDefaultIconSize, kDefaultIconSize)); - break; - } -} - -+ (void)drawLocationBarIconHTTPForScale:(int)scaleFactor { - if (scaleFactor > 1) { - NSRect ovalRect = NSMakeRect(2.25, 1.75, 12, 12); - NSBezierPath* circlePath = - [NSBezierPath bezierPathWithOvalInRect:ovalRect]; - [circlePath setLineWidth:1.5]; - [circlePath stroke]; - - NSRectFill(NSMakeRect(7.5, 4.5, 1.5, 4)); - NSRectFill(NSMakeRect(7.5, 9.5, 1.5, 1.5)); - } else { - NSRect ovalRect = NSMakeRect(2, 2, 12, 12); - NSBezierPath* circlePath = - [NSBezierPath bezierPathWithOvalInRect:ovalRect]; - [circlePath setLineWidth:1.5]; - [circlePath stroke]; - - NSRectFill(NSMakeRect(7, 4, 2, 5)); - NSRectFill(NSMakeRect(7, 10, 2, 2)); - } -} - -+ (void)drawLocationBarIconHTTPSInvalidForScale:(int)scaleFactor { - // The vector icon is upside down relative to the default OS X coordinate - // system so rotate by 180 degrees. - CGContextRef context = static_cast<CGContextRef>( - [[NSGraphicsContext currentContext] graphicsPort]); - const int kHalfDefaultIconSize = kDefaultIconSize / 2; - CGContextTranslateCTM(context, kHalfDefaultIconSize, kHalfDefaultIconSize); - CGContextRotateCTM(context, M_PI); - CGContextTranslateCTM(context, -kHalfDefaultIconSize, -kHalfDefaultIconSize); - - // If Retina, nudge the icon up 1/2pt. - if (scaleFactor == 2) { - CGContextTranslateCTM(context, 0, -0.5); - } - - NSBezierPath* trianglePath = [NSBezierPath bezierPath]; - [trianglePath moveToPoint:NSMakePoint(0.5f, 14)]; - [trianglePath relativeLineToPoint:NSMakePoint(15, 0)]; - [trianglePath lineToPoint:NSMakePoint(8, 1)]; - [trianglePath closePath]; - - NSBezierPath* cutOutPath = [NSBezierPath bezierPath]; - [cutOutPath moveToPoint:NSMakePoint(9, 12)]; - [cutOutPath relativeLineToPoint:NSMakePoint(-2, 0)]; - [cutOutPath relativeLineToPoint:NSMakePoint(0, -2)]; - [cutOutPath relativeLineToPoint:NSMakePoint(2, 0)]; - [cutOutPath relativeLineToPoint:NSMakePoint(0, 2)]; - [cutOutPath closePath]; - [cutOutPath relativeMoveToPoint:NSMakePoint(0, -3)]; - [cutOutPath relativeLineToPoint:NSMakePoint(-2, 0)]; - [cutOutPath relativeLineToPoint:NSMakePoint(0, -3)]; - [cutOutPath relativeLineToPoint:NSMakePoint(2, 0)]; - [cutOutPath relativeLineToPoint:NSMakePoint(0, 3)]; - [cutOutPath closePath]; - - [trianglePath appendBezierPath:cutOutPath]; - [trianglePath fill]; -} - -+ (void)drawLocationBarIconHTTPSValidForScale:(int)scaleFactor { - NSAffineTransform* transform = [NSAffineTransform transform]; - // Adjust down 1px in Retina, so that the lock sits on the text baseline. - if (scaleFactor > 1) { - [transform translateXBy:0 yBy:-0.5]; - } - - NSBezierPath* rectPath = - [NSBezierPath bezierPathWithRoundedRect:NSMakeRect(4, 3, 8, 7) - xRadius:1 - yRadius:1]; - [rectPath transformUsingAffineTransform:transform]; - [rectPath fill]; - - NSBezierPath* curvePath = [NSBezierPath bezierPath]; - [curvePath moveToPoint:NSMakePoint(5.5, 9.75)]; - [curvePath lineToPoint:NSMakePoint(5.5, 10)]; - [curvePath curveToPoint:NSMakePoint(8, 13) - controlPoint1:NSMakePoint(5.5, 13) - controlPoint2:NSMakePoint(7.5, 13)]; - [curvePath curveToPoint:NSMakePoint(10.5, 10) - controlPoint1:NSMakePoint(8.5, 13) - controlPoint2:NSMakePoint(10.5, 13)]; - [curvePath lineToPoint:NSMakePoint(10.5, 9.75)]; - [curvePath setLineWidth:1.25]; - [curvePath transformUsingAffineTransform:transform]; - [curvePath stroke]; -} - -@end - // TODO(shess): This code is mostly copied from the gtk // implementation. Make sure it's all appropriate and flesh it out. @@ -767,9 +595,10 @@ vector_icon_color = kMaterialDarkVectorIconColor; DCHECK(vector_icon_id != gfx::VectorIconId::VECTOR_ICON_NONE); - NSImage* image = - [LocationBarImageRep imageForId:vector_icon_id color:vector_icon_color]; - + NSImage* image = NSImageFromImageSkiaWithColorSpace( + gfx::CreateVectorIcon(vector_icon_id, kDefaultIconSize, + vector_icon_color), + base::mac::GetSRGBColorSpace()); location_icon_decoration_->SetImage(image); ev_bubble_decoration_->SetImage(image); Layout();
diff --git a/chrome/browser/ui/cocoa/passwords/signin_promo_view_controller.mm b/chrome/browser/ui/cocoa/passwords/signin_promo_view_controller.mm index 769992b..83ceb3c 100644 --- a/chrome/browser/ui/cocoa/passwords/signin_promo_view_controller.mm +++ b/chrome/browser/ui/cocoa/passwords/signin_promo_view_controller.mm
@@ -9,6 +9,7 @@ #import "chrome/browser/ui/cocoa/hover_close_button.h" #include "chrome/browser/ui/cocoa/passwords/passwords_bubble_utils.h" #include "chrome/browser/ui/passwords/manage_passwords_bubble_model.h" +#include "content/public/browser/user_metrics.h" #include "grit/generated_resources.h" #import "ui/base/cocoa/controls/hyperlink_text_view.h" #include "ui/base/l10n/l10n_util_mac.h" @@ -99,6 +100,8 @@ [_closeButton setFrameOrigin:closeButtonOrigin]; [view setFrame:NSMakeRect(0, 0, kDesiredBubbleWidth, height)]; [self setView:view]; + content::RecordAction( + base::UserMetricsAction("Signin_Impression_FromPasswordBubble")); } - (void)onSignInClicked:(id)sender {
diff --git a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.h b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.h index 94b9fd9f..ef790db 100644 --- a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.h +++ b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.h
@@ -34,7 +34,7 @@ protected: // RenderViewContextMenu implementation. bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void AppendPlatformEditableItems() override; private:
diff --git a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm index 21963a0..833b3317 100644 --- a/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm +++ b/chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac.mm
@@ -333,7 +333,7 @@ bool RenderViewContextMenuMac::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; }
diff --git a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h index d729f79..3801260 100644 --- a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h +++ b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h
@@ -20,10 +20,9 @@ // display of the WebContents view. // // Client code that inserts [controller view] into the view hierarchy needs to -// beforehand call the |-ensureContentsSizeDoesNotChange| method. This will -// avoid multiple resize messages being sent to the renderer and triggering -// redundant and costly layouts. After the view has been inserted, client code -// calls |-ensureContentsVisible| to display the WebContents view. +// call -ensureContentsVisibleInSuperview:(NSView*)superview to match the +// container to the [superview bounds] and avoid multiple resize messages being +// sent to the renderer, which triggers redundant and costly layouts. // // AutoEmbedFullscreen mode: When enabled, TabContentsController will observe // for WebContents fullscreen changes and automatically swap the normal @@ -57,15 +56,10 @@ // Create the contents of a tab represented by |contents|. - (id)initWithContents:(content::WebContents*)contents isPopup:(BOOL)popup; -// Call when the container view owned by TabContentsController is about to be -// resized and inserted into the view hierarchy, so as to not trigger -// unnecessary content re-layout. -- (void)ensureContentsSizeDoesNotChange; - -// Call after the container view is inserted into the view hierarchy and -// properly sized. Then, this method will select either the WebContents view or -// the fullscreen view and swap it into the view hierarchy for display. -- (void)ensureContentsVisible; +// Call to insert the container view into the view hierarchy, sizing it to match +// |superview|. Then, this method will select either the WebContents view or +// the fullscreen view and swap it into the container for display. +- (void)ensureContentsVisibleInSuperview:(NSView*)superview; // Called after we enter fullscreen to ensure that the fullscreen widget will // have the right frame.
diff --git a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm index 706f370..5bf3298 100644 --- a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm +++ b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
@@ -71,9 +71,9 @@ @interface TabContentsController (TabContentsContainerViewDelegate) - (BOOL)contentsInFullscreenCaptureMode; -// Computes and returns the frame to use for the contents view within the -// container view. -- (NSRect)frameForContentsView; +// Computes and returns the frame to use for the contents view using the size of +// |container| as the target size. +- (NSRect)frameForContentsViewIn:(NSView*)container; // Returns YES if the content view should be resized. - (BOOL)shouldResizeContentView; @@ -130,7 +130,7 @@ } ScopedCAActionDisabler disabler; - [contentsView setFrame:[delegate_ frameForContentsView]]; + [contentsView setFrame:[delegate_ frameForContentsViewIn:self]]; } // Update the background layer's color whenever the view needs to repaint. @@ -217,18 +217,10 @@ [self setView:view]; } -- (void)ensureContentsSizeDoesNotChange { - NSView* contentsContainer = [self view]; - NSArray* subviews = [contentsContainer subviews]; - if ([subviews count] > 0) { - NSView* currentSubview = [subviews objectAtIndex:0]; - [currentSubview setAutoresizingMask:NSViewNotSizable]; - } -} - -- (void)ensureContentsVisible { +- (void)ensureContentsVisibleInSuperview:(NSView*)superview { if (!contents_) return; + ScopedCAActionDisabler disabler; NSView* contentsContainer = [self view]; NSArray* subviews = [contentsContainer subviews]; @@ -244,7 +236,7 @@ } if ([self shouldResizeContentView]) - [contentsNativeView setFrame:[self frameForContentsView]]; + [contentsNativeView setFrame:[self frameForContentsViewIn:superview]]; if ([subviews count] == 0) { [contentsContainer addSubview:contentsNativeView]; @@ -252,6 +244,10 @@ [contentsContainer replaceSubview:[subviews objectAtIndex:0] with:contentsNativeView]; } + + [contentsNativeView setAutoresizingMask:NSViewNotSizable]; + [contentsContainer setFrame:[superview bounds]]; + [superview addSubview:contentsContainer]; [contentsNativeView setAutoresizingMask:NSViewWidthSizable| NSViewHeightSizable]; @@ -276,8 +272,10 @@ content::RenderWidgetHostView* const fullscreenView = contents_->GetFullscreenRenderWidgetHostView(); - if (fullscreenView) - [fullscreenView->GetNativeView() setFrame:[self frameForContentsView]]; + if (fullscreenView) { + [fullscreenView->GetNativeView() + setFrame:[self frameForContentsViewIn:[self view]]]; + } } - (void)changeWebContents:(WebContents*)newContents { @@ -329,14 +327,14 @@ // the view is different. if ([self webContents] != updatedContents) { [self changeWebContents:updatedContents]; - [self ensureContentsVisible]; + [self ensureContentsVisibleInSuperview:[[self view] superview]]; } } - (void)toggleFullscreenWidget:(BOOL)enterFullscreen { isEmbeddingFullscreenWidget_ = enterFullscreen && contents_ && contents_->GetFullscreenRenderWidgetHostView(); - [self ensureContentsVisible]; + [self ensureContentsVisibleInSuperview:[[self view] superview]]; } - (BOOL)contentsInFullscreenCaptureMode { @@ -353,11 +351,8 @@ return YES; } -- (NSRect)frameForContentsView { - const NSSize containerSize = [[self view] frame].size; - gfx::Rect rect; - rect.set_width(containerSize.width); - rect.set_height(containerSize.height); +- (NSRect)frameForContentsViewIn:(NSView*)container { + gfx::Rect rect([container bounds]); // In most cases, the contents view is simply sized to fill the container // view's bounds. Only WebContentses that are in fullscreen mode and being
diff --git a/chrome/browser/ui/cocoa/tabs/tab_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_controller.mm index eb31514..224ef9b7 100644 --- a/chrome/browser/ui/cocoa/tabs/tab_controller.mm +++ b/chrome/browser/ui/cocoa/tabs/tab_controller.mm
@@ -48,7 +48,7 @@ return [target_ isCommandEnabled:command forController:owner_]; } bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override { + ui::Accelerator* accelerator) const override { return false; } void ExecuteCommand(int command_id, int event_flags) override {
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm index 44d1d98..3a19757 100644 --- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm +++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
@@ -580,43 +580,22 @@ // positions. ScopedCAActionDisabler ca_disabler; - // Resize the new view to fit the window. Calling |view| may lazily - // instantiate the TabContentsController from the nib. Until we call - // |-ensureContentsVisible|, the controller doesn't install the RWHVMac into - // the view hierarchy. This is in order to avoid sending the renderer a - // spurious default size loaded from the nib during the call to |-view|. - NSView* newView = [controller view]; + // Ensure the nib is loaded. Sizing won't occur until it's added to the view + // hierarchy with -ensureContentsVisibleInSuperview:. + [controller view]; - // Turns content autoresizing off, so removing and inserting views won't - // trigger unnecessary content relayout. - [controller ensureContentsSizeDoesNotChange]; + // Remove the old view from the view hierarchy to suppress resizes. We know + // there's only one child of |switchView_| because we're the one who put it + // there. There may not be any children in the case of a tab that's been + // closed, in which case there's nothing removed. + [[[switchView_ subviews] firstObject] removeFromSuperview]; - // Remove the old view from the view hierarchy. We know there's only one - // child of |switchView_| because we're the one who put it there. There - // may not be any children in the case of a tab that's been closed, in - // which case there's no swapping going on. - NSArray* subviews = [switchView_ subviews]; - if ([subviews count]) { - NSView* oldView = [subviews objectAtIndex:0]; - // Set newView frame to the oldVew frame to prevent NSSplitView hosting - // sidebar and tab content from resizing sidebar's content view. - // ensureContentsVisible (see below) sets content size and autoresizing - // properties. - [newView setFrame:[oldView frame]]; - // Remove the old view first, to ensure ConstrainedWindowSheets keyed to the - // old WebContents are removed before adding new ones. - [oldView removeFromSuperview]; - [switchView_ addSubview:newView]; - } else { - [newView setFrame:[switchView_ bounds]]; - [switchView_ addSubview:newView]; - } - - // New content is in place, delegate should adjust itself accordingly. + // Prepare the container with any infobars or docked devtools it wants. [delegate_ onActivateTabWithContents:[controller webContents]]; - // It also restores content autoresizing properties. - [controller ensureContentsVisible]; + // Sizes the WebContents to match the possibly updated size of |switchView_|, + // then adds it and starts auto-resizing again. + [controller ensureContentsVisibleInSuperview:switchView_]; } // Create a new tab view and set its cell correctly so it draws the way we want
diff --git a/chrome/browser/ui/cocoa/website_settings/chooser_bubble_ui_cocoa.mm b/chrome/browser/ui/cocoa/website_settings/chooser_bubble_ui_cocoa.mm index 2e89087a..8ee3153 100644 --- a/chrome/browser/ui/cocoa/website_settings/chooser_bubble_ui_cocoa.mm +++ b/chrome/browser/ui/cocoa/website_settings/chooser_bubble_ui_cocoa.mm
@@ -11,7 +11,7 @@ #include "base/mac/scoped_nsobject.h" #include "base/memory/ptr_util.h" -#include "base/strings/utf_string_conversions.h" +#include "base/strings/sys_string_conversions.h" #include "chrome/browser/chooser_controller/chooser_controller.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" @@ -23,15 +23,10 @@ #import "chrome/browser/ui/cocoa/info_bubble_window.h" #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h" #include "chrome/browser/ui/website_settings/chooser_bubble_delegate.h" -#include "chrome/grit/generated_resources.h" #include "components/bubble/bubble_controller.h" -#include "components/url_formatter/elide_url.h" #include "content/public/browser/native_web_keyboard_event.h" #include "ui/base/cocoa/cocoa_base_utils.h" #include "ui/base/cocoa/window_size_constants.h" -#include "ui/base/l10n/l10n_util_mac.h" -#include "url/gurl.h" -#include "url/origin.h" std::unique_ptr<BubbleUi> ChooserBubbleDelegate::BuildBubbleUi() { return base::WrapUnique( @@ -120,13 +115,9 @@ name:NSWindowDidMoveNotification object:[self getExpectedParentWindow]]; - url::Origin origin = chooserController->GetOrigin(); + base::string16 chooserTitle = chooserController->GetTitle(); chooserContentView_.reset([[ChooserContentViewCocoa alloc] - initWithChooserTitle: - l10n_util::GetNSStringF( - IDS_DEVICE_CHOOSER_PROMPT, - url_formatter::FormatOriginForSecurityDisplay( - origin, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC)) + initWithChooserTitle:base::SysUTF16ToNSString(chooserTitle) chooserController:std::move(chooserController)]); tableView_ = [chooserContentView_ tableView];
diff --git a/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm b/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm index 6067243..d29878d43 100644 --- a/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm +++ b/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller.mm
@@ -623,7 +623,7 @@ previousContents:(content::WebContents*)oldContents atIndex:(NSInteger)index reason:(int)reason { - // The show/hide of this bubble is handled by the PermissionBubbleManager. + // The show/hide of this bubble is handled by the PermissionRequestManager. // So bypass the base class, which would close the bubble here. }
diff --git a/chrome/browser/ui/content_settings/content_setting_media_menu_model.cc b/chrome/browser/ui/content_settings/content_setting_media_menu_model.cc index 1b7cc3f..87c214e 100644 --- a/chrome/browser/ui/content_settings/content_setting_media_menu_model.cc +++ b/chrome/browser/ui/content_settings/content_setting_media_menu_model.cc
@@ -47,7 +47,7 @@ bool ContentSettingMediaMenuModel::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; }
diff --git a/chrome/browser/ui/content_settings/content_setting_media_menu_model.h b/chrome/browser/ui/content_settings/content_setting_media_menu_model.h index f2bfb30..280ae7b 100644 --- a/chrome/browser/ui/content_settings/content_setting_media_menu_model.h +++ b/chrome/browser/ui/content_settings/content_setting_media_menu_model.h
@@ -35,7 +35,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; private:
diff --git a/chrome/browser/ui/exclusive_access/flash_fullscreen_interactive_browsertest.cc b/chrome/browser/ui/exclusive_access/flash_fullscreen_interactive_browsertest.cc index cbeaf90..b476f58 100644 --- a/chrome/browser/ui/exclusive_access/flash_fullscreen_interactive_browsertest.cc +++ b/chrome/browser/ui/exclusive_access/flash_fullscreen_interactive_browsertest.cc
@@ -89,6 +89,38 @@ return !::testing::Test::HasFailure(); } + bool LaunchFlashFullscreenInSubframe() { + // Start the embedded test server and set it up to serve PPAPI test case + // URLs. + base::FilePath document_root; + EXPECT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&document_root)); + embedded_test_server()->AddDefaultHandlers(document_root); + if (!embedded_test_server()->Start()) { + ADD_FAILURE() << "Failed to launch embedded test server."; + return false; + } + + // Load a page with an <iframe> that points to the test case URL, which + // runs the simulated fullscreen Flash plugin. In OOPIF modes, the frame + // will render in a separate process. Block until the plugin has completed + // an attempt to enter Flash fullscreen mode. + GURL test_url = GetTestURL(*embedded_test_server(), + "FlashFullscreenForBrowserUI", std::string()); + GURL main_url("data:text/html,<iframe src='" + test_url.spec() + + "'></iframe>"); + OutOfProcessPPAPITest::RunTestURL(main_url); + + if (::testing::Test::HasFailure()) { + ADD_FAILURE() << ("Failed to launch simulated fullscreen Flash plugin. " + "Interactive UI testing cannot proceed."); + return false; + } + + EXPECT_TRUE(ObserveTabIsInFullscreen(true)); + + return !::testing::Test::HasFailure(); + } + void UseAcceleratorToOpenNewTab() { content::WebContents* const old_tab_contents = GetActiveWebContents(); EXPECT_TRUE(ui_test_utils::SendKeyPressSync( @@ -272,6 +304,17 @@ EXPECT_TRUE(ObserveTabIsInFullscreen(false)); } +IN_PROC_BROWSER_TEST_F(FlashFullscreenInteractiveBrowserTest, + FullscreenFromSubframe) { + ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); + StartFakingTabCapture(); + ASSERT_TRUE(LaunchFlashFullscreenInSubframe()); + content::WebContents* const first_tab_contents = GetActiveWebContents(); + EXPECT_TRUE(ObserveFlashHasFocus(first_tab_contents, true)); + PressEscape(); + EXPECT_TRUE(ObserveTabIsInFullscreen(false)); +} + // This tests that browser UI focus behavior is correct when switching between // tabs; particularly, that that focus between the omnibox and tab contents is // stored/restored correctly. Mouse and keyboard events are used to confirm
diff --git a/chrome/browser/ui/libgtk2ui/gtk2_ui.cc b/chrome/browser/ui/libgtk2ui/gtk2_ui.cc index c9d25bf..b9d22c54 100644 --- a/chrome/browser/ui/libgtk2ui/gtk2_ui.cc +++ b/chrome/browser/ui/libgtk2ui/gtk2_ui.cc
@@ -6,6 +6,7 @@ #include <math.h> #include <pango/pango.h> +#include <X11/Xcursor/Xcursor.h> #include <set> #include <utility> @@ -49,6 +50,7 @@ #include "ui/gfx/image/image_skia_source.h" #include "ui/gfx/skbitmap_operations.h" #include "ui/gfx/skia_util.h" +#include "ui/gfx/x/x11_types.h" #include "ui/native_theme/native_theme.h" #include "ui/resources/grit/ui_resources.h" #include "ui/views/controls/button/blue_button.h" @@ -508,9 +510,10 @@ G_CALLBACK(OnThemeChanged), this); - LoadGtkValues(); + LoadCursorTheme(); + #if defined(ENABLE_BASIC_PRINTING) printing::PrintingContextLinux::SetCreatePrintDialogFunction( &PrintDialogGtk2::CreatePrintDialog); @@ -996,6 +999,24 @@ theme->GetSystemColor(ui::NativeTheme::kColorId_ThrobberWaitingColor); } +void Gtk2UI::LoadCursorTheme() { + GtkSettings* settings = gtk_settings_get_default(); + + gchar* theme = nullptr; + gint size = 0; + g_object_get(settings, + "gtk-cursor-theme-name", &theme, + "gtk-cursor-theme-size", &size, + nullptr); + + if (theme) + XcursorSetTheme(gfx::GetXDisplay(), theme); + if (size) + XcursorSetDefaultSize(gfx::GetXDisplay(), size); + + g_free(theme); +} + void Gtk2UI::UpdateMaterialDesignColors() { // TODO(varkha): This should be merged back into LoadGtkValues() once Material // Design is on unconditionally.
diff --git a/chrome/browser/ui/libgtk2ui/gtk2_ui.h b/chrome/browser/ui/libgtk2ui/gtk2_ui.h index cd5d8af..fa7f268 100644 --- a/chrome/browser/ui/libgtk2ui/gtk2_ui.h +++ b/chrome/browser/ui/libgtk2ui/gtk2_ui.h
@@ -134,6 +134,9 @@ // ThemeService interface and the colors we send to webkit. void LoadGtkValues(); + // Initialize the Xcursor theme and size with the GTK theme and size. + void LoadCursorTheme(); + // Updates colors if necessary after possible modification of command line. // TODO(varkha): This should not be necessary once Material Design is on // unconditionally.
diff --git a/chrome/browser/ui/login/login_handler.cc b/chrome/browser/ui/login/login_handler.cc index f721962..b5bb94d 100644 --- a/chrome/browser/ui/login/login_handler.cc +++ b/chrome/browser/ui/login/login_handler.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/command_line.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/synchronization/lock.h" @@ -59,6 +60,15 @@ namespace { +// Auth prompt types for UMA. Do not reorder or delete entries; only add to the +// end. +enum AuthPromptType { + AUTH_PROMPT_TYPE_WITH_INTERSTITIAL = 0, + AUTH_PROMPT_TYPE_MAIN_FRAME = 1, + AUTH_PROMPT_TYPE_SUBRESOURCE = 2, + AUTH_PROMPT_TYPE_ENUM_COUNT = 3 +}; + // Helper to remove the ref from an net::URLRequest to the LoginHandler. // Should only be called from the IO thread, since it accesses an // net::URLRequest. @@ -66,6 +76,11 @@ ResourceDispatcherHost::Get()->ClearLoginDelegateForRequest(request); } +void RecordHttpAuthPromptType(AuthPromptType prompt_type) { + UMA_HISTOGRAM_ENUMERATION("Net.HttpAuthPromptType", prompt_type, + AUTH_PROMPT_TYPE_ENUM_COUNT); +} + } // namespace // ---------------------------------------------------------------------------- @@ -597,6 +612,8 @@ (parent_contents->ShowingInterstitialPage() || auth_info->is_proxy || parent_contents->GetLastCommittedURL().GetOrigin() != request_url.GetOrigin())) { + RecordHttpAuthPromptType(AUTH_PROMPT_TYPE_WITH_INTERSTITIAL); + // Show a blank interstitial for main-frame, cross origin requests // so that the correct URL is shown in the omnibox. base::Closure callback = @@ -609,7 +626,10 @@ parent_contents, auth_info->is_proxy ? GURL() : request_url, callback)) ->GetWeakPtr()); + } else { + RecordHttpAuthPromptType(is_main_frame ? AUTH_PROMPT_TYPE_MAIN_FRAME + : AUTH_PROMPT_TYPE_SUBRESOURCE); ShowLoginPrompt(request_url, auth_info, handler); } } @@ -628,4 +648,3 @@ is_main_frame)); return handler; } -
diff --git a/chrome/browser/ui/panels/panel_extension_browsertest.cc b/chrome/browser/ui/panels/panel_extension_browsertest.cc index fe70e98..54cc05645 100644 --- a/chrome/browser/ui/panels/panel_extension_browsertest.cc +++ b/chrome/browser/ui/panels/panel_extension_browsertest.cc
@@ -129,7 +129,7 @@ protected: // RenderViewContextMenu implementation. bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override { + ui::Accelerator* accelerator) const override { return false; } };
diff --git a/chrome/browser/ui/search/instant_controller.cc b/chrome/browser/ui/search/instant_controller.cc index d1f628f..2045725 100644 --- a/chrome/browser/ui/search/instant_controller.cc +++ b/chrome/browser/ui/search/instant_controller.cc
@@ -8,37 +8,30 @@ #include <utility> #include "base/location.h" -#include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/platform_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search/instant_service.h" #include "chrome/browser/search/instant_service_factory.h" #include "chrome/browser/search/search.h" -#include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/ui/browser_instant_controller.h" #include "chrome/browser/ui/search/instant_tab.h" #include "chrome/browser/ui/search/search_tab_helper.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/search/search_urls.h" -#include "chrome/common/url_constants.h" -#include "components/prefs/pref_service.h" -#include "components/search_engines/template_url_service.h" #include "components/sessions/core/serialized_navigation_entry.h" +#include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/notification_service.h" -#include "content/public/browser/render_process_host.h" -#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" -#include "net/base/escape.h" -#include "net/base/network_change_notifier.h" #include "url/gurl.h" +// Macro used for logging debug events. |message| should be a std::string. +#define LOG_INSTANT_DEBUG_EVENT(controller, message) \ + controller->LogDebugEvent(message) + namespace { -bool IsContentsFrom(const InstantPage* page, +bool IsContentsFrom(const InstantTab* page, const content::WebContents* contents) { return page && (page->web_contents() == contents); } @@ -107,12 +100,6 @@ ResetInstantTab(); } -void InstantController::TabDeactivated(content::WebContents* contents) { - // If user is deactivating an NTP tab, give it a change to log stats. - if (search::IsInstantNTP(contents)) - InstantTab::TabDeactivated(contents); -} - void InstantController::LogDebugEvent(const std::string& info) const { DVLOG(1) << info; @@ -137,8 +124,8 @@ void InstantController::InstantSupportChanged( InstantSupportState instant_support) { - // Handle INSTANT_SUPPORT_YES here because InstantPage is not hooked up to the - // active tab. Search model changed listener in InstantPage will handle other + // Handle INSTANT_SUPPORT_YES here because InstantTab is not hooked up to the + // active tab. Search model changed listener in InstantTab will handle other // cases. if (instant_support != INSTANT_SUPPORT_YES) return; @@ -161,7 +148,7 @@ content::NotificationService::NoDetails()); } -void InstantController::InstantPageAboutToNavigateMainFrame( +void InstantController::InstantTabAboutToNavigateMainFrame( const content::WebContents* contents, const GURL& url) { DCHECK(IsContentsFrom(instant_tab(), contents)); @@ -175,7 +162,7 @@ if (!search_mode_.is_origin_default()) { content::WebContents* active_tab = browser_->GetActiveWebContents(); if (!instant_tab_ || active_tab != instant_tab_->web_contents()) { - instant_tab_.reset(new InstantTab(this, browser_->profile())); + instant_tab_.reset(new InstantTab(this)); instant_tab_->Init(active_tab); UpdateInfoForInstantTab(); }
diff --git a/chrome/browser/ui/search/instant_controller.h b/chrome/browser/ui/search/instant_controller.h index 9a099ff..165152c 100644 --- a/chrome/browser/ui/search/instant_controller.h +++ b/chrome/browser/ui/search/instant_controller.h
@@ -11,19 +11,16 @@ #include <memory> #include <string> #include <utility> -#include <vector> #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/strings/string16.h" -#include "chrome/browser/ui/search/instant_page.h" +#include "chrome/browser/ui/search/instant_tab.h" #include "chrome/common/search/search_types.h" -#include "ui/gfx/native_widget_types.h" class BrowserInstantController; class GURL; class InstantService; -class InstantTab; class Profile; struct EmbeddedSearchRequestParams; @@ -31,20 +28,16 @@ class WebContents; } -// Macro used for logging debug events. |message| should be a std::string. -#define LOG_INSTANT_DEBUG_EVENT(controller, message) \ - controller->LogDebugEvent(message) - // InstantController drives Chrome Instant, i.e., the browser implementation of // the Embedded Search API (see http://dev.chromium.org/embeddedsearch). // -// In extended mode, InstantController maintains and coordinates an InstantTab -// instance of InstantPage. An InstantTab instance points to the currently -// active tab, if it supports the Embedded Search API. InstantTab is backed by a -// WebContents and it does not own that WebContents. +// In extended mode, InstantController maintains and coordinates an InstantTab. +// An InstantTab instance points to the currently active tab, if it supports the +// Embedded Search API. InstantTab is backed by a WebContents and it does not +// own that WebContents. // // InstantController is owned by Browser via BrowserInstantController. -class InstantController : public InstantPage::Delegate { +class InstantController : public InstantTab::Delegate { public: explicit InstantController(BrowserInstantController* browser); ~InstantController() override; @@ -64,9 +57,6 @@ // Instant search results page. void ActiveTabChanged(); - // The user is about to switch tabs. - void TabDeactivated(content::WebContents* contents); - // Adds a new event to |debug_events_| and also DVLOG's it. Ensures that // |debug_events_| doesn't get too large. void LogDebugEvent(const std::string& info) const; @@ -113,26 +103,19 @@ FRIEND_TEST_ALL_PREFIXES(InstantExtendedTest, DispatchMVChangeEventWhileNavigatingBackToNTP); - // Overridden from InstantPage::Delegate: + // Overridden from InstantTab::Delegate: // TODO(shishir): We assume that the WebContent's current RenderViewHost is // the RenderViewHost being created which is not always true. Fix this. void InstantSupportDetermined(const content::WebContents* contents, bool supports_instant) override; - void InstantPageAboutToNavigateMainFrame(const content::WebContents* contents, - const GURL& url) override; - - // Helper function to navigate the given contents to the local fallback - // Instant URL and trim the history correctly. - void RedirectToLocalNTP(content::WebContents* contents); - - // Helper for OmniboxFocusChanged. Commit or discard the overlay. - void OmniboxLostFocus(gfx::NativeView view_gaining_focus); + void InstantTabAboutToNavigateMainFrame(const content::WebContents* contents, + const GURL& url) override; // If the active tab is an Instant search results page, sets |instant_tab_| to // point to it. Else, deletes any existing |instant_tab_|. void ResetInstantTab(); - // Sends theme info, omnibox bounds, etc. down to the Instant tab. + // Sends theme info and most visited items to the Instant tab. void UpdateInfoForInstantTab(); // Returns the InstantService for the browser profile. @@ -140,7 +123,7 @@ BrowserInstantController* const browser_; - // The instance of InstantPage maintained by InstantController. + // The instance of InstantTab maintained by InstantController. std::unique_ptr<InstantTab> instant_tab_; // The search model mode for the active tab.
diff --git a/chrome/browser/ui/search/instant_page.cc b/chrome/browser/ui/search/instant_page.cc deleted file mode 100644 index 9b4625d..0000000 --- a/chrome/browser/ui/search/instant_page.cc +++ /dev/null
@@ -1,103 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/search/instant_page.h" - -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/search/search.h" -#include "chrome/browser/ui/search/search_model.h" -#include "chrome/browser/ui/search/search_tab_helper.h" -#include "chrome/common/url_constants.h" -#include "content/public/browser/navigation_controller.h" -#include "content/public/browser/navigation_details.h" -#include "content/public/browser/navigation_entry.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_source.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/web_contents.h" -#include "content/public/common/frame_navigate_params.h" - -InstantPage::Delegate::~Delegate() { -} - -InstantPage::~InstantPage() { - if (web_contents()) { - SearchTabHelper::FromWebContents(web_contents())->model()->RemoveObserver( - this); - } -} - -bool InstantPage::supports_instant() const { - return web_contents() && - SearchTabHelper::FromWebContents(web_contents())->SupportsInstant(); -} - -const std::string& InstantPage::instant_url() const { - return instant_url_; -} - -bool InstantPage::IsLocal() const { - return web_contents() && - web_contents()->GetURL() == GURL(chrome::kChromeSearchLocalNtpUrl); -} - -InstantPage::InstantPage(Delegate* delegate, - const std::string& instant_url, - Profile* profile) - : profile_(profile), - delegate_(delegate), - instant_url_(instant_url) { -} - -void InstantPage::SetContents(content::WebContents* new_web_contents) { - ClearContents(); - - if (!new_web_contents) - return; - - Observe(new_web_contents); - SearchModel* model = - SearchTabHelper::FromWebContents(web_contents())->model(); - model->AddObserver(this); - - // Already know whether the page supports instant. - if (model->instant_support() != INSTANT_SUPPORT_UNKNOWN) - InstantSupportDetermined(model->instant_support() == INSTANT_SUPPORT_YES); -} - -bool InstantPage::ShouldProcessAboutToNavigateMainFrame() { - return false; -} - -void InstantPage::DidCommitProvisionalLoadForFrame( - content::RenderFrameHost* render_frame_host, - const GURL& url, - ui::PageTransition /* transition_type */) { - if (!render_frame_host->GetParent() && - ShouldProcessAboutToNavigateMainFrame()) - delegate_->InstantPageAboutToNavigateMainFrame(web_contents(), url); -} - -void InstantPage::ModelChanged(const SearchModel::State& old_state, - const SearchModel::State& new_state) { - if (old_state.instant_support != new_state.instant_support) - InstantSupportDetermined(new_state.instant_support == INSTANT_SUPPORT_YES); -} - -void InstantPage::InstantSupportDetermined(bool supports_instant) { - delegate_->InstantSupportDetermined(web_contents(), supports_instant); - - // If the page doesn't support Instant, stop listening to it. - if (!supports_instant) - ClearContents(); -} - -void InstantPage::ClearContents() { - if (web_contents()) { - SearchTabHelper::FromWebContents(web_contents())->model()->RemoveObserver( - this); - } - - Observe(NULL); -}
diff --git a/chrome/browser/ui/search/instant_page.h b/chrome/browser/ui/search/instant_page.h deleted file mode 100644 index 23fef3f5..0000000 --- a/chrome/browser/ui/search/instant_page.h +++ /dev/null
@@ -1,127 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_SEARCH_INSTANT_PAGE_H_ -#define CHROME_BROWSER_UI_SEARCH_INSTANT_PAGE_H_ - -#include <vector> - -#include "base/compiler_specific.h" -#include "base/gtest_prod_util.h" -#include "base/macros.h" -#include "base/strings/string16.h" -#include "chrome/browser/ui/search/search_model_observer.h" -#include "content/public/browser/web_contents_observer.h" -#include "ui/base/page_transition_types.h" - -class GURL; -class Profile; - -namespace content { -struct FrameNavigateParams; -struct LoadCommittedDetails; -class WebContents; -} - -namespace gfx { -class Rect; -} - -// InstantPage is used to exchange messages with a page that implements the -// Instant/Embedded Search API (http://dev.chromium.org/embeddedsearch). -// InstantPage is not used directly but via one of its derived classes, -// InstantNTP and InstantTab. -class InstantPage : public content::WebContentsObserver, - public SearchModelObserver { - public: - // InstantPage calls its delegate in response to messages received from the - // page. Each method is called with the |contents| corresponding to the page - // we are observing. - class Delegate { - public: - // Called upon determination of Instant API support. Either in response to - // the page loading or because we received some other message. - virtual void InstantSupportDetermined(const content::WebContents* contents, - bool supports_instant) = 0; - - // Called when the page is about to navigate to |url|. - virtual void InstantPageAboutToNavigateMainFrame( - const content::WebContents* contents, - const GURL& url) = 0; - - protected: - virtual ~Delegate(); - }; - - ~InstantPage() override; - - // Returns the Instant URL that was loaded for this page. Returns the empty - // string if no URL was explicitly loaded as is the case for InstantTab. - virtual const std::string& instant_url() const; - - // Returns true if the page is known to support the Instant API. This starts - // out false, and is set to true whenever we get any message from the page. - // Once true, it never becomes false (the page isn't expected to drop API - // support suddenly). - virtual bool supports_instant() const; - - // Returns true if the page is the local NTP (i.e. its URL is - // chrome::kChromeSearchLocalNTPURL). - virtual bool IsLocal() const; - - protected: - InstantPage(Delegate* delegate, - const std::string& instant_url, - Profile* profile); - - // Sets |web_contents| as the page to communicate with. |web_contents| may be - // NULL, which effectively stops all communication. - void SetContents(content::WebContents* web_contents); - - Delegate* delegate() const { return delegate_; } - - Profile* profile() const { return profile_; } - - // These functions are called before processing messages received from the - // page. By default, all messages are handled, but any derived classes may - // choose to ignore some or all of the received messages by overriding these - // methods. - virtual bool ShouldProcessAboutToNavigateMainFrame(); - - private: - FRIEND_TEST_ALL_PREFIXES(InstantPageTest, IsLocal); - FRIEND_TEST_ALL_PREFIXES(InstantPageTest, - DetermineIfPageSupportsInstant_Local); - FRIEND_TEST_ALL_PREFIXES(InstantPageTest, - DetermineIfPageSupportsInstant_NonLocal); - FRIEND_TEST_ALL_PREFIXES(InstantPageTest, - PageURLDoesntBelongToInstantRenderer); - FRIEND_TEST_ALL_PREFIXES(InstantPageTest, PageSupportsInstant); - - // Overridden from content::WebContentsObserver: - void DidCommitProvisionalLoadForFrame( - content::RenderFrameHost* render_frame_host, - const GURL& url, - ui::PageTransition transition_type) override; - - // Overridden from SearchModelObserver: - void ModelChanged(const SearchModel::State& old_state, - const SearchModel::State& new_state) override; - - // Update the status of Instant support. - void InstantSupportDetermined(bool supports_instant); - - void ClearContents(); - - // TODO(kmadhusu): Remove |profile_| from here and update InstantNTP to get - // |profile| from InstantNTPPrerenderer. - Profile* profile_; - - Delegate* const delegate_; - const std::string instant_url_; - - DISALLOW_COPY_AND_ASSIGN(InstantPage); -}; - -#endif // CHROME_BROWSER_UI_SEARCH_INSTANT_PAGE_H_
diff --git a/chrome/browser/ui/search/instant_page_unittest.cc b/chrome/browser/ui/search/instant_page_unittest.cc deleted file mode 100644 index c9b57f1..0000000 --- a/chrome/browser/ui/search/instant_page_unittest.cc +++ /dev/null
@@ -1,157 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/search/instant_page.h" - -#include <stdint.h> - -#include <memory> - -#include "base/command_line.h" -#include "chrome/browser/ui/search/search_tab_helper.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/render_messages.h" -#include "chrome/common/url_constants.h" -#include "chrome/test/base/chrome_render_view_host_test_harness.h" -#include "content/public/browser/navigation_controller.h" -#include "content/public/browser/navigation_entry.h" -#include "content/public/browser/web_contents.h" -#include "content/public/test/mock_render_process_host.h" -#include "ipc/ipc_test_sink.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -class Profile; - -namespace { - -class FakePageDelegate : public InstantPage::Delegate { - public: - virtual ~FakePageDelegate() { - } - - MOCK_METHOD2(InstantSupportDetermined, - void(const content::WebContents* contents, - bool supports_instant)); - MOCK_METHOD1(InstantPageRenderProcessGone, - void(const content::WebContents* contents)); - MOCK_METHOD2(InstantPageAboutToNavigateMainFrame, - void(const content::WebContents* contents, - const GURL& url)); - MOCK_METHOD5(NavigateToURL, - void(const content::WebContents* contents, - const GURL& url, - ui::PageTransition transition, - WindowOpenDisposition disposition, - bool is_search_type)); -}; - -} // namespace - -class InstantPageTest : public ChromeRenderViewHostTestHarness { - public: - void SetUp() override; - - bool MessageWasSent(uint32_t id) { - return process()->sink().GetFirstMessageMatching(id) != NULL; - } - - std::unique_ptr<InstantPage> page; - FakePageDelegate delegate; -}; - -void InstantPageTest::SetUp() { - ChromeRenderViewHostTestHarness::SetUp(); - SearchTabHelper::CreateForWebContents(web_contents()); -} - -TEST_F(InstantPageTest, IsLocal) { - page.reset(new InstantPage(&delegate, "", NULL)); - EXPECT_FALSE(page->supports_instant()); - EXPECT_FALSE(page->IsLocal()); - page->SetContents(web_contents()); - NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl)); - EXPECT_TRUE(page->IsLocal()); - NavigateAndCommit(GURL("http://example.com")); - EXPECT_FALSE(page->IsLocal()); -} - -TEST_F(InstantPageTest, DetermineIfPageSupportsInstant_Local) { - page.reset(new InstantPage(&delegate, "", NULL)); - EXPECT_FALSE(page->supports_instant()); - page->SetContents(web_contents()); - NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl)); - EXPECT_TRUE(page->IsLocal()); - EXPECT_CALL(delegate, InstantSupportDetermined(web_contents(), true)) - .Times(1); - SearchTabHelper::FromWebContents(web_contents())-> - DetermineIfPageSupportsInstant(); - EXPECT_TRUE(page->supports_instant()); -} - -TEST_F(InstantPageTest, DetermineIfPageSupportsInstant_NonLocal) { - page.reset(new InstantPage(&delegate, "", NULL)); - EXPECT_FALSE(page->supports_instant()); - page->SetContents(web_contents()); - NavigateAndCommit(GURL("chrome-search://foo/bar")); - EXPECT_FALSE(page->IsLocal()); - process()->sink().ClearMessages(); - SearchTabHelper::FromWebContents(web_contents())-> - DetermineIfPageSupportsInstant(); - const IPC::Message* message = process()->sink().GetFirstMessageMatching( - ChromeViewMsg_DetermineIfPageSupportsInstant::ID); - ASSERT_TRUE(message != NULL); - EXPECT_EQ(web_contents()->GetRoutingID(), message->routing_id()); -} - -TEST_F(InstantPageTest, PageURLDoesntBelongToInstantRenderer) { - page.reset(new InstantPage(&delegate, "", NULL)); - EXPECT_FALSE(page->supports_instant()); - NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl)); - page->SetContents(web_contents()); - - // Navigate to a page URL that doesn't belong to Instant renderer. - // SearchTabHelper::DeterminerIfPageSupportsInstant() should return - // immediately without dispatching any message to the renderer. - NavigateAndCommit(GURL("http://www.example.com")); - EXPECT_FALSE(page->IsLocal()); - process()->sink().ClearMessages(); - EXPECT_CALL(delegate, InstantSupportDetermined(web_contents(), false)) - .Times(1); - - SearchTabHelper::FromWebContents(web_contents())-> - DetermineIfPageSupportsInstant(); - const IPC::Message* message = process()->sink().GetFirstMessageMatching( - ChromeViewMsg_DetermineIfPageSupportsInstant::ID); - ASSERT_TRUE(message == NULL); - EXPECT_FALSE(page->supports_instant()); -} - -// Test to verify that ChromeViewMsg_DetermineIfPageSupportsInstant message -// reply handler updates the instant support state in InstantPage. -TEST_F(InstantPageTest, PageSupportsInstant) { - page.reset(new InstantPage(&delegate, "", NULL)); - EXPECT_FALSE(page->supports_instant()); - page->SetContents(web_contents()); - NavigateAndCommit(GURL("chrome-search://foo/bar")); - process()->sink().ClearMessages(); - SearchTabHelper::FromWebContents(web_contents())-> - DetermineIfPageSupportsInstant(); - const IPC::Message* message = process()->sink().GetFirstMessageMatching( - ChromeViewMsg_DetermineIfPageSupportsInstant::ID); - ASSERT_TRUE(message != NULL); - EXPECT_EQ(web_contents()->GetRoutingID(), message->routing_id()); - - EXPECT_CALL(delegate, InstantSupportDetermined(web_contents(), true)) - .Times(1); - - // Assume the page supports instant. Invoke the message reply handler to make - // sure the InstantPage is notified about the instant support state. - const content::NavigationEntry* entry = - web_contents()->GetController().GetLastCommittedEntry(); - EXPECT_TRUE(entry); - SearchTabHelper::FromWebContents(web_contents())->InstantSupportChanged(true); - EXPECT_TRUE(page->supports_instant()); -}
diff --git a/chrome/browser/ui/search/instant_tab.cc b/chrome/browser/ui/search/instant_tab.cc index 7c60de47..dea3f31 100644 --- a/chrome/browser/ui/search/instant_tab.cc +++ b/chrome/browser/ui/search/instant_tab.cc
@@ -1,36 +1,83 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/ui/search/instant_tab.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/webui/ntp/ntp_user_data_logger.h" +#include "chrome/browser/ui/search/search_model.h" +#include "chrome/browser/ui/search/search_tab_helper.h" +#include "chrome/common/url_constants.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" -InstantTab::InstantTab(InstantPage::Delegate* delegate, - Profile* profile) - : InstantPage(delegate, "", profile) { +InstantTab::Delegate::~Delegate() { } InstantTab::~InstantTab() { + if (web_contents()) { + SearchTabHelper::FromWebContents(web_contents())->model()->RemoveObserver( + this); + } } -void InstantTab::Init(content::WebContents* contents) { - SetContents(contents); +bool InstantTab::supports_instant() const { + return web_contents() && + SearchTabHelper::FromWebContents(web_contents())->SupportsInstant(); } -// static -void InstantTab::TabDeactivated(content::WebContents* contents) { - NTPUserDataLogger::GetOrCreateFromWebContents(contents)->TabDeactivated(); +bool InstantTab::IsLocal() const { + return web_contents() && + web_contents()->GetURL() == GURL(chrome::kChromeSearchLocalNtpUrl); } -// static -void InstantTab::MostVisitedItemsChanged(content::WebContents* contents) { - NTPUserDataLogger::GetOrCreateFromWebContents(contents) - ->MostVisitedItemsChanged(); +InstantTab::InstantTab(Delegate* delegate) + : delegate_(delegate) { } -bool InstantTab::ShouldProcessAboutToNavigateMainFrame() { - return true; +void InstantTab::Init(content::WebContents* new_web_contents) { + ClearContents(); + + if (!new_web_contents) + return; + + Observe(new_web_contents); + SearchModel* model = + SearchTabHelper::FromWebContents(web_contents())->model(); + model->AddObserver(this); + + // Already know whether the page supports instant. + if (model->instant_support() != INSTANT_SUPPORT_UNKNOWN) + InstantSupportDetermined(model->instant_support() == INSTANT_SUPPORT_YES); +} + +void InstantTab::DidCommitProvisionalLoadForFrame( + content::RenderFrameHost* render_frame_host, + const GURL& url, + ui::PageTransition /* transition_type */) { + if (!render_frame_host->GetParent()) { + delegate_->InstantTabAboutToNavigateMainFrame(web_contents(), url); + } +} + +void InstantTab::ModelChanged(const SearchModel::State& old_state, + const SearchModel::State& new_state) { + if (old_state.instant_support != new_state.instant_support) + InstantSupportDetermined(new_state.instant_support == INSTANT_SUPPORT_YES); +} + +void InstantTab::InstantSupportDetermined(bool supports_instant) { + delegate_->InstantSupportDetermined(web_contents(), supports_instant); + + // If the page doesn't support Instant, stop listening to it. + if (!supports_instant) + ClearContents(); +} + +void InstantTab::ClearContents() { + if (web_contents()) { + SearchTabHelper::FromWebContents(web_contents())->model()->RemoveObserver( + this); + } + + Observe(NULL); }
diff --git a/chrome/browser/ui/search/instant_tab.h b/chrome/browser/ui/search/instant_tab.h index e879cbae..c77f21c 100644 --- a/chrome/browser/ui/search/instant_tab.h +++ b/chrome/browser/ui/search/instant_tab.h
@@ -1,4 +1,4 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,29 +6,87 @@ #define CHROME_BROWSER_UI_SEARCH_INSTANT_TAB_H_ #include "base/compiler_specific.h" +#include "base/gtest_prod_util.h" #include "base/macros.h" -#include "chrome/browser/ui/search/instant_page.h" +#include "chrome/browser/ui/search/search_model_observer.h" +#include "content/public/browser/web_contents_observer.h" +#include "ui/base/page_transition_types.h" -class Profile; +class GURL; -// InstantTab represents a committed page (i.e. an actual tab on the tab strip) -// that supports the Instant API. -class InstantTab : public InstantPage { +namespace content { +class RenderFrameHost; +class WebContents; +} + +// InstantTab is used to exchange messages with a page that implements the +// Instant/Embedded Search API (http://dev.chromium.org/embeddedsearch). +class InstantTab : public content::WebContentsObserver, + public SearchModelObserver { public: - InstantTab(InstantPage::Delegate* delegate, Profile* profile); + // InstantTab calls its delegate in response to messages received from the + // page. Each method is called with the |contents| corresponding to the page + // we are observing. + class Delegate { + public: + // Called upon determination of Instant API support. Either in response to + // the page loading or because we received some other message. + virtual void InstantSupportDetermined(const content::WebContents* contents, + bool supports_instant) = 0; + + // Called when the page is about to navigate to |url|. + virtual void InstantTabAboutToNavigateMainFrame( + const content::WebContents* contents, + const GURL& url) = 0; + + protected: + virtual ~Delegate(); + }; + + explicit InstantTab(Delegate* delegate); + ~InstantTab() override; - // Start observing |contents| for messages. Sends a message to determine if - // the page supports the Instant API. - void Init(content::WebContents* contents); + // Sets |web_contents| as the page to communicate with. |web_contents| may be + // NULL, which effectively stops all communication. + void Init(content::WebContents* web_contents); - // Logs statistics regarding the NTP. - static void TabDeactivated(content::WebContents* contents); - static void MostVisitedItemsChanged(content::WebContents* contents); + // Returns true if the page is known to support the Instant API. This starts + // out false, and is set to true whenever we get any message from the page. + // Once true, it never becomes false (the page isn't expected to drop API + // support suddenly). + bool supports_instant() const; + + // Returns true if the page is the local NTP (i.e. its URL is + // chrome::kChromeSearchLocalNTPURL). + bool IsLocal() const; private: - // Overridden from InstantPage: - bool ShouldProcessAboutToNavigateMainFrame() override; + FRIEND_TEST_ALL_PREFIXES(InstantTabTest, IsLocal); + FRIEND_TEST_ALL_PREFIXES(InstantTabTest, + DetermineIfPageSupportsInstant_Local); + FRIEND_TEST_ALL_PREFIXES(InstantTabTest, + DetermineIfPageSupportsInstant_NonLocal); + FRIEND_TEST_ALL_PREFIXES(InstantTabTest, + PageURLDoesntBelongToInstantRenderer); + FRIEND_TEST_ALL_PREFIXES(InstantTabTest, PageSupportsInstant); + + // Overridden from content::WebContentsObserver: + void DidCommitProvisionalLoadForFrame( + content::RenderFrameHost* render_frame_host, + const GURL& url, + ui::PageTransition transition_type) override; + + // Overridden from SearchModelObserver: + void ModelChanged(const SearchModel::State& old_state, + const SearchModel::State& new_state) override; + + // Update the status of Instant support. + void InstantSupportDetermined(bool supports_instant); + + void ClearContents(); + + Delegate* const delegate_; DISALLOW_COPY_AND_ASSIGN(InstantTab); };
diff --git a/chrome/browser/ui/search/instant_tab_unittest.cc b/chrome/browser/ui/search/instant_tab_unittest.cc new file mode 100644 index 0000000..97d92e0 --- /dev/null +++ b/chrome/browser/ui/search/instant_tab_unittest.cc
@@ -0,0 +1,157 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/search/instant_tab.h" + +#include <stdint.h> + +#include <memory> + +#include "base/command_line.h" +#include "chrome/browser/ui/search/search_tab_helper.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/render_messages.h" +#include "chrome/common/url_constants.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "content/public/browser/navigation_controller.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/mock_render_process_host.h" +#include "ipc/ipc_test_sink.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +class Profile; + +namespace { + +class FakePageDelegate : public InstantTab::Delegate { + public: + virtual ~FakePageDelegate() { + } + + MOCK_METHOD2(InstantSupportDetermined, + void(const content::WebContents* contents, + bool supports_instant)); + MOCK_METHOD1(InstantTabRenderProcessGone, + void(const content::WebContents* contents)); + MOCK_METHOD2(InstantTabAboutToNavigateMainFrame, + void(const content::WebContents* contents, + const GURL& url)); + MOCK_METHOD5(NavigateToURL, + void(const content::WebContents* contents, + const GURL& url, + ui::PageTransition transition, + WindowOpenDisposition disposition, + bool is_search_type)); +}; + +} // namespace + +class InstantTabTest : public ChromeRenderViewHostTestHarness { + public: + void SetUp() override; + + bool MessageWasSent(uint32_t id) { + return process()->sink().GetFirstMessageMatching(id) != NULL; + } + + std::unique_ptr<InstantTab> page; + FakePageDelegate delegate; +}; + +void InstantTabTest::SetUp() { + ChromeRenderViewHostTestHarness::SetUp(); + SearchTabHelper::CreateForWebContents(web_contents()); +} + +TEST_F(InstantTabTest, IsLocal) { + page.reset(new InstantTab(&delegate)); + EXPECT_FALSE(page->supports_instant()); + EXPECT_FALSE(page->IsLocal()); + page->Init(web_contents()); + NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl)); + EXPECT_TRUE(page->IsLocal()); + NavigateAndCommit(GURL("http://example.com")); + EXPECT_FALSE(page->IsLocal()); +} + +TEST_F(InstantTabTest, DetermineIfPageSupportsInstant_Local) { + page.reset(new InstantTab(&delegate)); + EXPECT_FALSE(page->supports_instant()); + page->Init(web_contents()); + NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl)); + EXPECT_TRUE(page->IsLocal()); + EXPECT_CALL(delegate, InstantSupportDetermined(web_contents(), true)) + .Times(1); + SearchTabHelper::FromWebContents(web_contents())-> + DetermineIfPageSupportsInstant(); + EXPECT_TRUE(page->supports_instant()); +} + +TEST_F(InstantTabTest, DetermineIfPageSupportsInstant_NonLocal) { + page.reset(new InstantTab(&delegate)); + EXPECT_FALSE(page->supports_instant()); + page->Init(web_contents()); + NavigateAndCommit(GURL("chrome-search://foo/bar")); + EXPECT_FALSE(page->IsLocal()); + process()->sink().ClearMessages(); + SearchTabHelper::FromWebContents(web_contents())-> + DetermineIfPageSupportsInstant(); + const IPC::Message* message = process()->sink().GetFirstMessageMatching( + ChromeViewMsg_DetermineIfPageSupportsInstant::ID); + ASSERT_TRUE(message != NULL); + EXPECT_EQ(web_contents()->GetRoutingID(), message->routing_id()); +} + +TEST_F(InstantTabTest, PageURLDoesntBelongToInstantRenderer) { + page.reset(new InstantTab(&delegate)); + EXPECT_FALSE(page->supports_instant()); + NavigateAndCommit(GURL(chrome::kChromeSearchLocalNtpUrl)); + page->Init(web_contents()); + + // Navigate to a page URL that doesn't belong to Instant renderer. + // SearchTabHelper::DeterminerIfPageSupportsInstant() should return + // immediately without dispatching any message to the renderer. + NavigateAndCommit(GURL("http://www.example.com")); + EXPECT_FALSE(page->IsLocal()); + process()->sink().ClearMessages(); + EXPECT_CALL(delegate, InstantSupportDetermined(web_contents(), false)) + .Times(1); + + SearchTabHelper::FromWebContents(web_contents())-> + DetermineIfPageSupportsInstant(); + const IPC::Message* message = process()->sink().GetFirstMessageMatching( + ChromeViewMsg_DetermineIfPageSupportsInstant::ID); + ASSERT_TRUE(message == NULL); + EXPECT_FALSE(page->supports_instant()); +} + +// Test to verify that ChromeViewMsg_DetermineIfPageSupportsInstant message +// reply handler updates the instant support state in InstantTab. +TEST_F(InstantTabTest, PageSupportsInstant) { + page.reset(new InstantTab(&delegate)); + EXPECT_FALSE(page->supports_instant()); + page->Init(web_contents()); + NavigateAndCommit(GURL("chrome-search://foo/bar")); + process()->sink().ClearMessages(); + SearchTabHelper::FromWebContents(web_contents())-> + DetermineIfPageSupportsInstant(); + const IPC::Message* message = process()->sink().GetFirstMessageMatching( + ChromeViewMsg_DetermineIfPageSupportsInstant::ID); + ASSERT_TRUE(message != NULL); + EXPECT_EQ(web_contents()->GetRoutingID(), message->routing_id()); + + EXPECT_CALL(delegate, InstantSupportDetermined(web_contents(), true)) + .Times(1); + + // Assume the page supports instant. Invoke the message reply handler to make + // sure the InstantTab is notified about the instant support state. + const content::NavigationEntry* entry = + web_contents()->GetController().GetLastCommittedEntry(); + EXPECT_TRUE(entry); + SearchTabHelper::FromWebContents(web_contents())->InstantSupportChanged(true); + EXPECT_TRUE(page->supports_instant()); +}
diff --git a/chrome/browser/ui/search/search_tab_helper.cc b/chrome/browser/ui/search/search_tab_helper.cc index 2ba04505..3ff3225 100644 --- a/chrome/browser/ui/search/search_tab_helper.cc +++ b/chrome/browser/ui/search/search_tab_helper.cc
@@ -385,28 +385,7 @@ void SearchTabHelper::MostVisitedItemsChanged( const std::vector<InstantMostVisitedItem>& items) { - // When most visited change, the NTP usually reloads the tiles. This means - // our metrics get inconsistent. So we'd rather emit stats now. - InstantTab::MostVisitedItemsChanged(web_contents_); ipc_router_.SendMostVisitedItems(items); - LogMostVisitedItemsSource(items); -} - -void SearchTabHelper::LogMostVisitedItemsSource( - const std::vector<InstantMostVisitedItem>& items) { - for (auto item : items) { - NTPLoggingEventType event; - if (item.is_server_side_suggestion) { - event = NTP_SERVER_SIDE_SUGGESTION; - } else { - event = NTP_CLIENT_SIDE_SUGGESTION; - } - // The metrics are emitted for each suggestion as the design requirement - // even the ntp_user_data_logger.cc now only supports the scenario: - // all suggestions are provided by server OR - // all suggestions are provided by client. - this->OnLogEvent(event, base::TimeDelta()); - } } void SearchTabHelper::FocusOmnibox(OmniboxFocusState state) {
diff --git a/chrome/browser/ui/search/search_tab_helper.h b/chrome/browser/ui/search/search_tab_helper.h index 6543142..bc1188e 100644 --- a/chrome/browser/ui/search/search_tab_helper.h +++ b/chrome/browser/ui/search/search_tab_helper.h
@@ -27,8 +27,8 @@ } class GURL; -class InstantPageTest; class InstantService; +class InstantTabTest; class OmniboxView; class Profile; class SearchIPCRouterTest; @@ -97,7 +97,7 @@ private: friend class content::WebContentsUserData<SearchTabHelper>; - friend class InstantPageTest; + friend class InstantTabTest; friend class SearchIPCRouterPolicyTest; friend class SearchIPCRouterTest; friend class SearchTabHelperPrerenderTest; @@ -134,13 +134,13 @@ FRIEND_TEST_ALL_PREFIXES(SearchIPCRouterTest, DoNotSendSetDisplayInstantResultsMsg); FRIEND_TEST_ALL_PREFIXES(SearchIPCRouterTest, HandleTabChangedEvents); - FRIEND_TEST_ALL_PREFIXES(InstantPageTest, + FRIEND_TEST_ALL_PREFIXES(InstantTabTest, DetermineIfPageSupportsInstant_Local); - FRIEND_TEST_ALL_PREFIXES(InstantPageTest, + FRIEND_TEST_ALL_PREFIXES(InstantTabTest, DetermineIfPageSupportsInstant_NonLocal); - FRIEND_TEST_ALL_PREFIXES(InstantPageTest, + FRIEND_TEST_ALL_PREFIXES(InstantTabTest, PageURLDoesntBelongToInstantRenderer); - FRIEND_TEST_ALL_PREFIXES(InstantPageTest, PageSupportsInstant); + FRIEND_TEST_ALL_PREFIXES(InstantTabTest, PageSupportsInstant); explicit SearchTabHelper(content::WebContents* web_contents); @@ -201,10 +201,6 @@ // Returns the OmniboxView for |web_contents_| or NULL if not available. OmniboxView* GetOmniboxView() const; - // Record whether each suggestion comes from server or client. - void LogMostVisitedItemsSource( - const std::vector<InstantMostVisitedItem>& items); - typedef bool (*OmniboxHasFocusFn)(OmniboxView*); void set_omnibox_has_focus_fn(OmniboxHasFocusFn fn) {
diff --git a/chrome/browser/ui/search/search_tab_helper_unittest.cc b/chrome/browser/ui/search/search_tab_helper_unittest.cc index eda53e3..357c77eb 100644 --- a/chrome/browser/ui/search/search_tab_helper_unittest.cc +++ b/chrome/browser/ui/search/search_tab_helper_unittest.cc
@@ -320,46 +320,6 @@ ASSERT_FALSE(std::get<0>(params)); } -TEST_F(SearchTabHelperTest, OnMostVisitedItemsChangedFromServer) { - InstantMostVisitedItem item; - item.is_server_side_suggestion = true; - std::vector<InstantMostVisitedItem> items; - items.push_back(item); - - SearchTabHelper* search_tab_helper = - SearchTabHelper::FromWebContents(web_contents()); - ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper); - - auto logger = NTPUserDataLogger::GetOrCreateFromWebContents(web_contents()); - ASSERT_FALSE(logger->has_server_side_suggestions_); - ASSERT_FALSE(logger->has_client_side_suggestions_); - - search_tab_helper->MostVisitedItemsChanged(items); - - ASSERT_TRUE(logger->has_server_side_suggestions_); - ASSERT_FALSE(logger->has_client_side_suggestions_); -} - -TEST_F(SearchTabHelperTest, OnMostVisitedItemsChangedFromClient) { - InstantMostVisitedItem item; - item.is_server_side_suggestion = false; - std::vector<InstantMostVisitedItem> items; - items.push_back(item); - - SearchTabHelper* search_tab_helper = - SearchTabHelper::FromWebContents(web_contents()); - ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper); - - auto logger = NTPUserDataLogger::GetOrCreateFromWebContents(web_contents()); - ASSERT_FALSE(logger->has_server_side_suggestions_); - ASSERT_FALSE(logger->has_client_side_suggestions_); - - search_tab_helper->MostVisitedItemsChanged(items); - - ASSERT_FALSE(logger->has_server_side_suggestions_); - ASSERT_TRUE(logger->has_client_side_suggestions_); -} - class TabTitleObserver : public content::WebContentsObserver { public: explicit TabTitleObserver(content::WebContents* contents)
diff --git a/chrome/browser/ui/startup/default_browser_infobar_delegate.cc b/chrome/browser/ui/startup/default_browser_infobar_delegate.cc index bab51d9..b9175c7 100644 --- a/chrome/browser/ui/startup/default_browser_infobar_delegate.cc +++ b/chrome/browser/ui/startup/default_browser_infobar_delegate.cc
@@ -57,6 +57,7 @@ : ConfirmInfoBarDelegate(), profile_(profile), should_expire_(false), + action_taken_(false), weak_factory_(this) { // We want the info-bar to stick-around for few seconds and then be hidden // on the next navigation after that. @@ -66,7 +67,13 @@ base::TimeDelta::FromSeconds(8)); } -DefaultBrowserInfoBarDelegate::~DefaultBrowserInfoBarDelegate() = default; +DefaultBrowserInfoBarDelegate::~DefaultBrowserInfoBarDelegate() { + if (!action_taken_) { + UMA_HISTOGRAM_ENUMERATION("DefaultBrowser.InfoBar.UserInteraction", + IGNORE_INFO_BAR, + NUM_INFO_BAR_USER_INTERACTION_TYPES); + } +} void DefaultBrowserInfoBarDelegate::AllowExpiry() { should_expire_ = true; @@ -127,10 +134,11 @@ } void DefaultBrowserInfoBarDelegate::InfoBarDismissed() { + action_taken_ = true; content::RecordAction( base::UserMetricsAction("DefaultBrowserInfoBar_Dismiss")); UMA_HISTOGRAM_ENUMERATION("DefaultBrowser.InfoBar.UserInteraction", - IGNORE_INFO_BAR, + DISMISS_INFO_BAR, NUM_INFO_BAR_USER_INTERACTION_TYPES); } @@ -164,6 +172,7 @@ } bool DefaultBrowserInfoBarDelegate::Accept() { + action_taken_ = true; content::RecordAction( base::UserMetricsAction("DefaultBrowserInfoBar_Accept")); UMA_HISTOGRAM_ENUMERATION("DefaultBrowser.InfoBar.UserInteraction", @@ -190,6 +199,7 @@ } bool DefaultBrowserInfoBarDelegate::Cancel() { + action_taken_ = true; // This can get reached in tests where profile_ is null. if (profile_) chrome::DefaultBrowserPromptDeclined(profile_);
diff --git a/chrome/browser/ui/startup/default_browser_infobar_delegate.h b/chrome/browser/ui/startup/default_browser_infobar_delegate.h index 99b7ffd6..9b56c47 100644 --- a/chrome/browser/ui/startup/default_browser_infobar_delegate.h +++ b/chrome/browser/ui/startup/default_browser_infobar_delegate.h
@@ -46,6 +46,8 @@ CANCEL_INFO_BAR = 1, // The user did not interact with the info bar. IGNORE_INFO_BAR = 2, + // The user explicitly closed the infobar. + DISMISS_INFO_BAR = 3, NUM_INFO_BAR_USER_INTERACTION_TYPES }; @@ -85,6 +87,9 @@ // Whether the info bar should be dismissed on the next navigation. bool should_expire_; + // Indicates if the user interacted with the infobar. + bool action_taken_; + // Used to delay the expiration of the info-bar. base::WeakPtrFactory<DefaultBrowserInfoBarDelegate> weak_factory_;
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc index 8cb76a7..2af51d8 100644 --- a/chrome/browser/ui/startup/startup_browser_creator.cc +++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -29,6 +29,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_tokenizer.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_restrictions.h" #include "base/trace_event/trace_event.h" @@ -521,25 +522,27 @@ url = url_formatter::FixupRelativeFile(cur_dir, param); } // Exclude dangerous schemes. - if (url.is_valid()) { - ChildProcessSecurityPolicy* policy = - ChildProcessSecurityPolicy::GetInstance(); - if (policy->IsWebSafeScheme(url.scheme()) || - url.SchemeIs(url::kFileScheme) || + if (!url.is_valid()) + continue; + + ChildProcessSecurityPolicy* policy = + ChildProcessSecurityPolicy::GetInstance(); + if (policy->IsWebSafeScheme(url.scheme()) || + url.SchemeIs(url::kFileScheme) || #if defined(OS_CHROMEOS) - // In ChromeOS, allow any settings page to be specified on the command - // line. See ExistingUserController::OnLoginSuccess. - (url.spec().find(chrome::kChromeUISettingsURL) == 0) || + // In ChromeOS, allow any settings page to be specified on the command + // line. See ExistingUserController::OnLoginSuccess. + base::StartsWith(url.spec(), chrome::kChromeUISettingsURL, + base::CompareCase::SENSITIVE) || #else - // Exposed for external cleaners to offer a settings reset to the - // user. So the URL must match exactly, without any param or prefix. - (url.spec() == - std::string(chrome::kChromeUISettingsURL) + - chrome::kResetProfileSettingsSubPage) || + // Exposed for external cleaners to offer a settings reset to the + // user. So the URL must match exactly, without any param or prefix. + (url.spec() == + std::string(chrome::kChromeUISettingsURL) + + chrome::kResetProfileSettingsSubPage) || #endif - (url.spec().compare(url::kAboutBlankURL) == 0)) { - urls.push_back(url); - } + (url.spec().compare(url::kAboutBlankURL) == 0)) { + urls.push_back(url); } } return urls;
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index 2981c67..85c3e1d 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc
@@ -53,6 +53,7 @@ #include "content/public/browser/web_contents.h" #if BUILDFLAG(ANDROID_JAVA_UI) +#include "chrome/browser/android/banners/app_banner_manager_android.h" #include "chrome/browser/android/data_usage/data_use_tab_helper.h" #include "chrome/browser/android/offline_pages/offline_page_tab_helper.h" #include "chrome/browser/android/offline_pages/recent_tab_helper.h" @@ -63,6 +64,7 @@ #include "components/offline_pages/offline_page_feature.h" #else #include "chrome/browser/banners/app_banner_manager_desktop.h" +#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/plugins/plugin_observer.h" #include "chrome/browser/safe_browsing/safe_browsing_tab_observer.h" #include "chrome/browser/thumbnails/thumbnail_tab_helper.h" @@ -71,7 +73,6 @@ #include "chrome/browser/ui/sad_tab_helper.h" #include "chrome/browser/ui/search_engines/search_engine_tab_helper.h" #include "chrome/browser/ui/sync/tab_contents_synced_tab_delegate.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" #include "components/pdf/browser/pdf_web_contents_helper.h" #include "components/web_modal/web_contents_modal_dialog_manager.h" #include "components/zoom/zoom_controller.h" @@ -182,6 +183,7 @@ // --- Platform-specific tab helpers --- #if BUILDFLAG(ANDROID_JAVA_UI) + banners::AppBannerManagerAndroid::CreateForWebContents(web_contents); ContextMenuHelper::CreateForWebContents(web_contents); DataUseTabHelper::CreateForWebContents(web_contents); @@ -202,7 +204,7 @@ pdf::PDFWebContentsHelper::CreateForWebContentsWithClient( web_contents, std::unique_ptr<pdf::PDFWebContentsHelperClient>( new ChromePDFWebContentsHelperClient())); - PermissionBubbleManager::CreateForWebContents(web_contents); + PermissionRequestManager::CreateForWebContents(web_contents); PluginObserver::CreateForWebContents(web_contents); SadTabHelper::CreateForWebContents(web_contents); safe_browsing::SafeBrowsingTabObserver::CreateForWebContents(web_contents); @@ -212,9 +214,8 @@ ThumbnailTabHelper::CreateForWebContents(web_contents); web_modal::WebContentsModalDialogManager::CreateForWebContents(web_contents); - if (banners::AppBannerManagerDesktop::IsEnabled()) { + if (banners::AppBannerManagerDesktop::IsEnabled()) banners::AppBannerManagerDesktop::CreateForWebContents(web_contents); - } #endif // --- Feature tab helpers behind flags ---
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc index 19f6fef..9209ab16 100644 --- a/chrome/browser/ui/toolbar/app_menu_model.cc +++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -171,7 +171,7 @@ bool EncodingMenuModel::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; } @@ -721,8 +721,9 @@ } } -bool AppMenuModel::GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) { +bool AppMenuModel::GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const { return provider_->GetAcceleratorForCommandId(command_id, accelerator); }
diff --git a/chrome/browser/ui/toolbar/app_menu_model.h b/chrome/browser/ui/toolbar/app_menu_model.h index 11afa0c..96349154 100644 --- a/chrome/browser/ui/toolbar/app_menu_model.h +++ b/chrome/browser/ui/toolbar/app_menu_model.h
@@ -86,7 +86,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; private: @@ -148,7 +148,7 @@ bool IsCommandIdEnabled(int command_id) const override; bool IsCommandIdVisible(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; // Overridden from TabStripModelObserver: void ActiveTabChanged(content::WebContents* old_contents,
diff --git a/chrome/browser/ui/toolbar/app_menu_model_unittest.cc b/chrome/browser/ui/toolbar/app_menu_model_unittest.cc index 5397452..c0d0e98 100644 --- a/chrome/browser/ui/toolbar/app_menu_model_unittest.cc +++ b/chrome/browser/ui/toolbar/app_menu_model_unittest.cc
@@ -59,7 +59,7 @@ public: // Don't handle accelerators. bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override { + ui::Accelerator* accelerator) const override { return false; }
diff --git a/chrome/browser/ui/toolbar/media_router_contextual_menu.cc b/chrome/browser/ui/toolbar/media_router_contextual_menu.cc index 50558b9..8caf084b7 100644 --- a/chrome/browser/ui/toolbar/media_router_contextual_menu.cc +++ b/chrome/browser/ui/toolbar/media_router_contextual_menu.cc
@@ -85,7 +85,7 @@ bool MediaRouterContextualMenu::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; }
diff --git a/chrome/browser/ui/toolbar/media_router_contextual_menu.h b/chrome/browser/ui/toolbar/media_router_contextual_menu.h index 060e4738..42b57ed 100644 --- a/chrome/browser/ui/toolbar/media_router_contextual_menu.h +++ b/chrome/browser/ui/toolbar/media_router_contextual_menu.h
@@ -25,7 +25,7 @@ bool IsCommandIdEnabled(int command_id) const override; bool IsCommandIdVisible(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; void ReportIssue();
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc index dac90372..9e478df 100644 --- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc +++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
@@ -252,7 +252,8 @@ } bool RecentTabsSubMenuModel::GetAcceleratorForCommandId( - int command_id, ui::Accelerator* accelerator) { + int command_id, + ui::Accelerator* accelerator) const { // If there are no recently closed items, we show the accelerator beside // the header, otherwise, we show it beside the first item underneath it. int index_in_menu = GetIndexOfCommandId(command_id);
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h index 895a2a8..ca5b0be 100644 --- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h +++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
@@ -67,7 +67,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; const gfx::FontList* GetLabelFontListAt(int index) const override;
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc index 1b80cf7..50d190f5 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
@@ -190,7 +190,7 @@ bool BookmarkEditorView::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return GetWidget()->GetAccelerator(command_id, accelerator); }
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h index a601c30..0bd8f63 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h +++ b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.h
@@ -109,7 +109,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; // Creates a Window and adds the BookmarkEditorView to it. When the window is
diff --git a/chrome/browser/ui/views/chooser_content_view.cc b/chrome/browser/ui/views/chooser_content_view.cc index ad6a040a..24b0e254 100644 --- a/chrome/browser/ui/views/chooser_content_view.cc +++ b/chrome/browser/ui/views/chooser_content_view.cc
@@ -143,11 +143,15 @@ return gfx::Size(kChooserWidth, kChooserHeight); } +base::string16 ChooserContentView::GetWindowTitle() const { + return chooser_controller_->GetTitle(); +} + base::string16 ChooserContentView::GetDialogButtonLabel( ui::DialogButton button) const { - return l10n_util::GetStringUTF16(button == ui::DIALOG_BUTTON_OK - ? IDS_DEVICE_CHOOSER_CONNECT_BUTTON_TEXT - : IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT); + return button == ui::DIALOG_BUTTON_OK + ? chooser_controller_->GetOkButtonLabel() + : l10n_util::GetStringUTF16(IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT); } bool ChooserContentView::IsDialogButtonEnabled(ui::DialogButton button) const {
diff --git a/chrome/browser/ui/views/chooser_content_view.h b/chrome/browser/ui/views/chooser_content_view.h index 57c5dd1..2a9c45a 100644 --- a/chrome/browser/ui/views/chooser_content_view.h +++ b/chrome/browser/ui/views/chooser_content_view.h
@@ -37,6 +37,7 @@ // views::View: gfx::Size GetPreferredSize() const override; + base::string16 GetWindowTitle() const; base::string16 GetDialogButtonLabel(ui::DialogButton button) const; bool IsDialogButtonEnabled(ui::DialogButton button) const; // Ownership of the view is passed to the caller.
diff --git a/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc b/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc index 662c976..0644dbc 100644 --- a/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc +++ b/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc
@@ -154,6 +154,8 @@ max_size_(max_size) { SetWebContents(GetWebContents()); AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE)); + if (!max_size_.IsEmpty()) + EnableAutoResize(); } ~ConstrainedWebDialogDelegateViewViews() override {} @@ -235,13 +237,10 @@ EnableAutoResize(); } void DocumentOnLoadCompletedInMainFrame() override { - if (!max_size_.IsEmpty()) { - EnableAutoResize(); - if (initiator_observer_.web_contents()) { - web_modal::WebContentsModalDialogManager::FromWebContents( - initiator_observer_.web_contents()) - ->ShowModalDialog(GetWidget()->GetNativeWindow()); - } + if (!max_size_.IsEmpty() && initiator_observer_.web_contents()) { + web_modal::WebContentsModalDialogManager::FromWebContents( + initiator_observer_.web_contents()) + ->ShowModalDialog(GetWidget()->GetNativeWindow()); } }
diff --git a/chrome/browser/ui/views/extensions/chooser_dialog_view.cc b/chrome/browser/ui/views/extensions/chooser_dialog_view.cc index 51dae6b..b7d0215d 100644 --- a/chrome/browser/ui/views/extensions/chooser_dialog_view.cc +++ b/chrome/browser/ui/views/extensions/chooser_dialog_view.cc
@@ -10,18 +10,13 @@ #include "chrome/browser/ui/views/chooser_content_view.h" #include "chrome/grit/generated_resources.h" #include "components/constrained_window/constrained_window_views.h" -#include "components/url_formatter/elide_url.h" #include "components/web_modal/web_contents_modal_dialog_manager.h" #include "content/public/browser/browser_thread.h" -#include "extensions/browser/extension_registry.h" -#include "ui/base/l10n/l10n_util.h" #include "ui/views/controls/styled_label.h" #include "ui/views/window/dialog_client_view.h" ChooserDialogView::ChooserDialogView( - content::WebContents* web_contents, - std::unique_ptr<ChooserController> chooser_controller) - : web_contents_(web_contents), chooser_content_view_(nullptr) { + std::unique_ptr<ChooserController> chooser_controller) { // ------------------------------------ // | Chooser dialog title | // | -------------------------------- | @@ -37,9 +32,7 @@ // | Not seeing your device? Get help | // ------------------------------------ - DCHECK(web_contents_); DCHECK(chooser_controller); - origin_ = chooser_controller->GetOrigin(); chooser_content_view_ = new ChooserContentView(this, std::move(chooser_controller)); } @@ -47,24 +40,7 @@ ChooserDialogView::~ChooserDialogView() {} base::string16 ChooserDialogView::GetWindowTitle() const { - base::string16 chooser_title; - content::BrowserContext* browser_context = web_contents_->GetBrowserContext(); - extensions::ExtensionRegistry* extension_registry = - extensions::ExtensionRegistry::Get(browser_context); - if (extension_registry) { - const extensions::Extension* extension = - extension_registry->enabled_extensions().GetExtensionOrAppByURL( - GURL(origin_.Serialize())); - if (extension) - chooser_title = base::UTF8ToUTF16(extension->name()); - } - - if (chooser_title.empty()) { - chooser_title = url_formatter::FormatOriginForSecurityDisplay( - origin_, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC); - } - - return l10n_util::GetStringFUTF16(IDS_DEVICE_CHOOSER_PROMPT, chooser_title); + return chooser_content_view_->GetWindowTitle(); } bool ChooserDialogView::ShouldShowCloseButton() const { @@ -138,7 +114,6 @@ web_modal::WebContentsModalDialogManager::FromWebContents(web_contents_); if (manager) { constrained_window::ShowWebModalDialogViews( - new ChooserDialogView(web_contents_, std::move(chooser_controller)), - web_contents_); + new ChooserDialogView(std::move(chooser_controller)), web_contents_); } }
diff --git a/chrome/browser/ui/views/extensions/chooser_dialog_view.h b/chrome/browser/ui/views/extensions/chooser_dialog_view.h index b33100a..f68d01ab 100644 --- a/chrome/browser/ui/views/extensions/chooser_dialog_view.h +++ b/chrome/browser/ui/views/extensions/chooser_dialog_view.h
@@ -11,15 +11,10 @@ #include "ui/views/controls/styled_label_listener.h" #include "ui/views/controls/table/table_view_observer.h" #include "ui/views/window/dialog_delegate.h" -#include "url/origin.h" class ChooserContentView; class ChooserController; -namespace content { -class WebContents; -} - namespace views { class TableView; } @@ -30,8 +25,8 @@ public views::StyledLabelListener, public views::TableViewObserver { public: - ChooserDialogView(content::WebContents* web_contents, - std::unique_ptr<ChooserController> chooser_controller); + explicit ChooserDialogView( + std::unique_ptr<ChooserController> chooser_controller); ~ChooserDialogView() override; // views::WidgetDelegate: @@ -63,8 +58,6 @@ views::TableView* table_view_for_test() const; private: - content::WebContents* web_contents_; - url::Origin origin_; ChooserContentView* chooser_content_view_; DISALLOW_COPY_AND_ASSIGN(ChooserDialogView);
diff --git a/chrome/browser/ui/views/extensions/chooser_dialog_view_browsertest.cc b/chrome/browser/ui/views/extensions/chooser_dialog_view_browsertest.cc index 2ef2625a..1b65c6c 100644 --- a/chrome/browser/ui/views/extensions/chooser_dialog_view_browsertest.cc +++ b/chrome/browser/ui/views/extensions/chooser_dialog_view_browsertest.cc
@@ -9,7 +9,6 @@ #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/grit/generated_resources.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -25,14 +24,11 @@ ~ChooserDialogViewTest() override {} void SetUpOnMainThread() override { - content::WebContents* web_contents = - browser()->tab_strip_model()->GetWebContentsAt(0); std::unique_ptr<MockChooserController> mock_chooser_controller( new MockChooserController(nullptr)); mock_chooser_controller_ = mock_chooser_controller.get(); std::unique_ptr<ChooserDialogView> chooser_dialog_view( - new ChooserDialogView(web_contents, - std::move(mock_chooser_controller))); + new ChooserDialogView(std::move(mock_chooser_controller))); chooser_dialog_view_ = chooser_dialog_view.get(); table_view_ = chooser_dialog_view_->table_view_for_test(); ASSERT_TRUE(table_view_);
diff --git a/chrome/browser/ui/views/find_bar_view.cc b/chrome/browser/ui/views/find_bar_view.cc index 7ff6b56..002e56c 100644 --- a/chrome/browser/ui/views/find_bar_view.cc +++ b/chrome/browser/ui/views/find_bar_view.cc
@@ -594,7 +594,7 @@ } void FindBarView::UpdateMatchCountAppearance(bool no_match) { - bool enable_buttons = !match_count_text_->text().empty() && !no_match; + bool enable_buttons = !find_text_->text().empty() && !no_match; find_previous_button_->SetEnabled(enable_buttons); find_next_button_->SetEnabled(enable_buttons);
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 31581e1..34aaf62 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -31,6 +31,7 @@ #include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/native_window_notification_source.h" +#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/profiles/avatar_menu.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_attributes_entry.h" @@ -99,7 +100,6 @@ #include "chrome/browser/ui/views/update_recommended_message_box.h" #include "chrome/browser/ui/views/website_settings/permissions_bubble_view.h" #include "chrome/browser/ui/views/website_settings/website_settings_popup_view.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" #include "chrome/browser/ui/window_sizer/window_sizer.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/command.h" @@ -844,11 +844,11 @@ infobar_container_->ChangeInfoBarManager( InfoBarService::FromWebContents(new_contents)); - if (old_contents && PermissionBubbleManager::FromWebContents(old_contents)) - PermissionBubbleManager::FromWebContents(old_contents)->HideBubble(); + if (old_contents && PermissionRequestManager::FromWebContents(old_contents)) + PermissionRequestManager::FromWebContents(old_contents)->HideBubble(); - if (new_contents && PermissionBubbleManager::FromWebContents(new_contents)) { - PermissionBubbleManager::FromWebContents(new_contents) + if (new_contents && PermissionRequestManager::FromWebContents(new_contents)) { + PermissionRequestManager::FromWebContents(new_contents) ->DisplayPendingRequests(); } @@ -1562,8 +1562,8 @@ } void BrowserView::TabDetachedAt(WebContents* contents, int index) { - if (PermissionBubbleManager::FromWebContents(contents)) - PermissionBubbleManager::FromWebContents(contents)->HideBubble(); + if (PermissionRequestManager::FromWebContents(contents)) + PermissionRequestManager::FromWebContents(contents)->HideBubble(); // We use index here rather than comparing |contents| because by this time // the model has already removed |contents| from its list, so @@ -1580,8 +1580,8 @@ } void BrowserView::TabDeactivated(WebContents* contents) { - if (PermissionBubbleManager::FromWebContents(contents)) - PermissionBubbleManager::FromWebContents(contents)->HideBubble(); + if (PermissionRequestManager::FromWebContents(contents)) + PermissionRequestManager::FromWebContents(contents)->HideBubble(); // We do not store the focus when closing the tab to work-around bug 4633. // Some reports seem to show that the focus manager and/or focused view can @@ -1608,8 +1608,9 @@ /////////////////////////////////////////////////////////////////////////////// // BrowserView, ui::AcceleratorProvider implementation: -bool BrowserView::GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) { +bool BrowserView::GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const { // Let's let the ToolbarView own the canonical implementation of this method. return toolbar_->GetAcceleratorForCommandId(command_id, accelerator); } @@ -2359,8 +2360,8 @@ ToolbarSizeChanged(false); WebContents* contents = browser_->tab_strip_model()->GetActiveWebContents(); - if (contents && PermissionBubbleManager::FromWebContents(contents)) - PermissionBubbleManager::FromWebContents(contents)->UpdateAnchorPosition(); + if (contents && PermissionRequestManager::FromWebContents(contents)) + PermissionRequestManager::FromWebContents(contents)->UpdateAnchorPosition(); } bool BrowserView::ShouldUseImmersiveFullscreenForUrl(const GURL& url) const {
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index 7c9c94d..92bbc40 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -383,7 +383,7 @@ // Overridden from ui::AcceleratorProvider: bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; // Overridden from views::WidgetDelegate: bool CanResize() const override;
diff --git a/chrome/browser/ui/views/frame/system_menu_model_delegate.cc b/chrome/browser/ui/views/frame/system_menu_model_delegate.cc index 77849cb3..aa6e7055 100644 --- a/chrome/browser/ui/views/frame/system_menu_model_delegate.cc +++ b/chrome/browser/ui/views/frame/system_menu_model_delegate.cc
@@ -59,8 +59,9 @@ return true; } -bool SystemMenuModelDelegate::GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) { +bool SystemMenuModelDelegate::GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const { return provider_->GetAcceleratorForCommandId(command_id, accelerator); }
diff --git a/chrome/browser/ui/views/frame/system_menu_model_delegate.h b/chrome/browser/ui/views/frame/system_menu_model_delegate.h index 49b0d8f..bd5b810 100644 --- a/chrome/browser/ui/views/frame/system_menu_model_delegate.h +++ b/chrome/browser/ui/views/frame/system_menu_model_delegate.h
@@ -24,7 +24,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; bool IsItemForCommandIdDynamic(int command_id) const override; base::string16 GetLabelForCommandId(int command_id) const override; void ExecuteCommand(int command_id, int event_flags) override;
diff --git a/chrome/browser/ui/views/message_center/web_notification_tray_browsertest.cc b/chrome/browser/ui/views/message_center/web_notification_tray_browsertest.cc index ac8380d..f1b5dad 100644 --- a/chrome/browser/ui/views/message_center/web_notification_tray_browsertest.cc +++ b/chrome/browser/ui/views/message_center/web_notification_tray_browsertest.cc
@@ -8,9 +8,9 @@ #include <set> +#include "ash/common/system/status_area_widget.h" #include "ash/common/system/tray/system_tray_item.h" #include "ash/root_window_controller.h" -#include "ash/system/status_area_widget.h" #include "base/macros.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/ui/views/new_task_manager_view.cc b/chrome/browser/ui/views/new_task_manager_view.cc index 01a5d3c7..a73d48a 100644 --- a/chrome/browser/ui/views/new_task_manager_view.cc +++ b/chrome/browser/ui/views/new_task_manager_view.cc
@@ -280,7 +280,7 @@ bool NewTaskManagerView::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; }
diff --git a/chrome/browser/ui/views/new_task_manager_view.h b/chrome/browser/ui/views/new_task_manager_view.h index fe94e35..1f9543a6d 100644 --- a/chrome/browser/ui/views/new_task_manager_view.h +++ b/chrome/browser/ui/views/new_task_manager_view.h
@@ -89,7 +89,7 @@ bool IsCommandIdChecked(int id) const override; bool IsCommandIdEnabled(int id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int id, int event_flags) override; private:
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 10dcaab..74c2694 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc +++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/ui/views/passwords/manage_password_items_view.h" #include "chrome/browser/ui/views/passwords/manage_passwords_icon_views.h" #include "chrome/grit/generated_resources.h" +#include "content/public/browser/user_metrics.h" #include "grit/components_strings.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/material_design/material_design_controller.h" @@ -593,6 +594,8 @@ layout->AddView(no_button_); parent_->set_initially_focused_view(signin_button_); + content::RecordAction( + base::UserMetricsAction("Signin_Impression_FromPasswordBubble")); } void ManagePasswordsBubbleView::SignInPromoView::ButtonPressed(
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc index 7ea8a87..5500499 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc +++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -765,6 +765,7 @@ delete_account_button_map_.clear(); reauth_account_button_map_.clear(); manage_accounts_link_ = nullptr; + manage_accounts_button_ = nullptr; signin_current_profile_button_ = nullptr; auth_error_email_button_ = nullptr; current_profile_photo_ = nullptr;
diff --git a/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc b/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc index 6cf6659..639219ea 100644 --- a/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc +++ b/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.cc
@@ -62,7 +62,7 @@ bool RenderViewContextMenuViews::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accel) { + ui::Accelerator* accel) const { // There are no formally defined accelerators we can query so we assume // that Ctrl+C, Ctrl+V, Ctrl+X, Ctrl-A, etc do what they normally do. ui::AcceleratorProvider* accelerator_provider = nullptr;
diff --git a/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.h b/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.h index 29b4263..3e052117 100644 --- a/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.h +++ b/chrome/browser/ui/views/renderer_context_menu/render_view_context_menu_views.h
@@ -49,7 +49,7 @@ // RenderViewContextMenu implementation. bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; private: void AppendPlatformEditableItems() override;
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc index d7ff874..0d00ebe 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -132,7 +132,7 @@ tab_); } bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override { + ui::Accelerator* accelerator) const override { int browser_cmd; return TabStripModel::ContextMenuCommandToBrowserCommand(command_id, &browser_cmd) ?
diff --git a/chrome/browser/ui/views/toolbar/reload_button.cc b/chrome/browser/ui/views/toolbar/reload_button.cc index 4d9b593..bfa4fae 100644 --- a/chrome/browser/ui/views/toolbar/reload_button.cc +++ b/chrome/browser/ui/views/toolbar/reload_button.cc
@@ -181,8 +181,9 @@ return true; } -bool ReloadButton::GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) { +bool ReloadButton::GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const { switch (command_id) { case IDS_RELOAD_MENU_NORMAL_RELOAD_ITEM: GetWidget()->GetAccelerator(IDC_RELOAD, accelerator);
diff --git a/chrome/browser/ui/views/toolbar/reload_button.h b/chrome/browser/ui/views/toolbar/reload_button.h index b9e8bf2..31717773 100644 --- a/chrome/browser/ui/views/toolbar/reload_button.h +++ b/chrome/browser/ui/views/toolbar/reload_button.h
@@ -63,7 +63,7 @@ bool IsCommandIdEnabled(int command_id) const override; bool IsCommandIdVisible(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; private:
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc index c4785ea..1bb235c 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -463,7 +463,7 @@ // ToolbarView, ui::AcceleratorProvider implementation: bool ToolbarView::GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return GetWidget()->GetAccelerator(command_id, accelerator); }
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h index 9276225a..d8a12a50 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.h +++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -137,7 +137,7 @@ // ui::AcceleratorProvider: bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; // views::View: gfx::Size GetPreferredSize() const override;
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc index a864fc1..29f24e21 100644 --- a/chrome/browser/ui/views/translate/translate_bubble_view.cc +++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc
@@ -318,7 +318,7 @@ bool TranslateBubbleView::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; }
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.h b/chrome/browser/ui/views/translate/translate_bubble_view.h index 7bf93806..ec8f744 100644 --- a/chrome/browser/ui/views/translate/translate_bubble_view.h +++ b/chrome/browser/ui/views/translate/translate_bubble_view.h
@@ -109,7 +109,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; // views::StyledLabelListener method.
diff --git a/chrome/browser/ui/views/website_settings/chooser_bubble_ui_view.cc b/chrome/browser/ui/views/website_settings/chooser_bubble_ui_view.cc index b247e10..c6cb2d1 100644 --- a/chrome/browser/ui/views/website_settings/chooser_bubble_ui_view.cc +++ b/chrome/browser/ui/views/website_settings/chooser_bubble_ui_view.cc
@@ -21,15 +21,11 @@ #include "chrome/browser/ui/views/location_bar/location_bar_view.h" #include "chrome/browser/ui/views/location_bar/location_icon_view.h" #include "chrome/browser/ui/website_settings/chooser_bubble_delegate.h" -#include "chrome/grit/generated_resources.h" #include "components/bubble/bubble_controller.h" -#include "components/url_formatter/elide_url.h" -#include "ui/base/l10n/l10n_util.h" #include "ui/views/controls/styled_label.h" #include "ui/views/controls/styled_label_listener.h" #include "ui/views/controls/table/table_view_observer.h" #include "ui/views/window/dialog_client_view.h" -#include "url/origin.h" std::unique_ptr<BubbleUi> ChooserBubbleDelegate::BuildBubbleUi() { return base::WrapUnique( @@ -81,7 +77,6 @@ void UpdateTableModel() const; private: - url::Origin origin_; ChooserContentView* chooser_content_view_; BubbleReference bubble_reference_; @@ -109,7 +104,6 @@ // | Not seeing your device? Get help | // ------------------------------------ - origin_ = chooser_controller->GetOrigin(); chooser_content_view_ = new ChooserContentView(this, std::move(chooser_controller)); } @@ -117,10 +111,7 @@ ChooserBubbleUiViewDelegate::~ChooserBubbleUiViewDelegate() {} base::string16 ChooserBubbleUiViewDelegate::GetWindowTitle() const { - return l10n_util::GetStringFUTF16( - IDS_DEVICE_CHOOSER_PROMPT, - url_formatter::FormatOriginForSecurityDisplay( - origin_, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC)); + return chooser_content_view_->GetWindowTitle(); } base::string16 ChooserBubbleUiViewDelegate::GetDialogButtonLabel(
diff --git a/chrome/browser/ui/website_settings/mock_permission_bubble_factory.cc b/chrome/browser/ui/website_settings/mock_permission_bubble_factory.cc index 94955902..fc135d73 100644 --- a/chrome/browser/ui/website_settings/mock_permission_bubble_factory.cc +++ b/chrome/browser/ui/website_settings/mock_permission_bubble_factory.cc
@@ -7,16 +7,16 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/run_loop.h" +#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/ui/website_settings/mock_permission_bubble_view.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" MockPermissionBubbleFactory::MockPermissionBubbleFactory( - PermissionBubbleManager* manager) + PermissionRequestManager* manager) : can_update_ui_(false), show_count_(0), requests_count_(0), total_requests_count_(0), - response_type_(PermissionBubbleManager::NONE), + response_type_(PermissionRequestManager::NONE), manager_(manager) { manager->view_factory_ = base::Bind(&MockPermissionBubbleFactory::Create, base::Unretained(this));
diff --git a/chrome/browser/ui/website_settings/mock_permission_bubble_factory.h b/chrome/browser/ui/website_settings/mock_permission_bubble_factory.h index 471039f..5574e0d 100644 --- a/chrome/browser/ui/website_settings/mock_permission_bubble_factory.h +++ b/chrome/browser/ui/website_settings/mock_permission_bubble_factory.h
@@ -8,8 +8,7 @@ #include <memory> #include <vector> -#include "base/callback.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" +#include "chrome/browser/permissions/permission_request_manager.h" class Browser; class PermissionBubbleView; @@ -19,10 +18,10 @@ // test the bubble manager logic. Should not be used for anything that requires // actual UI. // See example usage in -// chrome/browser/ui/website_settings/permission_bubble_manager_unittest.cc +// chrome/browser/permissions/permission_request_manager_unittest.cc class MockPermissionBubbleFactory { public: - explicit MockPermissionBubbleFactory(PermissionBubbleManager* manager); + explicit MockPermissionBubbleFactory(PermissionRequestManager* manager); ~MockPermissionBubbleFactory(); // Create method called by the PBM to show a bubble. @@ -34,7 +33,7 @@ void DocumentOnLoadCompletedInMainFrame(); - void set_response_type(PermissionBubbleManager::AutoResponseType type) { + void set_response_type(PermissionRequestManager::AutoResponseType type) { response_type_ = type; } @@ -65,12 +64,12 @@ int requests_count_; int total_requests_count_; std::vector<MockPermissionBubbleView*> views_; - PermissionBubbleManager::AutoResponseType response_type_; + PermissionRequestManager::AutoResponseType response_type_; base::Closure show_bubble_quit_closure_; // The bubble manager that will be associated with this factory. - PermissionBubbleManager* manager_; + PermissionRequestManager* manager_; DISALLOW_COPY_AND_ASSIGN(MockPermissionBubbleFactory); };
diff --git a/chrome/browser/ui/website_settings/mock_permission_bubble_view.cc b/chrome/browser/ui/website_settings/mock_permission_bubble_view.cc index 470ac0a4..598375e 100644 --- a/chrome/browser/ui/website_settings/mock_permission_bubble_view.cc +++ b/chrome/browser/ui/website_settings/mock_permission_bubble_view.cc
@@ -6,8 +6,8 @@ #include "base/bind.h" #include "base/run_loop.h" +#include "chrome/browser/permissions/permission_request_manager.h" #include "chrome/browser/ui/website_settings/mock_permission_bubble_factory.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" MockPermissionBubbleView::~MockPermissionBubbleView() { Hide(); @@ -48,7 +48,7 @@ MockPermissionBubbleView::MockPermissionBubbleView( MockPermissionBubbleFactory* factory, - PermissionBubbleManager* manager) + PermissionRequestManager* manager) : factory_(factory), manager_(manager), can_update_ui_(true),
diff --git a/chrome/browser/ui/website_settings/mock_permission_bubble_view.h b/chrome/browser/ui/website_settings/mock_permission_bubble_view.h index 2a27f997..dd29f8b7 100644 --- a/chrome/browser/ui/website_settings/mock_permission_bubble_view.h +++ b/chrome/browser/ui/website_settings/mock_permission_bubble_view.h
@@ -8,7 +8,7 @@ #include "chrome/browser/ui/website_settings/permission_bubble_view.h" class MockPermissionBubbleFactory; -class PermissionBubbleManager; +class PermissionRequestManager; // Provides a skeleton class for unit and browser testing when trying to test // the bubble manager logic. Should not be used for anything that requires @@ -32,10 +32,10 @@ friend class MockPermissionBubbleFactory; MockPermissionBubbleView(MockPermissionBubbleFactory* factory, - PermissionBubbleManager* manager); + PermissionRequestManager* manager); MockPermissionBubbleFactory* factory_; - PermissionBubbleManager* manager_; + PermissionRequestManager* manager_; bool can_update_ui_; bool is_visible_; };
diff --git a/chrome/browser/ui/website_settings/permission_bubble_manager.cc b/chrome/browser/ui/website_settings/permission_bubble_manager.cc deleted file mode 100644 index a0ccb8fb..0000000 --- a/chrome/browser/ui/website_settings/permission_bubble_manager.cc +++ /dev/null
@@ -1,514 +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. - -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" - -#include <algorithm> - -#include "base/command_line.h" -#include "base/metrics/user_metrics_action.h" -#include "build/build_config.h" -#include "chrome/browser/permissions/permission_uma_util.h" -#include "chrome/browser/ui/website_settings/permission_bubble_request.h" -#include "chrome/common/chrome_switches.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/navigation_details.h" -#include "content/public/browser/user_metrics.h" -#include "url/origin.h" - -#if !defined(OS_ANDROID) -#include "chrome/browser/ui/browser_finder.h" -#endif - -namespace { - -class CancelledRequest : public PermissionBubbleRequest { - public: - explicit CancelledRequest(PermissionBubbleRequest* cancelled) - : icon_(cancelled->GetIconId()), - message_fragment_(cancelled->GetMessageTextFragment()), - origin_(cancelled->GetOrigin()) {} - ~CancelledRequest() override {} - - int GetIconId() const override { return icon_; } - base::string16 GetMessageTextFragment() const override { - return message_fragment_; - } - GURL GetOrigin() const override { return origin_; } - - // These are all no-ops since the placeholder is non-forwarding. - void PermissionGranted() override {} - void PermissionDenied() override {} - void Cancelled() override {} - - void RequestFinished() override { delete this; } - - private: - int icon_; - base::string16 message_fragment_; - GURL origin_; -}; - -bool IsMessageTextEqual(PermissionBubbleRequest* a, - PermissionBubbleRequest* b) { - if (a == b) - return true; - if (a->GetMessageTextFragment() == b->GetMessageTextFragment() && - a->GetOrigin() == b->GetOrigin()) { - return true; - } - return false; -} - -} // namespace - -// PermissionBubbleManager::Observer ------------------------------------------- - -PermissionBubbleManager::Observer::~Observer() { -} - -void PermissionBubbleManager::Observer::OnBubbleAdded() { -} - -// PermissionBubbleManager ----------------------------------------------------- - -DEFINE_WEB_CONTENTS_USER_DATA_KEY(PermissionBubbleManager); - -PermissionBubbleManager::PermissionBubbleManager( - content::WebContents* web_contents) - : content::WebContentsObserver(web_contents), -#if !defined(OS_ANDROID) // No bubbles in android tests. - view_factory_(base::Bind(&PermissionBubbleView::Create)), -#endif - view_(nullptr), - main_frame_has_fully_loaded_(false), - auto_response_for_test_(NONE), - weak_factory_(this) { -} - -PermissionBubbleManager::~PermissionBubbleManager() { - if (view_ != NULL) - view_->SetDelegate(NULL); - - for (PermissionBubbleRequest* request : requests_) - request->RequestFinished(); - for (PermissionBubbleRequest* request : queued_requests_) - request->RequestFinished(); - for (PermissionBubbleRequest* request : queued_frame_requests_) - request->RequestFinished(); - for (const auto& entry : duplicate_requests_) - entry.second->RequestFinished(); -} - -void PermissionBubbleManager::AddRequest(PermissionBubbleRequest* request) { - content::RecordAction(base::UserMetricsAction("PermissionBubbleRequest")); - // TODO(gbillock): is there a race between an early request on a - // newly-navigated page and the to-be-cleaned-up requests on the previous - // page? We should maybe listen to DidStartNavigationToPendingEntry (and - // any other renderer-side nav initiations?). Double-check this for - // correct behavior on interstitials -- we probably want to basically queue - // any request for which GetVisibleURL != GetLastCommittedURL. - request_url_ = web_contents()->GetLastCommittedURL(); - bool is_main_frame = url::Origin(request_url_) - .IsSameOriginWith(url::Origin(request->GetOrigin())); - - // Don't re-add an existing request or one with a duplicate text request. - PermissionBubbleRequest* existing_request = GetExistingRequest(request); - if (existing_request) { - // |request| is a duplicate. Add it to |duplicate_requests_| unless it's the - // same object as |existing_request| or an existing duplicate. - if (request == existing_request) - return; - auto range = duplicate_requests_.equal_range(existing_request); - for (auto it = range.first; it != range.second; ++it) { - if (request == it->second) - return; - } - duplicate_requests_.insert(std::make_pair(existing_request, request)); - return; - } - - if (IsBubbleVisible()) { - if (is_main_frame) { - content::RecordAction( - base::UserMetricsAction("PermissionBubbleRequestQueued")); - queued_requests_.push_back(request); - } else { - content::RecordAction( - base::UserMetricsAction("PermissionBubbleIFrameRequestQueued")); - queued_frame_requests_.push_back(request); - } - return; - } - - if (is_main_frame) { - requests_.push_back(request); - accept_states_.push_back(true); - } else { - content::RecordAction( - base::UserMetricsAction("PermissionBubbleIFrameRequestQueued")); - queued_frame_requests_.push_back(request); - } - - ScheduleShowBubble(); -} - -void PermissionBubbleManager::CancelRequest(PermissionBubbleRequest* request) { - // First look in the queued requests, where we can simply finish the request - // and go on. - std::vector<PermissionBubbleRequest*>::iterator requests_iter; - for (requests_iter = queued_requests_.begin(); - requests_iter != queued_requests_.end(); - requests_iter++) { - if (*requests_iter == request) { - RequestFinishedIncludingDuplicates(*requests_iter); - queued_requests_.erase(requests_iter); - return; - } - } - for (requests_iter = queued_frame_requests_.begin(); - requests_iter != queued_frame_requests_.end(); requests_iter++) { - if (*requests_iter == request) { - RequestFinishedIncludingDuplicates(*requests_iter); - queued_frame_requests_.erase(requests_iter); - return; - } - } - - std::vector<bool>::iterator accepts_iter = accept_states_.begin(); - for (requests_iter = requests_.begin(), accepts_iter = accept_states_.begin(); - requests_iter != requests_.end(); - requests_iter++, accepts_iter++) { - if (*requests_iter != request) - continue; - - // We can simply erase the current entry in the request table if we aren't - // showing the dialog, or if we are showing it and it can accept the update. - bool can_erase = !IsBubbleVisible() || view_->CanAcceptRequestUpdate(); - if (can_erase) { - RequestFinishedIncludingDuplicates(*requests_iter); - requests_.erase(requests_iter); - accept_states_.erase(accepts_iter); - - if (IsBubbleVisible()) { - view_->Hide(); - // Will redraw the bubble if it is being shown. - TriggerShowBubble(); - } - return; - } - - // Cancel the existing request and replace it with a dummy. - PermissionBubbleRequest* cancelled_request = - new CancelledRequest(*requests_iter); - RequestFinishedIncludingDuplicates(*requests_iter); - *requests_iter = cancelled_request; - return; - } - - // Since |request| wasn't found in queued_requests_, queued_frame_requests_ or - // requests_ it must have been marked as a duplicate. We can't search - // duplicate_requests_ by value, so instead use GetExistingRequest to find the - // key (request it was duped against), and iterate through duplicates of that. - PermissionBubbleRequest* existing_request = GetExistingRequest(request); - auto range = duplicate_requests_.equal_range(existing_request); - for (auto it = range.first; it != range.second; ++it) { - if (request == it->second) { - it->second->RequestFinished(); - duplicate_requests_.erase(it); - return; - } - } - - NOTREACHED(); // Callers should not cancel requests that are not pending. -} - -void PermissionBubbleManager::HideBubble() { - // Disengage from the existing view if there is one. - if (!view_) - return; - - view_->SetDelegate(nullptr); - view_->Hide(); - view_.reset(); -} - -void PermissionBubbleManager::DisplayPendingRequests() { - if (IsBubbleVisible()) - return; - -#if defined(OS_ANDROID) - NOTREACHED(); - return; -#else - view_ = view_factory_.Run(chrome::FindBrowserWithWebContents(web_contents())); - view_->SetDelegate(this); -#endif - - TriggerShowBubble(); -} - -void PermissionBubbleManager::UpdateAnchorPosition() { - if (view_) - view_->UpdateAnchorPosition(); -} - -bool PermissionBubbleManager::IsBubbleVisible() { - return view_ && view_->IsVisible(); -} - -gfx::NativeWindow PermissionBubbleManager::GetBubbleWindow() { - if (view_) - return view_->GetNativeWindow(); - return nullptr; -} - -void PermissionBubbleManager::DidNavigateMainFrame( - const content::LoadCommittedDetails& details, - const content::FrameNavigateParams& params) { - if (details.is_in_page) - return; - - CancelPendingQueues(); - FinalizeBubble(); - main_frame_has_fully_loaded_ = false; -} - -void PermissionBubbleManager::DocumentOnLoadCompletedInMainFrame() { - main_frame_has_fully_loaded_ = true; - // This is scheduled because while all calls to the browser have been - // issued at DOMContentLoaded, they may be bouncing around in scheduled - // callbacks finding the UI thread still. This makes sure we allow those - // scheduled calls to AddRequest to complete before we show the page-load - // permissions bubble. - ScheduleShowBubble(); -} - -void PermissionBubbleManager::DocumentLoadedInFrame( - content::RenderFrameHost* render_frame_host) { - ScheduleShowBubble(); -} - -void PermissionBubbleManager::WebContentsDestroyed() { - // If the web contents has been destroyed, treat the bubble as cancelled. - CancelPendingQueues(); - FinalizeBubble(); - - // The WebContents is going away; be aggressively paranoid and delete - // ourselves lest other parts of the system attempt to add permission bubbles - // or use us otherwise during the destruction. - web_contents()->RemoveUserData(UserDataKey()); - // That was the equivalent of "delete this". This object is now destroyed; - // returning from this function is the only safe thing to do. -} - -void PermissionBubbleManager::ToggleAccept(int request_index, bool new_value) { - DCHECK(request_index < static_cast<int>(accept_states_.size())); - accept_states_[request_index] = new_value; -} - -void PermissionBubbleManager::Accept() { - PermissionUmaUtil::PermissionPromptAccepted(requests_, accept_states_); - - std::vector<PermissionBubbleRequest*>::iterator requests_iter; - std::vector<bool>::iterator accepts_iter = accept_states_.begin(); - for (requests_iter = requests_.begin(), accepts_iter = accept_states_.begin(); - requests_iter != requests_.end(); - requests_iter++, accepts_iter++) { - if (*accepts_iter) { - PermissionGrantedIncludingDuplicates(*requests_iter); - } else { - PermissionDeniedIncludingDuplicates(*requests_iter); - } - } - FinalizeBubble(); -} - -void PermissionBubbleManager::Deny() { - PermissionUmaUtil::PermissionPromptDenied(requests_); - - std::vector<PermissionBubbleRequest*>::iterator requests_iter; - for (requests_iter = requests_.begin(); - requests_iter != requests_.end(); - requests_iter++) { - PermissionDeniedIncludingDuplicates(*requests_iter); - } - FinalizeBubble(); -} - -void PermissionBubbleManager::Closing() { - std::vector<PermissionBubbleRequest*>::iterator requests_iter; - for (requests_iter = requests_.begin(); - requests_iter != requests_.end(); - requests_iter++) { - CancelledIncludingDuplicates(*requests_iter); - } - FinalizeBubble(); -} - -void PermissionBubbleManager::ScheduleShowBubble() { - // ::ScheduleShowBubble() will be called again when the main frame will be - // loaded. - if (!main_frame_has_fully_loaded_) - return; - - content::BrowserThread::PostTask( - content::BrowserThread::UI, - FROM_HERE, - base::Bind(&PermissionBubbleManager::TriggerShowBubble, - weak_factory_.GetWeakPtr())); -} - -void PermissionBubbleManager::TriggerShowBubble() { - if (!view_) - return; - if (IsBubbleVisible()) - return; - if (!main_frame_has_fully_loaded_) - return; - if (requests_.empty() && queued_requests_.empty() && - queued_frame_requests_.empty()) { - return; - } - - if (requests_.empty()) { - if (queued_requests_.size()) - requests_.swap(queued_requests_); - else - requests_.swap(queued_frame_requests_); - - // Sets the default value for each request to be 'accept'. - accept_states_.resize(requests_.size(), true); - } - - view_->Show(requests_, accept_states_); - PermissionUmaUtil::PermissionPromptShown(requests_); - NotifyBubbleAdded(); - - // If in testing mode, automatically respond to the bubble that was shown. - if (auto_response_for_test_ != NONE) - DoAutoResponseForTesting(); -} - -void PermissionBubbleManager::FinalizeBubble() { - if (view_) - view_->Hide(); - - std::vector<PermissionBubbleRequest*>::iterator requests_iter; - for (requests_iter = requests_.begin(); - requests_iter != requests_.end(); - requests_iter++) { - RequestFinishedIncludingDuplicates(*requests_iter); - } - requests_.clear(); - accept_states_.clear(); - if (queued_requests_.size() || queued_frame_requests_.size()) - TriggerShowBubble(); - else - request_url_ = GURL(); -} - -void PermissionBubbleManager::CancelPendingQueues() { - std::vector<PermissionBubbleRequest*>::iterator requests_iter; - for (requests_iter = queued_requests_.begin(); - requests_iter != queued_requests_.end(); - requests_iter++) { - RequestFinishedIncludingDuplicates(*requests_iter); - } - for (requests_iter = queued_frame_requests_.begin(); - requests_iter != queued_frame_requests_.end(); - requests_iter++) { - RequestFinishedIncludingDuplicates(*requests_iter); - } - queued_requests_.clear(); - queued_frame_requests_.clear(); -} - -PermissionBubbleRequest* PermissionBubbleManager::GetExistingRequest( - PermissionBubbleRequest* request) { - for (PermissionBubbleRequest* existing_request : requests_) - if (IsMessageTextEqual(existing_request, request)) - return existing_request; - for (PermissionBubbleRequest* existing_request : queued_requests_) - if (IsMessageTextEqual(existing_request, request)) - return existing_request; - for (PermissionBubbleRequest* existing_request : queued_frame_requests_) - if (IsMessageTextEqual(existing_request, request)) - return existing_request; - return nullptr; -} - -void PermissionBubbleManager::PermissionGrantedIncludingDuplicates( - PermissionBubbleRequest* request) { - DCHECK_EQ(request, GetExistingRequest(request)) - << "Only requests in [queued_[frame_]]requests_ can have duplicates"; - request->PermissionGranted(); - auto range = duplicate_requests_.equal_range(request); - for (auto it = range.first; it != range.second; ++it) - it->second->PermissionGranted(); -} -void PermissionBubbleManager::PermissionDeniedIncludingDuplicates( - PermissionBubbleRequest* request) { - DCHECK_EQ(request, GetExistingRequest(request)) - << "Only requests in [queued_[frame_]]requests_ can have duplicates"; - request->PermissionDenied(); - auto range = duplicate_requests_.equal_range(request); - for (auto it = range.first; it != range.second; ++it) - it->second->PermissionDenied(); -} -void PermissionBubbleManager::CancelledIncludingDuplicates( - PermissionBubbleRequest* request) { - DCHECK_EQ(request, GetExistingRequest(request)) - << "Only requests in [queued_[frame_]]requests_ can have duplicates"; - request->Cancelled(); - auto range = duplicate_requests_.equal_range(request); - for (auto it = range.first; it != range.second; ++it) - it->second->Cancelled(); -} -void PermissionBubbleManager::RequestFinishedIncludingDuplicates( - PermissionBubbleRequest* request) { - // We can't call GetExistingRequest here, because other entries in requests_, - // queued_requests_ or queued_frame_requests_ might already have been deleted. - DCHECK_EQ(1, std::count(requests_.begin(), requests_.end(), request) + - std::count(queued_requests_.begin(), queued_requests_.end(), - request) + - std::count(queued_frame_requests_.begin(), - queued_frame_requests_.end(), request)) - << "Only requests in [queued_[frame_]]requests_ can have duplicates"; - request->RequestFinished(); - // Beyond this point, |request| has probably been deleted. - auto range = duplicate_requests_.equal_range(request); - for (auto it = range.first; it != range.second; ++it) - it->second->RequestFinished(); - // Additionally, we can now remove the duplicates. - duplicate_requests_.erase(request); -} - -void PermissionBubbleManager::AddObserver(Observer* observer) { - observer_list_.AddObserver(observer); -} - -void PermissionBubbleManager::RemoveObserver(Observer* observer) { - observer_list_.RemoveObserver(observer); -} - -void PermissionBubbleManager::NotifyBubbleAdded() { - FOR_EACH_OBSERVER(Observer, observer_list_, OnBubbleAdded()); -} - -void PermissionBubbleManager::DoAutoResponseForTesting() { - switch (auto_response_for_test_) { - case ACCEPT_ALL: - Accept(); - break; - case DENY_ALL: - Deny(); - break; - case DISMISS: - Closing(); - break; - case NONE: - NOTREACHED(); - } -}
diff --git a/chrome/browser/ui/website_settings/permission_bubble_manager.h b/chrome/browser/ui/website_settings/permission_bubble_manager.h deleted file mode 100644 index 6a1c036..0000000 --- a/chrome/browser/ui/website_settings/permission_bubble_manager.h +++ /dev/null
@@ -1,194 +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 CHROME_BROWSER_UI_WEBSITE_SETTINGS_PERMISSION_BUBBLE_MANAGER_H_ -#define CHROME_BROWSER_UI_WEBSITE_SETTINGS_PERMISSION_BUBBLE_MANAGER_H_ - -#include <unordered_map> -#include <vector> - -#include "base/gtest_prod_util.h" -#include "base/memory/weak_ptr.h" -#include "base/observer_list.h" -#include "chrome/browser/ui/website_settings/permission_bubble_view.h" -#include "content/public/browser/web_contents_observer.h" -#include "content/public/browser/web_contents_user_data.h" - -class PermissionBubbleRequest; - -// Provides access to permissions bubbles. Allows clients to add a request -// callback interface to the existing permission bubble configuration. -// Depending on the situation and policy, that may add new UI to an existing -// permission bubble, create and show a new permission bubble, or provide no -// visible UI action at all. (In that case, the request will be immediately -// informed that the permission request failed.) -// -// A PermissionBubbleManager is associated with a particular WebContents. -// Requests attached to a particular WebContents' PBM must outlive it. -// -// The PermissionBubbleManager should be addressed on the UI thread. -class PermissionBubbleManager - : public content::WebContentsObserver, - public content::WebContentsUserData<PermissionBubbleManager>, - public PermissionBubbleView::Delegate { - public: - class Observer { - public: - virtual ~Observer(); - virtual void OnBubbleAdded(); - }; - - enum AutoResponseType { - NONE, - ACCEPT_ALL, - DENY_ALL, - DISMISS - }; - - ~PermissionBubbleManager() override; - - // Adds a new request to the permission bubble. Ownership of the request - // remains with the caller. The caller must arrange for the request to - // outlive the PermissionBubbleManager. If a bubble is visible when this - // call is made, the request will be queued up and shown after the current - // bubble closes. A request with message text identical to an outstanding - // request will be merged with the outstanding request, and will have the same - // callbacks called as the outstanding request. - void AddRequest(PermissionBubbleRequest* request); - - // Cancels an outstanding request. This may have different effects depending - // on what is going on with the bubble. If the request is pending, it will be - // removed and never shown. If the request is showing, it will continue to be - // shown, but the user's action won't be reported back to the request object. - // In some circumstances, we can remove the request from the bubble, and may - // do so. The request will have RequestFinished executed on it if it is found, - // at which time the caller is free to delete the request. - void CancelRequest(PermissionBubbleRequest* request); - - // Hides the bubble. - void HideBubble(); - - // Will show a permission bubble if there is a pending permission request on - // the web contents that the PermissionBubbleManager belongs to. - void DisplayPendingRequests(); - - // Will reposition the bubble (may change parent if necessary). - void UpdateAnchorPosition(); - - // True if a permission bubble is currently visible. - // TODO(hcarmona): Remove this as part of the bubble API work. - bool IsBubbleVisible(); - - // Get the native window of the bubble. - // TODO(hcarmona): Remove this as part of the bubble API work. - gfx::NativeWindow GetBubbleWindow(); - - // For observing the status of the permission bubble manager. - void AddObserver(Observer* observer); - void RemoveObserver(Observer* observer); - - // Do NOT use this methods in production code. Use this methods in browser - // tests that need to accept or deny permissions when requested in - // JavaScript. Your test needs to set this appropriately, and then the bubble - // will proceed as desired as soon as Show() is called. - void set_auto_response_for_test(AutoResponseType response) { - auto_response_for_test_ = response; - } - - private: - // TODO(felt): Update testing so that it doesn't involve a lot of friends. - friend class GeolocationBrowserTest; - friend class GeolocationPermissionContextTests; - friend class MockPermissionBubbleFactory; - friend class MockPermissionBubbleView; - friend class PermissionBubbleManagerTest; - friend class PermissionContextBaseTests; - friend class content::WebContentsUserData<PermissionBubbleManager>; - FRIEND_TEST_ALL_PREFIXES(DownloadTest, TestMultipleDownloadsBubble); - - explicit PermissionBubbleManager(content::WebContents* web_contents); - - // WebContentsObserver: - void DidNavigateMainFrame( - const content::LoadCommittedDetails& details, - const content::FrameNavigateParams& params) override; - void DocumentOnLoadCompletedInMainFrame() override; - void DocumentLoadedInFrame( - content::RenderFrameHost* render_frame_host) override; - void WebContentsDestroyed() override; - - // PermissionBubbleView::Delegate: - void ToggleAccept(int request_index, bool new_value) override; - void Accept() override; - void Deny() override; - void Closing() override; - - // Posts a task which will allow the bubble to become visible if it is needed. - void ScheduleShowBubble(); - - // Shows the bubble if it is not already visible and there are pending - // requests. - void TriggerShowBubble(); - - // Finalize the pending permissions request. - void FinalizeBubble(); - - // Cancel any pending requests. This is called if the WebContents - // on which permissions calls are pending is destroyed or navigated away - // from the requesting page. - void CancelPendingQueues(); - - // Searches |requests_|, |queued_requests_| and |queued_frame_requests_| - but - // *not* |duplicate_requests_| - for a request matching |request|, and returns - // the matching request, or |nullptr| if no match. Note that the matching - // request may or may not be the same object as |request|. - PermissionBubbleRequest* GetExistingRequest(PermissionBubbleRequest* request); - - // Returns true if |queue| contains a request which was generated by a user - // gesture. Returns false otherwise. - bool HasUserGestureRequest( - const std::vector<PermissionBubbleRequest*>& queue); - - // Calls PermissionGranted on a request and all its duplicates. - void PermissionGrantedIncludingDuplicates(PermissionBubbleRequest* request); - // Calls PermissionDenied on a request and all its duplicates. - void PermissionDeniedIncludingDuplicates(PermissionBubbleRequest* request); - // Calls Cancelled on a request and all its duplicates. - void CancelledIncludingDuplicates(PermissionBubbleRequest* request); - // Calls RequestFinished on a request and all its duplicates. - void RequestFinishedIncludingDuplicates(PermissionBubbleRequest* request); - - void NotifyBubbleAdded(); - - void DoAutoResponseForTesting(); - - // Factory to be used to create views when needed. - PermissionBubbleView::Factory view_factory_; - - // The UI surface to be used to display the permissions requests. - std::unique_ptr<PermissionBubbleView> view_; - - std::vector<PermissionBubbleRequest*> requests_; - std::vector<PermissionBubbleRequest*> queued_requests_; - std::vector<PermissionBubbleRequest*> queued_frame_requests_; - // Maps from the first request of a kind to subsequent requests that were - // duped against it. - std::unordered_multimap<PermissionBubbleRequest*, PermissionBubbleRequest*> - duplicate_requests_; - - // URL of the main frame in the WebContents to which this manager is attached. - // TODO(gbillock): if there are iframes in the page, we need to deal with it. - GURL request_url_; - bool main_frame_has_fully_loaded_; - - // Whether each of the requests in |requests_| is accepted by the user. - std::vector<bool> accept_states_; - - base::ObserverList<Observer> observer_list_; - AutoResponseType auto_response_for_test_; - - base::WeakPtrFactory<PermissionBubbleManager> weak_factory_; -}; - -#endif // CHROME_BROWSER_UI_WEBSITE_SETTINGS_PERMISSION_BUBBLE_MANAGER_H_
diff --git a/chrome/browser/ui/website_settings/permission_bubble_manager_browsertest.cc b/chrome/browser/ui/website_settings/permission_bubble_manager_browsertest.cc deleted file mode 100644 index 01155cb..0000000 --- a/chrome/browser/ui/website_settings/permission_bubble_manager_browsertest.cc +++ /dev/null
@@ -1,251 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" - -#include "base/command_line.h" -#include "base/metrics/field_trial.h" -#include "build/build_config.h" -#include "chrome/browser/permissions/permission_context_base.h" -#include "chrome/browser/permissions/permission_util.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/website_settings/mock_permission_bubble_factory.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "chrome/test/base/ui_test_utils.h" -#include "components/variations/variations_associated_data.h" -#include "content/public/browser/permission_type.h" -#include "content/public/test/browser_test_utils.h" -#include "content/public/test/test_utils.h" -#include "net/test/embedded_test_server/embedded_test_server.h" - -namespace { - -const char* kPermissionsKillSwitchFieldStudy = - PermissionContextBase::kPermissionsKillSwitchFieldStudy; -const char* kPermissionsKillSwitchBlockedValue = - PermissionContextBase::kPermissionsKillSwitchBlockedValue; -const char kPermissionsKillSwitchTestGroup[] = "TestGroup"; - -class PermissionBubbleManagerBrowserTest : public InProcessBrowserTest { - public: - PermissionBubbleManagerBrowserTest() = default; - ~PermissionBubbleManagerBrowserTest() override = default; - - void SetUpOnMainThread() override { - InProcessBrowserTest::SetUpOnMainThread(); - PermissionBubbleManager* manager = GetPermissionBubbleManager(); - mock_permission_bubble_factory_.reset( - new MockPermissionBubbleFactory(manager)); - manager->DisplayPendingRequests(); - } - - void TearDownOnMainThread() override { - mock_permission_bubble_factory_.reset(); - InProcessBrowserTest::TearDownOnMainThread(); - } - - PermissionBubbleManager* GetPermissionBubbleManager() { - return PermissionBubbleManager::FromWebContents( - browser()->tab_strip_model()->GetActiveWebContents()); - } - - MockPermissionBubbleFactory* bubble_factory() { - return mock_permission_bubble_factory_.get(); - } - - void EnableKillSwitch(content::PermissionType permission_type) { - std::map<std::string, std::string> params; - params[PermissionUtil::GetPermissionString(permission_type)] = - kPermissionsKillSwitchBlockedValue; - variations::AssociateVariationParams( - kPermissionsKillSwitchFieldStudy, kPermissionsKillSwitchTestGroup, - params); - base::FieldTrialList::CreateFieldTrial(kPermissionsKillSwitchFieldStudy, - kPermissionsKillSwitchTestGroup); - } - - private: - std::unique_ptr<MockPermissionBubbleFactory> mock_permission_bubble_factory_; -}; - -// Requests before the load event should be bundled into one bubble. -// http://crbug.com/512849 flaky -IN_PROC_BROWSER_TEST_F(PermissionBubbleManagerBrowserTest, - DISABLED_RequestsBeforeLoad) { - ASSERT_TRUE(embedded_test_server()->Start()); - - ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( - browser(), - embedded_test_server()->GetURL("/permissions/requests-before-load.html"), - 1); - bubble_factory()->WaitForPermissionBubble(); - - EXPECT_EQ(1, bubble_factory()->show_count()); - EXPECT_EQ(2, bubble_factory()->total_request_count()); -} - -// Requests before the load should not be bundled with a request after the load. -IN_PROC_BROWSER_TEST_F(PermissionBubbleManagerBrowserTest, - RequestsBeforeAfterLoad) { - ASSERT_TRUE(embedded_test_server()->Start()); - - ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( - browser(), - embedded_test_server()->GetURL( - "/permissions/requests-before-after-load.html"), - 1); - bubble_factory()->WaitForPermissionBubble(); - - EXPECT_EQ(1, bubble_factory()->show_count()); - EXPECT_EQ(1, bubble_factory()->total_request_count()); -} - -// Navigating twice to the same URL should be equivalent to refresh. This means -// showing the bubbles twice. -// http://crbug.com/512849 flaky -#if defined(OS_WIN) -#define MAYBE_NavTwice DISABLED_NavTwice -#else -#define MAYBE_NavTwice NavTwice -#endif -IN_PROC_BROWSER_TEST_F(PermissionBubbleManagerBrowserTest, MAYBE_NavTwice) { - ASSERT_TRUE(embedded_test_server()->Start()); - - ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( - browser(), - embedded_test_server()->GetURL("/permissions/requests-before-load.html"), - 1); - bubble_factory()->WaitForPermissionBubble(); - - ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( - browser(), - embedded_test_server()->GetURL("/permissions/requests-before-load.html"), - 1); - bubble_factory()->WaitForPermissionBubble(); - - EXPECT_EQ(2, bubble_factory()->show_count()); - EXPECT_EQ(4, bubble_factory()->total_request_count()); -} - -// Navigating twice to the same URL with a hash should be navigation within the -// page. This means the bubble is only shown once. -// http://crbug.com/512849 flaky -#if defined(OS_WIN) -#define MAYBE_NavTwiceWithHash DISABLED_NavTwiceWithHash -#else -#define MAYBE_NavTwiceWithHash NavTwiceWithHash -#endif -IN_PROC_BROWSER_TEST_F(PermissionBubbleManagerBrowserTest, - MAYBE_NavTwiceWithHash) { - ASSERT_TRUE(embedded_test_server()->Start()); - - ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( - browser(), - embedded_test_server()->GetURL("/permissions/requests-before-load.html"), - 1); - bubble_factory()->WaitForPermissionBubble(); - - ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( - browser(), - embedded_test_server()->GetURL( - "/permissions/requests-before-load.html#0"), - 1); - bubble_factory()->WaitForPermissionBubble(); - - EXPECT_EQ(1, bubble_factory()->show_count()); - EXPECT_EQ(2, bubble_factory()->total_request_count()); -} - -// Bubble requests should be shown after in-page navigation. -IN_PROC_BROWSER_TEST_F(PermissionBubbleManagerBrowserTest, InPageNavigation) { - ASSERT_TRUE(embedded_test_server()->Start()); - - ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( - browser(), - embedded_test_server()->GetURL("/empty.html"), - 1); - - ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( - browser(), - embedded_test_server()->GetURL("/empty.html#0"), - 1); - - // Request 'geolocation' permission. - ExecuteScriptAndGetValue( - browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(), - "navigator.geolocation.getCurrentPosition(function(){});"); - bubble_factory()->WaitForPermissionBubble(); - - EXPECT_EQ(1, bubble_factory()->show_count()); - EXPECT_EQ(1, bubble_factory()->total_request_count()); -} - -// Bubble requests should not be shown when the killswitch is on. -IN_PROC_BROWSER_TEST_F(PermissionBubbleManagerBrowserTest, - KillSwitchGeolocation) { - ASSERT_TRUE(embedded_test_server()->Start()); - - ui_test_utils::NavigateToURL( - browser(), - embedded_test_server()->GetURL("/permissions/killswitch_tester.html")); - - // Now enable the geolocation killswitch. - EnableKillSwitch(content::PermissionType::GEOLOCATION); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - - std::string result; - EXPECT_TRUE(content::ExecuteScriptAndExtractString( - web_contents, "requestGeolocation();", &result)); - EXPECT_EQ("denied", result); - EXPECT_EQ(0, bubble_factory()->show_count()); - EXPECT_EQ(0, bubble_factory()->total_request_count()); - - // Disable the trial. - variations::testing::ClearAllVariationParams(); - - // Reload the page to get around blink layer caching for geolocation - // requests. - ui_test_utils::NavigateToURL( - browser(), - embedded_test_server()->GetURL("/permissions/killswitch_tester.html")); - - EXPECT_TRUE(content::ExecuteScript(web_contents, "requestGeolocation();")); - bubble_factory()->WaitForPermissionBubble(); - EXPECT_EQ(1, bubble_factory()->show_count()); - EXPECT_EQ(1, bubble_factory()->total_request_count()); -} - -// Bubble requests should not be shown when the killswitch is on. -IN_PROC_BROWSER_TEST_F(PermissionBubbleManagerBrowserTest, - KillSwitchNotifications) { - ASSERT_TRUE(embedded_test_server()->Start()); - - ui_test_utils::NavigateToURL( - browser(), - embedded_test_server()->GetURL("/permissions/killswitch_tester.html")); - - // Now enable the notifications killswitch. - EnableKillSwitch(content::PermissionType::NOTIFICATIONS); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - - std::string result; - EXPECT_TRUE(content::ExecuteScriptAndExtractString( - web_contents, "requestNotification();", &result)); - EXPECT_EQ("denied", result); - EXPECT_EQ(0, bubble_factory()->show_count()); - EXPECT_EQ(0, bubble_factory()->total_request_count()); - - // Disable the trial. - variations::testing::ClearAllVariationParams(); - - EXPECT_TRUE(content::ExecuteScript(web_contents, "requestNotification();")); - bubble_factory()->WaitForPermissionBubble(); - EXPECT_EQ(1, bubble_factory()->show_count()); - EXPECT_EQ(1, bubble_factory()->total_request_count()); -} - -} // anonymous namespace
diff --git a/chrome/browser/ui/website_settings/permission_bubble_manager_unittest.cc b/chrome/browser/ui/website_settings/permission_bubble_manager_unittest.cc deleted file mode 100644 index a75aab1..0000000 --- a/chrome/browser/ui/website_settings/permission_bubble_manager_unittest.cc +++ /dev/null
@@ -1,606 +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. - -#include <stddef.h> - -#include "base/bind.h" -#include "base/command_line.h" -#include "base/run_loop.h" -#include "base/strings/utf_string_conversions.h" -#include "base/test/histogram_tester.h" -#include "chrome/browser/permissions/permission_uma_util.h" -#include "chrome/browser/ui/website_settings/mock_permission_bubble_factory.h" -#include "chrome/browser/ui/website_settings/mock_permission_bubble_request.h" -#include "chrome/browser/ui/website_settings/permission_bubble_manager.h" -#include "chrome/browser/ui/website_settings/permission_bubble_request.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/test/base/chrome_render_view_host_test_harness.h" -#include "testing/gtest/include/gtest/gtest.h" - -class PermissionBubbleManagerTest : public ChromeRenderViewHostTestHarness { - public: - PermissionBubbleManagerTest() - : ChromeRenderViewHostTestHarness(), - request1_("test1", PermissionBubbleType::QUOTA), - request2_("test2", PermissionBubbleType::DOWNLOAD), - iframe_request_same_domain_("iframe", - GURL("http://www.google.com/some/url")), - iframe_request_other_domain_("iframe", - GURL("http://www.youtube.com")) {} - ~PermissionBubbleManagerTest() override {} - - void SetUp() override { - ChromeRenderViewHostTestHarness::SetUp(); - SetContents(CreateTestWebContents()); - NavigateAndCommit(GURL("http://www.google.com")); - - manager_.reset(new PermissionBubbleManager(web_contents())); - view_factory_.reset(new MockPermissionBubbleFactory(manager_.get())); - } - - void TearDown() override { - view_factory_.reset(); - manager_.reset(); - ChromeRenderViewHostTestHarness::TearDown(); - } - - void ToggleAccept(int index, bool value) { - manager_->ToggleAccept(index, value); - } - - void Accept() { - manager_->Accept(); - } - - void Deny() { - manager_->Deny(); - } - - void Closing() { - manager_->Closing(); - } - - void WaitForFrameLoad() { - // PermissionBubbleManager ignores all parameters. Yay? - manager_->DocumentLoadedInFrame(NULL); - base::RunLoop().RunUntilIdle(); - } - - void WaitForCoalescing() { - manager_->DocumentOnLoadCompletedInMainFrame(); - base::RunLoop().RunUntilIdle(); - } - - void MockTabSwitchAway() { manager_->HideBubble(); } - - void MockTabSwitchBack() { manager_->DisplayPendingRequests(); } - - virtual void NavigationEntryCommitted( - const content::LoadCommittedDetails& details) { - manager_->NavigationEntryCommitted(details); - } - - protected: - MockPermissionBubbleRequest request1_; - MockPermissionBubbleRequest request2_; - MockPermissionBubbleRequest iframe_request_same_domain_; - MockPermissionBubbleRequest iframe_request_other_domain_; - std::unique_ptr<PermissionBubbleManager> manager_; - std::unique_ptr<MockPermissionBubbleFactory> view_factory_; -}; - -TEST_F(PermissionBubbleManagerTest, SingleRequest) { - manager_->AddRequest(&request1_); - manager_->DisplayPendingRequests(); - WaitForCoalescing(); - - EXPECT_TRUE(view_factory_->is_visible()); - ASSERT_EQ(view_factory_->request_count(), 1); - - ToggleAccept(0, true); - Accept(); - EXPECT_TRUE(request1_.granted()); -} - -TEST_F(PermissionBubbleManagerTest, SingleRequestViewFirst) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&request1_); - WaitForCoalescing(); - - EXPECT_TRUE(view_factory_->is_visible()); - ASSERT_EQ(view_factory_->request_count(), 1); - - ToggleAccept(0, true); - Accept(); - EXPECT_TRUE(request1_.granted()); -} - -TEST_F(PermissionBubbleManagerTest, TwoRequests) { - manager_->AddRequest(&request1_); - manager_->AddRequest(&request2_); - manager_->DisplayPendingRequests(); - WaitForCoalescing(); - - EXPECT_TRUE(view_factory_->is_visible()); - ASSERT_EQ(view_factory_->request_count(), 2); - - ToggleAccept(0, true); - ToggleAccept(1, false); - Accept(); - EXPECT_TRUE(request1_.granted()); - EXPECT_FALSE(request2_.granted()); -} - -TEST_F(PermissionBubbleManagerTest, TwoRequestsTabSwitch) { - manager_->AddRequest(&request1_); - manager_->AddRequest(&request2_); - manager_->DisplayPendingRequests(); - WaitForCoalescing(); - - EXPECT_TRUE(view_factory_->is_visible()); - ASSERT_EQ(view_factory_->request_count(), 2); - - ToggleAccept(0, true); - ToggleAccept(1, false); - - MockTabSwitchAway(); - EXPECT_FALSE(view_factory_->is_visible()); - - MockTabSwitchBack(); - WaitForCoalescing(); - EXPECT_TRUE(view_factory_->is_visible()); - ASSERT_EQ(view_factory_->request_count(), 2); - - Accept(); - EXPECT_TRUE(request1_.granted()); - EXPECT_FALSE(request2_.granted()); -} - -TEST_F(PermissionBubbleManagerTest, NoRequests) { - manager_->DisplayPendingRequests(); - WaitForCoalescing(); - EXPECT_FALSE(view_factory_->is_visible()); -} - -TEST_F(PermissionBubbleManagerTest, NoView) { - manager_->AddRequest(&request1_); - // Don't display the pending requests. - WaitForCoalescing(); - EXPECT_FALSE(view_factory_->is_visible()); -} - -TEST_F(PermissionBubbleManagerTest, TwoRequestsCoalesce) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&request1_); - manager_->AddRequest(&request2_); - EXPECT_FALSE(view_factory_->is_visible()); - WaitForCoalescing(); - - EXPECT_TRUE(view_factory_->is_visible()); - ASSERT_EQ(view_factory_->request_count(), 2); -} - -TEST_F(PermissionBubbleManagerTest, TwoRequestsDoNotCoalesce) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&request1_); - WaitForCoalescing(); - manager_->AddRequest(&request2_); - - EXPECT_TRUE(view_factory_->is_visible()); - ASSERT_EQ(view_factory_->request_count(), 1); -} - -TEST_F(PermissionBubbleManagerTest, TwoRequestsShownInTwoBubbles) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&request1_); - WaitForCoalescing(); - manager_->AddRequest(&request2_); - - EXPECT_TRUE(view_factory_->is_visible()); - ASSERT_EQ(view_factory_->request_count(), 1); - - Accept(); - WaitForCoalescing(); - - EXPECT_TRUE(view_factory_->is_visible()); - ASSERT_EQ(view_factory_->request_count(), 1); - ASSERT_EQ(view_factory_->show_count(), 2); -} - -TEST_F(PermissionBubbleManagerTest, TestAddDuplicateRequest) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&request1_); - manager_->AddRequest(&request2_); - manager_->AddRequest(&request1_); - - WaitForCoalescing(); - EXPECT_TRUE(view_factory_->is_visible()); - ASSERT_EQ(view_factory_->request_count(), 2); -} - -TEST_F(PermissionBubbleManagerTest, SequentialRequests) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&request1_); - WaitForCoalescing(); - EXPECT_TRUE(view_factory_->is_visible()); - - Accept(); - EXPECT_TRUE(request1_.granted()); - - EXPECT_FALSE(view_factory_->is_visible()); - - manager_->AddRequest(&request2_); - WaitForCoalescing(); - EXPECT_TRUE(view_factory_->is_visible()); - Accept(); - EXPECT_FALSE(view_factory_->is_visible()); - EXPECT_TRUE(request2_.granted()); -} - -TEST_F(PermissionBubbleManagerTest, SameRequestRejected) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&request1_); - manager_->AddRequest(&request1_); - EXPECT_FALSE(request1_.finished()); - - WaitForCoalescing(); - EXPECT_TRUE(view_factory_->is_visible()); - ASSERT_EQ(view_factory_->request_count(), 1); -} - -TEST_F(PermissionBubbleManagerTest, DuplicateRequestCancelled) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&request1_); - MockPermissionBubbleRequest dupe_request("test1"); - manager_->AddRequest(&dupe_request); - EXPECT_FALSE(dupe_request.finished()); - EXPECT_FALSE(request1_.finished()); - manager_->CancelRequest(&request1_); - EXPECT_TRUE(dupe_request.finished()); - EXPECT_TRUE(request1_.finished()); -} - -TEST_F(PermissionBubbleManagerTest, DuplicateQueuedRequest) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&request1_); - WaitForCoalescing(); - manager_->AddRequest(&request2_); - - MockPermissionBubbleRequest dupe_request("test1"); - manager_->AddRequest(&dupe_request); - EXPECT_FALSE(dupe_request.finished()); - EXPECT_FALSE(request1_.finished()); - - MockPermissionBubbleRequest dupe_request2("test2"); - manager_->AddRequest(&dupe_request2); - EXPECT_FALSE(dupe_request2.finished()); - EXPECT_FALSE(request2_.finished()); - - manager_->CancelRequest(&request1_); - EXPECT_TRUE(dupe_request.finished()); - EXPECT_TRUE(request1_.finished()); - - manager_->CancelRequest(&request2_); - EXPECT_TRUE(dupe_request2.finished()); - EXPECT_TRUE(request2_.finished()); -} - -TEST_F(PermissionBubbleManagerTest, ForgetRequestsOnPageNavigation) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&request1_); - WaitForCoalescing(); - manager_->AddRequest(&request2_); - manager_->AddRequest(&iframe_request_other_domain_); - - EXPECT_TRUE(view_factory_->is_visible()); - ASSERT_EQ(view_factory_->request_count(), 1); - - NavigateAndCommit(GURL("http://www2.google.com/")); - WaitForCoalescing(); - - EXPECT_FALSE(view_factory_->is_visible()); - EXPECT_TRUE(request1_.finished()); - EXPECT_TRUE(request2_.finished()); - EXPECT_TRUE(iframe_request_other_domain_.finished()); -} - -TEST_F(PermissionBubbleManagerTest, TestCancelQueued) { - manager_->AddRequest(&request1_); - EXPECT_FALSE(view_factory_->is_visible()); - - manager_->CancelRequest(&request1_); - EXPECT_TRUE(request1_.finished()); - EXPECT_FALSE(view_factory_->is_visible()); - manager_->DisplayPendingRequests(); - EXPECT_FALSE(view_factory_->is_visible()); - - manager_->AddRequest(&request2_); - WaitForCoalescing(); - EXPECT_TRUE(view_factory_->is_visible()); - ASSERT_EQ(view_factory_->request_count(), 1); -} - -TEST_F(PermissionBubbleManagerTest, TestCancelWhileDialogShown) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&request1_); - WaitForCoalescing(); - - view_factory_->SetCanUpdateUi(true); - EXPECT_TRUE(view_factory_->is_visible()); - EXPECT_FALSE(request1_.finished()); - manager_->CancelRequest(&request1_); - WaitForCoalescing(); - EXPECT_TRUE(request1_.finished()); - EXPECT_FALSE(view_factory_->is_visible()); -} - -TEST_F(PermissionBubbleManagerTest, TestCancelWhileDialogShownNoUpdate) { - manager_->DisplayPendingRequests(); - view_factory_->SetCanUpdateUi(false); - manager_->AddRequest(&request1_); - WaitForCoalescing(); - view_factory_->SetCanUpdateUi(false); - - EXPECT_TRUE(view_factory_->is_visible()); - EXPECT_FALSE(request1_.finished()); - manager_->CancelRequest(&request1_); - EXPECT_TRUE(request1_.finished()); - EXPECT_TRUE(view_factory_->is_visible()); - Closing(); -} - -TEST_F(PermissionBubbleManagerTest, TestCancelPendingRequest) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&request1_); - WaitForCoalescing(); - manager_->AddRequest(&request2_); - - EXPECT_TRUE(view_factory_->is_visible()); - ASSERT_EQ(view_factory_->request_count(), 1); - manager_->CancelRequest(&request2_); - - EXPECT_TRUE(view_factory_->is_visible()); - EXPECT_FALSE(request1_.finished()); - EXPECT_TRUE(request2_.finished()); -} - -TEST_F(PermissionBubbleManagerTest, MainFrameNoRequestIFrameRequest) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&iframe_request_same_domain_); - WaitForCoalescing(); - WaitForFrameLoad(); - - EXPECT_TRUE(view_factory_->is_visible()); - Closing(); - EXPECT_TRUE(iframe_request_same_domain_.finished()); -} - -TEST_F(PermissionBubbleManagerTest, MainFrameAndIFrameRequestSameDomain) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&request1_); - manager_->AddRequest(&iframe_request_same_domain_); - WaitForFrameLoad(); - WaitForCoalescing(); - - EXPECT_TRUE(view_factory_->is_visible()); - ASSERT_EQ(view_factory_->request_count(), 2); - Closing(); - EXPECT_TRUE(request1_.finished()); - EXPECT_TRUE(iframe_request_same_domain_.finished()); - EXPECT_FALSE(view_factory_->is_visible()); -} - -TEST_F(PermissionBubbleManagerTest, MainFrameAndIFrameRequestOtherDomain) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&request1_); - manager_->AddRequest(&iframe_request_other_domain_); - WaitForFrameLoad(); - WaitForCoalescing(); - - EXPECT_TRUE(view_factory_->is_visible()); - Closing(); - EXPECT_TRUE(request1_.finished()); - EXPECT_FALSE(iframe_request_other_domain_.finished()); - EXPECT_TRUE(view_factory_->is_visible()); - Closing(); - EXPECT_TRUE(iframe_request_other_domain_.finished()); -} - -TEST_F(PermissionBubbleManagerTest, IFrameRequestWhenMainRequestVisible) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&request1_); - WaitForCoalescing(); - EXPECT_TRUE(view_factory_->is_visible()); - - manager_->AddRequest(&iframe_request_same_domain_); - WaitForFrameLoad(); - ASSERT_EQ(view_factory_->request_count(), 1); - Closing(); - EXPECT_TRUE(request1_.finished()); - EXPECT_FALSE(iframe_request_same_domain_.finished()); - EXPECT_TRUE(view_factory_->is_visible()); - ASSERT_EQ(view_factory_->request_count(), 1); - Closing(); - EXPECT_TRUE(iframe_request_same_domain_.finished()); -} - -TEST_F(PermissionBubbleManagerTest, - IFrameRequestOtherDomainWhenMainRequestVisible) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&request1_); - WaitForCoalescing(); - EXPECT_TRUE(view_factory_->is_visible()); - - manager_->AddRequest(&iframe_request_other_domain_); - WaitForFrameLoad(); - Closing(); - EXPECT_TRUE(request1_.finished()); - EXPECT_FALSE(iframe_request_other_domain_.finished()); - EXPECT_TRUE(view_factory_->is_visible()); - Closing(); - EXPECT_TRUE(iframe_request_other_domain_.finished()); -} - -TEST_F(PermissionBubbleManagerTest, RequestsDontNeedUserGesture) { - manager_->DisplayPendingRequests(); - WaitForFrameLoad(); - WaitForCoalescing(); - manager_->AddRequest(&request1_); - manager_->AddRequest(&iframe_request_other_domain_); - manager_->AddRequest(&request2_); - base::RunLoop().RunUntilIdle(); - - EXPECT_TRUE(view_factory_->is_visible()); -} - -TEST_F(PermissionBubbleManagerTest, UMAForSimpleAcceptedBubble) { - base::HistogramTester histograms; - - manager_->AddRequest(&request1_); - manager_->DisplayPendingRequests(); - WaitForCoalescing(); - histograms.ExpectUniqueSample( - PermissionUmaUtil::kPermissionsPromptShown, - static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), - 1); - histograms.ExpectUniqueSample( - PermissionUmaUtil::kPermissionsPromptRequestsPerPrompt, 1, 1); - - ToggleAccept(0, true); - Accept(); - histograms.ExpectUniqueSample( - PermissionUmaUtil::kPermissionsPromptAccepted, - static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), 1); -} - -TEST_F(PermissionBubbleManagerTest, UMAForSimpleDeniedBubble) { - base::HistogramTester histograms; - - manager_->AddRequest(&request1_); - manager_->DisplayPendingRequests(); - WaitForCoalescing(); - // No need to test UMA for showing prompts again, they were tested in - // UMAForSimpleAcceptedBubble. - - Deny(); - histograms.ExpectUniqueSample( - PermissionUmaUtil::kPermissionsPromptDenied, - static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), 1); -} - -// This code path (calling Accept on a non-merged bubble, with no accepted -// permission) would never be used in actual Chrome, but its still tested for -// completeness. -TEST_F(PermissionBubbleManagerTest, UMAForSimpleDeniedBubbleAlternatePath) { - base::HistogramTester histograms; - - manager_->AddRequest(&request1_); - manager_->DisplayPendingRequests(); - WaitForCoalescing(); - // No need to test UMA for showing prompts again, they were tested in - // UMAForSimpleAcceptedBubble. - - ToggleAccept(0, false); - Accept(); - histograms.ExpectUniqueSample( - PermissionUmaUtil::kPermissionsPromptDenied, - static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), 1); -} - -TEST_F(PermissionBubbleManagerTest, UMAForMergedAcceptedBubble) { - base::HistogramTester histograms; - - manager_->AddRequest(&request1_); - manager_->AddRequest(&request2_); - manager_->DisplayPendingRequests(); - WaitForCoalescing(); - - histograms.ExpectUniqueSample( - PermissionUmaUtil::kPermissionsPromptShown, - static_cast<base::HistogramBase::Sample>(PermissionBubbleType::MULTIPLE), - 1); - histograms.ExpectBucketCount( - PermissionUmaUtil::kPermissionsPromptMergedBubbleTypes, - static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), - 1); - histograms.ExpectBucketCount( - PermissionUmaUtil::kPermissionsPromptMergedBubbleTypes, - static_cast<base::HistogramBase::Sample>(PermissionBubbleType::DOWNLOAD), - 1); - histograms.ExpectUniqueSample( - PermissionUmaUtil::kPermissionsPromptRequestsPerPrompt, 2, 1); - - ToggleAccept(0, true); - ToggleAccept(1, true); - Accept(); - - histograms.ExpectUniqueSample( - PermissionUmaUtil::kPermissionsPromptAccepted, - static_cast<base::HistogramBase::Sample>(PermissionBubbleType::MULTIPLE), - 1); - histograms.ExpectBucketCount( - PermissionUmaUtil::kPermissionsPromptMergedBubbleAccepted, - static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), - 1); - histograms.ExpectBucketCount( - PermissionUmaUtil::kPermissionsPromptMergedBubbleAccepted, - static_cast<base::HistogramBase::Sample>(PermissionBubbleType::DOWNLOAD), - 1); -} - -TEST_F(PermissionBubbleManagerTest, UMAForMergedMixedBubble) { - base::HistogramTester histograms; - - manager_->AddRequest(&request1_); - manager_->AddRequest(&request2_); - manager_->DisplayPendingRequests(); - WaitForCoalescing(); - // No need to test UMA for showing prompts again, they were tested in - // UMAForMergedAcceptedBubble. - - ToggleAccept(0, true); - ToggleAccept(1, false); - Accept(); - - histograms.ExpectUniqueSample( - PermissionUmaUtil::kPermissionsPromptDenied, - static_cast<base::HistogramBase::Sample>(PermissionBubbleType::MULTIPLE), - 1); - histograms.ExpectBucketCount( - PermissionUmaUtil::kPermissionsPromptMergedBubbleAccepted, - static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), - 1); - histograms.ExpectBucketCount( - PermissionUmaUtil::kPermissionsPromptMergedBubbleDenied, - static_cast<base::HistogramBase::Sample>(PermissionBubbleType::DOWNLOAD), - 1); -} - -TEST_F(PermissionBubbleManagerTest, UMAForMergedDeniedBubble) { - base::HistogramTester histograms; - - manager_->AddRequest(&request1_); - manager_->AddRequest(&request2_); - manager_->DisplayPendingRequests(); - WaitForCoalescing(); - // No need to test UMA for showing prompts again, they were tested in - // UMAForMergedAcceptedBubble. - - ToggleAccept(0, false); - ToggleAccept(1, false); - Accept(); - - histograms.ExpectUniqueSample( - PermissionUmaUtil::kPermissionsPromptDenied, - static_cast<base::HistogramBase::Sample>(PermissionBubbleType::MULTIPLE), - 1); - histograms.ExpectBucketCount( - PermissionUmaUtil::kPermissionsPromptMergedBubbleDenied, - static_cast<base::HistogramBase::Sample>(PermissionBubbleType::QUOTA), - 1); - histograms.ExpectBucketCount( - PermissionUmaUtil::kPermissionsPromptMergedBubbleDenied, - static_cast<base::HistogramBase::Sample>(PermissionBubbleType::DOWNLOAD), - 1); -}
diff --git a/chrome/browser/ui/website_settings/permission_bubble_view.h b/chrome/browser/ui/website_settings/permission_bubble_view.h index 2c6cabd..15afc8f 100644 --- a/chrome/browser/ui/website_settings/permission_bubble_view.h +++ b/chrome/browser/ui/website_settings/permission_bubble_view.h
@@ -12,7 +12,7 @@ #include "ui/gfx/native_widget_types.h" class Browser; -class PermissionBubbleManager; +class PermissionRequestManager; class PermissionBubbleRequest; // This class is the platform-independent interface through which the permission
diff --git a/chrome/browser/ui/website_settings/permission_menu_model.cc b/chrome/browser/ui/website_settings/permission_menu_model.cc index 7a6ff0d..9944b12 100644 --- a/chrome/browser/ui/website_settings/permission_menu_model.cc +++ b/chrome/browser/ui/website_settings/permission_menu_model.cc
@@ -121,7 +121,7 @@ bool PermissionMenuModel::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { // Accelerators are not supported. return false; }
diff --git a/chrome/browser/ui/website_settings/permission_menu_model.h b/chrome/browser/ui/website_settings/permission_menu_model.h index 7ec2ad2..8a28b1a 100644 --- a/chrome/browser/ui/website_settings/permission_menu_model.h +++ b/chrome/browser/ui/website_settings/permission_menu_model.h
@@ -35,7 +35,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; private:
diff --git a/chrome/browser/ui/website_settings/website_settings.cc b/chrome/browser/ui/website_settings/website_settings.cc index eb8ff4b..b6d3012d 100644 --- a/chrome/browser/ui/website_settings/website_settings.cc +++ b/chrome/browser/ui/website_settings/website_settings.cc
@@ -293,8 +293,8 @@ // in the permissions layer. See crbug.com/469221. content::PermissionType permission_type; if (PermissionUtil::GetPermissionType(type, &permission_type)) { - PermissionUmaUtil::PermissionRevoked(permission_type, - this->site_url_); + PermissionUmaUtil::PermissionRevoked(permission_type, this->site_url_, + this->profile_); } }
diff --git a/chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.cc b/chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.cc index bdbf7fc..b8bb9d6 100644 --- a/chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.cc
@@ -5,9 +5,12 @@ #include "chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.h" #include "chrome/browser/chromeos/login/ui/webui_login_display.h" +#include "chrome/browser/chromeos/options/network_config_view.h" +#include "chrome/browser/chromeos/ui/choose_mobile_network_dialog.h" #include "chrome/browser/ui/webui/chromeos/login/network_dropdown.h" #include "chrome/grit/generated_resources.h" #include "components/login/localized_values_builder.h" +#include "third_party/cros_system_api/dbus/service_constants.h" namespace { @@ -18,6 +21,10 @@ const char kJsApiNetworkDropdownShow[] = "networkDropdownShow"; const char kJsApiNetworkDropdownHide[] = "networkDropdownHide"; const char kJsApiNetworkDropdownRefresh[] = "networkDropdownRefresh"; +const char kJsApiLaunchProxySettingsDialog[] = "launchProxySettingsDialog"; +const char kJsApiLaunchAddWiFiNetworkDialog[] = "launchAddWiFiNetworkDialog"; +const char kJsApiLaunchAddMobileNetworkDialog[] = + "launchAddMobileNetworkDialog"; } // namespace @@ -57,6 +64,28 @@ &NetworkDropdownHandler::HandleNetworkDropdownHide); AddCallback(kJsApiNetworkDropdownRefresh, &NetworkDropdownHandler::HandleNetworkDropdownRefresh); + + // MD-OOBE + AddCallback(kJsApiLaunchProxySettingsDialog, + &NetworkDropdownHandler::HandleLaunchProxySettingsDialog); + AddCallback(kJsApiLaunchAddWiFiNetworkDialog, + &NetworkDropdownHandler::HandleLaunchAddWiFiNetworkDialog); + AddCallback(kJsApiLaunchAddMobileNetworkDialog, + &NetworkDropdownHandler::HandleLaunchAddMobileNetworkDialog); +} + +void NetworkDropdownHandler::HandleLaunchProxySettingsDialog() { + dropdown_->OpenButtonOptions(); +} + +void NetworkDropdownHandler::HandleLaunchAddWiFiNetworkDialog() { + gfx::NativeWindow native_window = GetNativeWindow(); + NetworkConfigView::ShowForType(shill::kTypeWifi, native_window); +} + +void NetworkDropdownHandler::HandleLaunchAddMobileNetworkDialog() { + gfx::NativeWindow native_window = GetNativeWindow(); + ChooseMobileNetworkDialog::ShowDialog(native_window); } void NetworkDropdownHandler::OnConnectToNetworkRequested() {
diff --git a/chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.h b/chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.h index 6a707f7..6c70b655 100644 --- a/chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/network_dropdown_handler.h
@@ -52,6 +52,10 @@ // Handles network drop-down refresh. void HandleNetworkDropdownRefresh(); + void HandleLaunchProxySettingsDialog(); + void HandleLaunchAddWiFiNetworkDialog(); + void HandleLaunchAddMobileNetworkDialog(); + std::unique_ptr<NetworkDropdown> dropdown_; base::ObserverList<Observer> observers_;
diff --git a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc index 2f69776..483fc906 100644 --- a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
@@ -162,6 +162,13 @@ builder->Add("proxySettings", IDS_OPTIONS_PROXIES_CONFIGURE_BUTTON); builder->Add("continueButton", IDS_NETWORK_SELECTION_CONTINUE_BUTTON); builder->Add("debuggingFeaturesLink", IDS_NETWORK_ENABLE_DEV_FEATURES_LINK); + + // MD-OOBE + builder->Add("networkSectionTitle", IDS_NETWORK_SECTION_TITE); + builder->Add("networkSectionHint", IDS_NETWORK_SECTION_HINT); + builder->Add("proxySettingsMenuName", IDS_PROXY_SETTINGS_MENU_NAME); + builder->Add("addWiFiNetworkMenuName", IDS_ADD_WI_FI_NETWORK_MENU_NAME); + builder->Add("addMobileNetworkMenuName", IDS_ADD_MOBILE_NETWORK_MENU_NAME); } void NetworkScreenHandler::GetAdditionalParameters(
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc index 71d86f2..d06042f 100644 --- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc +++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -499,8 +499,9 @@ bool new_kiosk_ui = KioskAppMenuHandler::EnableNewKioskUI(); localized_strings->SetString("newKioskUI", new_kiosk_ui ? "on" : "off"); - localized_strings->SetString("newOobeUI", UseMDOobe() ? "on" : "off"); + + NetworkUI::GetLocalizedStrings(localized_strings); } void OobeUI::AddScreenHandler(BaseScreenHandler* handler) {
diff --git a/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc index ffeed71..0d010810 100644 --- a/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc
@@ -4,9 +4,9 @@ #include "chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.h" -#include "ash/audio/sounds.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" +#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/login/screens/user_selection_screen.h" #include "chrome/browser/chromeos/login/supervised/supervised_user_creation_flow.h" #include "chrome/browser/chromeos/login/users/chrome_user_manager.h" @@ -23,6 +23,7 @@ #include "components/user_manager/user_type.h" #include "google_apis/gaia/gaia_auth_util.h" #include "grit/browser_resources.h" +#include "media/audio/sounds/sounds_manager.h" #include "net/base/data_url.h" #include "net/base/escape.h" #include "ui/base/l10n/l10n_util.h" @@ -436,11 +437,13 @@ } void SupervisedUserCreationScreenHandler::HandleTakePhoto() { - ash::PlaySystemSoundIfSpokenFeedback(SOUND_CAMERA_SNAP); + AccessibilityManager::Get()->PlayEarcon( + SOUND_CAMERA_SNAP, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED); } void SupervisedUserCreationScreenHandler::HandleDiscardPhoto() { - ash::PlaySystemSoundIfSpokenFeedback(SOUND_OBJECT_DELETE); + AccessibilityManager::Get()->PlayEarcon( + SOUND_OBJECT_DELETE, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED); } void SupervisedUserCreationScreenHandler::HandleSelectImage(
diff --git a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc index d986b9b6..c571be6f 100644 --- a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc
@@ -4,11 +4,11 @@ #include "chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.h" -#include "ash/audio/sounds.h" #include "base/command_line.h" #include "base/logging.h" #include "base/metrics/histogram.h" #include "base/values.h" +#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/login/existing_user_controller.h" #include "chrome/browser/chromeos/login/screens/user_image_model.h" #include "chrome/browser/chromeos/login/ui/webui_login_display.h" @@ -166,11 +166,13 @@ } void UserImageScreenHandler::HandleTakePhoto() { - ash::PlaySystemSoundIfSpokenFeedback(SOUND_CAMERA_SNAP); + AccessibilityManager::Get()->PlayEarcon( + SOUND_CAMERA_SNAP, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED); } void UserImageScreenHandler::HandleDiscardPhoto() { - ash::PlaySystemSoundIfSpokenFeedback(SOUND_OBJECT_DELETE); + AccessibilityManager::Get()->PlayEarcon( + SOUND_OBJECT_DELETE, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED); } void UserImageScreenHandler::HandleSelectImage(const std::string& image_url,
diff --git a/chrome/browser/ui/webui/chromeos/network_ui.cc b/chrome/browser/ui/webui/chromeos/network_ui.cc index c6593376..29f0eaac 100644 --- a/chrome/browser/ui/webui/chromeos/network_ui.cc +++ b/chrome/browser/ui/webui/chromeos/network_ui.cc
@@ -23,6 +23,7 @@ #include "content/public/browser/web_ui_message_handler.h" #include "grit/browser_resources.h" #include "third_party/cros_system_api/dbus/service_constants.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/chromeos/strings/grit/ui_chromeos_strings.h" namespace chromeos { @@ -137,6 +138,74 @@ } // namespace +// static +void NetworkUI::GetLocalizedStrings(base::DictionaryValue* localized_strings) { + localized_strings->SetString("titleText", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_TITLE)); + + localized_strings->SetString("titleText", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_TITLE)); + localized_strings->SetString( + "autoRefreshText", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_AUTO_REFRESH)); + localized_strings->SetString( + "deviceLogLinkText", l10n_util::GetStringUTF16(IDS_DEVICE_LOG_LINK_TEXT)); + localized_strings->SetString( + "networkRefreshText", l10n_util::GetStringUTF16(IDS_NETWORK_UI_REFRESH)); + localized_strings->SetString( + "clickToExpandText", l10n_util::GetStringUTF16(IDS_NETWORK_UI_EXPAND)); + localized_strings->SetString( + "propertyFormatText", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_PROPERTY_FORMAT)); + + localized_strings->SetString( + "normalFormatOption", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_FORMAT_NORMAL)); + localized_strings->SetString( + "managedFormatOption", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_FORMAT_MANAGED)); + localized_strings->SetString( + "stateFormatOption", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_FORMAT_STATE)); + localized_strings->SetString( + "shillFormatOption", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_FORMAT_SHILL)); + + localized_strings->SetString( + "visibleNetworksLabel", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_VISIBLE_NETWORKS)); + localized_strings->SetString( + "favoriteNetworksLabel", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_FAVORITE_NETWORKS)); + + localized_strings->SetString( + "networkConnected", + l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED)); + localized_strings->SetString( + "networkConnecting", + l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_CONNECTING)); + localized_strings->SetString( + "networkDisabled", + l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_NETWORK_DISABLED)); + localized_strings->SetString( + "networkNotConnected", + l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_NOT_CONNECTED)); + localized_strings->SetString( + "OncTypeCellular", l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_CELLULAR)); + localized_strings->SetString( + "OncTypeEthernet", l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_ETHERNET)); + localized_strings->SetString("OncTypeVPN", + l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_VPN)); + localized_strings->SetString( + "OncTypeWiFi", l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_WIFI)); + localized_strings->SetString( + "OncTypeWimax", l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_WIMAX)); + localized_strings->SetString( + "vpnNameTemplate", + l10n_util::GetStringUTF16( + IDS_OPTIONS_SETTINGS_SECTION_THIRD_PARTY_VPN_NAME_TEMPLATE)); +} + NetworkUI::NetworkUI(content::WebUI* web_ui) : content::WebUIController(web_ui) { web_ui->AddMessageHandler(new NetworkConfigMessageHandler()); @@ -144,44 +213,12 @@ // Enable extension API calls in the WebUI. extensions::TabHelper::CreateForWebContents(web_ui->GetWebContents()); + base::DictionaryValue localized_strings; + GetLocalizedStrings(&localized_strings); + content::WebUIDataSource* html = content::WebUIDataSource::Create(chrome::kChromeUINetworkHost); - - html->AddLocalizedString("titleText", IDS_NETWORK_UI_TITLE); - html->AddLocalizedString("autoRefreshText", IDS_NETWORK_UI_AUTO_REFRESH); - html->AddLocalizedString("deviceLogLinkText", IDS_DEVICE_LOG_LINK_TEXT); - html->AddLocalizedString("networkRefreshText", IDS_NETWORK_UI_REFRESH); - html->AddLocalizedString("clickToExpandText", IDS_NETWORK_UI_EXPAND); - html->AddLocalizedString("propertyFormatText", - IDS_NETWORK_UI_PROPERTY_FORMAT); - - html->AddLocalizedString("normalFormatOption", IDS_NETWORK_UI_FORMAT_NORMAL); - html->AddLocalizedString("managedFormatOption", - IDS_NETWORK_UI_FORMAT_MANAGED); - html->AddLocalizedString("stateFormatOption", IDS_NETWORK_UI_FORMAT_STATE); - html->AddLocalizedString("shillFormatOption", IDS_NETWORK_UI_FORMAT_SHILL); - - html->AddLocalizedString("visibleNetworksLabel", - IDS_NETWORK_UI_VISIBLE_NETWORKS); - html->AddLocalizedString("favoriteNetworksLabel", - IDS_NETWORK_UI_FAVORITE_NETWORKS); - - html->AddLocalizedString("networkConnected", - IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED); - html->AddLocalizedString("networkConnecting", - IDS_ASH_STATUS_TRAY_NETWORK_CONNECTING); - html->AddLocalizedString("networkDisabled", - IDS_OPTIONS_SETTINGS_NETWORK_DISABLED); - html->AddLocalizedString("networkNotConnected", - IDS_ASH_STATUS_TRAY_NETWORK_NOT_CONNECTED); - html->AddLocalizedString("OncTypeCellular", IDS_NETWORK_TYPE_CELLULAR); - html->AddLocalizedString("OncTypeEthernet", IDS_NETWORK_TYPE_ETHERNET); - html->AddLocalizedString("OncTypeVPN", IDS_NETWORK_TYPE_VPN); - html->AddLocalizedString("OncTypeWiFi", IDS_NETWORK_TYPE_WIFI); - html->AddLocalizedString("OncTypeWimax", IDS_NETWORK_TYPE_WIMAX); - html->AddLocalizedString( - "vpnNameTemplate", - IDS_OPTIONS_SETTINGS_SECTION_THIRD_PARTY_VPN_NAME_TEMPLATE); + html->AddLocalizedStrings(localized_strings); html->SetJsonPath("strings.js"); html->AddResourcePath("network_ui.css", IDR_NETWORK_UI_CSS);
diff --git a/chrome/browser/ui/webui/chromeos/network_ui.h b/chrome/browser/ui/webui/chromeos/network_ui.h index 72d7863..e06e6344 100644 --- a/chrome/browser/ui/webui/chromeos/network_ui.h +++ b/chrome/browser/ui/webui/chromeos/network_ui.h
@@ -8,6 +8,10 @@ #include "base/macros.h" #include "content/public/browser/web_ui_controller.h" +namespace base { +class DictionaryValue; +}; + namespace chromeos { class NetworkUI : public content::WebUIController { @@ -15,6 +19,8 @@ explicit NetworkUI(content::WebUI* web_ui); ~NetworkUI() override; + static void GetLocalizedStrings(base::DictionaryValue* localized_strings); + private: DISALLOW_COPY_AND_ASSIGN(NetworkUI); };
diff --git a/chrome/browser/ui/webui/extensions/extension_settings_browsertest.h b/chrome/browser/ui/webui/extensions/extension_settings_browsertest.h index 59d1405..b690cc3 100644 --- a/chrome/browser/ui/webui/extensions/extension_settings_browsertest.h +++ b/chrome/browser/ui/webui/extensions/extension_settings_browsertest.h
@@ -7,12 +7,12 @@ #include "base/macros.h" #include "chrome/browser/extensions/extension_test_notification_observer.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/test/base/web_ui_browser_test.h" #include "extensions/browser/extension_dialog_auto_confirm.h" #include "extensions/browser/test_management_policy.h" #include "extensions/common/extension.h" #include "extensions/common/feature_switch.h" +#include "extensions/common/features/feature_channel.h" class Profile;
diff --git a/chrome/browser/ui/webui/ntp/ntp_user_data_logger.cc b/chrome/browser/ui/webui/ntp/ntp_user_data_logger.cc index 6773db8..16f07de 100644 --- a/chrome/browser/ui/webui/ntp/ntp_user_data_logger.cc +++ b/chrome/browser/ui/webui/ntp/ntp_user_data_logger.cc
@@ -100,27 +100,21 @@ void NTPUserDataLogger::LogEvent(NTPLoggingEventType event, base::TimeDelta time) { switch (event) { - // It is possible that our page gets update with a different set of - // suggestions if the NTP is left open enough time. - // In either case, we want to flush our stats before recounting again. case NTP_SERVER_SIDE_SUGGESTION: - if (has_client_side_suggestions_) - EmitNtpStatistics(EmitReason::INTERNAL_FLUSH); has_server_side_suggestions_ = true; break; case NTP_CLIENT_SIDE_SUGGESTION: - if (has_server_side_suggestions_) - EmitNtpStatistics(EmitReason::INTERNAL_FLUSH); has_client_side_suggestions_ = true; break; case NTP_TILE: + // TODO(sfiera): remove NTP_TILE and use NTP_*_SIDE_SUGGESTION. number_of_tiles_++; break; case NTP_TILE_LOADED: - // The time at which the last tile has loaded (title, thumbnail or single) - // is a good proxy for the total load time of the NTP, therefore we keep - // the max as the load time. - load_time_ = std::max(load_time_, time); + // We no longer emit statistics for the multi-iframe NTP. + break; + case NTP_ALL_TILES_LOADED: + EmitNtpStatistics(time); break; default: NOTREACHED(); @@ -165,17 +159,8 @@ content::RecordAction(base::UserMetricsAction("MostVisited_Clicked")); } -void NTPUserDataLogger::TabDeactivated() { - EmitNtpStatistics(EmitReason::CLOSED); -} - -void NTPUserDataLogger::MostVisitedItemsChanged() { - EmitNtpStatistics(EmitReason::MV_CHANGED); -} - NTPUserDataLogger::NTPUserDataLogger(content::WebContents* contents) - : content::WebContentsObserver(contents), - has_server_side_suggestions_(false), + : has_server_side_suggestions_(false), has_client_side_suggestions_(false), number_of_tiles_(0), has_emitted_(false), @@ -201,40 +186,25 @@ } } -// content::WebContentsObserver override -void NTPUserDataLogger::NavigationEntryCommitted( - const content::LoadCommittedDetails& load_details) { - if (!load_details.previous_url.is_valid()) - return; - - if (search::MatchesOriginAndPath(ntp_url_, load_details.previous_url)) - EmitNtpStatistics(EmitReason::NAVIGATED_AWAY); -} - -void NTPUserDataLogger::EmitNtpStatistics(EmitReason reason) { +void NTPUserDataLogger::EmitNtpStatistics(base::TimeDelta load_time) { // We only send statistics once per page. - // And we don't send if there are no tiles recorded. - if (has_emitted_ || !number_of_tiles_) + if (has_emitted_) return; - // LoadTime only gets update once per page, so we don't have it on reloads. - if (load_time_ > base::TimeDelta::FromMilliseconds(0)) { - logLoadTimeHistogram("NewTabPage.LoadTime", load_time_); + logLoadTimeHistogram("NewTabPage.LoadTime", load_time); - // Split between ML and MV. - std::string type = has_server_side_suggestions_ ? - "MostLikely" : "MostVisited"; - logLoadTimeHistogram("NewTabPage.LoadTime." + type, load_time_); - // Split between Web and Local. - std::string source = ntp_url_.SchemeIsHTTPOrHTTPS() ? "Web" : "LocalNTP"; - logLoadTimeHistogram("NewTabPage.LoadTime." + source, load_time_); + // Split between ML and MV. + std::string type = has_server_side_suggestions_ ? + "MostLikely" : "MostVisited"; + logLoadTimeHistogram("NewTabPage.LoadTime." + type, load_time); + // Split between Web and Local. + std::string source = ntp_url_.SchemeIsHTTPOrHTTPS() ? "Web" : "LocalNTP"; + logLoadTimeHistogram("NewTabPage.LoadTime." + source, load_time); - // Split between Startup and non-startup. - std::string status = during_startup_ ? "Startup" : "NewTab"; - logLoadTimeHistogram("NewTabPage.LoadTime." + status, load_time_); + // Split between Startup and non-startup. + std::string status = during_startup_ ? "Startup" : "NewTab"; + logLoadTimeHistogram("NewTabPage.LoadTime." + status, load_time); - load_time_ = base::TimeDelta::FromMilliseconds(0); - } has_server_side_suggestions_ = false; has_client_side_suggestions_ = false; UMA_HISTOGRAM_CUSTOM_COUNTS(
diff --git a/chrome/browser/ui/webui/ntp/ntp_user_data_logger.h b/chrome/browser/ui/webui/ntp/ntp_user_data_logger.h index 6e6f965..bb96075 100644 --- a/chrome/browser/ui/webui/ntp/ntp_user_data_logger.h +++ b/chrome/browser/ui/webui/ntp/ntp_user_data_logger.h
@@ -11,7 +11,6 @@ #include "base/macros.h" #include "base/time/time.h" #include "chrome/common/search/ntp_logging_events.h" -#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" namespace content { @@ -20,8 +19,7 @@ // Helper class for logging data from the NTP. Attached to each NTP instance. class NTPUserDataLogger - : public content::WebContentsObserver, - public content::WebContentsUserData<NTPUserDataLogger> { + : public content::WebContentsUserData<NTPUserDataLogger> { public: ~NTPUserDataLogger() override; @@ -39,12 +37,6 @@ // Logs a navigation on one of the NTP tiles by a given source. void LogMostVisitedNavigation(int position, NTPLoggingTileSource tile_source); - // Called when the tab is closed. Logs statistics. - void TabDeactivated(); - - // Called when the set of most visited sites changes. Flushes statistics. - void MostVisitedItemsChanged(); - protected: explicit NTPUserDataLogger(content::WebContents* contents); @@ -58,20 +50,10 @@ FRIEND_TEST_ALL_PREFIXES(NTPUserDataLoggerTest, TestLogging); - // content::WebContentsObserver override - void NavigationEntryCommitted( - const content::LoadCommittedDetails& load_details) override; - - // To clarify at the call site whether we are calling EmitNtpStatistics() for - // a good reason (CLOSED, NAVIGATED_AWAY) or a questionable one (MV_CHANGED, - // INTERNAL_FLUSH). - // TODO(sfiera): remove MV_CHANGED, INTERNAL_FLUSH. - enum class EmitReason { CLOSED, NAVIGATED_AWAY, MV_CHANGED, INTERNAL_FLUSH }; - // Logs a number of statistics regarding the NTP. Called when an NTP tab is // about to be deactivated (be it by switching tabs, losing focus or closing // the tab/shutting down Chrome), or when the user navigates to a URL. - void EmitNtpStatistics(EmitReason reason); + void EmitNtpStatistics(base::TimeDelta load_time); // True if at least one iframe came from a server-side suggestion. bool has_server_side_suggestions_; @@ -83,9 +65,6 @@ // or an external tile. size_t number_of_tiles_; - // Time from navigation start it took to load the NTP in milliseconds. - base::TimeDelta load_time_; - // Whether we have already emitted NTP stats for this web contents. bool has_emitted_;
diff --git a/chrome/browser/ui/webui/ntp/ntp_user_data_logger_unittest.cc b/chrome/browser/ui/webui/ntp/ntp_user_data_logger_unittest.cc index dbdedeb..43d9cbc7 100644 --- a/chrome/browser/ui/webui/ntp/ntp_user_data_logger_unittest.cc +++ b/chrome/browser/ui/webui/ntp/ntp_user_data_logger_unittest.cc
@@ -52,13 +52,13 @@ logger.LogEvent(NTP_TILE, delta); logger.LogEvent(NTP_SERVER_SIDE_SUGGESTION, delta); - logger.EmitNtpStatistics(NTPUserDataLogger::EmitReason::NAVIGATED_AWAY); + logger.LogEvent(NTP_ALL_TILES_LOADED, delta); EXPECT_EQ(1, GetTotalCount("NewTabPage.NumberOfTiles")); EXPECT_EQ(1, GetBinCount("NewTabPage.NumberOfTiles", 8)); // Statistics should be reset to 0, so we should not log anything else. - logger.EmitNtpStatistics(NTPUserDataLogger::EmitReason::NAVIGATED_AWAY); + logger.LogEvent(NTP_ALL_TILES_LOADED, delta); EXPECT_EQ(1, GetTotalCount("NewTabPage.NumberOfTiles")); }
diff --git a/chrome/browser/ui/webui/offline_internals_ui.cc b/chrome/browser/ui/webui/offline_internals_ui.cc index 8968b824..93ed449 100644 --- a/chrome/browser/ui/webui/offline_internals_ui.cc +++ b/chrome/browser/ui/webui/offline_internals_ui.cc
@@ -202,6 +202,7 @@ offline_page->SetDouble("lastAccessTime", page.last_access_time.ToJsTime()); offline_page->SetInteger("accessCount", page.access_count); + offline_page->SetString("isExpired", page.IsExpired() ? "Yes" : "No"); } ResolveJavascriptCallback(base::StringValue(callback_id), results); }
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.cc b/chrome/browser/ui/webui/options/browser_options_handler.cc index f0366fd..c745a6fa 100644 --- a/chrome/browser/ui/webui/options/browser_options_handler.cc +++ b/chrome/browser/ui/webui/options/browser_options_handler.cc
@@ -537,10 +537,6 @@ { "backgroundModeCheckbox", IDS_OPTIONS_SYSTEM_ENABLE_BACKGROUND_MODE }, #endif // defined(OS_MACOSX) && !defined(OS_CHROMEOS) -#if defined(ENABLE_SETTINGS_APP) - { "profilesAppListSwitch", IDS_SETTINGS_APP_PROFILES_SWITCH_BUTTON_LABEL }, -#endif // defined(ENABLE_SETTINGS_APP) - #if defined(ENABLE_SERVICE_DISCOVERY) { "cloudPrintDevicesPageButton", IDS_LOCAL_DISCOVERY_DEVICES_PAGE_BUTTON }, { "cloudPrintEnableNotificationsLabel", @@ -548,23 +544,6 @@ #endif // defined(ENABLE_SERVICE_DISCOVERY) }; -#if defined(ENABLE_SETTINGS_APP) - static OptionsStringResource app_resources[] = { - { "syncOverview", IDS_SETTINGS_APP_SYNC_OVERVIEW }, - { "syncButtonTextStart", IDS_SYNC_START_SYNC_BUTTON_LABEL, - IDS_SETTINGS_APP_LAUNCHER_PRODUCT_NAME }, - { "profilesSingleUser", IDS_PROFILES_SINGLE_USER_MESSAGE, - IDS_SETTINGS_APP_LAUNCHER_PRODUCT_NAME }, - { "languageSectionLabel", IDS_OPTIONS_ADVANCED_LANGUAGE_LABEL, - IDS_SETTINGS_APP_LAUNCHER_PRODUCT_NAME }, - { "proxiesLabelSystem", IDS_OPTIONS_SYSTEM_PROXIES_LABEL, - IDS_SETTINGS_APP_LAUNCHER_PRODUCT_NAME }, - }; - base::DictionaryValue* app_values = NULL; - CHECK(values->GetDictionary(kSettingsAppKey, &app_values)); - RegisterStrings(app_values, app_resources, arraysize(app_resources)); -#endif - RegisterStrings(values, resources, arraysize(resources)); RegisterTitle(values, "doNotTrackConfirmOverlay", IDS_OPTIONS_ENABLE_DO_NOT_TRACK_BUBBLE_TITLE);
diff --git a/chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.cc index 60cd365..d9f87d9 100644 --- a/chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.cc +++ b/chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.h" -#include "ash/audio/sounds.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/command_line.h" @@ -14,6 +13,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/camera_presence_notifier.h" #include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h" #include "chrome/browser/chromeos/login/users/chrome_user_manager.h" @@ -35,6 +35,7 @@ #include "content/public/browser/web_ui.h" #include "content/public/common/url_constants.h" #include "grit/browser_resources.h" +#include "media/audio/sounds/sounds_manager.h" #include "net/base/data_url.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" @@ -214,13 +215,15 @@ void ChangePictureOptionsHandler::HandleTakePhoto( const base::ListValue* args) { DCHECK(args->empty()); - ash::PlaySystemSoundIfSpokenFeedback(SOUND_CAMERA_SNAP); + AccessibilityManager::Get()->PlayEarcon( + SOUND_CAMERA_SNAP, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED); } void ChangePictureOptionsHandler::HandleDiscardPhoto( const base::ListValue* args) { DCHECK(args->empty()); - ash::PlaySystemSoundIfSpokenFeedback(SOUND_OBJECT_DELETE); + AccessibilityManager::Get()->PlayEarcon( + SOUND_OBJECT_DELETE, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED); } void ChangePictureOptionsHandler::HandlePhotoTaken(
diff --git a/chrome/browser/ui/webui/options/chromeos/storage_manager_handler.cc b/chrome/browser/ui/webui/options/chromeos/storage_manager_handler.cc index 6aa8e1f..c49798d 100644 --- a/chrome/browser/ui/webui/options/chromeos/storage_manager_handler.cc +++ b/chrome/browser/ui/webui/options/chromeos/storage_manager_handler.cc
@@ -371,6 +371,13 @@ base::Bind(&StorageManagerHandler::OnGetOtherUserSize, weak_ptr_factory_.GetWeakPtr())); } + // We should show "0 B" if there is no other user. + if (other_users_.empty()) { + updating_other_users_size_ = false; + web_ui()->CallJavascriptFunctionUnsafe( + "options.StorageManager.setOtherUsersSize", + base::StringValue(ui::FormatBytes(0))); + } } void StorageManagerHandler::OnGetOtherUserSize(bool success, int64_t size) {
diff --git a/chrome/browser/ui/webui/options/clear_browser_data_handler.cc b/chrome/browser/ui/webui/options/clear_browser_data_handler.cc index 11d122f..eecef3ad 100644 --- a/chrome/browser/ui/webui/options/clear_browser_data_handler.cc +++ b/chrome/browser/ui/webui/options/clear_browser_data_handler.cc
@@ -60,11 +60,11 @@ const int kMaxTimesHistoryNoticeShown = 1; const char* kCounterPrefs[] = { - prefs::kDeleteBrowsingHistory, - prefs::kDeleteCache, - prefs::kDeleteFormData, - prefs::kDeleteMediaLicenses, - prefs::kDeletePasswords, + browsing_data::prefs::kDeleteBrowsingHistory, + browsing_data::prefs::kDeleteCache, + browsing_data::prefs::kDeleteFormData, + browsing_data::prefs::kDeleteMediaLicenses, + browsing_data::prefs::kDeletePasswords, }; } // namespace @@ -254,27 +254,27 @@ int remove_mask = 0; int origin_mask = 0; - if (prefs->GetBoolean(prefs::kDeleteBrowsingHistory) && + if (prefs->GetBoolean(browsing_data::prefs::kDeleteBrowsingHistory) && *allow_deleting_browser_history_) { remove_mask |= BrowsingDataRemover::REMOVE_HISTORY; } - if (prefs->GetBoolean(prefs::kDeleteDownloadHistory) && + if (prefs->GetBoolean(browsing_data::prefs::kDeleteDownloadHistory) && *allow_deleting_browser_history_) { remove_mask |= BrowsingDataRemover::REMOVE_DOWNLOADS; } - if (prefs->GetBoolean(prefs::kDeleteCache)) + if (prefs->GetBoolean(browsing_data::prefs::kDeleteCache)) remove_mask |= BrowsingDataRemover::REMOVE_CACHE; - if (prefs->GetBoolean(prefs::kDeleteCookies)) { + if (prefs->GetBoolean(browsing_data::prefs::kDeleteCookies)) { remove_mask |= site_data_mask; origin_mask |= BrowsingDataHelper::UNPROTECTED_WEB; } - if (prefs->GetBoolean(prefs::kDeletePasswords)) + if (prefs->GetBoolean(browsing_data::prefs::kDeletePasswords)) remove_mask |= BrowsingDataRemover::REMOVE_PASSWORDS; - if (prefs->GetBoolean(prefs::kDeleteFormData)) + if (prefs->GetBoolean(browsing_data::prefs::kDeleteFormData)) remove_mask |= BrowsingDataRemover::REMOVE_FORM_DATA; - if (prefs->GetBoolean(prefs::kDeleteMediaLicenses)) + if (prefs->GetBoolean(browsing_data::prefs::kDeleteMediaLicenses)) remove_mask |= BrowsingDataRemover::REMOVE_MEDIA_LICENSES; - if (prefs->GetBoolean(prefs::kDeleteHostedAppsData)) { + if (prefs->GetBoolean(browsing_data::prefs::kDeleteHostedAppsData)) { remove_mask |= site_data_mask; origin_mask |= BrowsingDataHelper::PROTECTED_WEB; } @@ -282,11 +282,11 @@ // Record the deletion of cookies and cache. BrowsingDataRemover::CookieOrCacheDeletionChoice choice = BrowsingDataRemover::NEITHER_COOKIES_NOR_CACHE; - if (prefs->GetBoolean(prefs::kDeleteCookies)) { - choice = prefs->GetBoolean(prefs::kDeleteCache) - ? BrowsingDataRemover::BOTH_COOKIES_AND_CACHE - : BrowsingDataRemover::ONLY_COOKIES; - } else if (prefs->GetBoolean(prefs::kDeleteCache)) { + if (prefs->GetBoolean(browsing_data::prefs::kDeleteCookies)) { + choice = prefs->GetBoolean(browsing_data::prefs::kDeleteCache) + ? BrowsingDataRemover::BOTH_COOKIES_AND_CACHE + : BrowsingDataRemover::ONLY_COOKIES; + } else if (prefs->GetBoolean(browsing_data::prefs::kDeleteCache)) { choice = BrowsingDataRemover::ONLY_CACHE; } UMA_HISTOGRAM_ENUMERATION( @@ -294,15 +294,15 @@ choice, BrowsingDataRemover::MAX_CHOICE_VALUE); // Record the circumstances under which passwords are deleted. - if (prefs->GetBoolean(prefs::kDeletePasswords)) { + if (prefs->GetBoolean(browsing_data::prefs::kDeletePasswords)) { static const char* other_types[] = { - prefs::kDeleteBrowsingHistory, - prefs::kDeleteDownloadHistory, - prefs::kDeleteCache, - prefs::kDeleteCookies, - prefs::kDeleteFormData, - prefs::kDeleteHostedAppsData, - prefs::kDeleteMediaLicenses, + browsing_data::prefs::kDeleteBrowsingHistory, + browsing_data::prefs::kDeleteDownloadHistory, + browsing_data::prefs::kDeleteCache, + browsing_data::prefs::kDeleteCookies, + browsing_data::prefs::kDeleteFormData, + browsing_data::prefs::kDeleteHostedAppsData, + browsing_data::prefs::kDeleteMediaLicenses, }; static size_t num_other_types = arraysize(other_types); int checked_other_types = std::count_if( @@ -343,7 +343,7 @@ // 1. The dialog is relevant for the user. should_show_history_deletion_dialog_ && // 2. The selected data types contained browsing history. - prefs->GetBoolean(prefs::kDeleteBrowsingHistory) && + prefs->GetBoolean(browsing_data::prefs::kDeleteBrowsingHistory) && // 3. The notice has been shown less than |kMaxTimesHistoryNoticeShown|. notice_shown_times < kMaxTimesHistoryNoticeShown;
diff --git a/chrome/browser/ui/webui/options/cookies_view_handler.cc b/chrome/browser/ui/webui/options/cookies_view_handler.cc index 0d2fb42c..2737f661 100644 --- a/chrome/browser/ui/webui/options/cookies_view_handler.cc +++ b/chrome/browser/ui/webui/options/cookies_view_handler.cc
@@ -216,10 +216,8 @@ new BrowsingDataServiceWorkerHelper(service_worker_context), new BrowsingDataCacheStorageHelper(cache_storage_context), BrowsingDataFlashLSOHelper::Create(profile)); - cookies_tree_model_.reset( - new CookiesTreeModel(container, - profile->GetExtensionSpecialStoragePolicy(), - false)); + cookies_tree_model_.reset(new CookiesTreeModel( + container, profile->GetExtensionSpecialStoragePolicy())); cookies_tree_model_->AddCookiesTreeObserver(this); } }
diff --git a/chrome/browser/ui/webui/options/language_options_handler_common.cc b/chrome/browser/ui/webui/options/language_options_handler_common.cc index 579895e..ee249ea 100644 --- a/chrome/browser/ui/webui/options/language_options_handler_common.cc +++ b/chrome/browser/ui/webui/options/language_options_handler_common.cc
@@ -95,23 +95,6 @@ IDS_OPTIONS_LANGUAGES_CANNOT_TRANSLATE_IN_THIS_LANGUAGE }, }; -#if defined(ENABLE_SETTINGS_APP) - static OptionsStringResource app_resources[] = { - { "cannotBeDisplayedInThisLanguage", - IDS_OPTIONS_SETTINGS_LANGUAGES_CANNOT_BE_DISPLAYED_IN_THIS_LANGUAGE, - IDS_SETTINGS_APP_LAUNCHER_PRODUCT_NAME }, - { "isDisplayedInThisLanguage", - IDS_OPTIONS_SETTINGS_LANGUAGES_IS_DISPLAYED_IN_THIS_LANGUAGE, - IDS_SETTINGS_APP_LAUNCHER_PRODUCT_NAME }, - { "displayInThisLanguage", - IDS_OPTIONS_SETTINGS_LANGUAGES_DISPLAY_IN_THIS_LANGUAGE, - IDS_SETTINGS_APP_LAUNCHER_PRODUCT_NAME }, - }; - base::DictionaryValue* app_values = NULL; - CHECK(localized_strings->GetDictionary(kSettingsAppKey, &app_values)); - RegisterStrings(app_values, app_resources, arraysize(app_resources)); -#endif - RegisterStrings(localized_strings, resources, arraysize(resources)); // The following are resources, rather than local strings.
diff --git a/chrome/browser/ui/webui/options/manage_profile_handler.cc b/chrome/browser/ui/webui/options/manage_profile_handler.cc index 387e7ce..a1a2493c 100644 --- a/chrome/browser/ui/webui/options/manage_profile_handler.cc +++ b/chrome/browser/ui/webui/options/manage_profile_handler.cc
@@ -47,11 +47,6 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" -#if defined(ENABLE_SETTINGS_APP) -#include "chrome/browser/ui/app_list/app_list_service.h" -#include "content/public/browser/web_contents.h" -#endif - namespace options { namespace { @@ -185,11 +180,6 @@ web_ui()->RegisterMessageCallback("profileIconSelectionChanged", base::Bind(&ManageProfileHandler::ProfileIconSelectionChanged, base::Unretained(this))); -#if defined(ENABLE_SETTINGS_APP) - web_ui()->RegisterMessageCallback("switchAppListProfile", - base::Bind(&ManageProfileHandler::SwitchAppListProfile, - base::Unretained(this))); -#endif web_ui()->RegisterMessageCallback("addProfileShortcut", base::Bind(&ManageProfileHandler::AddProfileShortcut, base::Unretained(this))); @@ -413,26 +403,6 @@ profiles::UpdateProfileName(profile, new_profile_name); } -#if defined(ENABLE_SETTINGS_APP) -void ManageProfileHandler::SwitchAppListProfile(const base::ListValue* args) { - DCHECK(args); - DCHECK(profiles::IsMultipleProfilesEnabled()); - - const base::Value* file_path_value; - base::FilePath profile_file_path; - if (!args->Get(0, &file_path_value) || - !base::GetValueAsFilePath(*file_path_value, &profile_file_path)) - return; - - AppListService* app_list_service = AppListService::Get(); - app_list_service->SetProfilePath(profile_file_path); - app_list_service->Show(); - - // Close the settings app, since it will now be for the wrong profile. - web_ui()->GetWebContents()->Close(); -} -#endif // defined(ENABLE_SETTINGS_APP) - void ManageProfileHandler::ProfileIconSelectionChanged( const base::ListValue* args) { DCHECK(args);
diff --git a/chrome/browser/ui/webui/options/manage_profile_handler.h b/chrome/browser/ui/webui/options/manage_profile_handler.h index 4407c92..fe6ec6c 100644 --- a/chrome/browser/ui/webui/options/manage_profile_handler.h +++ b/chrome/browser/ui/webui/options/manage_profile_handler.h
@@ -88,13 +88,6 @@ // ] void SetProfileIconAndName(const base::ListValue* args); -#if defined(ENABLE_SETTINGS_APP) - // Callback for the "switchAppListProfile" message. Asks the - // app_list_controller to change the profile registered for the AppList. - // |args| is of the form: [ {string} profileFilePath ] - void SwitchAppListProfile(const base::ListValue* args); -#endif - // Callback for the 'profileIconSelectionChanged' message. Used to update the // name in the manager profile dialog based on the selected icon. void ProfileIconSelectionChanged(const base::ListValue* args);
diff --git a/chrome/browser/ui/webui/options/options_ui.cc b/chrome/browser/ui/webui/options/options_ui.cc index ac1f5d9..9662d5fce 100644 --- a/chrome/browser/ui/webui/options/options_ui.cc +++ b/chrome/browser/ui/webui/options/options_ui.cc
@@ -207,8 +207,6 @@ // //////////////////////////////////////////////////////////////////////////////// -const char OptionsPageUIHandler::kSettingsAppKey[] = "settingsApp"; - OptionsPageUIHandler::OptionsPageUIHandler() { } @@ -260,9 +258,6 @@ WebContentsObserver(web_ui->GetWebContents()), initialized_handlers_(false) { base::DictionaryValue* localized_strings = new base::DictionaryValue(); - localized_strings->Set(OptionsPageUIHandler::kSettingsAppKey, - new base::DictionaryValue()); - CoreOptionsHandler* core_handler; #if defined(OS_CHROMEOS) core_handler = new chromeos::options::CoreChromeOSOptionsHandler();
diff --git a/chrome/browser/ui/webui/options/options_ui.h b/chrome/browser/ui/webui/options/options_ui.h index 1e836f19..a56fbc2 100644 --- a/chrome/browser/ui/webui/options/options_ui.h +++ b/chrome/browser/ui/webui/options/options_ui.h
@@ -41,9 +41,6 @@ // The base class handler of Javascript messages of options pages. class OptionsPageUIHandler : public content::WebUIMessageHandler { public: - // Key for identifying the Settings App localized_strings in loadTimeData. - static const char kSettingsAppKey[]; - OptionsPageUIHandler(); ~OptionsPageUIHandler() override;
diff --git a/chrome/browser/ui/webui/options/settings_app_browsertest.js b/chrome/browser/ui/webui/options/settings_app_browsertest.js deleted file mode 100644 index 03d11ec6..0000000 --- a/chrome/browser/ui/webui/options/settings_app_browsertest.js +++ /dev/null
@@ -1,70 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * TestFixture for App Launcher's Settings App testing. - * @extends {testing.Test} - * @constructor - */ -function SettingsAppWebUITest() {} - -SettingsAppWebUITest.prototype = { - __proto__: testing.Test.prototype, - - /** - * Browse to Settings App page, in a browser. - */ - browsePreload: 'chrome://settings-frame/options_settings_app.html', -}; - -GEN('#if defined(ENABLE_SETTINGS_APP)'); - -// This test is flaky on Linux and Windows bots. See crbug.com/579666 -GEN('#if defined(OS_LINUX) || defined(OS_WIN)'); -GEN('#define MAYBE_testOpenSettingsApp DISABLED_testOpenSettingsApp'); -GEN('#else'); -GEN('#define MAYBE_testOpenSettingsApp testOpenSettingsApp'); -GEN('#endif // defined(OS_LINUX) || defined(OS_WIN)'); -// Test opening Settings App, and do some checks on section visibility. -TEST_F('SettingsAppWebUITest', 'MAYBE_testOpenSettingsApp', function() { - // Note there is no location bar in the Settings App. - - // Some things are hidden via a parent, so make a helper function. - function isVisible(elementId) { - var elem = $(elementId); - return elem.offsetWidth > 0 || elem.offsetHeight > 0; - } - assertTrue(OptionsPage.isSettingsApp()); - assertTrue(isVisible('sync-users-section')); - assertTrue(isVisible('sync-section')); - - // Spot-check some regular settings items that should be hidden. - assertFalse(isVisible('change-home-page-section')); - assertFalse(isVisible('default-search-engine')); - assertFalse(isVisible('hotword-search')); - assertFalse(isVisible('privacy-section')); - assertFalse(isVisible('startup-section')); -}); - -// This test is flaky on Linux and Windows bot. See crbug.com/579666 -GEN('#if defined(OS_LINUX) || defined(OS_WIN)'); -GEN('#define MAYBE_testStrings DISABLED_testStrings'); -GEN('#else'); -GEN('#define MAYBE_testStrings testStrings'); -GEN('#endif // defined(OS_LINUX) || defined(OS_WIN)'); -// Check functionality of LoadTimeData.overrideValues(), which the Settings App -// uses. Do spot checks, so the test is not too fragile. Some of the content -// strings rely on waiting for sync sign-in status, or platform-specifics. -TEST_F('SettingsAppWebUITest', 'MAYBE_testStrings', function() { - // Ensure we check against the override values. - assertTrue(!!loadTimeData.getValue('settingsApp')); - - // Check a product-specific label, to ensure it uses "App Launcher", and not - // Chrome / Chromium. - var languagesLabelElement = - document.querySelector('[i18n-content="languageSectionLabel"]'); - assertNotEquals(-1, languagesLabelElement.innerHTML.indexOf('App Launcher')); -}); - -GEN('#endif // defined(ENABLE_SETTINGS_APP)');
diff --git a/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc b/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc index bd17943..649d0fb 100644 --- a/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h" -#include "ash/audio/sounds.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/command_line.h" @@ -14,6 +13,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/camera_presence_notifier.h" #include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h" #include "chrome/browser/chromeos/login/users/chrome_user_manager.h" @@ -35,6 +35,7 @@ #include "content/public/browser/web_ui.h" #include "content/public/common/url_constants.h" #include "grit/browser_resources.h" +#include "media/audio/sounds/sounds_manager.h" #include "net/base/data_url.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" @@ -170,12 +171,14 @@ void ChangePictureHandler::HandleDiscardPhoto(const base::ListValue* args) { DCHECK(args->empty()); - ash::PlaySystemSoundIfSpokenFeedback(SOUND_OBJECT_DELETE); + AccessibilityManager::Get()->PlayEarcon( + SOUND_OBJECT_DELETE, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED); } void ChangePictureHandler::HandlePhotoTaken(const base::ListValue* args) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - ash::PlaySystemSoundIfSpokenFeedback(SOUND_CAMERA_SNAP); + AccessibilityManager::Get()->PlayEarcon( + SOUND_CAMERA_SNAP, PlaySoundOption::SPOKEN_FEEDBACK_ENABLED); std::string image_url; if (!args || args->GetSize() != 1 || !args->GetString(0, &image_url))
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 374fb38..9b08524 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
@@ -153,17 +153,25 @@ {"aboutUpgradeUpdating", IDS_SETTINGS_UPGRADE_UPDATING}, #if defined(OS_CHROMEOS) - {"aboutChannelStable", IDS_SETTINGS_ABOUT_PAGE_CURRENT_CHANNEL_STABLE}, + {"aboutArcVersionLabel", IDS_SETTINGS_ABOUT_PAGE_ARC_VERSION}, + {"aboutBuildDateLabel", IDS_VERSION_UI_BUILD_DATE}, {"aboutChannelBeta", IDS_SETTINGS_ABOUT_PAGE_CURRENT_CHANNEL_BETA}, {"aboutChannelDev", IDS_SETTINGS_ABOUT_PAGE_CURRENT_CHANNEL_DEV}, + {"aboutChannelLabel", IDS_SETTINGS_ABOUT_PAGE_CHANNEL}, + {"aboutChannelStable", IDS_SETTINGS_ABOUT_PAGE_CURRENT_CHANNEL_STABLE}, {"aboutCheckForUpdates", IDS_SETTINGS_ABOUT_PAGE_CHECK_FOR_UPDATES}, + {"aboutCommandLineLabel", IDS_VERSION_UI_COMMAND_LINE}, {"aboutCurrentlyOnChannel", IDS_SETTINGS_ABOUT_PAGE_CURRENT_CHANNEL}, + {"aboutDetailedBuildInfo", IDS_SETTINGS_ABOUT_PAGE_DETAILED_BUILD_INFO}, + {"aboutFirmwareLabel", IDS_SETTINGS_ABOUT_PAGE_FIRMWARE}, + {"aboutPlatformLabel", IDS_SETTINGS_ABOUT_PAGE_PLATFORM}, {"aboutRelaunchAndPowerwash", IDS_SETTINGS_ABOUT_PAGE_RELAUNCH_AND_POWERWASH}, {"aboutUpgradeUpdatingChannelSwitch", IDS_SETTINGS_UPGRADE_UPDATING_CHANNEL_SWITCH}, {"aboutUpgradeSuccessChannelSwitch", IDS_SETTINGS_UPGRADE_SUCCESSFUL_CHANNEL_SWITCH}, + {"aboutUserAgentLabel", IDS_VERSION_UI_USER_AGENT}, // About page, channel switcher dialog. {"aboutChangeChannel", IDS_SETTINGS_ABOUT_PAGE_CHANGE_CHANNEL}, @@ -704,6 +712,11 @@ {"googlePayments", IDS_SETTINGS_GOOGLE_PAYMENTS}, {"googlePaymentsCached", IDS_SETTINGS_GOOGLE_PAYMENTS_CACHED}, {"addresses", IDS_SETTINGS_AUTOFILL_ADDRESSES_HEADING}, + {"addAddressTitle", IDS_SETTINGS_AUTOFILL_ADDRESSES_ADD_TITLE}, + {"editAddressTitle", IDS_SETTINGS_AUTOFILL_ADDRESSES_EDIT_TITLE}, + {"addressCountry", IDS_SETTINGS_AUTOFILL_ADDRESSES_COUNTRY}, + {"addressPhone", IDS_SETTINGS_AUTOFILL_ADDRESSES_PHONE}, + {"addressEmail", IDS_SETTINGS_AUTOFILL_ADDRESSES_EMAIL}, {"addAddress", IDS_SETTINGS_AUTOFILL_ADD_ADDRESS_BUTTON}, {"editAddress", IDS_SETTINGS_ADDRESS_EDIT}, {"removeAddress", IDS_SETTINGS_ADDRESS_REMOVE}, @@ -782,6 +795,8 @@ IDS_SETTINGS_PEOPLE_QUICK_UNLOCK_CONFIGURE_PIN_CHOOSE_PIN_TITLE}, {"quickUnlockConfigurePinChoosePinWeakPinWarning", IDS_SETTINGS_PEOPLE_QUICK_UNLOCK_CONFIGURE_PIN_CHOOSE_PIN_WEAK_PIN_WARNING}, + {"quickUnlockConfigurePinChoosePinTooShort", + IDS_SETTINGS_PEOPLE_QUICK_UNLOCK_CONFIGURE_PIN_CHOOSE_PIN_TOO_SHORT}, {"quickUnlockConfigurePinContinueButton", IDS_SETTINGS_PEOPLE_QUICK_UNLOCK_CONFIGURE_PIN_CONTINUE_BUTTON}, {"quickUnlockConfigurePinConfirmPinTitle", @@ -1042,6 +1057,7 @@ {"siteSettingsCategoryCamera", IDS_SETTINGS_SITE_SETTINGS_CAMERA}, {"siteSettingsCategoryCookies", IDS_SETTINGS_SITE_SETTINGS_COOKIES}, {"siteSettingsCategoryFullscreen", IDS_SETTINGS_SITE_SETTINGS_FULLSCREEN}, + {"siteSettingsCategoryHandlers", IDS_SETTINGS_SITE_SETTINGS_HANDLERS}, {"siteSettingsCategoryImages", IDS_SETTINGS_SITE_SETTINGS_IMAGES}, {"siteSettingsCategoryLocation", IDS_SETTINGS_SITE_SETTINGS_LOCATION}, {"siteSettingsCategoryJavascript", IDS_SETTINGS_SITE_SETTINGS_JAVASCRIPT}, @@ -1058,6 +1074,7 @@ IDS_SETTINGS_SITE_SETTINGS_BACKGROUND_SYNC}, {"siteSettingsCamera", IDS_SETTINGS_SITE_SETTINGS_CAMERA}, {"siteSettingsCookies", IDS_SETTINGS_SITE_SETTINGS_COOKIES}, + {"siteSettingsHandlers", IDS_SETTINGS_SITE_SETTINGS_HANDLERS}, {"siteSettingsKeygen", IDS_SETTINGS_SITE_SETTINGS_KEYGEN}, {"siteSettingsLocation", IDS_SETTINGS_SITE_SETTINGS_LOCATION}, {"siteSettingsMic", IDS_SETTINGS_SITE_SETTINGS_MIC}, @@ -1095,6 +1112,12 @@ IDS_SETTINGS_SITE_SETTINGS_BACKGROUND_SYNC_ALLOW_RECENTLY_CLOSED_SITES_RECOMMENDED}, {"siteSettingsBackgroundSyncBlocked", IDS_SETTINGS_SITE_SETTINGS_BACKGROUND_SYNC_BLOCKED}, + {"siteSettingsHandlersAsk", + IDS_SETTINGS_SITE_SETTINGS_HANDLERS_ASK}, + {"siteSettingsHandlersAskRecommended", + IDS_SETTINGS_SITE_SETTINGS_HANDLERS_ASK_RECOMMENDED}, + {"siteSettingsHandlersBlocked", + IDS_SETTINGS_SITE_SETTINGS_HANDLERS_BLOCKED}, {"siteSettingsKeygenAllow", IDS_SETTINGS_SITE_SETTINGS_KEYGEN_ALLOW}, {"siteSettingsKeygenBlock", @@ -1153,6 +1176,9 @@ {"thirdPartyCookie", IDS_SETTINGS_SITE_SETTINGS_THIRD_PARTY_COOKIE}, {"thirdPartyCookieSublabel", IDS_SETTINGS_SITE_SETTINGS_THIRD_PARTY_COOKIE_SUBLABEL}, + {"handlerIsDefault", IDS_SETTINGS_SITE_SETTINGS_HANDLER_IS_DEFAULT}, + {"handlerSetDefault", IDS_SETTINGS_SITE_SETTINGS_HANDLER_SET_DEFAULT}, + {"handlerRemove", IDS_SETTINGS_SITE_SETTINGS_REMOVE}, }; AddLocalizedStringsBulk(html_source, localized_strings, arraysize(localized_strings));
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc index bd6d743..b8f7380 100644 --- a/chrome/browser/ui/webui/settings/md_settings_ui.cc +++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -19,6 +19,7 @@ #include "chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.h" #include "chrome/browser/ui/webui/settings/people_handler.h" #include "chrome/browser/ui/webui/settings/profile_info_handler.h" +#include "chrome/browser/ui/webui/settings/protocol_handlers_handler.h" #include "chrome/browser/ui/webui/settings/reset_settings_handler.h" #include "chrome/browser/ui/webui/settings/search_engines_handler.h" #include "chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h" @@ -69,6 +70,7 @@ AddSettingsPageUIHandler(new CookiesViewHandler()); AddSettingsPageUIHandler(new DownloadsHandler()); AddSettingsPageUIHandler(new FontHandler(web_ui)); + AddSettingsPageUIHandler(new ProtocolHandlersHandler()); AddSettingsPageUIHandler(new LanguagesHandler(web_ui)); AddSettingsPageUIHandler(new MediaDevicesSelectionHandler(profile)); AddSettingsPageUIHandler(new PeopleHandler(profile));
diff --git a/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc b/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc new file mode 100644 index 0000000..1d10197 --- /dev/null +++ b/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc
@@ -0,0 +1,221 @@ +// 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/ui/webui/settings/protocol_handlers_handler.h" + +#include <memory> +#include <utility> +#include <vector> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/macros.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/url_constants.h" +#include "chrome/grit/generated_resources.h" +#include "components/google/core/browser/google_util.h" +#include "components/prefs/pref_service.h" +#include "content/public/browser/web_ui.h" + +namespace settings { + +ProtocolHandlersHandler::ProtocolHandlersHandler() { +} + +ProtocolHandlersHandler::~ProtocolHandlersHandler() { +} + +void ProtocolHandlersHandler::OnJavascriptAllowed() { + notification_registrar_.Add( + this, chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED, + content::Source<Profile>(Profile::FromWebUI(web_ui()))); +} + +void ProtocolHandlersHandler::OnJavascriptDisallowed() { + notification_registrar_.RemoveAll(); +} + +void ProtocolHandlersHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback("initializeProtocolHandlerList", + base::Bind(&ProtocolHandlersHandler::InitializeProtocolHandlerList, + base::Unretained(this))); + web_ui()->RegisterMessageCallback("clearDefault", + base::Bind(&ProtocolHandlersHandler::ClearDefault, + base::Unretained(this))); + web_ui()->RegisterMessageCallback("removeHandler", + base::Bind(&ProtocolHandlersHandler::RemoveHandler, + base::Unretained(this))); + web_ui()->RegisterMessageCallback("setHandlersEnabled", + base::Bind(&ProtocolHandlersHandler::SetHandlersEnabled, + base::Unretained(this))); + web_ui()->RegisterMessageCallback("setDefault", + base::Bind(&ProtocolHandlersHandler::SetDefault, + base::Unretained(this))); + web_ui()->RegisterMessageCallback("removeIgnoredHandler", + base::Bind(&ProtocolHandlersHandler::RemoveIgnoredHandler, + base::Unretained(this))); +} + +ProtocolHandlerRegistry* ProtocolHandlersHandler::GetProtocolHandlerRegistry() { + return ProtocolHandlerRegistryFactory::GetForBrowserContext( + Profile::FromWebUI(web_ui())); +} + +static void GetHandlersAsListValue( + const ProtocolHandlerRegistry::ProtocolHandlerList& handlers, + base::ListValue* handler_list) { + ProtocolHandlerRegistry::ProtocolHandlerList::const_iterator handler; + for (handler = handlers.begin(); handler != handlers.end(); ++handler) { + std::unique_ptr<base::DictionaryValue> handler_value( + new base::DictionaryValue()); + handler_value->SetString("protocol", handler->protocol()); + handler_value->SetString("spec", handler->url().spec()); + handler_value->SetString("host", handler->url().host()); + handler_list->Append(std::move(handler_value)); + } +} + +void ProtocolHandlersHandler::GetHandlersForProtocol( + const std::string& protocol, + base::DictionaryValue* handlers_value) { + ProtocolHandlerRegistry* registry = GetProtocolHandlerRegistry(); + // The items which are to be written into |handlers_value| are also described + // in chrome/browser/resources/options/handler_options.js in @typedef + // for Handlers. Please update them whenever you add or remove any keys here. + handlers_value->SetString("protocol", protocol); + handlers_value->SetInteger("default_handler", + registry->GetHandlerIndex(protocol)); + handlers_value->SetBoolean( + "is_default_handler_set_by_user", + registry->IsRegisteredByUser(registry->GetHandlerFor(protocol))); + handlers_value->SetBoolean("has_policy_recommendations", + registry->HasPolicyRegisteredHandler(protocol)); + + base::ListValue* handlers_list = new base::ListValue(); + GetHandlersAsListValue(registry->GetHandlersFor(protocol), handlers_list); + handlers_value->Set("handlers", handlers_list); +} + +void ProtocolHandlersHandler::GetIgnoredHandlers(base::ListValue* handlers) { + ProtocolHandlerRegistry* registry = GetProtocolHandlerRegistry(); + ProtocolHandlerRegistry::ProtocolHandlerList ignored_handlers = + registry->GetIgnoredHandlers(); + return GetHandlersAsListValue(ignored_handlers, handlers); +} + +void ProtocolHandlersHandler::UpdateHandlerList() { + ProtocolHandlerRegistry* registry = GetProtocolHandlerRegistry(); + std::vector<std::string> protocols; + registry->GetRegisteredProtocols(&protocols); + + base::ListValue handlers; + for (std::vector<std::string>::iterator protocol = protocols.begin(); + protocol != protocols.end(); protocol++) { + std::unique_ptr<base::DictionaryValue> handler_value( + new base::DictionaryValue()); + GetHandlersForProtocol(*protocol, handler_value.get()); + handlers.Append(std::move(handler_value)); + } + + std::unique_ptr<base::ListValue> ignored_handlers(new base::ListValue()); + GetIgnoredHandlers(ignored_handlers.get()); + CallJavascriptFunction("cr.webUIListenerCallback", + base::StringValue("setProtocolHandlers"), + handlers); + CallJavascriptFunction("cr.webUIListenerCallback", + base::StringValue("setIgnoredProtocolHandlers"), + *ignored_handlers); +} + +void ProtocolHandlersHandler::InitializeProtocolHandlerList( + const base::ListValue* args) { + AllowJavascript(); + SendHandlersEnabledValue(); + UpdateHandlerList(); +} + +void ProtocolHandlersHandler::SendHandlersEnabledValue() { + CallJavascriptFunction("cr.webUIListenerCallback", + base::StringValue("setHandlersEnabled"), + base::FundamentalValue( + GetProtocolHandlerRegistry()->enabled())); +} + +void ProtocolHandlersHandler::RemoveHandler(const base::ListValue* args) { + const base::ListValue* list; + if (!args->GetList(0, &list)) { + NOTREACHED(); + return; + } + + ProtocolHandler handler(ParseHandlerFromArgs(list)); + GetProtocolHandlerRegistry()->RemoveHandler(handler); + + // No need to call UpdateHandlerList() - we should receive a notification + // that the ProtocolHandlerRegistry has changed and we will update the view + // then. +} + +void ProtocolHandlersHandler::RemoveIgnoredHandler( + const base::ListValue* args) { + const base::ListValue* list; + if (!args->GetList(0, &list)) { + NOTREACHED(); + return; + } + + ProtocolHandler handler(ParseHandlerFromArgs(list)); + GetProtocolHandlerRegistry()->RemoveIgnoredHandler(handler); +} + +void ProtocolHandlersHandler::SetHandlersEnabled(const base::ListValue* args) { + bool enabled = true; + CHECK(args->GetBoolean(0, &enabled)); + if (enabled) + GetProtocolHandlerRegistry()->Enable(); + else + GetProtocolHandlerRegistry()->Disable(); +} + +void ProtocolHandlersHandler::ClearDefault(const base::ListValue* args) { + const base::Value* value; + CHECK(args->Get(0, &value)); + std::string protocol_to_clear; + CHECK(value->GetAsString(&protocol_to_clear)); + GetProtocolHandlerRegistry()->ClearDefault(protocol_to_clear); +} + +void ProtocolHandlersHandler::SetDefault(const base::ListValue* args) { + const base::ListValue* list; + CHECK(args->GetList(0, &list)); + const ProtocolHandler& handler(ParseHandlerFromArgs(list)); + CHECK(!handler.IsEmpty()); + GetProtocolHandlerRegistry()->OnAcceptRegisterProtocolHandler(handler); +} + +ProtocolHandler ProtocolHandlersHandler::ParseHandlerFromArgs( + const base::ListValue* args) const { + base::string16 protocol; + base::string16 url; + bool ok = args->GetString(0, &protocol) && args->GetString(1, &url); + if (!ok) + return ProtocolHandler::EmptyProtocolHandler(); + return ProtocolHandler::CreateProtocolHandler(base::UTF16ToUTF8(protocol), + GURL(base::UTF16ToUTF8(url))); +} + +void ProtocolHandlersHandler::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + DCHECK_EQ(chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED, type); + SendHandlersEnabledValue(); + UpdateHandlerList(); +} + +} // namespace settings
diff --git a/chrome/browser/ui/webui/settings/protocol_handlers_handler.h b/chrome/browser/ui/webui/settings/protocol_handlers_handler.h new file mode 100644 index 0000000..87a38241 --- /dev/null +++ b/chrome/browser/ui/webui/settings/protocol_handlers_handler.h
@@ -0,0 +1,95 @@ +// 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_UI_WEBUI_SETTINGS_PROTOCOL_HANDLERS_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_PROTOCOL_HANDLERS_HANDLER_H_ + +#include <string> + +#include "base/macros.h" +#include "chrome/browser/custom_handlers/protocol_handler_registry.h" +#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" +#include "chrome/common/custom_handlers/protocol_handler.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" + +//////////////////////////////////////////////////////////////////////////////// +// ProtocolHandlersHandler + +// Listen for changes to protocol handlers (i.e. registerProtocolHandler()). +// This get triggered whenever a user allows a specific website or application +// to handle clicks on a link with a specified protocol (i.e. mailto: -> Gmail). + +namespace base { +class DictionaryValue; +} + +namespace settings { + +class ProtocolHandlersHandler : public SettingsPageUIHandler, + public content::NotificationObserver { + public: + ProtocolHandlersHandler(); + ~ProtocolHandlersHandler() override; + + // SettingsPageUIHandler: + void OnJavascriptAllowed() override; + void OnJavascriptDisallowed() override; + void RegisterMessages() override; + + // content::NotificationObserver: + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override; + + private: + // Called to fetch the initial list of data to show. + void InitializeProtocolHandlerList(const base::ListValue* args); + + // Notifies the JS side whether the handlers are enabled or not. + void SendHandlersEnabledValue(); + + // Called when the user toggles whether custom handlers are enabled. + void SetHandlersEnabled(const base::ListValue* args); + + // Called when the user sets a new default handler for a protocol. + void SetDefault(const base::ListValue* args); + + // Called when the user clears the default handler for a protocol. + // |args| is the string name of the protocol to clear. + void ClearDefault(const base::ListValue* args); + + // Parses a ProtocolHandler out of the arguments passed back from the view. + // |args| is a list of [protocol, url, title]. + ProtocolHandler ParseHandlerFromArgs(const base::ListValue* args) const; + + // Returns a JSON object describing the set of protocol handlers for the + // given protocol. + void GetHandlersForProtocol(const std::string& protocol, + base::DictionaryValue* value); + + // Returns a JSON list of the ignored protocol handlers. + void GetIgnoredHandlers(base::ListValue* handlers); + + // Called when the JS PasswordManager object is initialized. + void UpdateHandlerList(); + + // Remove a handler. + // |args| is a list of [protocol, url, title]. + void RemoveHandler(const base::ListValue* args); + + // Remove an ignored handler. + // |args| is a list of [protocol, url, title]. + void RemoveIgnoredHandler(const base::ListValue* args); + + ProtocolHandlerRegistry* GetProtocolHandlerRegistry(); + + content::NotificationRegistrar notification_registrar_; + + DISALLOW_COPY_AND_ASSIGN(ProtocolHandlersHandler); +}; + +} // namespace settings + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_PROTOCOL_HANDLERS_HANDLER_H_
diff --git a/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc b/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc index 97a3ceb0..91dd603 100644 --- a/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc +++ b/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc
@@ -29,13 +29,13 @@ // TODO(msramek): Get the list of deletion preferences from the JS side. const char* kCounterPrefs[] = { - prefs::kDeleteBrowsingHistory, - prefs::kDeleteCache, - prefs::kDeleteDownloadHistory, - prefs::kDeleteFormData, - prefs::kDeleteHostedAppsData, - prefs::kDeleteMediaLicenses, - prefs::kDeletePasswords, + browsing_data::prefs::kDeleteBrowsingHistory, + browsing_data::prefs::kDeleteCache, + browsing_data::prefs::kDeleteDownloadHistory, + browsing_data::prefs::kDeleteFormData, + browsing_data::prefs::kDeleteHostedAppsData, + browsing_data::prefs::kDeleteMediaLicenses, + browsing_data::prefs::kDeletePasswords, }; } // namespace @@ -102,31 +102,31 @@ int remove_mask = 0; if (prefs->GetBoolean(prefs::kAllowDeletingBrowserHistory)) { - if (prefs->GetBoolean(prefs::kDeleteBrowsingHistory)) + if (prefs->GetBoolean(browsing_data::prefs::kDeleteBrowsingHistory)) remove_mask |= BrowsingDataRemover::REMOVE_HISTORY; - if (prefs->GetBoolean(prefs::kDeleteDownloadHistory)) + if (prefs->GetBoolean(browsing_data::prefs::kDeleteDownloadHistory)) remove_mask |= BrowsingDataRemover::REMOVE_DOWNLOADS; } - if (prefs->GetBoolean(prefs::kDeleteCache)) + if (prefs->GetBoolean(browsing_data::prefs::kDeleteCache)) remove_mask |= BrowsingDataRemover::REMOVE_CACHE; int origin_mask = 0; - if (prefs->GetBoolean(prefs::kDeleteCookies)) { + if (prefs->GetBoolean(browsing_data::prefs::kDeleteCookies)) { remove_mask |= site_data_mask; origin_mask |= BrowsingDataHelper::UNPROTECTED_WEB; } - if (prefs->GetBoolean(prefs::kDeletePasswords)) + if (prefs->GetBoolean(browsing_data::prefs::kDeletePasswords)) remove_mask |= BrowsingDataRemover::REMOVE_PASSWORDS; - if (prefs->GetBoolean(prefs::kDeleteFormData)) + if (prefs->GetBoolean(browsing_data::prefs::kDeleteFormData)) remove_mask |= BrowsingDataRemover::REMOVE_FORM_DATA; - if (prefs->GetBoolean(prefs::kDeleteMediaLicenses)) + if (prefs->GetBoolean(browsing_data::prefs::kDeleteMediaLicenses)) remove_mask |= BrowsingDataRemover::REMOVE_MEDIA_LICENSES; - if (prefs->GetBoolean(prefs::kDeleteHostedAppsData)) { + if (prefs->GetBoolean(browsing_data::prefs::kDeleteHostedAppsData)) { remove_mask |= site_data_mask; origin_mask |= BrowsingDataHelper::PROTECTED_WEB; } @@ -134,11 +134,11 @@ // Record the deletion of cookies and cache. BrowsingDataRemover::CookieOrCacheDeletionChoice choice = BrowsingDataRemover::NEITHER_COOKIES_NOR_CACHE; - if (prefs->GetBoolean(prefs::kDeleteCookies)) { - choice = prefs->GetBoolean(prefs::kDeleteCache) + if (prefs->GetBoolean(browsing_data::prefs::kDeleteCookies)) { + choice = prefs->GetBoolean(browsing_data::prefs::kDeleteCache) ? BrowsingDataRemover::BOTH_COOKIES_AND_CACHE : BrowsingDataRemover::ONLY_COOKIES; - } else if (prefs->GetBoolean(prefs::kDeleteCache)) { + } else if (prefs->GetBoolean(browsing_data::prefs::kDeleteCache)) { choice = BrowsingDataRemover::ONLY_CACHE; } @@ -147,15 +147,15 @@ BrowsingDataRemover::MAX_CHOICE_VALUE); // Record the circumstances under which passwords are deleted. - if (prefs->GetBoolean(prefs::kDeletePasswords)) { + if (prefs->GetBoolean(browsing_data::prefs::kDeletePasswords)) { static const char* other_types[] = { - prefs::kDeleteBrowsingHistory, - prefs::kDeleteDownloadHistory, - prefs::kDeleteCache, - prefs::kDeleteCookies, - prefs::kDeleteFormData, - prefs::kDeleteHostedAppsData, - prefs::kDeleteMediaLicenses, + browsing_data::prefs::kDeleteBrowsingHistory, + browsing_data::prefs::kDeleteDownloadHistory, + browsing_data::prefs::kDeleteCache, + browsing_data::prefs::kDeleteCookies, + browsing_data::prefs::kDeleteFormData, + browsing_data::prefs::kDeleteHostedAppsData, + browsing_data::prefs::kDeleteMediaLicenses, }; static size_t num_other_types = arraysize(other_types); int checked_other_types = std::count_if( @@ -191,7 +191,7 @@ // 2. The notice has been shown less than |kMaxTimesHistoryNoticeShown|. notice_shown_times < kMaxTimesHistoryNoticeShown && // 3. The selected data types contained browsing history. - prefs->GetBoolean(prefs::kDeleteBrowsingHistory); + prefs->GetBoolean(browsing_data::prefs::kDeleteBrowsingHistory); if (show_notice) { // Increment the preference.
diff --git a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc index 156ff88..de86c63 100644 --- a/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc +++ b/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc
@@ -161,8 +161,7 @@ BrowsingDataFlashLSOHelper::Create(profile)); cookies_tree_model_.reset( new CookiesTreeModel(container, - profile->GetExtensionSpecialStoragePolicy(), - false)); + profile->GetExtensionSpecialStoragePolicy())); cookies_tree_model_->AddCookiesTreeObserver(this); } }
diff --git a/chrome/browser/ui/webui/snippets_internals_message_handler.cc b/chrome/browser/ui/webui/snippets_internals_message_handler.cc index 89a20ea..fdb57a837 100644 --- a/chrome/browser/ui/webui/snippets_internals_message_handler.cc +++ b/chrome/browser/ui/webui/snippets_internals_message_handler.cc
@@ -14,16 +14,22 @@ #include "base/feature_list.h" #include "base/i18n/time_formatting.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/values.h" #include "chrome/browser/android/chrome_feature_list.h" +#include "chrome/browser/ntp_snippets/content_suggestions_service_factory.h" #include "chrome/browser/ntp_snippets/ntp_snippets_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "components/ntp_snippets/ntp_snippet.h" #include "components/ntp_snippets/switches.h" #include "content/public/browser/web_ui.h" +using ntp_snippets::ContentSuggestion; +using ntp_snippets::ContentSuggestionsCategory; +using ntp_snippets::ContentSuggestionsCategoryStatus; + namespace { std::unique_ptr<base::DictionaryValue> PrepareSnippet( @@ -52,12 +58,68 @@ return entry; } +std::unique_ptr<base::DictionaryValue> PrepareSuggestion( + const ContentSuggestion& suggestion, + int index) { + auto entry = base::MakeUnique<base::DictionaryValue>(); + entry->SetString("suggestionId", suggestion.id()); + entry->SetString("url", suggestion.url().spec()); + entry->SetString("ampUrl", suggestion.amp_url().spec()); + entry->SetString("title", suggestion.title()); + entry->SetString("snippetText", suggestion.snippet_text()); + entry->SetString("publishDate", + TimeFormatShortDateAndTime(suggestion.publish_date())); + entry->SetString("publisherName", suggestion.publisher_name()); + entry->SetString("id", "content-suggestion-" + base::IntToString(index)); + return entry; +} + +std::string MapCategoryName(ContentSuggestionsCategory category) { + switch (category) { + case ContentSuggestionsCategory::ARTICLES: + return "Articles"; + case ContentSuggestionsCategory::COUNT: + NOTREACHED() << "Category::COUNT must not be used as a value"; + } + return std::string(); +} + +std::string MapCategoryStatus(ContentSuggestionsCategoryStatus status) { + switch (status) { + case ContentSuggestionsCategoryStatus::INITIALIZING: + return "INITIALIZING"; + case ContentSuggestionsCategoryStatus::AVAILABLE: + return "AVAILABLE"; + case ContentSuggestionsCategoryStatus::AVAILABLE_LOADING: + return "AVAILABLE_LOADING"; + case ContentSuggestionsCategoryStatus::NOT_PROVIDED: + return "NOT_PROVIDED"; + case ContentSuggestionsCategoryStatus::ALL_SUGGESTIONS_EXPLICITLY_DISABLED: + return "ALL_SUGGESTIONS_EXPLICITLY_DISABLED"; + case ContentSuggestionsCategoryStatus::CATEGORY_EXPLICITLY_DISABLED: + return "CATEGORY_EXPLICITLY_DISABLED"; + case ContentSuggestionsCategoryStatus::SIGNED_OUT: + return "SIGNED_OUT"; + case ContentSuggestionsCategoryStatus::SYNC_DISABLED: + return "SYNC_DISABLED"; + case ContentSuggestionsCategoryStatus::PASSPHRASE_ENCRYPTION_ENABLED: + return "PASSPHRASE_ENCRYPTION_ENABLED"; + case ContentSuggestionsCategoryStatus::HISTORY_SYNC_DISABLED: + return "HISTORY_SYNC_DISABLED"; + case ContentSuggestionsCategoryStatus::LOADING_ERROR: + return "LOADING_ERROR"; + } + return std::string(); +} + } // namespace SnippetsInternalsMessageHandler::SnippetsInternalsMessageHandler() - : observer_(this), + : ntp_snippets_service_observer_(this), + content_suggestions_service_observer_(this), dom_loaded_(false), - ntp_snippets_service_(nullptr) {} + ntp_snippets_service_(nullptr), + content_suggestions_service_(nullptr) {} SnippetsInternalsMessageHandler::~SnippetsInternalsMessageHandler() {} @@ -77,11 +139,33 @@ void SnippetsInternalsMessageHandler::NTPSnippetsServiceDisabledReasonChanged( ntp_snippets::DisabledReason disabled_reason) {} +void SnippetsInternalsMessageHandler::OnNewSuggestions() { + if (!dom_loaded_) + return; + SendContentSuggestions(); +} + +void SnippetsInternalsMessageHandler::OnCategoryStatusChanged( + ContentSuggestionsCategory category, + ContentSuggestionsCategoryStatus new_status) { + if (!dom_loaded_) + return; + SendContentSuggestions(); +} + +void SnippetsInternalsMessageHandler::ContentSuggestionsServiceShutdown() {} + void SnippetsInternalsMessageHandler::RegisterMessages() { // additional initialization (web_ui() does not work from the constructor) - ntp_snippets_service_ = NTPSnippetsServiceFactory::GetInstance()-> - GetForProfile(Profile::FromWebUI(web_ui())); - observer_.Add(ntp_snippets_service_); + Profile* profile = Profile::FromWebUI(web_ui()); + + ntp_snippets_service_ = + NTPSnippetsServiceFactory::GetInstance()->GetForProfile(profile); + ntp_snippets_service_observer_.Add(ntp_snippets_service_); + + content_suggestions_service_ = + ContentSuggestionsServiceFactory::GetInstance()->GetForProfile(profile); + content_suggestions_service_observer_.Add(content_suggestions_service_); web_ui()->RegisterMessageCallback( "loaded", @@ -100,6 +184,17 @@ "clearDiscarded", base::Bind(&SnippetsInternalsMessageHandler::HandleClearDiscarded, base::Unretained(this))); + + web_ui()->RegisterMessageCallback( + "clearCachedSuggestions", + base::Bind(&SnippetsInternalsMessageHandler::HandleClearCachedSuggestions, + base::Unretained(this))); + + web_ui()->RegisterMessageCallback( + "clearDiscardedSuggestions", + base::Bind( + &SnippetsInternalsMessageHandler::HandleClearDiscardedSuggestions, + base::Unretained(this))); } void SnippetsInternalsMessageHandler::HandleLoaded( @@ -114,14 +209,14 @@ void SnippetsInternalsMessageHandler::HandleClear(const base::ListValue* args) { DCHECK_EQ(0u, args->GetSize()); - ntp_snippets_service_->ClearSnippets(); + ntp_snippets_service_->ClearCachedSuggestionsForDebugging(); } void SnippetsInternalsMessageHandler::HandleClearDiscarded( const base::ListValue* args) { DCHECK_EQ(0u, args->GetSize()); - ntp_snippets_service_->ClearDiscardedSnippets(); + ntp_snippets_service_->ClearDiscardedSuggestionsForDebugging(); SendDiscardedSnippets(); } @@ -141,6 +236,20 @@ ntp_snippets_service_->FetchSnippetsFromHosts(hosts); } +void SnippetsInternalsMessageHandler::HandleClearCachedSuggestions( + const base::ListValue* args) { + DCHECK_EQ(0u, args->GetSize()); + + content_suggestions_service_->ClearCachedSuggestionsForDebugging(); +} + +void SnippetsInternalsMessageHandler::HandleClearDiscardedSuggestions( + const base::ListValue* args) { + DCHECK_EQ(0u, args->GetSize()); + + content_suggestions_service_->ClearDiscardedSuggestionsForDebugging(); +} + void SnippetsInternalsMessageHandler::SendInitialData() { SendHosts(); @@ -170,6 +279,7 @@ SendSnippets(); SendDiscardedSnippets(); + SendContentSuggestions(); } void SnippetsInternalsMessageHandler::SendSnippets() { @@ -222,6 +332,36 @@ "chrome.SnippetsInternals.receiveHosts", result); } +void SnippetsInternalsMessageHandler::SendContentSuggestions() { + std::unique_ptr<base::ListValue> categories_list(new base::ListValue); + + int index = 0; + for (ContentSuggestionsCategory category : + content_suggestions_service_->GetCategories()) { + ContentSuggestionsCategoryStatus status = + content_suggestions_service_->GetCategoryStatus(category); + const std::vector<ContentSuggestion>& suggestions = + content_suggestions_service_->GetSuggestionsForCategory(category); + + std::unique_ptr<base::ListValue> suggestions_list(new base::ListValue); + for (const ContentSuggestion& suggestion : suggestions) { + suggestions_list->Append(PrepareSuggestion(suggestion, index++)); + } + + std::unique_ptr<base::DictionaryValue> category_entry( + new base::DictionaryValue); + category_entry->SetString("name", MapCategoryName(category)); + category_entry->SetString("status", MapCategoryStatus(status)); + category_entry->Set("suggestions", std::move(suggestions_list)); + categories_list->Append(std::move(category_entry)); + } + + base::DictionaryValue result; + result.Set("list", std::move(categories_list)); + web_ui()->CallJavascriptFunctionUnsafe( + "chrome.SnippetsInternals.receiveContentSuggestions", result); +} + void SnippetsInternalsMessageHandler::SendBoolean(const std::string& name, bool value) { SendString(name, value ? "True" : "False");
diff --git a/chrome/browser/ui/webui/snippets_internals_message_handler.h b/chrome/browser/ui/webui/snippets_internals_message_handler.h index 2b2c2207..d70f04e 100644 --- a/chrome/browser/ui/webui/snippets_internals_message_handler.h +++ b/chrome/browser/ui/webui/snippets_internals_message_handler.h
@@ -9,6 +9,9 @@ #include "base/macros.h" #include "base/scoped_observer.h" +#include "components/ntp_snippets/content_suggestions_category.h" +#include "components/ntp_snippets/content_suggestions_category_status.h" +#include "components/ntp_snippets/content_suggestions_service.h" #include "components/ntp_snippets/ntp_snippets_service.h" #include "content/public/browser/web_ui_message_handler.h" @@ -19,7 +22,8 @@ // The implementation for the chrome://snippets-internals page. class SnippetsInternalsMessageHandler : public content::WebUIMessageHandler, - public ntp_snippets::NTPSnippetsServiceObserver { + public ntp_snippets::NTPSnippetsServiceObserver, + public ntp_snippets::ContentSuggestionsService::Observer { public: SnippetsInternalsMessageHandler(); ~SnippetsInternalsMessageHandler() override; @@ -34,25 +38,41 @@ void NTPSnippetsServiceDisabledReasonChanged( ntp_snippets::DisabledReason disabled_reason) override; + // ntp_snippets::ContentSuggestionsService::Observer: + void OnNewSuggestions() override; + void OnCategoryStatusChanged( + ntp_snippets::ContentSuggestionsCategory category, + ntp_snippets::ContentSuggestionsCategoryStatus new_status) override; + void ContentSuggestionsServiceShutdown() override; + void HandleLoaded(const base::ListValue* args); void HandleClear(const base::ListValue* args); void HandleClearDiscarded(const base::ListValue* args); void HandleDownload(const base::ListValue* args); + void HandleClearCachedSuggestions(const base::ListValue* args); + void HandleClearDiscardedSuggestions(const base::ListValue* args); void SendInitialData(); void SendSnippets(); void SendDiscardedSnippets(); void SendHosts(); + void SendContentSuggestions(); void SendBoolean(const std::string& name, bool value); void SendString(const std::string& name, const std::string& value); ScopedObserver<ntp_snippets::NTPSnippetsService, - ntp_snippets::NTPSnippetsServiceObserver> observer_; + ntp_snippets::NTPSnippetsServiceObserver> + ntp_snippets_service_observer_; + + ScopedObserver<ntp_snippets::ContentSuggestionsService, + ntp_snippets::ContentSuggestionsService::Observer> + content_suggestions_service_observer_; // Tracks whether we can already send messages to the page. bool dom_loaded_; ntp_snippets::NTPSnippetsService* ntp_snippets_service_; + ntp_snippets::ContentSuggestionsService* content_suggestions_service_; DISALLOW_COPY_AND_ASSIGN(SnippetsInternalsMessageHandler); };
diff --git a/chrome/browser/upgrade_detector.cc b/chrome/browser/upgrade_detector.cc index f15bfbc..4e940089 100644 --- a/chrome/browser/upgrade_detector.cc +++ b/chrome/browser/upgrade_detector.cc
@@ -59,7 +59,7 @@ DCHECK_NE(gfx::kPlaceholderColor, color); return gfx::Image( - gfx::CreateVectorIcon(gfx::VectorIconId::UPGRADE_MENU_ITEM, 16, color)); + gfx::CreateVectorIcon(gfx::VectorIconId::BROWSER_TOOLS_UPDATE, color)); } UpgradeDetector::UpgradeDetector()
diff --git a/chrome/browser/usb/usb_chooser_controller.cc b/chrome/browser/usb/usb_chooser_controller.cc index e6ce755..52c64d2 100644 --- a/chrome/browser/usb/usb_chooser_controller.cc +++ b/chrome/browser/usb/usb_chooser_controller.cc
@@ -46,7 +46,9 @@ mojo::Array<device::usb::DeviceFilterPtr> device_filters, content::RenderFrameHost* render_frame_host, const device::usb::ChooserService::GetPermissionCallback& callback) - : ChooserController(owner), + : ChooserController(owner, + IDS_USB_DEVICE_CHOOSER_PROMPT_ORIGIN, + IDS_USB_DEVICE_CHOOSER_PROMPT_EXTENSION_NAME), render_frame_host_(render_frame_host), callback_(callback), usb_service_observer_(this), @@ -71,6 +73,10 @@ callback_.Run(nullptr); } +base::string16 UsbChooserController::GetOkButtonLabel() const { + return l10n_util::GetStringUTF16(IDS_USB_DEVICE_CHOOSER_CONNECT_BUTTON_TEXT); +} + size_t UsbChooserController::NumOptions() const { return devices_.size(); }
diff --git a/chrome/browser/usb/usb_chooser_controller.h b/chrome/browser/usb/usb_chooser_controller.h index 2021a4f..a7e472f 100644 --- a/chrome/browser/usb/usb_chooser_controller.h +++ b/chrome/browser/usb/usb_chooser_controller.h
@@ -40,6 +40,7 @@ ~UsbChooserController() override; // ChooserController: + base::string16 GetOkButtonLabel() const override; size_t NumOptions() const override; base::string16 GetOption(size_t index) const override; void Select(size_t index) override;
diff --git a/chrome/browser/win/chrome_elf_init.cc b/chrome/browser/win/chrome_elf_init.cc index 7c55ed7..a0a4f48 100644 --- a/chrome/browser/win/chrome_elf_init.cc +++ b/chrome/browser/win/chrome_elf_init.cc
@@ -130,16 +130,22 @@ HKEY_CURRENT_USER, blacklist::kRegistryFinchListPath, KEY_SET_VALUE); std::map<std::string, std::string> params; - variations::GetVariationParams(kBrowserBlacklistTrialName, ¶ms); + std::string value = variations::GetVariationParamValue( + kBrowserBlacklistTrialName, blacklist::kRegistryFinchListValueNameStr); + if (value.empty()) + return; + base::string16 value_wcs = base::UTF8ToWide(value); - for (std::map<std::string, std::string>::iterator it = params.begin(); - it != params.end(); - ++it) { - std::wstring name = base::UTF8ToWide(it->first); - std::wstring val = base::UTF8ToWide(it->second); + // The dll names are comma-separated in this param value. We need to turn + // this into REG_MULTI_SZ format (double-null terminates). + // Note that the strings are wide character in registry. + value_wcs.push_back(L'\0'); + value_wcs.push_back(L'\0'); + std::replace(value_wcs.begin(), value_wcs.end(), L',', L'\0'); - finch_blacklist_registry_key.WriteValue(name.c_str(), val.c_str()); - } + finch_blacklist_registry_key.WriteValue( + blacklist::kRegistryFinchListValueName, value_wcs.data(), + (value_wcs.size() * sizeof(wchar_t)), REG_MULTI_SZ); } void BrowserBlacklistBeaconSetup() {
diff --git a/chrome/browser/win/chrome_elf_init_unittest.cc b/chrome/browser/win/chrome_elf_init_unittest.cc index 46171f5..3c23e49 100644 --- a/chrome/browser/win/chrome_elf_init_unittest.cc +++ b/chrome/browser/win/chrome_elf_init_unittest.cc
@@ -166,8 +166,9 @@ // Set up the trial with the desired parameters. std::map<std::string, std::string> desired_params; - desired_params["TestDllName1"] = "TestDll1.dll"; - desired_params["TestDllName2"] = "TestDll2.dll"; + + desired_params[blacklist::kRegistryFinchListValueNameStr] = + "TestDll1.dll,TestDll2.dll"; variations::AssociateVariationParams( kBrowserBlacklistTrialName, @@ -177,21 +178,23 @@ // This should add the dlls in those parameters to the registry. AddFinchBlacklistToRegistry(); - // Check that all the values in desired_params were added to the registry. + // Check that all the dll names in desired_params were added to the registry. + std::vector<std::wstring> dlls; + base::win::RegKey finch_blacklist_registry_key( HKEY_CURRENT_USER, blacklist::kRegistryFinchListPath, KEY_QUERY_VALUE | KEY_SET_VALUE); - ASSERT_EQ(desired_params.size(), - finch_blacklist_registry_key.GetValueCount()); + ASSERT_TRUE(finch_blacklist_registry_key.HasValue( + blacklist::kRegistryFinchListValueName)); + ASSERT_EQ(ERROR_SUCCESS, finch_blacklist_registry_key.ReadValues( + blacklist::kRegistryFinchListValueName, &dlls)); - for (std::map<std::string, std::string>::iterator it = desired_params.begin(); - it != desired_params.end(); - ++it) { - std::wstring name = base::UTF8ToWide(it->first); - ASSERT_TRUE(finch_blacklist_registry_key.HasValue(name.c_str())); - } + ASSERT_EQ((size_t)2, + /* Number of dll names passed in this test. */ dlls.size()); + EXPECT_STREQ(L"TestDll1.dll", dlls[0].c_str()); + EXPECT_STREQ(L"TestDll2.dll", dlls[1].c_str()); } } // namespace
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index d111a9e..4ad9a95 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi
@@ -410,8 +410,12 @@ 'browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.h', 'browser/page_load_metrics/observers/google_captcha_observer.cc', 'browser/page_load_metrics/observers/google_captcha_observer.h', - 'browser/page_load_metrics/observers/https_engagement_page_load_metrics_observer.cc', - 'browser/page_load_metrics/observers/https_engagement_page_load_metrics_observer.h', + 'browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.cc', + 'browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.h', + 'browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service.cc', + 'browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service.h', + 'browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service_factory.cc', + 'browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_service_factory.h', 'browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc', 'browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h', 'browser/page_load_metrics/observers/stale_while_revalidate_metrics_observer.cc', @@ -2112,6 +2116,8 @@ 'browser/metrics/chrome_stability_metrics_provider.h', 'browser/metrics/field_trial_synchronizer.cc', 'browser/metrics/field_trial_synchronizer.h', + 'browser/metrics/https_engagement_metrics_provider.cc', + 'browser/metrics/https_engagement_metrics_provider.h', 'browser/metrics/google_update_metrics_provider_win.cc', 'browser/metrics/google_update_metrics_provider_win.h', 'browser/metrics/jumplist_metrics_win.cc', @@ -2335,6 +2341,8 @@ 'browser/permissions/permission_manager_factory.h', 'browser/permissions/permission_request_id.cc', 'browser/permissions/permission_request_id.h', + 'browser/permissions/permission_request_manager.cc', + 'browser/permissions/permission_request_manager.h', 'browser/permissions/permission_uma_util.cc', 'browser/permissions/permission_uma_util.h', 'browser/permissions/permission_util.cc',
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi index 2a4cc8c..c935e68b 100644 --- a/chrome/chrome_browser_chromeos.gypi +++ b/chrome/chrome_browser_chromeos.gypi
@@ -57,7 +57,7 @@ 'browser/chromeos/app_mode/startup_app_launcher.cc', 'browser/chromeos/app_mode/startup_app_launcher.h', 'browser/chromeos/arc/arc_android_management_checker.cc', - 'browser/chromeos/arc/arc_android_management_checker.h', + 'browser/chromeos/arc/arc_android_management_checker.h', 'browser/chromeos/arc/arc_android_management_checker_delegate.h', 'browser/chromeos/arc/arc_auth_context.cc', 'browser/chromeos/arc/arc_auth_context.h', @@ -511,6 +511,8 @@ 'browser/chromeos/login/proxy_settings_dialog.h', 'browser/chromeos/login/reauth_stats.cc', 'browser/chromeos/login/reauth_stats.h', + 'browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.cc', + 'browser/chromeos/login/quick_unlock/quick_unlock_notification_controller.h', 'browser/chromeos/login/quick_unlock/pin_storage.cc', 'browser/chromeos/login/quick_unlock/pin_storage.h', 'browser/chromeos/login/quick_unlock/pin_storage_factory.cc',
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index 25d95b0..272b022 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi
@@ -112,8 +112,6 @@ 'browser/ui/protocol_dialog_delegate.h', 'browser/ui/proximity_auth/proximity_auth_error_bubble.h', 'browser/ui/screen_capture_notification_ui.h', - 'browser/ui/search/instant_page.cc', - 'browser/ui/search/instant_page.h', 'browser/ui/search/instant_search_prerenderer.cc', 'browser/ui/search/instant_search_prerenderer.h', 'browser/ui/search/instant_tab.cc', @@ -609,6 +607,8 @@ 'browser/ui/ash/multi_user/multi_user_window_manager_stub.h', 'browser/ui/ash/multi_user/user_switch_animator_chromeos.cc', 'browser/ui/ash/multi_user/user_switch_animator_chromeos.h', + 'browser/ui/ash/multi_user/user_switch_util.cc', + 'browser/ui/ash/multi_user/user_switch_util.h', 'browser/ui/ash/network_connect_delegate_chromeos.cc', 'browser/ui/ash/network_connect_delegate_chromeos.h', 'browser/ui/ash/networking_config_delegate_chromeos.cc', @@ -1851,8 +1851,6 @@ 'browser/ui/user_manager.h', 'browser/ui/website_settings/chooser_bubble_delegate.cc', 'browser/ui/website_settings/chooser_bubble_delegate.h', - 'browser/ui/website_settings/permission_bubble_manager.cc', - 'browser/ui/website_settings/permission_bubble_manager.h', 'browser/ui/website_settings/permission_bubble_view.h', 'browser/ui/website_settings/permission_menu_model.cc', 'browser/ui/website_settings/permission_menu_model.h', @@ -2060,6 +2058,8 @@ 'browser/ui/webui/settings/people_handler.h', 'browser/ui/webui/settings/profile_info_handler.cc', 'browser/ui/webui/settings/profile_info_handler.h', + 'browser/ui/webui/settings/protocol_handlers_handler.cc', + 'browser/ui/webui/settings/protocol_handlers_handler.h', 'browser/ui/webui/settings/reset_settings_handler.cc', 'browser/ui/webui/settings/reset_settings_handler.h', 'browser/ui/webui/settings/search_engines_handler.cc',
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index a0c7de7..39b33f6 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi
@@ -155,10 +155,6 @@ 'common/extensions/extension_metrics.h', 'common/extensions/extension_process_policy.cc', 'common/extensions/extension_process_policy.h', - 'common/extensions/features/chrome_channel_feature_filter.cc', - 'common/extensions/features/chrome_channel_feature_filter.h', - 'common/extensions/features/feature_channel.cc', - 'common/extensions/features/feature_channel.h', 'common/extensions/features/feature_util.cc', 'common/extensions/features/feature_util.h', 'common/extensions/image_writer/image_writer_util_mac.cc',
diff --git a/chrome/chrome_installer_static.gypi b/chrome/chrome_installer_static.gypi index d1f8136..0fc597f 100644 --- a/chrome/chrome_installer_static.gypi +++ b/chrome/chrome_installer_static.gypi
@@ -2,8 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# The install_static_util target should only depend on functions in kernel32 -# and advapi32. Please don't add dependencies on other system libraries. +# The install_static_util target should only depend on functions in kernel32. +# Please don't add dependencies on other system libraries. { 'target_defaults': { 'variables': { @@ -33,15 +33,13 @@ 'installer_static_target': 1, }, 'dependencies': [ - 'installer_util_strings', - '<(DEPTH)/base/base.gyp:base', + '../chrome_elf/nt_registry/nt_registry.gyp:chrome_elf_nt_registry', ], 'msvs_settings': { 'VCLinkerTool': { # Please don't add dependencies on other system libraries. 'AdditionalDependencies': [ 'kernel32.lib', - 'advapi32.lib', ], }, }, @@ -91,7 +89,7 @@ 'installer_static_target': 1, }, 'dependencies': [ - 'installer_util_strings', + '../chrome_elf/nt_registry/nt_registry.gyp:chrome_elf_nt_registry_nacl_win64', ], 'include_dirs': [ '<(SHARED_INTERMEDIATE_DIR)', @@ -106,7 +104,6 @@ # Please don't add dependencies on other system libraries. 'AdditionalDependencies': [ 'kernel32.lib', - 'advapi32.lib', ], }, },
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 8a69a728..2cc06448 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi
@@ -379,12 +379,13 @@ 'browser/net/sdch_browsertest.cc', 'browser/net/websocket_browsertest.cc', 'browser/page_load_metrics/page_load_metrics_browsertest.cc', - 'browser/page_load_metrics/observers/https_engagement_page_load_metrics_observer_browsertest.cc', + 'browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer_browsertest.cc', 'browser/password_manager/credential_manager_browsertest.cc', 'browser/password_manager/password_manager_browsertest.cc', 'browser/pdf/pdf_extension_test.cc', 'browser/pdf/pdf_extension_test_util.cc', 'browser/pdf/pdf_extension_test_util.h', + 'browser/permissions/permission_request_manager_browsertest.cc', 'browser/plugins/plugin_power_saver_browsertest.cc', 'browser/policy/cloud/cloud_policy_browsertest.cc', 'browser/policy/cloud/cloud_policy_manager_browsertest.cc', @@ -522,7 +523,6 @@ 'browser/ui/website_settings/mock_permission_bubble_view.h', 'browser/ui/website_settings/permission_bubble_browser_test_util.cc', 'browser/ui/website_settings/permission_bubble_browser_test_util.h', - 'browser/ui/website_settings/permission_bubble_manager_browsertest.cc', 'browser/ui/webui/bidi_checker_web_ui_test.cc', 'browser/ui/webui/bidi_checker_web_ui_test.h', 'browser/ui/webui/bookmarks_ui_browsertest.cc', @@ -988,7 +988,6 @@ 'browser/ui/webui/options/password_manager_browsertest.js', 'browser/ui/webui/options/profile_settings_reset_browsertest.js', 'browser/ui/webui/options/search_engine_manager_browsertest.js', - 'browser/ui/webui/options/settings_app_browsertest.js', 'browser/ui/webui/options/settings_format_browsertest.js', 'browser/ui/webui/options/startup_page_list_browsertest.js', 'browser/ui/webui/sync_internals_browsertest.js',
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 23787082..100ed0f 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi
@@ -175,6 +175,7 @@ 'browser/permissions/delegation_tracker_unittest.cc', 'browser/permissions/permission_context_base_unittest.cc', 'browser/permissions/permission_manager_unittest.cc', + 'browser/permissions/permission_uma_util_unittest.cc', 'browser/permissions/permission_util_unittest.cc', 'browser/policy/cloud/cloud_policy_invalidator_unittest.cc', 'browser/policy/cloud/remote_commands_invalidator_unittest.cc', @@ -278,6 +279,10 @@ 'browser/ui/sync/sync_promo_ui_unittest.cc', 'browser/ui/tests/ui_gfx_image_unittest.cc', 'browser/ui/tests/ui_gfx_image_unittest.mm', + 'browser/ui/website_settings/mock_permission_bubble_factory.cc', + 'browser/ui/website_settings/mock_permission_bubble_factory.h', + 'browser/ui/website_settings/mock_permission_bubble_view.cc', + 'browser/ui/website_settings/mock_permission_bubble_view.h', 'browser/ui/website_settings/website_settings_unittest.cc', 'browser/ui/webui/browsing_history_handler_unittest.cc', 'browser/ui/webui/fileicon_source_unittest.cc', @@ -360,10 +365,6 @@ 'browser/ui/autofill/country_combobox_model_unittest.cc', 'browser/ui/autofill/save_card_bubble_controller_impl_unittest.cc', 'browser/ui/passwords/manage_passwords_ui_controller_unittest.cc', - 'browser/ui/website_settings/mock_permission_bubble_factory.cc', - 'browser/ui/website_settings/mock_permission_bubble_factory.h', - 'browser/ui/website_settings/mock_permission_bubble_view.cc', - 'browser/ui/website_settings/mock_permission_bubble_view.h', ], 'chrome_unit_tests_spellchecker_sources': [ 'browser/spellchecker/feedback_sender_unittest.cc', @@ -635,7 +636,6 @@ 'common/extensions/extension_icon_set_unittest.cc', 'common/extensions/extension_unittest.cc', 'common/extensions/feature_switch_unittest.cc', - 'common/extensions/features/chrome_channel_feature_filter_unittest.cc', 'common/extensions/manifest_handlers/automation_unittest.cc', 'common/extensions/manifest_handlers/content_scripts_manifest_unittest.cc', 'common/extensions/manifest_handlers/exclude_matches_manifest_unittest.cc', @@ -716,6 +716,7 @@ 'browser/ui/ash/multi_user/multi_user_notification_blocker_chromeos_unittest.cc', 'browser/ui/ash/multi_user/multi_user_util_chromeos_unittest.cc', 'browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc', + 'browser/ui/ash/multi_user/user_switch_util_unittest.cc', 'browser/ui/ash/session_state_delegate_chromeos_unittest.cc', 'browser/ui/ash/window_positioner_unittest.cc', 'browser/ui/window_sizer/window_sizer_ash_unittest.cc', @@ -1499,6 +1500,7 @@ 'browser/memory/tab_manager_unittest.cc', 'browser/memory/tab_manager_web_contents_data_unittest.cc', 'browser/net/firefox_proxy_settings_unittest.cc', + 'browser/permissions/permission_request_manager_unittest.cc', 'browser/platform_util_unittest.cc', 'browser/power/process_power_collector_unittest.cc', 'browser/process_singleton_posix_unittest.cc', @@ -1535,8 +1537,8 @@ 'browser/ui/passwords/manage_passwords_bubble_model_unittest.cc', 'browser/ui/passwords/manage_passwords_view_utils_desktop_unittest.cc', 'browser/ui/passwords/password_dialog_controller_impl_unittest.cc', - 'browser/ui/search/instant_page_unittest.cc', 'browser/ui/search/instant_search_prerenderer_unittest.cc', + 'browser/ui/search/instant_tab_unittest.cc', 'browser/ui/search/search_delegate_unittest.cc', 'browser/ui/search/search_ipc_router_policy_unittest.cc', 'browser/ui/search/search_ipc_router_unittest.cc', @@ -1566,7 +1568,6 @@ 'browser/ui/toolbar/toolbar_actions_bar_unittest.h', 'browser/ui/toolbar/toolbar_actions_model_unittest.cc', 'browser/ui/toolbar/toolbar_model_unittest.cc', - 'browser/ui/website_settings/permission_bubble_manager_unittest.cc', 'browser/ui/website_settings/permission_menu_model_unittest.cc', 'browser/ui/webui/help/version_updater_chromeos_unittest.cc', 'browser/ui/webui/md_downloads/downloads_list_tracker_unittest.cc',
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 761c6131..6b511d1 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -55,7 +55,7 @@ // Enables or disables the Material Design version of chrome://history. const base::Feature kMaterialDesignHistoryFeature { - "MaterialDesignHistory", base::FEATURE_DISABLED_BY_DEFAULT + "MaterialDesignHistory", base::FEATURE_ENABLED_BY_DEFAULT }; // Enables or disables the Material Design version of chrome://settings.
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 36d3023..a125d33 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -38,20 +38,6 @@ // no blocking of requests). const char kAllowInsecureLocalhost[] = "allow-insecure-localhost"; -#if defined(ENABLE_PLUGINS) -// Specifies comma-separated list of extension ids or hosts to grant -// access to CRX file system APIs. -const char kAllowNaClCrxFsAPI[] = "allow-nacl-crxfs-api"; - -// Specifies comma-separated list of extension ids or hosts to grant -// access to file handle APIs. -const char kAllowNaClFileHandleAPI[] = "allow-nacl-file-handle-api"; - -// Specifies comma-separated list of extension ids or hosts to grant -// access to TCP/UDP socket APIs. -const char kAllowNaClSocketAPI[] = "allow-nacl-socket-api"; -#endif - // Don't block outdated plugins. const char kAllowOutdatedPlugins[] = "allow-outdated-plugins"; @@ -66,23 +52,13 @@ // but less commonly used plugins. const char kAlwaysAuthorizePlugins[] = "always-authorize-plugins"; -// Specifies that the extension-app with the specified id should be launched -// according to its configuration. -const char kAppId[] = "app-id"; - // Specifies that the associated value should be launched in "application" // mode. const char kApp[] = "app"; -// The URL that the webstore APIs download extensions from. -// Note: the URL must contain one '%s' for the extension ID. -const char kAppsGalleryDownloadURL[] = "apps-gallery-download-url"; - -// The URL to use for the gallery link in the app launcher. -const char kAppsGalleryURL[] = "apps-gallery-url"; - -// The update url used by gallery/webstore extensions. -const char kAppsGalleryUpdateURL[] = "apps-gallery-update-url"; +// Specifies that the extension-app with the specified id should be launched +// according to its configuration. +const char kAppId[] = "app-id"; // Value of GAIA auth code for --force-app-mode. const char kAppModeAuthCode[] = "app-mode-auth-code"; @@ -90,6 +66,16 @@ // Value of OAuth2 refresh token for --force-app-mode. const char kAppModeOAuth2Token[] = "app-mode-oauth-token"; +// The URL that the webstore APIs download extensions from. +// Note: the URL must contain one '%s' for the extension ID. +const char kAppsGalleryDownloadURL[] = "apps-gallery-download-url"; + +// The update url used by gallery/webstore extensions. +const char kAppsGalleryUpdateURL[] = "apps-gallery-update-url"; + +// The URL to use for the gallery link in the app launcher. +const char kAppsGalleryURL[] = "apps-gallery-url"; + // Enables overriding the path for the default authentication extension. const char kAuthExtensionPath[] = "auth-ext-path"; @@ -99,8 +85,7 @@ // This flag makes Chrome auto-open DevTools window for each tab. It is // intended to be used by developers and automation to not require user // interaction for opening DevTools. -const char kAutoOpenDevToolsForTabs[] = - "auto-open-devtools-for-tabs"; +const char kAutoOpenDevToolsForTabs[] = "auto-open-devtools-for-tabs"; // This flag makes Chrome auto-select the provided choice when an extension asks // permission to start desktop capture. Should only be used for tests. For @@ -127,8 +112,7 @@ // assumed to be HTTPS as required by RFC6962). // Multiple logs can be specified by repeating description:key pairs, // separated by a comma. -const char kCertificateTransparencyLog[] = - "certificate-transparency-log"; +const char kCertificateTransparencyLog[] = "certificate-transparency-log"; // How often (in seconds) to check for updates. Should only be used for testing // purposes. @@ -146,13 +130,13 @@ // unspecified. const char kCloudPrintFileType[] = "cloud-print-file-type"; +// Used with kCloudPrintFile to specify a title for the resulting print job. +const char kCloudPrintJobTitle[] = "cloud-print-job-title"; + // Used with kCloudPrintFile to specify a JSON print ticket for the resulting // print job. Defaults to null if unspecified. const char kCloudPrintPrintTicket[] = "cloud-print-print-ticket"; -// Used with kCloudPrintFile to specify a title for the resulting print job. -const char kCloudPrintJobTitle[] = "cloud-print-job-title"; - // Setup cloud print proxy for provided printers. This does not start // service or register proxy for autostart. const char kCloudPrintSetupProxy[] = "cloud-print-setup-proxy"; @@ -200,10 +184,6 @@ // app to their shelf (or platform-specific equivalent) const char kDisableAddToShelf[] = "disable-add-to-shelf"; -#if defined(OS_ANDROID) -const char kDisableAppLink[] = "disable-app-link"; -#endif - // Disables the experimental asynchronous DNS client. const char kDisableAsyncDns[] = "disable-async-dns"; @@ -280,24 +260,27 @@ const char kDisableNewBookmarkApps[] = "disable-new-bookmark-apps"; // Disable auto-reload of error pages if offline. -const char kDisableOfflineAutoReload[] = "disable-offline-auto-reload"; +const char kDisableOfflineAutoReload[] = "disable-offline-auto-reload"; // Disable only auto-reloading error pages when the tab is visible. const char kDisableOfflineAutoReloadVisibleOnly[] = "disable-offline-auto-reload-visible-only"; // Disable out-of-process V8 proxy resolver. -const char kDisableOutOfProcessPac[] = "disable-out-of-process-pac"; +const char kDisableOutOfProcessPac[] = "disable-out-of-process-pac"; -// Disables the Permissions Blacklist, which blocks access to permissions -// for blacklisted sites. -const char kDisablePermissionsBlacklist[] = "disable-permissions-blacklist"; +// Disables panels (always on-top docked pop-up windows). +const char kDisablePanels[] = "disable-panels"; // Disables permission action reporting to Safe Browsing servers for opted in // users. const char kDisablePermissionActionReporting[] = "disable-permission-action-reporting"; +// Disables the Permissions Blacklist, which blocks access to permissions +// for blacklisted sites. +const char kDisablePermissionsBlacklist[] = "disable-permissions-blacklist"; + // Disable pop-up blocking. const char kDisablePopupBlocking[] = "disable-popup-blocking"; @@ -312,18 +295,20 @@ // disable that check. This switch is used during automated testing. const char kDisablePromptOnRepost[] = "disable-prompt-on-repost"; +// Enable background mode for the Push API. +const char kDisablePushApiBackgroundMode[] = "disable-push-api-background-mode"; + // Disables using bubbles for session restore request. const char kDisableSessionCrashedBubble[] = "disable-session-crashed-bubble"; +// Disable settings in a separate browser window per profile +// (see SettingsWindowEnabled() below). +const char kDisableSettingsWindow[] = "disable-settings-window"; + // Disables the Site Engagement service, which records interaction with sites // and allocates certain resources accordingly. const char kDisableSiteEngagementService[] = "disable-site-engagement-service"; -#if defined(OS_ANDROID) -// Disable VR UI if supported. -const char kDisableVrShell[] = "disable-vr-shell"; -#endif - // Disables Web Notification custom layouts. const char kDisableWebNotificationCustomLayouts[] = "disable-web-notification-custom-layouts"; @@ -365,18 +350,9 @@ // Enables all bookmarks view in bookmark manager. const char kEnableAllBookmarksView[] = "enable-all-bookmarks-view"; -#if defined(OS_ANDROID) -const char kEnableAppLink[] = "enable-app-link"; -#endif - // Enable OS integration for Chrome app file associations. const char kEnableAppsFileAssociations[] = "enable-apps-file-associations"; -#if defined(OS_CHROMEOS) -// Enables the intent picker so the user can handle URL links with ARC apps. -const char kEnableIntentPicker[] = "enable-intent-picker"; -#endif // defined(OS_CHROMEOS) - // If the WebRTC logging private API is active, enables audio debug recordings. const char kEnableAudioDebugRecordingsFromExtension[] = "enable-audio-debug-recordings-from-extension"; @@ -399,13 +375,13 @@ // Print Proxy component within the service process. const char kEnableCloudPrintProxy[] = "enable-cloud-print-proxy"; -// If true devtools experimental settings are enabled. -const char kEnableDevToolsExperiments[] = "enable-devtools-experiments"; - // Enable device discovery notifications. const char kEnableDeviceDiscoveryNotifications[] = "enable-device-discovery-notifications"; +// If true devtools experimental settings are enabled. +const char kEnableDevToolsExperiments[] = "enable-devtools-experiments"; + // Enables Domain Reliability Monitoring. const char kEnableDomainReliability[] = "enable-domain-reliability"; @@ -424,12 +400,6 @@ // crbug.com/142458 . const char kEnableFastUnload[] = "enable-fast-unload"; -#if defined(GOOGLE_CHROME_BUILD) -// Shows a Google icon next to context menu items powered by Google services. -const char kEnableGoogleBrandedContextMenu[] = - "enable-google-branded-context-menu"; -#endif // defined(GOOGLE_CHROME_BUILD) - // Enables the Material Design version of chrome://extensions. const char kEnableMaterialDesignExtensions[] = "enable-md-extensions"; @@ -443,11 +413,6 @@ // (internally adds lEnableGpuPlugin to the command line). const char kEnableNaCl[] = "enable-nacl"; -#if defined(OS_CHROMEOS) -// Enables native cups integration -const char kEnableNativeCups[] = "enable-native-cups"; -#endif // defined(OS_CHROMEOS) - // Enables the use of native notifications instead of using the Chrome based // ones. const char kEnableNativeNotifications[] = "enable-native-notifications"; @@ -470,19 +435,18 @@ const char kEnableOfflineAutoReloadVisibleOnly[] = "enable-offline-auto-reload-visible-only"; -// Enables or disables panels (always on-top docked pop-up windows). +// Enables panels (always on-top docked pop-up windows). const char kEnablePanels[] = "enable-panels"; -const char kDisablePanels[] = "disable-panels"; - -// Enables the Permissions Blacklist, which blocks access to permissions -// for blacklisted sites. -const char kEnablePermissionsBlacklist[] = "enable-permissions-blacklist"; // Enables permission action reporting to Safe Browsing servers for opted in // users. const char kEnablePermissionActionReporting[] = "enable-permission-action-reporting"; +// Enables the Permissions Blacklist, which blocks access to permissions +// for blacklisted sites. +const char kEnablePermissionsBlacklist[] = "enable-permissions-blacklist"; + // Enables a number of potentially annoying security features (strict mixed // content mode, powerful feature restrictions, etc.) const char kEnablePotentiallyAnnoyingSecurityFeatures[] = @@ -502,21 +466,15 @@ // during chrome_browser_main. const char kEnableProfiling[] = "enable-profiling"; -// Enable or disable background mode for the Push API. +// Enable background mode for the Push API. const char kEnablePushApiBackgroundMode[] = "enable-push-api-background-mode"; -const char kDisablePushApiBackgroundMode[] = "disable-push-api-background-mode"; - -// If the WebRTC logging private API is active, enables WebRTC event logging. -const char kEnableWebRtcEventLoggingFromExtension[] = - "enable-webrtc-event-logging-from-extension"; // Enables using bubbles for session restore request instead of infobars. const char kEnableSessionCrashedBubble[] = "enable-session-crashed-bubble"; -// Enable or disable settings in a separate browser window per profile +// Enable settings in a separate browser window per profile // (see SettingsWindowEnabled() below). const char kEnableSettingsWindow[] = "enable-settings-window"; -const char kDisableSettingsWindow[] = "disable-settings-window"; // Enable the Site Engagement App Banner which triggers app install banners // using the site engagement service rather than a navigation-based heuristic. @@ -549,34 +507,28 @@ const char kEnableUserAlternateProtocolPorts[] = "enable-user-controlled-alternate-protocol-ports"; -#if defined(OS_ANDROID) -// Enable VR UI if supported. -const char kEnableVrShell[] = "enable-vr-shell"; -#endif - // Enables a new "web app" style frame for hosted apps (including bookmark // apps). const char kEnableWebAppFrame[] = "enable-web-app-frame"; -#if defined(OS_ANDROID) -// Enables "Add to Home screen" in the app menu to generate WebAPKs. -const char kEnableWebApk[] = "enable-webapk"; -#endif - // Enables Web Notification custom layouts. const char kEnableWebNotificationCustomLayouts[] = "enable-web-notification-custom-layouts"; -// Values for the kExtensionContentVerification flag. -// See ContentVerifierDelegate::Mode for more explanation. -const char kExtensionContentVerificationBootstrap[] = "bootstrap"; -const char kExtensionContentVerificationEnforceStrict[] = "enforce_strict"; -const char kExtensionContentVerificationEnforce[] = "enforce"; +// If the WebRTC logging private API is active, enables WebRTC event logging. +const char kEnableWebRtcEventLoggingFromExtension[] = + "enable-webrtc-event-logging-from-extension"; // Name of the command line flag to force content verification to be on in one // of various modes. const char kExtensionContentVerification[] = "extension-content-verification"; +// Values for the kExtensionContentVerification flag. +// See ContentVerifierDelegate::Mode for more explanation. +const char kExtensionContentVerificationBootstrap[] = "bootstrap"; +const char kExtensionContentVerificationEnforce[] = "enforce"; +const char kExtensionContentVerificationEnforceStrict[] = "enforce_strict"; + // Turns on extension install verification if it would not otherwise have been // turned on. const char kExtensionsInstallVerification[] = "extensions-install-verification"; @@ -611,14 +563,14 @@ // whether or not it's actually the First Run (this overrides kNoFirstRun). const char kForceFirstRun[] = "force-first-run"; +// Forces Chrome to use localNTP instead of server (GWS) NTP. +const char kForceLocalNtp[] = "force-local-ntp"; + // Forces additional Chrome Variation Ids that will be sent in X-Client-Data // header, specified as a 64-bit encoded list of numeric experiment ids. Ids // prefixed with the character "t" will be treated as Trigger Variation Ids. const char kForceVariationIds[] = "force-variation-ids"; -// Forces Chrome to use localNTP instead of server (GWS) NTP. -const char kForceLocalNtp[] = "force-local-ntp"; - // Enables grouping websites by domain and filtering them by period. const char kHistoryEnableGroupByDomain[] = "enable-grouped-history"; @@ -627,6 +579,10 @@ // http://google.com. const char kHomePage[] = "homepage"; +// The maximum number of retry attempts to resolve the host. Set this to zero +// to disable host resolver retry attempts. +const char kHostResolverRetryAttempts[] = "host-resolver-retry-attempts"; + // Comma-separated list of rules that control how hostnames are mapped. // // For example: @@ -644,10 +600,6 @@ // proxy connection, and the endpoint host in a SOCKS proxy connection). const char kHostRules[] = "host-rules"; -// The maximum number of retry attempts to resolve the host. Set this to zero -// to disable host resolver retry attempts. -const char kHostResolverRetryAttempts[] = "host-resolver-retry-attempts"; - // Causes the browser to launch directly in incognito mode. const char kIncognito[] = "incognito"; @@ -681,12 +633,6 @@ // Loads an extension from the specified directory. const char kLoadExtension[] = "load-extension"; -#if !defined(GOOGLE_CHROME_BUILD) -// Enables a live-reload for local NTP resources. This only works when Chrome -// is running from a Chrome source directory. -const char kLocalNtpReload[] = "local-ntp-reload"; -#endif - // Makes Chrome default browser const char kMakeDefaultBrowser[] = "make-default-browser"; @@ -814,6 +760,7 @@ // effect when Instant is either disabled or restricted to search, and when // prerender is enabled. const char kPrerenderFromOmnibox[] = "prerender-from-omnibox"; + // These are the values the kPrerenderFromOmnibox switch may have, as in // "--prerender-from-omnibox=auto". auto: Allow field trial selection. const char kPrerenderFromOmniboxSwitchValueAuto[] = "auto"; @@ -821,9 +768,11 @@ const char kPrerenderFromOmniboxSwitchValueDisabled[] = "disabled"; // enabled: Guaranteed prerendering. const char kPrerenderFromOmniboxSwitchValueEnabled[] = "enabled"; + // Controls speculative prerendering of pages, and content prefetching. Both // are dispatched from <link rel=prefetch href=...> elements. const char kPrerenderMode[] = "prerender"; + // These are the values the kPrerenderMode switch may have, as in // "--prerender=disabled". // disabled: No prerendering. @@ -922,12 +871,6 @@ // If true the app list will be shown. const char kShowAppList[] = "show-app-list"; -// Causes SSL key material to be logged to the specified file for debugging -// purposes. See -// https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format -// for the format. -const char kSSLKeyLogFile[] = "ssl-key-log-file"; - // Does not show an infobar when an extension attaches to a page using // chrome.debugger page. Required to attach to extension background pages. const char kSilentDebuggerExtensionAPI[] = "silent-debugger-extension-api"; @@ -936,12 +879,12 @@ // one wishes to use Chrome as an ash server. const char kSilentLaunch[] = "silent-launch"; -// Simulates that elevation is needed to recover upgrade channel. -const char kSimulateElevatedRecovery[] = "simulate-elevated-recovery"; - // Simulates a critical update being available. const char kSimulateCriticalUpdate[] = "simulate-critical-update"; +// Simulates that elevation is needed to recover upgrade channel. +const char kSimulateElevatedRecovery[] = "simulate-elevated-recovery"; + // Simulates that current version is outdated. const char kSimulateOutdated[] = "simulate-outdated"; @@ -958,38 +901,18 @@ // Speculative resource prefetching is disabled. const char kSpeculativeResourcePrefetchingDisabled[] = "disabled"; +// Speculative resource prefetching is enabled. +const char kSpeculativeResourcePrefetchingEnabled[] = "enabled"; + // Speculative resource prefetching will only learn about resources that need to // be prefetched but will not prefetch them. const char kSpeculativeResourcePrefetchingLearning[] = "learning"; -// Speculative resource prefetching is enabled. -const char kSpeculativeResourcePrefetchingEnabled[] = "enabled"; - -#if defined(ENABLE_SPELLCHECK) -#if defined(OS_ANDROID) -// Enables use of the Android spellchecker. -const char kEnableAndroidSpellChecker[] = "enable-android-spellchecker"; -#endif - -// Enables participation in the field trial for user feedback to spelling -// service. -const char kEnableSpellingFeedbackFieldTrial[] = - "enable-spelling-feedback-field-trial"; - -// Specifies the URL where spelling service feedback data will be sent instead -// of the default URL. This switch is for temporary testing only. -// TODO(rouslan): Remove this flag when feedback testing is complete. Revisit by -// August 2013. -const char kSpellingServiceFeedbackUrl[] = "spelling-service-feedback-url"; - -// Specifies the number of seconds between sending batches of feedback to -// spelling service. The default is 30 minutes. The minimum is 5 seconds. This -// switch is for temporary testing only. -// TODO(rouslan): Remove this flag when feedback testing is complete. Revisit by -// August 2013. -const char kSpellingServiceFeedbackIntervalSeconds[] = - "spelling-service-feedback-interval-seconds"; -#endif +// Causes SSL key material to be logged to the specified file for debugging +// purposes. See +// https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format +// for the format. +const char kSSLKeyLogFile[] = "ssl-key-log-file"; // Starts the browser maximized, regardless of any previous settings. const char kStartMaximized[] = "start-maximized"; @@ -1042,9 +965,6 @@ // all of its state. const char kUserDataDir[] = "user-data-dir"; -// Examines a .crx for validity and prints the result. -const char kValidateCrx[] = "validate-crx"; - // Uses experimental simple cache backend if possible. const char kUseSimpleCacheBackend[] = "use-simple-cache-backend"; @@ -1054,6 +974,9 @@ // Enables using an out-of-process Mojo service for the v8 proxy resolver. const char kV8PacMojoOutOfProcess[] = "v8-pac-mojo-out-of-process"; +// Examines a .crx for validity and prints the result. +const char kValidateCrx[] = "validate-crx"; + // Prints version information and quits. const char kVersion[] = "version"; @@ -1074,17 +997,64 @@ // resulted in a browser startup. const char kWinJumplistAction[] = "win-jumplist-action"; +#if defined(ENABLE_SPELLCHECK) +#if defined(OS_ANDROID) +// Enables use of the Android spellchecker. +const char kEnableAndroidSpellChecker[] = "enable-android-spellchecker"; +#endif // defined(OS_ANDROID) + +// Enables participation in the field trial for user feedback to spelling +// service. +const char kEnableSpellingFeedbackFieldTrial[] = + "enable-spelling-feedback-field-trial"; + +// Specifies the number of seconds between sending batches of feedback to +// spelling service. The default is 30 minutes. The minimum is 5 seconds. This +// switch is for temporary testing only. +// TODO(rouslan): Remove this flag when feedback testing is complete. Revisit by +// August 2013. +const char kSpellingServiceFeedbackIntervalSeconds[] = + "spelling-service-feedback-interval-seconds"; + +// Specifies the URL where spelling service feedback data will be sent instead +// of the default URL. This switch is for temporary testing only. +// TODO(rouslan): Remove this flag when feedback testing is complete. Revisit by +// August 2013. +const char kSpellingServiceFeedbackUrl[] = "spelling-service-feedback-url"; +#endif // defined(ENABLE_SPELLCHECK) + +#if defined(GOOGLE_CHROME_BUILD) +// Shows a Google icon next to context menu items powered by Google services. +const char kEnableGoogleBrandedContextMenu[] = + "enable-google-branded-context-menu"; +#endif // defined(GOOGLE_CHROME_BUILD) + +#if !defined(GOOGLE_CHROME_BUILD) +// Enables a live-reload for local NTP resources. This only works when Chrome +// is running from a Chrome source directory. +const char kLocalNtpReload[] = "local-ntp-reload"; +#endif + #if defined(OS_ANDROID) // Android authentication account type for SPNEGO authentication const char kAuthAndroidNegotiateAccountType[] = "auth-spnego-account-type"; +// Disable App Link. +const char kDisableAppLink[] = "disable-app-link"; + // Disables Contextual Search. const char kDisableContextualSearch[] = "disable-contextual-search"; +// Disable VR UI if supported. +const char kDisableVrShell[] = "disable-vr-shell"; + // Enable the accessibility tab switcher. const char kEnableAccessibilityTabSwitcher[] = "enable-accessibility-tab-switcher"; +// Enable App Link. +const char kEnableAppLink[] = "enable-app-link"; + // Enables Contextual Search. const char kEnableContextualSearch[] = "enable-contextual-search"; @@ -1095,20 +1065,63 @@ // unresponsive web content. const char kEnableHungRendererInfoBar[] = "enable-hung-renderer-infobar"; -// Specifies Android phone page loading progress bar animation. -const char kProgressBarAnimation[] = "progress-bar-animation"; +// Enable theme colors in the tab switcher. +const char kEnableTabSwitcherThemeColors[] = "enable-tab-switcher-theme-colors"; -// Enabled tab switcher in document mode. -const char kEnableTabSwitcherInDocumentMode[] = - "enable-tab-switcher-in-document-mode"; +// Enable VR UI if supported. +const char kEnableVrShell[] = "enable-vr-shell"; + +// Enables "Add to Home screen" in the app menu to generate WebAPKs. +const char kEnableWebApk[] = "enable-webapk"; + +// Forces the update menu badge to show. +const char kForceShowUpdateMenuBadge[] = "force-show-update-menu-badge"; + +// Forces the update menu item to show. +const char kForceShowUpdateMenuItem[] = "force-show-update-menu-item"; + +// Forces a custom summary to be displayed below the update menu item. +const char kForceShowUpdateMenuItemCustomSummary[] = "custom_summary"; + +// Forces the new features summary to be displayed below the update menu item. +const char kForceShowUpdateMenuItemNewFeaturesSummary[] = + "use_new_features_summary"; + +// Forces a summary to be displayed below the update menu item. +const char kForceShowUpdateMenuItemSummary[] = "show_summary"; + +// Sets the market URL for Chrome for use in testing. +const char kMarketUrlForTesting[] = "market-url-for-testing"; // Switch to an existing tab for a suggestion opened from the New Tab Page. const char kNtpSwitchToExistingTab[] = "ntp-switch-to-existing-tab"; -// Enable theme colors in the tab switcher. -const char kEnableTabSwitcherThemeColors[] = "enable-tab-switcher-theme-colors"; +// Specifies Android phone page loading progress bar animation. +const char kProgressBarAnimation[] = "progress-bar-animation"; + +// Specifies a particular tab management experiment to enable. +const char kTabManagementExperimentTypeAnise[] = + "tab-management-experiment-type-anise"; +const char kTabManagementExperimentTypeBasil[] = + "tab-management-experiment-type-basil"; +const char kTabManagementExperimentTypeChive[] = + "tab-management-experiment-type-chive"; +const char kTabManagementExperimentTypeDill[] = + "tab-management-experiment-type-dill"; +const char kTabManagementExperimentTypeDisabled[] = + "tab-management-experiment-type-disabled"; +const char kTabManagementExperimentTypeElderberry[] = + "tab-management-experiment-type-elderberry"; #endif // defined(OS_ANDROID) +#if defined(OS_CHROMEOS) +// Enables the intent picker so the user can handle URL links with ARC apps. +const char kEnableIntentPicker[] = "enable-intent-picker"; + +// Enables native cups integration +const char kEnableNativeCups[] = "enable-native-cups"; +#endif // defined(OS_CHROMEOS) + #if defined(USE_ASH) const char kOpenAsh[] = "open-ash"; #endif @@ -1130,10 +1143,6 @@ // Prevents Chrome from quitting when Chrome Apps are open. const char kAppsKeepChromeAliveInTests[] = "apps-keep-chrome-alive-in-tests"; -// Shows a notification when quitting Chrome with hosted apps running. Default -// behavior is to also quit all hosted apps. -const char kHostedAppQuitNotification[] = "enable-hosted-app-quit-notification"; - // Disable the toolkit-views App Info dialog for Mac. const char kDisableAppInfoDialogMac[] = "disable-app-info-dialog-mac"; @@ -1171,6 +1180,10 @@ // Enables tab detaching in fullscreen mode on Mac. const char kEnableFullscreenTabDetaching[] = "enable-fullscreen-tab-detaching"; +// Enables the fullscreen toolbar to reveal itself for tab strip changes. +const char kEnableFullscreenToolbarReveal[] = + "enable-fullscreen-toolbar-reveal"; + // Allows hosted apps to be opened in windows on Mac. const char kEnableHostedAppsInWindows[] = "enable-hosted-apps-in-windows"; @@ -1178,13 +1191,13 @@ const char kEnableMacViewsNativeAppWindows[] = "enable-mac-views-native-app-windows"; -// Enables the fullscreen toolbar to reveal itself for tab strip changes. -const char kEnableFullscreenToolbarReveal[] = - "enable-fullscreen-toolbar-reveal"; - // Enables Translate experimental new UX which replaces the infobar. const char kEnableTranslateNewUX[] = "enable-translate-new-ux"; +// Shows a notification when quitting Chrome with hosted apps running. Default +// behavior is to also quit all hosted apps. +const char kHostedAppQuitNotification[] = "enable-hosted-app-quit-notification"; + // This is how the metrics client ID is passed from the browser process to its // children. With Crashpad, the metrics client ID is distinct from the crash // client ID. @@ -1216,6 +1229,12 @@ // they use a custom-user-data-dir which disables this. const char kEnableProfileShortcutManager[] = "enable-profile-shortcut-manager"; +// Makes Windows happy by allowing it to show "Enable access to this program" +// checkbox in Add/Remove Programs->Set Program Access and Defaults. This only +// shows an error box because the only way to hide Chrome is by uninstalling +// it. +const char kHideIcons[] = "hide-icons"; + // Whether or not the browser should warn if the profile is on a network share. // This flag is only relevant for Windows currently. const char kNoNetworkProfileWarning[] = "no-network-profile-warning"; @@ -1228,12 +1247,6 @@ // /prefetch:7 is used by crashpad, which can't depend on constants defined // here. See crashpad_win.cc for more details. -// Makes Windows happy by allowing it to show "Enable access to this program" -// checkbox in Add/Remove Programs->Set Program Access and Defaults. This only -// shows an error box because the only way to hide Chrome is by uninstalling -// it. -const char kHideIcons[] = "hide-icons"; - // See kHideIcons. const char kShowIcons[] = "show-icons"; @@ -1257,49 +1270,28 @@ const char kDebugPrint[] = "debug-print"; #endif +#if defined(ENABLE_PLUGINS) +// Specifies comma-separated list of extension ids or hosts to grant +// access to CRX file system APIs. +const char kAllowNaClCrxFsAPI[] = "allow-nacl-crxfs-api"; + +// Specifies comma-separated list of extension ids or hosts to grant +// access to file handle APIs. +const char kAllowNaClFileHandleAPI[] = "allow-nacl-file-handle-api"; + +// Specifies comma-separated list of extension ids or hosts to grant +// access to TCP/UDP socket APIs. +const char kAllowNaClSocketAPI[] = "allow-nacl-socket-api"; +#endif + #if defined(ENABLE_WAYLAND_SERVER) // Enables Wayland display server support. const char kEnableWaylandServer[] = "enable-wayland-server"; #endif -#if defined(OS_ANDROID) -// Forces the update menu item to show. -const char kForceShowUpdateMenuItem[] = "force-show-update-menu-item"; - -// Forces a summary to be displayed below the update menu item. -const char kForceShowUpdateMenuItemSummary[] = "show_summary"; - -// Forces the new features summary to be displayed below the update menu item. -const char kForceShowUpdateMenuItemNewFeaturesSummary[] = - "use_new_features_summary"; - -// Forces a custom summary to be displayed below the update menu item. -const char kForceShowUpdateMenuItemCustomSummary[] = "custom_summary"; - -// Forces the update menu badge to show. -const char kForceShowUpdateMenuBadge[] = "force-show-update-menu-badge"; - -// Sets the market URL for Chrome for use in testing. -const char kMarketUrlForTesting[] = "market-url-for-testing"; - -// Specifies a particular tab management experiment to enable. -const char kTabManagementExperimentTypeDisabled[] = - "tab-management-experiment-type-disabled"; -const char kTabManagementExperimentTypeAnise[] = - "tab-management-experiment-type-anise"; -const char kTabManagementExperimentTypeBasil[] = - "tab-management-experiment-type-basil"; -const char kTabManagementExperimentTypeChive[] = - "tab-management-experiment-type-chive"; -const char kTabManagementExperimentTypeDill[] = - "tab-management-experiment-type-dill"; -const char kTabManagementExperimentTypeElderberry[] = - "tab-management-experiment-type-elderberry"; -#endif // defined(OS_ANDROID) - #if defined(OS_WIN) || defined(OS_LINUX) -extern const char kEnableInputImeAPI[] = "enable-input-ime-api"; extern const char kDisableInputImeAPI[] = "disable-input-ime-api"; +extern const char kEnableInputImeAPI[] = "enable-input-ime-api"; #endif bool AboutInSettingsEnabled() {
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 4c50ffe..791767d 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -33,13 +33,13 @@ extern const char kAllowRunningInsecureContent[]; extern const char kAllowSilentPush[]; extern const char kAlwaysAuthorizePlugins[]; -extern const char kAppId[]; extern const char kApp[]; -extern const char kAppsGalleryDownloadURL[]; -extern const char kAppsGalleryURL[]; -extern const char kAppsGalleryUpdateURL[]; +extern const char kAppId[]; extern const char kAppModeAuthCode[]; extern const char kAppModeOAuth2Token[]; +extern const char kAppsGalleryDownloadURL[]; +extern const char kAppsGalleryUpdateURL[]; +extern const char kAppsGalleryURL[]; extern const char kAuthExtensionPath[]; extern const char kAuthServerWhitelist[]; extern const char kAutoOpenDevToolsForTabs[]; @@ -49,8 +49,8 @@ extern const char kCheckForUpdateIntervalSec[]; extern const char kCipherSuiteBlacklist[]; extern const char kCloudPrintFile[]; -extern const char kCloudPrintJobTitle[]; extern const char kCloudPrintFileType[]; +extern const char kCloudPrintJobTitle[]; extern const char kCloudPrintPrintTicket[]; extern const char kCloudPrintSetupProxy[]; extern const char kCrashOnHangThreads[]; @@ -62,9 +62,6 @@ extern const char kDiagnosticsRecovery[]; extern const char kDisableAboutInSettings[]; extern const char kDisableAddToShelf[]; -#if defined(OS_ANDROID) -extern const char kDisableAppLink[]; -#endif extern const char kDisableAsyncDns[]; extern const char kDisableBackgroundNetworking[]; extern const char kDisableBundledPpapiFlash[]; @@ -78,16 +75,16 @@ extern const char kDisableDeviceDiscoveryNotifications[]; extern const char kDisableDomainReliability[]; extern const char kDisableDownloadNotification[]; +extern const char kDisableExtensions[]; extern const char kDisableExtensionsFileAccessCheck[]; extern const char kDisableExtensionsHttpThrottling[]; -extern const char kDisableExtensions[]; extern const char kDisableFieldTrialTestingConfig[]; extern const char kDisableMinimizeOnSecondLauncherItemClick[]; extern const char kDisableNewBookmarkApps[]; extern const char kDisableOfflineAutoReload[]; extern const char kDisableOfflineAutoReloadVisibleOnly[]; extern const char kDisableOutOfProcessPac[]; -extern const char kDisablePasswordManagerReauthentication[]; +extern const char kDisablePanels[]; extern const char kDisablePermissionActionReporting[]; extern const char kDisablePermissionsBlacklist[]; extern const char kDisablePopupBlocking[]; @@ -96,10 +93,8 @@ extern const char kDisablePromptOnRepost[]; extern const char kDisablePushApiBackgroundMode[]; extern const char kDisableSessionCrashedBubble[]; +extern const char kDisableSettingsWindow[]; extern const char kDisableSiteEngagementService[]; -#if defined(OS_ANDROID) -extern const char kDisableVrShell[]; -#endif extern const char kDisableWebNotificationCustomLayouts[]; extern const char kDisableWebUsbSecurity[]; extern const char kDisableZeroBrowsersOpenForTests[]; @@ -111,36 +106,24 @@ extern const char kEasyUnlockAppPath[]; extern const char kEnableAddToShelf[]; extern const char kEnableAllBookmarksView[]; -#if defined(OS_ANDROID) -extern const char kEnableAppLink[]; -#endif extern const char kEnableAppsFileAssociations[]; -#if defined(OS_CHROMEOS) -extern const char kEnableIntentPicker[]; -#endif // defined(OS_CHROMEOS) extern const char kEnableAudioDebugRecordingsFromExtension[]; extern const char kEnableBenchmarking[]; extern const char kEnableBookmarkUndo[]; extern const char kEnableChildAccountDetection[]; extern const char kEnableClearBrowsingDataCounters[]; extern const char kEnableCloudPrintProxy[]; -extern const char kEnableDevToolsExperiments[]; extern const char kEnableDeviceDiscoveryNotifications[]; +extern const char kEnableDevToolsExperiments[]; extern const char kEnableDomainReliability[]; extern const char kEnableExperimentalHotwordHardware[]; extern const char kEnableExtensionActivityLogging[]; extern const char kEnableExtensionActivityLogTesting[]; extern const char kEnableFastUnload[]; -#if defined(GOOGLE_CHROME_BUILD) -extern const char kEnableGoogleBrandedContextMenu[]; -#endif // defined(GOOGLE_CHROME_BUILD) extern const char kEnableMaterialDesignExtensions[]; extern const char kEnableMaterialDesignFeedback[]; extern const char kEnableMaterialDesignPolicyPage[]; extern const char kEnableNaCl[]; -#if defined(OS_CHROMEOS) -extern const char kEnableNativeCups[]; -#endif // defined(OS_CHROMEOS) extern const char kEnableNativeNotifications[]; extern const char kEnableNavigationTracing[]; extern const char kEnableNetBenchmarking[]; @@ -148,7 +131,6 @@ extern const char kEnableOfflineAutoReload[]; extern const char kEnableOfflineAutoReloadVisibleOnly[]; extern const char kEnablePanels[]; -extern const char kDisablePanels[]; extern const char kEnablePermissionActionReporting[]; extern const char kEnablePermissionsBlacklist[]; extern const char kEnablePotentiallyAnnoyingSecurityFeatures[]; @@ -156,10 +138,8 @@ extern const char kEnablePrintPreviewRegisterPromos[]; extern const char kEnableProfiling[]; extern const char kEnablePushApiBackgroundMode[]; -extern const char kEnableWebRtcEventLoggingFromExtension[]; extern const char kEnableSessionCrashedBubble[]; extern const char kEnableSettingsWindow[]; -extern const char kDisableSettingsWindow[]; extern const char kEnableSiteEngagementAppBanner[]; extern const char kEnableSiteEngagementEvictionPolicy[]; extern const char kEnableSiteEngagementService[]; @@ -167,18 +147,13 @@ extern const char kEnableTabAudioMuting[]; extern const char kEnableThumbnailRetargeting[]; extern const char kEnableUserAlternateProtocolPorts[]; -#if defined(OS_ANDROID) -extern const char kEnableVrShell[]; -#endif extern const char kEnableWebAppFrame[]; -#if defined(OS_ANDROID) -extern const char kEnableWebApk[]; -#endif // defined(OS_ANDROID) extern const char kEnableWebNotificationCustomLayouts[]; -extern const char kExtensionContentVerificationBootstrap[]; -extern const char kExtensionContentVerificationEnforceStrict[]; -extern const char kExtensionContentVerificationEnforce[]; +extern const char kEnableWebRtcEventLoggingFromExtension[]; extern const char kExtensionContentVerification[]; +extern const char kExtensionContentVerificationBootstrap[]; +extern const char kExtensionContentVerificationEnforce[]; +extern const char kExtensionContentVerificationEnforceStrict[]; extern const char kExtensionsInstallVerification[]; extern const char kExtensionsNotWebstore[]; extern const char kExtensionsUpdateFrequency[]; @@ -186,12 +161,12 @@ extern const char kForceAppMode[]; extern const char kForceFieldTrialParams[]; extern const char kForceFirstRun[]; -extern const char kForceVariationIds[]; extern const char kForceLocalNtp[]; +extern const char kForceVariationIds[]; extern const char kHistoryEnableGroupByDomain[]; extern const char kHomePage[]; -extern const char kHostRules[]; extern const char kHostResolverRetryAttempts[]; +extern const char kHostRules[]; extern const char kIncognito[]; extern const char kInstallChromeApp[]; extern const char kInstallSupervisedUserWhitelists[]; @@ -202,9 +177,6 @@ extern const char kKioskModePrinting[]; extern const char kLoadComponentExtension[]; extern const char kLoadExtension[]; -#if !defined(GOOGLE_CHROME_BUILD) -extern const char kLocalNtpReload[]; -#endif extern const char kMakeDefaultBrowser[]; extern const char kMediaCacheSize[]; extern const char kMediaRouter[]; @@ -216,8 +188,8 @@ extern const char kNoDisplayingInsecureContent[]; extern const char kNoExperiments[]; extern const char kNoFirstRun[]; -extern const char kNoProxyServer[]; extern const char kNoPings[]; +extern const char kNoProxyServer[]; extern const char kNoServiceAutorun[]; extern const char kNoStartupWindow[]; extern const char kNoSupervisedUserAcknowledgmentCheck[]; @@ -258,27 +230,19 @@ extern const char kSbDisableExtensionBlacklist[]; extern const char kSbManualDownloadBlacklist[]; extern const char kServiceProcess[]; +extern const char kShowAppList[]; extern const char kSilentDebuggerExtensionAPI[]; extern const char kSilentLaunch[]; -extern const char kShowAppList[]; -extern const char kSSLKeyLogFile[]; -extern const char kSimulateElevatedRecovery[]; -extern const char kSimulateUpgrade[]; extern const char kSimulateCriticalUpdate[]; +extern const char kSimulateElevatedRecovery[]; extern const char kSimulateOutdated[]; extern const char kSimulateOutdatedNoAU[]; +extern const char kSimulateUpgrade[]; extern const char kSpeculativeResourcePrefetching[]; extern const char kSpeculativeResourcePrefetchingDisabled[]; extern const char kSpeculativeResourcePrefetchingEnabled[]; extern const char kSpeculativeResourcePrefetchingLearning[]; -#if defined(ENABLE_SPELLCHECK) -#if defined(OS_ANDROID) -extern const char kEnableAndroidSpellChecker[]; -#endif -extern const char kEnableSpellingFeedbackFieldTrial[]; -extern const char kSpellingServiceFeedbackUrl[]; -extern const char kSpellingServiceFeedbackIntervalSeconds[]; -#endif +extern const char kSSLKeyLogFile[]; extern const char kStartMaximized[]; extern const char kSupervisedUserId[]; extern const char kSupervisedUserSafeSites[]; @@ -289,9 +253,9 @@ extern const char kUnlimitedStorage[]; extern const char kUnsafelyTreatInsecureOriginAsSecure[]; extern const char kUnsafePacUrl[]; -extern const char kUseSimpleCacheBackend[]; extern const char kUserAgent[]; extern const char kUserDataDir[]; +extern const char kUseSimpleCacheBackend[]; extern const char kV8PacMojoInProcess[]; extern const char kV8PacMojoOutOfProcess[]; extern const char kValidateCrx[]; @@ -302,32 +266,57 @@ extern const char kWinHttpProxyResolver[]; extern const char kWinJumplistAction[]; +#if defined(ENABLE_SPELLCHECK) +#if defined(OS_ANDROID) +extern const char kEnableAndroidSpellChecker[]; +#endif // defined(OS_ANDROID) +extern const char kEnableSpellingFeedbackFieldTrial[]; +extern const char kSpellingServiceFeedbackIntervalSeconds[]; +extern const char kSpellingServiceFeedbackUrl[]; +#endif // defined(ENABLE_SPELLCHECK) + +#if defined(GOOGLE_CHROME_BUILD) +extern const char kEnableGoogleBrandedContextMenu[]; +#endif // defined(GOOGLE_CHROME_BUILD) + +#if !defined(GOOGLE_CHROME_BUILD) +extern const char kLocalNtpReload[]; +#endif + #if defined(OS_ANDROID) extern const char kAuthAndroidNegotiateAccountType[]; +extern const char kDisableAppLink[]; extern const char kDisableContextualSearch[]; +extern const char kDisableVrShell[]; extern const char kEnableAccessibilityTabSwitcher[]; +extern const char kEnableAppLink[]; extern const char kEnableContextualSearch[]; extern const char kEnableHostedMode[]; extern const char kEnableHungRendererInfoBar[]; -extern const char kProgressBarAnimation[]; -extern const char kEnableThemeColorInTabbedMode[]; -extern const char kEnableTabSwitcherInDocumentMode[]; extern const char kEnableTabSwitcherThemeColors[]; -extern const char kNtpSwitchToExistingTab[]; -extern const char kForceShowUpdateMenuItem[]; -extern const char kForceShowUpdateMenuItemSummary[]; -extern const char kForceShowUpdateMenuItemNewFeaturesSummary[]; -extern const char kForceShowUpdateMenuItemCustomSummary[]; +extern const char kEnableVrShell[]; +extern const char kEnableWebApk[]; extern const char kForceShowUpdateMenuBadge[]; +extern const char kForceShowUpdateMenuItem[]; +extern const char kForceShowUpdateMenuItemCustomSummary[]; +extern const char kForceShowUpdateMenuItemNewFeaturesSummary[]; +extern const char kForceShowUpdateMenuItemSummary[]; extern const char kMarketUrlForTesting[]; -extern const char kTabManagementExperimentTypeDisabled[]; +extern const char kNtpSwitchToExistingTab[]; +extern const char kProgressBarAnimation[]; extern const char kTabManagementExperimentTypeAnise[]; extern const char kTabManagementExperimentTypeBasil[]; extern const char kTabManagementExperimentTypeChive[]; extern const char kTabManagementExperimentTypeDill[]; +extern const char kTabManagementExperimentTypeDisabled[]; extern const char kTabManagementExperimentTypeElderberry[]; #endif // defined(OS_ANDROID) +#if defined(OS_CHROMEOS) +extern const char kEnableIntentPicker[]; +extern const char kEnableNativeCups[]; +#endif // defined(OS_CHROMEOS) + #if defined(USE_ASH) extern const char kOpenAsh[]; #endif @@ -341,7 +330,6 @@ #if defined(OS_MACOSX) extern const char kAppsKeepChromeAliveInTests[]; -extern const char kHostedAppQuitNotification[]; extern const char kDisableAppInfoDialogMac[]; extern const char kDisableAppWindowCycling[]; extern const char kDisableFullscreenLowPowerMode[]; @@ -357,6 +345,7 @@ extern const char kEnableHostedAppsInWindows[]; extern const char kEnableMacViewsNativeAppWindows[]; extern const char kEnableTranslateNewUX[]; +extern const char kHostedAppQuitNotification[]; extern const char kMetricsClientID[]; extern const char kRelauncherProcess[]; extern const char kRelauncherProcessDMGDevice[]; @@ -393,8 +382,8 @@ #endif #if defined(OS_WIN) || defined(OS_LINUX) -extern const char kEnableInputImeAPI[]; extern const char kDisableInputImeAPI[]; +extern const char kEnableInputImeAPI[]; #endif bool AboutInSettingsEnabled();
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json index dbabc8a..233a24f 100644 --- a/chrome/common/extensions/api/_api_features.json +++ b/chrome/common/extensions/api/_api_features.json
@@ -548,7 +548,8 @@ "channel": "stable", "contexts": ["webui"], "matches": [ - "chrome://md-settings/*" + "chrome://md-settings/*", + "chrome://settings/*" ] }], "instanceID": { @@ -699,7 +700,8 @@ "channel": "stable", "contexts": ["webui"], "matches": [ - "chrome://md-settings/*" + "chrome://md-settings/*", + "chrome://settings/*" ], "platforms": ["chromeos"] },
diff --git a/chrome/common/extensions/api/commands/commands_manifest_unittest.cc b/chrome/common/extensions/api/commands/commands_manifest_unittest.cc index 5e37f34..c5f156d 100644 --- a/chrome/common/extensions/api/commands/commands_manifest_unittest.cc +++ b/chrome/common/extensions/api/commands/commands_manifest_unittest.cc
@@ -10,7 +10,7 @@ #include "build/build_config.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/api/commands/commands_handler.h" -#include "chrome/common/extensions/features/feature_channel.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/manifest_constants.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/common/extensions/api/common_extension_api_unittest.cc b/chrome/common/extensions/api/common_extension_api_unittest.cc index d24fd46..edcb0b3 100644 --- a/chrome/common/extensions/api/common_extension_api_unittest.cc +++ b/chrome/common/extensions/api/common_extension_api_unittest.cc
@@ -24,7 +24,7 @@ #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" #include "extensions/common/features/api_feature.h" -#include "extensions/common/features/base_feature_provider.h" +#include "extensions/common/features/json_feature_provider.h" #include "extensions/common/features/simple_feature.h" #include "extensions/common/manifest.h" #include "extensions/common/manifest_constants.h" @@ -177,7 +177,7 @@ std::unique_ptr<base::DictionaryValue> value( static_cast<base::DictionaryValue*>( base::JSONReader::Read(api_features_str).release())); - BaseFeatureProvider api_feature_provider(*value, CreateAPIFeature); + JSONFeatureProvider api_feature_provider(*value, CreateAPIFeature); for (size_t i = 0; i < arraysize(test_data); ++i) { ExtensionAPI api; @@ -271,7 +271,7 @@ std::unique_ptr<base::DictionaryValue> value( static_cast<base::DictionaryValue*>( base::JSONReader::Read(api_features_str).release())); - BaseFeatureProvider api_feature_provider(*value, CreateAPIFeature); + JSONFeatureProvider api_feature_provider(*value, CreateAPIFeature); for (size_t i = 0; i < arraysize(test_data); ++i) { ExtensionAPI api; @@ -701,7 +701,7 @@ }; for (size_t i = 0; i < arraysize(test_data); ++i) { - BaseFeatureProvider api_feature_provider(*test_data[i].api_features, + JSONFeatureProvider api_feature_provider(*test_data[i].api_features, CreateAPIFeature); Feature* feature = api_feature_provider.GetFeature("test"); EXPECT_EQ(test_data[i].expect_success, feature != NULL) << i;
diff --git a/chrome/common/extensions/api/storage/storage_schema_manifest_handler_unittest.cc b/chrome/common/extensions/api/storage/storage_schema_manifest_handler_unittest.cc index 869e2b7..be03b51 100644 --- a/chrome/common/extensions/api/storage/storage_schema_manifest_handler_unittest.cc +++ b/chrome/common/extensions/api/storage/storage_schema_manifest_handler_unittest.cc
@@ -11,9 +11,9 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/values.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "components/version_info/version_info.h" #include "extensions/common/extension.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/file_util.h" #include "extensions/common/manifest.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/common/extensions/chrome_extensions_client.cc b/chrome/common/extensions/chrome_extensions_client.cc index d8339547..a261245 100644 --- a/chrome/common/extensions/chrome_extensions_client.cc +++ b/chrome/common/extensions/chrome_extensions_client.cc
@@ -16,8 +16,6 @@ #include "chrome/common/extensions/api/generated_schemas.h" #include "chrome/common/extensions/chrome_manifest_handlers.h" #include "chrome/common/extensions/extension_constants.h" -#include "chrome/common/extensions/features/chrome_channel_feature_filter.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/common/extensions/manifest_handlers/theme_handler.h" #include "chrome/common/url_constants.h" #include "chrome/grit/chromium_strings.h" @@ -34,9 +32,10 @@ #include "extensions/common/extension_icon_set.h" #include "extensions/common/extension_urls.h" #include "extensions/common/features/api_feature.h" -#include "extensions/common/features/base_feature_provider.h" #include "extensions/common/features/behavior_feature.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/features/feature_provider.h" +#include "extensions/common/features/json_feature_provider.h" #include "extensions/common/features/json_feature_provider_source.h" #include "extensions/common/features/manifest_feature.h" #include "extensions/common/features/permission_feature.h" @@ -66,9 +65,8 @@ template <class FeatureClass> SimpleFeature* CreateFeature() { - SimpleFeature* feature = new FeatureClass; - feature->AddFilter(std::unique_ptr<SimpleFeatureFilter>( - new ChromeChannelFeatureFilter(feature))); + SimpleFeature* feature = new FeatureClass(); + feature->set_check_channel(true); return feature; } @@ -147,16 +145,16 @@ std::unique_ptr<JSONFeatureProviderSource> source( CreateFeatureProviderSource(name)); if (name == "api") { - provider.reset(new BaseFeatureProvider(source->dictionary(), + provider.reset(new JSONFeatureProvider(source->dictionary(), CreateFeature<APIFeature>)); } else if (name == "manifest") { - provider.reset(new BaseFeatureProvider(source->dictionary(), + provider.reset(new JSONFeatureProvider(source->dictionary(), CreateFeature<ManifestFeature>)); } else if (name == "permission") { - provider.reset(new BaseFeatureProvider(source->dictionary(), + provider.reset(new JSONFeatureProvider(source->dictionary(), CreateFeature<PermissionFeature>)); } else if (name == "behavior") { - provider.reset(new BaseFeatureProvider(source->dictionary(), + provider.reset(new JSONFeatureProvider(source->dictionary(), CreateFeature<BehaviorFeature>)); } else { NOTREACHED();
diff --git a/chrome/common/extensions/chrome_manifest_url_handlers.cc b/chrome/common/extensions/chrome_manifest_url_handlers.cc index 200a53e6..3d13dd9 100644 --- a/chrome/common/extensions/chrome_manifest_url_handlers.cc +++ b/chrome/common/extensions/chrome_manifest_url_handlers.cc
@@ -103,7 +103,7 @@ // Validate that the overrides are all strings for (base::DictionaryValue::Iterator iter(*overrides); !iter.IsAtEnd(); iter.Advance()) { - std::string page = iter.key(); + const std::string& page = iter.key(); std::string val; // Restrict override pages to a list of supported URLs. bool is_allowed_host = page == chrome::kChromeUINewTabHost ||
diff --git a/chrome/common/extensions/command.h b/chrome/common/extensions/command.h index 601c7ab..63edc01 100644 --- a/chrome/common/extensions/command.h +++ b/chrome/common/extensions/command.h
@@ -61,7 +61,7 @@ bool global() const { return global_; } // Setter: - void set_accelerator(ui::Accelerator accelerator) { + void set_accelerator(const ui::Accelerator& accelerator) { accelerator_ = accelerator; } void set_global(bool global) {
diff --git a/chrome/common/extensions/command_unittest.cc b/chrome/common/extensions/command_unittest.cc index d5e489a..5edc4ce 100644 --- a/chrome/common/extensions/command_unittest.cc +++ b/chrome/common/extensions/command_unittest.cc
@@ -32,7 +32,7 @@ // |platform_specific_only| is true, only the latter is tested. |platforms| // specifies all platforms to use when populating the |suggested_key| // dictionary. -void CheckParse(ConstCommandsTestData data, +void CheckParse(const ConstCommandsTestData& data, int i, bool platform_specific_only, std::vector<std::string>& platforms) {
diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc index c6b2bd2..4aa72be 100644 --- a/chrome/common/extensions/extension_constants.cc +++ b/chrome/common/extensions/extension_constants.cc
@@ -51,7 +51,6 @@ "abjokfonkihficiokmkfboogholifghn"; const char kHotwordNewExtensionId[] = "nbpagnldghgfoolbancepceaanlmhfmd"; const char kHotwordSharedModuleId[] = "lccekmodgklaepjeofjdjpbminllajkg"; -const char kSettingsAppId[] = "ennkphjdgehloodpbhlhldgbnhmacadg"; const char kYoutubeAppId[] = "blpcfgokakmgnkcojhhkbfbldkacnbeo"; const char kInAppPaymentsSupportAppId[] = "nmmhkkegccagdldgiimedpiccmgmieda"; #if defined(ENABLE_MEDIA_ROUTER)
diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h index a7712827..ff4aaa5 100644 --- a/chrome/common/extensions/extension_constants.h +++ b/chrome/common/extensions/extension_constants.h
@@ -94,9 +94,6 @@ // The extension id of the hotword shared module. extern const char kHotwordSharedModuleId[]; -// The extension id of the settings application. -extern const char kSettingsAppId[]; - // The extension id of the Youtube application. extern const char kYoutubeAppId[];
diff --git a/chrome/common/extensions/features/chrome_channel_feature_filter.cc b/chrome/common/extensions/features/chrome_channel_feature_filter.cc deleted file mode 100644 index 3613f87..0000000 --- a/chrome/common/extensions/features/chrome_channel_feature_filter.cc +++ /dev/null
@@ -1,104 +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. - -#include "chrome/common/extensions/features/chrome_channel_feature_filter.h" - -#include <map> -#include <string> - -#include "base/lazy_instance.h" -#include "base/strings/stringprintf.h" -#include "chrome/common/extensions/features/feature_channel.h" -#include "chrome/grit/chromium_strings.h" -#include "components/version_info/version_info.h" -#include "extensions/common/features/simple_feature.h" -#include "ui/base/l10n/l10n_util.h" - -namespace extensions { - -namespace { - -static const char kFeatureChannelKey[] = "channel"; - -struct Mappings { - Mappings() { - channels["trunk"] = version_info::Channel::UNKNOWN; - channels["canary"] = version_info::Channel::CANARY; - channels["dev"] = version_info::Channel::DEV; - channels["beta"] = version_info::Channel::BETA; - channels["stable"] = version_info::Channel::STABLE; - } - - std::map<std::string, version_info::Channel> channels; -}; - -base::LazyInstance<Mappings> g_mappings = LAZY_INSTANCE_INITIALIZER; - -std::string GetChannelName(version_info::Channel channel) { - typedef std::map<std::string, version_info::Channel> ChannelsMap; - ChannelsMap channels = g_mappings.Get().channels; - for (ChannelsMap::iterator i = channels.begin(); i != channels.end(); ++i) { - if (i->second == channel) - return i->first; - } - NOTREACHED(); - return "unknown"; -} - -version_info::Channel GetChannelValue(const std::string& name) { - typedef std::map<std::string, version_info::Channel> ChannelsMap; - ChannelsMap channels = g_mappings.Get().channels; - ChannelsMap::const_iterator iter = channels.find(name); - CHECK(iter != channels.end()); - return iter->second; -} - -} // namespace - -ChromeChannelFeatureFilter::ChromeChannelFeatureFilter(SimpleFeature* feature) - : SimpleFeatureFilter(feature), - channel_has_been_set_(false), - channel_(version_info::Channel::UNKNOWN) {} - -ChromeChannelFeatureFilter::~ChromeChannelFeatureFilter() {} - -std::string ChromeChannelFeatureFilter::Parse( - const base::DictionaryValue* value) { - std::string channel_name; - if (value->GetString(kFeatureChannelKey, &channel_name)) { - channel_ = GetChannelValue(channel_name); - } - - // The "trunk" channel uses version_info::Channel::UNKNOWN, so we need to keep - // track of whether the channel has been set or not separately. - channel_has_been_set_ |= value->HasKey(kFeatureChannelKey); - - if (!channel_has_been_set_ && !feature()->HasDependencies()) { - return feature()->name() + - ": Must supply a value for channel or dependencies."; - } - - return std::string(); -} - -Feature::Availability ChromeChannelFeatureFilter::IsAvailableToManifest( - const std::string& extension_id, - Manifest::Type type, - Manifest::Location location, - int manifest_version, - Feature::Platform platfortm) const { - if (channel_has_been_set_ && channel_ < GetCurrentChannel()) { - return Feature::Availability( - Feature::UNSUPPORTED_CHANNEL, - base::StringPrintf( - "'%s' requires %s %s channel or newer, but this is the %s channel.", - feature()->name().c_str(), - l10n_util::GetStringUTF8(IDS_PRODUCT_NAME).c_str(), - GetChannelName(channel_).c_str(), - GetChannelName(GetCurrentChannel()).c_str())); - } - return Feature::Availability(Feature::IS_AVAILABLE, std::string()); -} - -} // namespace extensions
diff --git a/chrome/common/extensions/features/chrome_channel_feature_filter.h b/chrome/common/extensions/features/chrome_channel_feature_filter.h deleted file mode 100644 index bf1c05dc..0000000 --- a/chrome/common/extensions/features/chrome_channel_feature_filter.h +++ /dev/null
@@ -1,39 +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 CHROME_COMMON_EXTENSIONS_FEATURES_CHROME_CHANNEL_FEATURE_FILTER_H_ -#define CHROME_COMMON_EXTENSIONS_FEATURES_CHROME_CHANNEL_FEATURE_FILTER_H_ - -#include "extensions/common/features/simple_feature_filter.h" - -namespace version_info { -enum class Channel; -} - -namespace extensions { - -// This filter parses a "channel" key from feature value data and makes features -// unavailable if they aren't stable enough for the current channel. -class ChromeChannelFeatureFilter : public SimpleFeatureFilter { - public: - explicit ChromeChannelFeatureFilter(SimpleFeature* feature); - ~ChromeChannelFeatureFilter() override; - - // SimpleFeatureFilter implementation. - std::string Parse(const base::DictionaryValue* value) override; - Feature::Availability IsAvailableToManifest( - const std::string& extension_id, - Manifest::Type type, - Manifest::Location location, - int manifest_version, - Feature::Platform platform) const override; - - private: - bool channel_has_been_set_; - version_info::Channel channel_; -}; - -} // namespace extensions - -#endif // CHROME_COMMON_EXTENSIONS_FEATURES_CHROME_CHANNEL_FEATURE_FILTER_H_
diff --git a/chrome/common/extensions/features/chrome_channel_feature_filter_unittest.cc b/chrome/common/extensions/features/chrome_channel_feature_filter_unittest.cc deleted file mode 100644 index 806042b..0000000 --- a/chrome/common/extensions/features/chrome_channel_feature_filter_unittest.cc +++ /dev/null
@@ -1,302 +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. - -#include "chrome/common/extensions/features/chrome_channel_feature_filter.h" - -#include <memory> -#include <string> -#include <utility> - -#include "base/macros.h" -#include "base/values.h" -#include "chrome/common/extensions/features/feature_channel.h" -#include "components/version_info/version_info.h" -#include "extensions/common/features/base_feature_provider.h" -#include "extensions/common/features/complex_feature.h" -#include "extensions/common/features/permission_feature.h" -#include "extensions/common/features/simple_feature.h" -#include "extensions/common/value_builder.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace extensions { -namespace { - -template <class FeatureClass> -SimpleFeature* CreateFeature() { - SimpleFeature* feature = new FeatureClass(); - feature->AddFilter(std::unique_ptr<SimpleFeatureFilter>( - new ChromeChannelFeatureFilter(feature))); - return feature; -} - -Feature::AvailabilityResult IsAvailableInChannel( - const std::string& channel, - version_info::Channel channel_for_testing) { - ScopedCurrentChannel current_channel(channel_for_testing); - - SimpleFeature feature; - feature.AddFilter(std::unique_ptr<SimpleFeatureFilter>( - new ChromeChannelFeatureFilter(&feature))); - - base::DictionaryValue feature_value; - feature_value.SetString("channel", channel); - feature.Parse(&feature_value); - - return feature.IsAvailableToManifest("random-extension", - Manifest::TYPE_UNKNOWN, - Manifest::INVALID_LOCATION, - -1, - Feature::GetCurrentPlatform()).result(); -} - -} // namespace - -class ChromeChannelFeatureFilterTest : public testing::Test { - protected: - ChromeChannelFeatureFilterTest() - : current_channel_(version_info::Channel::UNKNOWN) {} - ~ChromeChannelFeatureFilterTest() override {} - - private: - ScopedCurrentChannel current_channel_; - - DISALLOW_COPY_AND_ASSIGN(ChromeChannelFeatureFilterTest); -}; - -// Tests that all combinations of feature channel and Chrome channel correctly -// compute feature availability. -TEST_F(ChromeChannelFeatureFilterTest, SupportedChannel) { - // stable supported. - EXPECT_EQ(Feature::IS_AVAILABLE, - IsAvailableInChannel("stable", version_info::Channel::UNKNOWN)); - EXPECT_EQ(Feature::IS_AVAILABLE, - IsAvailableInChannel("stable", version_info::Channel::CANARY)); - EXPECT_EQ(Feature::IS_AVAILABLE, - IsAvailableInChannel("stable", version_info::Channel::DEV)); - EXPECT_EQ(Feature::IS_AVAILABLE, - IsAvailableInChannel("stable", version_info::Channel::BETA)); - EXPECT_EQ(Feature::IS_AVAILABLE, - IsAvailableInChannel("stable", version_info::Channel::STABLE)); - - // beta supported. - EXPECT_EQ(Feature::IS_AVAILABLE, - IsAvailableInChannel("beta", version_info::Channel::UNKNOWN)); - EXPECT_EQ(Feature::IS_AVAILABLE, - IsAvailableInChannel("beta", version_info::Channel::CANARY)); - EXPECT_EQ(Feature::IS_AVAILABLE, - IsAvailableInChannel("beta", version_info::Channel::DEV)); - EXPECT_EQ(Feature::IS_AVAILABLE, - IsAvailableInChannel("beta", version_info::Channel::BETA)); - EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, - IsAvailableInChannel("beta", version_info::Channel::STABLE)); - - // dev supported. - EXPECT_EQ(Feature::IS_AVAILABLE, - IsAvailableInChannel("dev", version_info::Channel::UNKNOWN)); - EXPECT_EQ(Feature::IS_AVAILABLE, - IsAvailableInChannel("dev", version_info::Channel::CANARY)); - EXPECT_EQ(Feature::IS_AVAILABLE, - IsAvailableInChannel("dev", version_info::Channel::DEV)); - EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, - IsAvailableInChannel("dev", version_info::Channel::BETA)); - EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, - IsAvailableInChannel("dev", version_info::Channel::STABLE)); - - // canary supported. - EXPECT_EQ(Feature::IS_AVAILABLE, - IsAvailableInChannel("canary", version_info::Channel::UNKNOWN)); - EXPECT_EQ(Feature::IS_AVAILABLE, - IsAvailableInChannel("canary", version_info::Channel::CANARY)); - EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, - IsAvailableInChannel("canary", version_info::Channel::DEV)); - EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, - IsAvailableInChannel("canary", version_info::Channel::BETA)); - EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, - IsAvailableInChannel("canary", version_info::Channel::STABLE)); - - // trunk supported. - EXPECT_EQ(Feature::IS_AVAILABLE, - IsAvailableInChannel("trunk", version_info::Channel::UNKNOWN)); - EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, - IsAvailableInChannel("trunk", version_info::Channel::CANARY)); - EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, - IsAvailableInChannel("trunk", version_info::Channel::DEV)); - EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, - IsAvailableInChannel("trunk", version_info::Channel::BETA)); - EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, - IsAvailableInChannel("trunk", version_info::Channel::STABLE)); -} - -// Tests the validation of features with channel entries. -TEST_F(ChromeChannelFeatureFilterTest, FeatureValidation) { - std::unique_ptr<base::DictionaryValue> value(new base::DictionaryValue()); - - base::DictionaryValue* feature1 = new base::DictionaryValue(); - feature1->SetString("channel", "trunk"); - value->Set("feature1", feature1); - - base::DictionaryValue* feature2 = new base::DictionaryValue(); - feature2->SetString("channel", "trunk"); - base::ListValue* extension_types = new base::ListValue(); - extension_types->AppendString("extension"); - feature2->Set("extension_types", extension_types); - base::ListValue* contexts = new base::ListValue(); - contexts->AppendString("blessed_extension"); - feature2->Set("contexts", contexts); - value->Set("feature2", feature2); - - std::unique_ptr<BaseFeatureProvider> provider( - new BaseFeatureProvider(*value, CreateFeature<PermissionFeature>)); - - // feature1 won't validate because it lacks an extension type. - EXPECT_FALSE(provider->GetFeature("feature1")); - - // If we add one, it works. - feature1->Set("extension_types", extension_types->DeepCopy()); - provider.reset( - new BaseFeatureProvider(*value, CreateFeature<PermissionFeature>)); - EXPECT_TRUE(provider->GetFeature("feature1")); - - // Remove the channel, and feature1 won't validate. - feature1->Remove("channel", NULL); - provider.reset( - new BaseFeatureProvider(*value, CreateFeature<PermissionFeature>)); - EXPECT_FALSE(provider->GetFeature("feature1")); - - // feature2 won't validate because of the presence of "contexts". - EXPECT_FALSE(provider->GetFeature("feature2")); - - // If we remove it, it works. - feature2->Remove("contexts", NULL); - provider.reset( - new BaseFeatureProvider(*value, CreateFeature<PermissionFeature>)); - EXPECT_TRUE(provider->GetFeature("feature2")); -} - -// Tests simple feature availability across channels. -TEST_F(ChromeChannelFeatureFilterTest, SimpleFeatureAvailability) { - std::unique_ptr<base::DictionaryValue> rule( - DictionaryBuilder() - .Set("feature1", - ListBuilder() - .Append(DictionaryBuilder() - .Set("channel", "beta") - .Set("extension_types", - ListBuilder().Append("extension").Build()) - .Build()) - .Append(DictionaryBuilder() - .Set("channel", "beta") - .Set("extension_types", - ListBuilder() - .Append("legacy_packaged_app") - .Build()) - .Build()) - .Build()) - .Build()); - - std::unique_ptr<BaseFeatureProvider> provider( - new BaseFeatureProvider(*rule, CreateFeature<SimpleFeature>)); - - Feature* feature = provider->GetFeature("feature1"); - EXPECT_TRUE(feature); - - // Make sure both rules are applied correctly. - { - ScopedCurrentChannel current_channel(version_info::Channel::BETA); - EXPECT_EQ( - Feature::IS_AVAILABLE, - feature->IsAvailableToManifest("1", - Manifest::TYPE_EXTENSION, - Manifest::INVALID_LOCATION, - Feature::UNSPECIFIED_PLATFORM).result()); - EXPECT_EQ( - Feature::IS_AVAILABLE, - feature->IsAvailableToManifest("2", - Manifest::TYPE_LEGACY_PACKAGED_APP, - Manifest::INVALID_LOCATION, - Feature::UNSPECIFIED_PLATFORM).result()); - } - { - ScopedCurrentChannel current_channel(version_info::Channel::STABLE); - EXPECT_NE( - Feature::IS_AVAILABLE, - feature->IsAvailableToManifest("1", - Manifest::TYPE_EXTENSION, - Manifest::INVALID_LOCATION, - Feature::UNSPECIFIED_PLATFORM).result()); - EXPECT_NE( - Feature::IS_AVAILABLE, - feature->IsAvailableToManifest("2", - Manifest::TYPE_LEGACY_PACKAGED_APP, - Manifest::INVALID_LOCATION, - Feature::UNSPECIFIED_PLATFORM).result()); - } -} - -// Tests complex feature availability across channels. -TEST_F(ChromeChannelFeatureFilterTest, ComplexFeatureAvailability) { - std::unique_ptr<ComplexFeature::FeatureList> features( - new ComplexFeature::FeatureList()); - - // Rule: "extension", channel trunk. - std::unique_ptr<SimpleFeature> simple_feature(CreateFeature<SimpleFeature>()); - std::unique_ptr<base::DictionaryValue> rule( - DictionaryBuilder() - .Set("channel", "trunk") - .Set("extension_types", ListBuilder().Append("extension").Build()) - .Build()); - simple_feature->Parse(rule.get()); - features->push_back(std::move(simple_feature)); - - // Rule: "legacy_packaged_app", channel stable. - simple_feature.reset(CreateFeature<SimpleFeature>()); - rule = DictionaryBuilder() - .Set("channel", "stable") - .Set("extension_types", - ListBuilder().Append("legacy_packaged_app").Build()) - .Build(); - simple_feature->Parse(rule.get()); - features->push_back(std::move(simple_feature)); - - std::unique_ptr<ComplexFeature> feature( - new ComplexFeature(std::move(features))); - - // Test match 1st rule. - { - ScopedCurrentChannel current_channel(version_info::Channel::UNKNOWN); - EXPECT_EQ( - Feature::IS_AVAILABLE, - feature->IsAvailableToManifest("1", - Manifest::TYPE_EXTENSION, - Manifest::INVALID_LOCATION, - Feature::UNSPECIFIED_PLATFORM, - Feature::GetCurrentPlatform()).result()); - } - - // Test match 2nd rule. - { - ScopedCurrentChannel current_channel(version_info::Channel::BETA); - EXPECT_EQ( - Feature::IS_AVAILABLE, - feature->IsAvailableToManifest("2", - Manifest::TYPE_LEGACY_PACKAGED_APP, - Manifest::INVALID_LOCATION, - Feature::UNSPECIFIED_PLATFORM, - Feature::GetCurrentPlatform()).result()); - } - - // Test feature not available to extensions above channel unknown. - { - ScopedCurrentChannel current_channel(version_info::Channel::BETA); - EXPECT_NE( - Feature::IS_AVAILABLE, - feature->IsAvailableToManifest("1", - Manifest::TYPE_EXTENSION, - Manifest::INVALID_LOCATION, - Feature::UNSPECIFIED_PLATFORM, - Feature::GetCurrentPlatform()).result()); - } -} - -} // namespace extensions
diff --git a/chrome/common/extensions/features/feature_channel.cc b/chrome/common/extensions/features/feature_channel.cc deleted file mode 100644 index ba22f639..0000000 --- a/chrome/common/extensions/features/feature_channel.cc +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/common/extensions/features/feature_channel.h" - -#include "components/version_info/version_info.h" - -namespace { - -const version_info::Channel kDefaultChannel = version_info::Channel::STABLE; -version_info::Channel g_current_channel = kDefaultChannel; - -} // namespace - -namespace extensions { - -version_info::Channel GetCurrentChannel() { - return g_current_channel; -} - -void SetCurrentChannel(version_info::Channel channel) { - g_current_channel = channel; -} - -version_info::Channel GetDefaultChannel() { - return kDefaultChannel; -} - -ScopedCurrentChannel::ScopedCurrentChannel(version_info::Channel channel) - : original_channel_(version_info::Channel::UNKNOWN) { - original_channel_ = GetCurrentChannel(); - SetCurrentChannel(channel); -} - -ScopedCurrentChannel::~ScopedCurrentChannel() { - SetCurrentChannel(original_channel_); -} - -} // namespace extensions
diff --git a/chrome/common/extensions/features/feature_channel.h b/chrome/common/extensions/features/feature_channel.h deleted file mode 100644 index 9108dd4..0000000 --- a/chrome/common/extensions/features/feature_channel.h +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_COMMON_EXTENSIONS_FEATURES_FEATURE_CHANNEL_H_ -#define CHROME_COMMON_EXTENSIONS_FEATURES_FEATURE_CHANNEL_H_ - -#include "base/macros.h" - -namespace version_info { -enum class Channel; -} - -namespace extensions { - -// Gets the current channel as seen by the Feature system. -version_info::Channel GetCurrentChannel(); - -// Sets the current channel as seen by the Feature system. In the browser -// process this should be chrome::GetChannel(), and in the renderer this will -// need to come from an IPC. -void SetCurrentChannel(version_info::Channel channel); - -// Gets the default channel as seen by the Feature system. -version_info::Channel GetDefaultChannel(); - -// Scoped channel setter. Use for tests. -class ScopedCurrentChannel { - public: - explicit ScopedCurrentChannel(version_info::Channel channel); - ~ScopedCurrentChannel(); - - private: - version_info::Channel original_channel_; - - DISALLOW_COPY_AND_ASSIGN(ScopedCurrentChannel); -}; - -} // namespace extensions - -#endif // CHROME_COMMON_EXTENSIONS_FEATURES_FEATURE_CHANNEL_H_
diff --git a/chrome/common/extensions/features/feature_util.cc b/chrome/common/extensions/features/feature_util.cc index 44a3da0..b0c6b49 100644 --- a/chrome/common/extensions/features/feature_util.cc +++ b/chrome/common/extensions/features/feature_util.cc
@@ -4,8 +4,8 @@ #include "chrome/common/extensions/features/feature_util.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "components/version_info/version_info.h" +#include "extensions/common/features/feature_channel.h" namespace extensions { namespace feature_util {
diff --git a/chrome/common/extensions/manifest_handlers/automation.cc b/chrome/common/extensions/manifest_handlers/automation.cc index b53ab0c..113cc74d 100644 --- a/chrome/common/extensions/manifest_handlers/automation.cc +++ b/chrome/common/extensions/manifest_handlers/automation.cc
@@ -306,10 +306,9 @@ } AutomationInfo::AutomationInfo(bool desktop, - const URLPatternSet matches, + const URLPatternSet& matches, bool interact) - : desktop(desktop), matches(matches), interact(interact) { -} + : desktop(desktop), matches(matches), interact(interact) {} AutomationInfo::~AutomationInfo() { }
diff --git a/chrome/common/extensions/manifest_handlers/automation.h b/chrome/common/extensions/manifest_handlers/automation.h index afbaee1..eb1c1dc 100644 --- a/chrome/common/extensions/manifest_handlers/automation.h +++ b/chrome/common/extensions/manifest_handlers/automation.h
@@ -59,7 +59,7 @@ private: AutomationInfo(); - AutomationInfo(bool desktop, URLPatternSet matches, bool interact); + AutomationInfo(bool desktop, const URLPatternSet& matches, bool interact); static std::unique_ptr<api::manifest_types::Automation> AsManifestType( const AutomationInfo& info);
diff --git a/chrome/common/extensions/manifest_handlers/automation_unittest.cc b/chrome/common/extensions/manifest_handlers/automation_unittest.cc index f3769509..2a3650b 100644 --- a/chrome/common/extensions/manifest_handlers/automation_unittest.cc +++ b/chrome/common/extensions/manifest_handlers/automation_unittest.cc
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/common/extensions/manifest_handlers/automation.h" #include "chrome/common/extensions/manifest_tests/chrome_manifest_test.h" #include "chrome/grit/generated_resources.h" #include "components/version_info/version_info.h" #include "extensions/common/error_utils.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/permissions/permission_message_test_util.h" #include "extensions/common/permissions/permissions_data.h"
diff --git a/chrome/common/extensions/manifest_handlers/settings_overrides_handler_unittest.cc b/chrome/common/extensions/manifest_handlers/settings_overrides_handler_unittest.cc index c721db6..735fc19a 100644 --- a/chrome/common/extensions/manifest_handlers/settings_overrides_handler_unittest.cc +++ b/chrome/common/extensions/manifest_handlers/settings_overrides_handler_unittest.cc
@@ -9,10 +9,10 @@ #include "base/json/json_string_value_serializer.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "components/version_info/version_info.h" #include "extensions/common/error_utils.h" #include "extensions/common/extension.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/manifest_url_handlers.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/common/extensions/manifest_handlers/ui_overrides_handler_unittest.cc b/chrome/common/extensions/manifest_handlers/ui_overrides_handler_unittest.cc index 77e9ac6..5f75c03e 100644 --- a/chrome/common/extensions/manifest_handlers/ui_overrides_handler_unittest.cc +++ b/chrome/common/extensions/manifest_handlers/ui_overrides_handler_unittest.cc
@@ -9,10 +9,10 @@ #include "base/command_line.h" #include "base/json/json_string_value_serializer.h" #include "base/strings/utf_string_conversions.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "components/version_info/version_info.h" #include "extensions/common/error_utils.h" #include "extensions/common/extension.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/manifest_url_handlers.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/common/extensions/manifest_tests/chrome_manifest_test.h b/chrome/common/extensions/manifest_tests/chrome_manifest_test.h index 5722876..bfcd99b 100644 --- a/chrome/common/extensions/manifest_tests/chrome_manifest_test.h +++ b/chrome/common/extensions/manifest_tests/chrome_manifest_test.h
@@ -6,7 +6,7 @@ #define CHROME_COMMON_EXTENSIONS_MANIFEST_TESTS_CHROME_MANIFEST_TEST_H_ #include "base/macros.h" -#include "chrome/common/extensions/features/feature_channel.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/manifest_test.h" // Base class for unit tests that load manifest data from Chrome TEST_DATA_DIR.
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_background_unittest.cc b/chrome/common/extensions/manifest_tests/extension_manifests_background_unittest.cc index 78b5d61..0fba632 100644 --- a/chrome/common/extensions/manifest_tests/extension_manifests_background_unittest.cc +++ b/chrome/common/extensions/manifest_tests/extension_manifests_background_unittest.cc
@@ -6,12 +6,12 @@ #include "base/command_line.h" #include "base/values.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/common/extensions/manifest_tests/chrome_manifest_test.h" #include "components/version_info/version_info.h" #include "extensions/common/constants.h" #include "extensions/common/error_utils.h" #include "extensions/common/extension.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/manifest_handlers/background_info.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc index 5b7733a..97125507 100644 --- a/chrome/common/extensions/permissions/permission_set_unittest.cc +++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -18,13 +18,13 @@ #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension_test_util.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/common/extensions/permissions/chrome_permission_message_provider.h" #include "chrome/grit/generated_resources.h" #include "components/version_info/version_info.h" #include "extensions/common/error_utils.h" #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/permissions/permission_message_provider.h" #include "extensions/common/permissions/permission_message_test_util.h" #include "extensions/common/permissions/permission_message_util.h"
diff --git a/chrome/common/extensions/permissions/settings_override_permission_unittest.cc b/chrome/common/extensions/permissions/settings_override_permission_unittest.cc index a23e9bab..266bb88 100644 --- a/chrome/common/extensions/permissions/settings_override_permission_unittest.cc +++ b/chrome/common/extensions/permissions/settings_override_permission_unittest.cc
@@ -11,9 +11,9 @@ #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "build/build_config.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/common/extensions/manifest_tests/chrome_manifest_test.h" #include "components/version_info/version_info.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/permissions/permission_message_test_util.h" #include "extensions/common/permissions/permission_set.h"
diff --git a/chrome/common/features.gni b/chrome/common/features.gni index 5cc2a09..890cde1 100644 --- a/chrome/common/features.gni +++ b/chrome/common/features.gni
@@ -5,8 +5,10 @@ # This is the GN version of //chrome/chrome_features.gypi. # Please keep in sync! +import("//build/config/chromecast_build.gni") + declare_args() { - enable_google_now = !is_ios && !is_android + enable_google_now = !is_ios && !is_android && !is_chromecast # Whether the Java UI is being used (Java infobars and popups, Java native # settings and first run experience, sign-in etc.). @@ -19,9 +21,10 @@ use_vulcanize = true # Enables support for background apps. - enable_background = !is_ios && !is_android + enable_background = !is_ios && !is_android && !is_chromecast - enable_one_click_signin = is_win || is_mac || (is_linux && !is_chromeos) + enable_one_click_signin = + is_win || is_mac || (is_linux && !is_chromeos && !is_chromecast) # Set to true to bundle all the mash related mojo services into chrome. # Specify --mash to chrome to have chrome start the mash environment.
diff --git a/chrome/common/importer/firefox_importer_utils.cc b/chrome/common/importer/firefox_importer_utils.cc index 76a76a2..e1f5ada 100644 --- a/chrome/common/importer/firefox_importer_utils.cc +++ b/chrome/common/importer/firefox_importer_utils.cc
@@ -311,10 +311,11 @@ if (line == "[App]") { in_app_section = true; } else if (in_app_section) { - if (line.find(name_attr) == 0) { + if (base::StartsWith(line, name_attr, base::CompareCase::SENSITIVE)) { line.substr(name_attr.size()).CopyToString(&branding_name); break; - } else if (line.length() > 0 && line[0] == '[') { + } + if (line.length() > 0 && line[0] == '[') { // No longer in the [App] section. break; }
diff --git a/chrome/common/pepper_permission_util_unittest.cc b/chrome/common/pepper_permission_util_unittest.cc index 89f1dbd..1e6c9810 100644 --- a/chrome/common/pepper_permission_util_unittest.cc +++ b/chrome/common/pepper_permission_util_unittest.cc
@@ -9,11 +9,11 @@ #include <string> #include <utility> -#include "chrome/common/extensions/features/feature_channel.h" #include "components/crx_file/id_util.h" #include "components/version_info/version_info.h" #include "extensions/common/extension_builder.h" #include "extensions/common/extension_set.h" +#include "extensions/common/features/feature_channel.h" #include "testing/gtest/include/gtest/gtest.h" using chrome::IsExtensionOrSharedModuleWhitelisted;
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 356fc944..92fbcc3 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -888,6 +888,11 @@ // or dismissed HaTS (happiness-tracking) survey. const char kHatsLastInteractionTimestamp[] = "hats_last_interaction_timestamp"; +// A boolean pref. Indicates if we've already shown a notification to inform the +// current user about the quick unlock feature. +const char kQuickUnlockFeatureNotificationShown[] = + "quick_unlock_feature_notification_shown"; + // The salt and hash for the pin quick unlock mechanism. const char kQuickUnlockPinSalt[] = "quick_unlock.pin.salt"; const char kQuickUnlockPinSecret[] = "quick_unlock.pin.secret"; @@ -913,14 +918,6 @@ const char kRecentlySelectedEncoding[] = "profile.recently_selected_encodings"; // Clear Browsing Data dialog preferences. -const char kDeleteBrowsingHistory[] = "browser.clear_data.browsing_history"; -const char kDeleteDownloadHistory[] = "browser.clear_data.download_history"; -const char kDeleteCache[] = "browser.clear_data.cache"; -const char kDeleteCookies[] = "browser.clear_data.cookies"; -const char kDeletePasswords[] = "browser.clear_data.passwords"; -const char kDeleteFormData[] = "browser.clear_data.form_data"; -const char kDeleteHostedAppsData[] = "browser.clear_data.hosted_apps_data"; -const char kDeleteMediaLicenses[] = "browser.clear_data.media_licenses"; const char kLastClearBrowsingDataTime[] = "browser.last_clear_browsing_data_time"; const char kClearBrowsingDataHistoryNoticeShownTimes[] =
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 7a34ddd..86ba49a 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -299,17 +299,10 @@ extern const char kQuickUnlockPinSecret[]; extern const char kEolStatus[]; extern const char kEolNotificationDismissed[]; +extern const char kQuickUnlockFeatureNotificationShown[]; #endif // defined(OS_CHROMEOS) extern const char kShowHomeButton[]; extern const char kRecentlySelectedEncoding[]; -extern const char kDeleteBrowsingHistory[]; -extern const char kDeleteDownloadHistory[]; -extern const char kDeleteCache[]; -extern const char kDeleteCookies[]; -extern const char kDeletePasswords[]; -extern const char kDeleteFormData[]; -extern const char kDeleteHostedAppsData[]; -extern const char kDeleteMediaLicenses[]; extern const char kEnableContinuousSpellcheck[]; extern const char kSpeechRecognitionFilterProfanities[]; extern const char kSavingBrowserHistoryDisabled[];
diff --git a/chrome/common/search/ntp_logging_events.h b/chrome/common/search/ntp_logging_events.h index ba84f690..06aad77 100644 --- a/chrome/common/search/ntp_logging_events.h +++ b/chrome/common/search/ntp_logging_events.h
@@ -43,10 +43,15 @@ // Deleted: NTP_MOUSEOVER = 9 - // A NTP Tile has finished loading (successfully or failing). + // A NTP Tile has finished loading (successfully or failing). Logged only by + // the multi-iframe version of the NTP. NTP_TILE_LOADED = 10, - NTP_EVENT_TYPE_LAST = NTP_TILE_LOADED + // All NTP tiles have finished loading (successfully or failing). Logged only + // by the single-iframe version of the NTP. + NTP_ALL_TILES_LOADED = 11, + + NTP_EVENT_TYPE_LAST = NTP_ALL_TILES_LOADED }; // The source of an NTP tile.
diff --git a/chrome/install_static/BUILD.gn b/chrome/install_static/BUILD.gn index ec8ff5f6..a58ede4 100644 --- a/chrome/install_static/BUILD.gn +++ b/chrome/install_static/BUILD.gn
@@ -7,22 +7,19 @@ assert(is_win) -# This file only contains utility functions which must only depend on kernel32 -# and advapi32. Please don't add dependencies on other system libraries. +# This file only contains utility functions which must only depend on kernel32. +# Please don't add dependencies on other system libraries. static_library("install_static_util") { + public_deps = [ + "//chrome_elf/nt_registry:nt_registry", + ] + sources = [ "install_util.cc", "install_util.h", ] - deps = [ - "//base", - ] - - libs = [ - "kernel32.lib", - "advapi32.lib", - ] + libs = [ "kernel32.lib" ] configs += [ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
diff --git a/chrome/install_static/DEPS b/chrome/install_static/DEPS index 6eb75cd..23c5fa3 100644 --- a/chrome/install_static/DEPS +++ b/chrome/install_static/DEPS
@@ -1,10 +1,9 @@ include_rules = [ - # Nothing from base except the includes listed below. + # Nothing from base. "-base", - "+base/macros.h", - "+base/strings/string16.h", - "+build/build_config.h", # Nothing from chrome. "-chrome", "+chrome/install_static/install_util.h", + # All registry access should go through nt_registry. + "+chrome_elf/nt_registry/nt_registry.h", ]
diff --git a/chrome/install_static/install_util.cc b/chrome/install_static/install_util.cc index db7540d..1b96e8d 100644 --- a/chrome/install_static/install_util.cc +++ b/chrome/install_static/install_util.cc
@@ -12,8 +12,7 @@ #include <memory> #include <sstream> -#include "base/macros.h" -#include "build/build_config.h" +#include "chrome_elf/nt_registry/nt_registry.h" namespace install_static { @@ -36,7 +35,7 @@ #if defined(GOOGLE_CHROME_BUILD) const wchar_t kRegPathClientState[] = L"Software\\Google\\Update\\ClientState"; const wchar_t kRegPathClientStateMedium[] = -L"Software\\Google\\Update\\ClientStateMedium"; + L"Software\\Google\\Update\\ClientStateMedium"; const wchar_t kRegPathChromePolicy[] = L"SOFTWARE\\Policies\\Google\\Chrome"; #else const wchar_t kRegPathClientState[] = @@ -50,8 +49,7 @@ const wchar_t kUninstallArgumentsField[] = L"UninstallArguments"; const wchar_t kMetricsReportingEnabled[] = L"MetricsReportingEnabled"; -const wchar_t kAppGuidCanary[] = - L"{4ea16ac7-fd5a-47c3-875b-dbf4a2008c20}"; +const wchar_t kAppGuidCanary[] = L"{4ea16ac7-fd5a-47c3-875b-dbf4a2008c20}"; const wchar_t kAppGuidGoogleChrome[] = L"{8A69D345-D564-463c-AFF1-A69D9E530F96}"; const wchar_t kAppGuidGoogleBinaries[] = @@ -96,93 +94,11 @@ va_list args = {}; va_start(args, format_string); - vswprintf(buffer, arraysize(buffer), format_string, args); - OutputDebugString(buffer); + vswprintf(buffer, kMaxLogBufferSize, format_string, args); + OutputDebugStringW(buffer); va_end(args); } -// Reads a string value identified by |value_to_read| from the registry path -// under |key_path|. We look in HKLM or HKCU depending on whether the -// |system_install| parameter is true. -// Please note that this function only looks in the 32bit view of the registry. -bool ReadKeyValueString(bool system_install, const wchar_t* key_path, - const wchar_t* guid, const wchar_t* value_to_read, - base::string16* value_out) { - HKEY key = nullptr; - value_out->clear(); - - base::string16 full_key_path(key_path); - if (guid && *guid) { - full_key_path.append(1, L'\\'); - full_key_path.append(guid); - } - - if (::RegOpenKeyEx(system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, - full_key_path.c_str(), 0, - KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key) != - ERROR_SUCCESS) { - return false; - } - - const size_t kMaxStringLength = 1024; - wchar_t raw_value[kMaxStringLength] = {}; - DWORD size = sizeof(raw_value); - DWORD type = REG_SZ; - LONG result = ::RegQueryValueEx(key, value_to_read, 0, &type, - reinterpret_cast<LPBYTE>(raw_value), &size); - - if (result == ERROR_SUCCESS) { - if (type != REG_SZ || (size & 1) != 0) { - result = ERROR_NOT_SUPPORTED; - } else if (size == 0) { - *raw_value = L'\0'; - } else if (raw_value[size / sizeof(wchar_t) - 1] != L'\0') { - if ((size / sizeof(wchar_t)) < kMaxStringLength) - raw_value[size / sizeof(wchar_t)] = L'\0'; - else - result = ERROR_MORE_DATA; - } - } - - if (result == ERROR_SUCCESS) - *value_out = raw_value; - - ::RegCloseKey(key); - - return result == ERROR_SUCCESS; -} - -// Reads a DWORD value identified by |value_to_read| from the registry path -// under |key_path|. We look in HKLM or HKCU depending on whether the -// |system_install| parameter is true. -// Please note that this function only looks in the 32bit view of the registry. -bool ReadKeyValueDW(bool system_install, const wchar_t* key_path, - base::string16 guid, const wchar_t* value_to_read, - DWORD* value_out) { - HKEY key = nullptr; - *value_out = 0; - - base::string16 full_key_path(key_path); - full_key_path.append(1, L'\\'); - full_key_path.append(guid); - - if (::RegOpenKeyEx(system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, - full_key_path.c_str(), 0, - KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key) != - ERROR_SUCCESS) { - return false; - } - - DWORD size = sizeof(*value_out); - DWORD type = REG_DWORD; - LONG result = ::RegQueryValueEx(key, value_to_read, 0, &type, - reinterpret_cast<BYTE*>(value_out), &size); - - ::RegCloseKey(key); - - return result == ERROR_SUCCESS && size == sizeof(*value_out); -} - bool GetLanguageAndCodePageFromVersionResource(const char* version_resource, WORD* language, WORD* code_page) { @@ -196,10 +112,9 @@ LanguageAndCodePage* translation_info = nullptr; uint32_t data_size_in_bytes = 0; - BOOL query_result = VerQueryValue(version_resource, - L"\\VarFileInfo\\Translation", - reinterpret_cast<void**>(&translation_info), - &data_size_in_bytes); + BOOL query_result = VerQueryValueW( + version_resource, L"\\VarFileInfo\\Translation", + reinterpret_cast<void**>(&translation_info), &data_size_in_bytes); if (!query_result) return false; @@ -209,8 +124,8 @@ } bool GetValueFromVersionResource(const char* version_resource, - const base::string16& name, - base::string16* value_str) { + const std::wstring& name, + std::wstring* value_str) { assert(value_str); value_str->clear(); @@ -219,13 +134,13 @@ // in the version resource and return the value from the first match. WORD language = 0; WORD code_page = 0; - if (!GetLanguageAndCodePageFromVersionResource(version_resource, - &language, + if (!GetLanguageAndCodePageFromVersionResource(version_resource, &language, &code_page)) { return false; } - WORD lang_codepage[8] = {}; + const size_t array_size = 8; + WORD lang_codepage[array_size] = {}; size_t i = 0; // Use the language and codepage lang_codepage[i++] = language; @@ -240,20 +155,20 @@ lang_codepage[i++] = ::GetUserDefaultLangID(); lang_codepage[i++] = 1252; - static_assert((arraysize(lang_codepage) % 2) == 0, + static_assert((array_size % 2) == 0, "Language code page size should be a multiple of 2"); - assert(arraysize(lang_codepage) == i); + assert(array_size == i); - for (i = 0; i < arraysize(lang_codepage);) { + for (i = 0; i < array_size;) { wchar_t sub_block[MAX_PATH]; WORD language = lang_codepage[i++]; WORD code_page = lang_codepage[i++]; _snwprintf_s(sub_block, MAX_PATH, MAX_PATH, - L"\\StringFileInfo\\%04hx%04hx\\%ls", language, code_page, - name.c_str()); + L"\\StringFileInfo\\%04hx%04hx\\%ls", language, code_page, + name.c_str()); void* value = nullptr; uint32_t size = 0; - BOOL r = ::VerQueryValue(version_resource, sub_block, &value, &size); + BOOL r = ::VerQueryValueW(version_resource, sub_block, &value, &size); if (r && value) { value_str->assign(static_cast<wchar_t*>(value)); return true; @@ -263,14 +178,14 @@ } // Returns the executable path for the current process. -base::string16 GetCurrentProcessExePath() { +std::wstring GetCurrentProcessExePath() { wchar_t exe_path[MAX_PATH]; - if (GetModuleFileName(nullptr, exe_path, arraysize(exe_path)) == 0) - return base::string16(); + if (::GetModuleFileName(nullptr, exe_path, MAX_PATH) == 0) + return std::wstring(); return exe_path; } -bool RecursiveDirectoryCreate(const base::string16& full_path) { +bool RecursiveDirectoryCreate(const std::wstring& full_path) { // If the path exists, we've succeeded if it's a directory, failed otherwise. const wchar_t* full_path_str = full_path.c_str(); DWORD file_attributes = ::GetFileAttributes(full_path_str); @@ -289,9 +204,9 @@ // Attempt to create the parent recursively. This will immediately return // true if it already exists, otherwise will create all required parent // directories starting with the highest-level missing parent. - base::string16 parent_path; + std::wstring parent_path; std::size_t pos = full_path.find_last_of(L"/\\"); - if (pos != base::string16::npos) { + if (pos != std::wstring::npos) { parent_path = full_path.substr(0, pos); if (!RecursiveDirectoryCreate(parent_path)) { Trace(L"Failed to create one of the parent directories"); @@ -319,30 +234,41 @@ return true; } -bool GetCollectStatsConsentImpl(const base::string16& exe_path) { +bool GetCollectStatsConsentImpl(const std::wstring& exe_path) { bool enabled = true; - if (ReportingIsEnforcedByPolicy(&enabled)) - return enabled; + bool controlled_by_policy = ReportingIsEnforcedByPolicy(&enabled); + + if (controlled_by_policy && !enabled) + return false; bool system_install = IsSystemInstall(exe_path.c_str()); - base::string16 app_guid; + std::wstring app_guid; if (IsSxSChrome(exe_path.c_str())) { app_guid = kAppGuidCanary; } else { - app_guid = IsMultiInstall(system_install) ? kAppGuidGoogleBinaries : - kAppGuidGoogleChrome; + app_guid = IsMultiInstall(system_install) ? kAppGuidGoogleBinaries + : kAppGuidGoogleChrome; } DWORD out_value = 0; - if (system_install && - ReadKeyValueDW(system_install, kRegPathClientStateMedium, app_guid, - kRegValueUsageStats, &out_value)) { - return out_value == 1; - } - return ReadKeyValueDW(system_install, kRegPathClientState, app_guid, - kRegValueUsageStats, &out_value) && out_value == 1; + // If system_install, first try kRegPathClientStateMedium. + std::wstring full_key_path(kRegPathClientStateMedium); + full_key_path.append(1, L'\\'); + full_key_path.append(app_guid); + if (system_install && nt::QueryRegValueDWORD(nt::HKLM, full_key_path.c_str(), + kRegValueUsageStats, &out_value)) + return (out_value == 1); + + // Second, try kRegPathClientState. + full_key_path = kRegPathClientState; + full_key_path.append(1, L'\\'); + full_key_path.append(app_guid); + return (nt::QueryRegValueDWORD((system_install ? nt::HKLM : nt::HKCU), + full_key_path.c_str(), kRegValueUsageStats, + &out_value) && + out_value == 1); } // Returns true if the |source| string matches the |pattern|. The pattern @@ -355,8 +281,8 @@ // |source|. // |pattern_index| is the index of the current pattern character in |pattern| // which is matched with source. -bool MatchPatternImpl(const base::string16& source, - const base::string16& pattern, +bool MatchPatternImpl(const std::wstring& source, + const std::wstring& pattern, size_t source_index, size_t pattern_index) { if (source.empty() && pattern.empty()) @@ -392,8 +318,7 @@ // 1. We consider current character of source. // 2. We ignore current character of source. if (pattern[pattern_index] == L'*') { - return MatchPatternImpl(source, pattern, source_index + 1, - pattern_index) || + return MatchPatternImpl(source, pattern, source_index + 1, pattern_index) || MatchPatternImpl(source, pattern, source_index, pattern_index + 1); } return false; @@ -401,21 +326,22 @@ // Defines the type of whitespace characters typically found in strings. constexpr char kWhiteSpaces[] = " \t\n\r\f\v"; -constexpr base::char16 kWhiteSpaces16[] = L" \t\n\r\f\v"; +constexpr wchar_t kWhiteSpaces16[] = L" \t\n\r\f\v"; // Define specializations for white spaces based on the type of the string. -template<class StringType> StringType GetWhiteSpacesForType(); -template<> -base::string16 GetWhiteSpacesForType() { +template <class StringType> +StringType GetWhiteSpacesForType(); +template <> +std::wstring GetWhiteSpacesForType() { return kWhiteSpaces16; } -template<> +template <> std::string GetWhiteSpacesForType() { return kWhiteSpaces; } // Trim whitespaces from left & right -template<class StringType> +template <class StringType> void TrimT(StringType* str) { str->erase(str->find_last_not_of(GetWhiteSpacesForType<StringType>()) + 1); str->erase(0, str->find_first_not_of(GetWhiteSpacesForType<StringType>())); @@ -428,7 +354,7 @@ } // Tokenizes a string based on a single character delimiter. -template<class StringType> +template <class StringType> std::vector<StringType> TokenizeStringT( const StringType& str, typename StringType::value_type delimiter, @@ -446,22 +372,18 @@ } // namespace bool IsSxSChrome(const wchar_t* exe_path) { - return wcsstr(exe_path, L"Chrome SxS\\Application") != nullptr; + return ::wcsstr(exe_path, L"Chrome SxS\\Application") != nullptr; } bool IsSystemInstall(const wchar_t* exe_path) { wchar_t program_dir[MAX_PATH] = {}; - DWORD ret = ::GetEnvironmentVariable(L"PROGRAMFILES", program_dir, - arraysize(program_dir)); - if (ret && ret < arraysize(program_dir) && - !wcsnicmp(exe_path, program_dir, ret)) { + DWORD ret = ::GetEnvironmentVariable(L"PROGRAMFILES", program_dir, MAX_PATH); + if (ret && ret < MAX_PATH && !::wcsnicmp(exe_path, program_dir, ret)) { return true; } - ret = ::GetEnvironmentVariable(L"PROGRAMFILES(X86)", program_dir, - arraysize(program_dir)); - if (ret && ret < arraysize(program_dir) && - !wcsnicmp(exe_path, program_dir, ret)) { + ret = ::GetEnvironmentVariable(L"PROGRAMFILES(X86)", program_dir, MAX_PATH); + if (ret && ret < MAX_PATH && !::wcsnicmp(exe_path, program_dir, ret)) { return true; } @@ -469,48 +391,42 @@ } bool IsMultiInstall(bool is_system_install) { - base::string16 args; - if (!ReadKeyValueString(is_system_install, kRegPathClientState, - kAppGuidGoogleChrome, kUninstallArgumentsField, - &args)) { + std::wstring args; + + std::wstring full_key_path(kRegPathClientState); + full_key_path.append(1, L'\\'); + full_key_path.append(kAppGuidGoogleChrome); + if (!nt::QueryRegValueSZ((is_system_install ? nt::HKLM : nt::HKCU), + full_key_path.c_str(), kUninstallArgumentsField, + &args)) return false; - } - return args.find(L"--multi-install") != base::string16::npos; + + return (args.find(L"--multi-install") != std::wstring::npos); } bool GetCollectStatsConsent() { return GetCollectStatsConsentImpl(GetCurrentProcessExePath()); } -bool GetCollectStatsConsentForTesting(const base::string16& exe_path) { +bool GetCollectStatsConsentForTesting(const std::wstring& exe_path) { return GetCollectStatsConsentImpl(exe_path); } bool ReportingIsEnforcedByPolicy(bool* metrics_is_enforced_by_policy) { - HKEY key = nullptr; DWORD value = 0; - BYTE* value_bytes = reinterpret_cast<BYTE*>(&value); - DWORD size = sizeof(value); - DWORD type = REG_DWORD; - if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, kRegPathChromePolicy, 0, - KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) { - if (::RegQueryValueEx(key, kMetricsReportingEnabled, 0, &type, - value_bytes, &size) == ERROR_SUCCESS) { - *metrics_is_enforced_by_policy = value != 0; - } - ::RegCloseKey(key); - return size == sizeof(value); + // First, try HKLM. + if (nt::QueryRegValueDWORD(nt::HKLM, kRegPathChromePolicy, + kMetricsReportingEnabled, &value)) { + *metrics_is_enforced_by_policy = (value != 0); + return true; } - if (::RegOpenKeyEx(HKEY_CURRENT_USER, kRegPathChromePolicy, 0, - KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) { - if (::RegQueryValueEx(key, kMetricsReportingEnabled, 0, &type, - value_bytes, &size) == ERROR_SUCCESS) { - *metrics_is_enforced_by_policy = value != 0; - } - ::RegCloseKey(key); - return size == sizeof(value); + // Second, try HKCU. + if (nt::QueryRegValueDWORD(nt::HKCU, kRegPathChromePolicy, + kMetricsReportingEnabled, &value)) { + *metrics_is_enforced_by_policy = (value != 0); + return true; } return false; @@ -521,7 +437,7 @@ typedef bool (*IsSandboxedProcessFunc)(); IsSandboxedProcessFunc is_sandboxed_process_func = reinterpret_cast<IsSandboxedProcessFunc>( - GetProcAddress(GetModuleHandle(nullptr), "IsSandboxedProcess")); + ::GetProcAddress(::GetModuleHandle(nullptr), "IsSandboxedProcess")); if (is_sandboxed_process_func && is_sandboxed_process_func()) { g_process_type = ProcessType::NON_BROWSER_PROCESS; return; @@ -530,7 +446,7 @@ // TODO(robertshield): Drop the command line check when we drop support for // enabling chrome_elf in unsandboxed processes. const wchar_t* command_line = GetCommandLine(); - if (command_line && wcsstr(command_line, L"--type")) { + if (command_line && ::wcsstr(command_line, L"--type")) { g_process_type = ProcessType::NON_BROWSER_PROCESS; return; } @@ -543,7 +459,7 @@ return g_process_type == ProcessType::NON_BROWSER_PROCESS; } -bool GetDefaultUserDataDirectory(base::string16* result) { +bool GetDefaultUserDataDirectory(std::wstring* result) { static const wchar_t kLocalAppData[] = L"%LOCALAPPDATA%"; std::unique_ptr<wchar_t> user_data_dir_path; @@ -554,8 +470,7 @@ DWORD size = ::ExpandEnvironmentStrings(kLocalAppData, nullptr, 0); if (size) { user_data_dir_path.reset(new wchar_t[size]); - if (::ExpandEnvironmentStrings(kLocalAppData, - user_data_dir_path.get(), + if (::ExpandEnvironmentStrings(kLocalAppData, user_data_dir_path.get(), size) != size) { user_data_dir_path.reset(); } @@ -571,7 +486,7 @@ return false; } - base::string16 install_sub_directory = GetChromeInstallSubDirectory(); + std::wstring install_sub_directory = GetChromeInstallSubDirectory(); *result = user_data_dir_path.get(); if ((*result)[result->length() - 1] != L'\\') @@ -582,7 +497,7 @@ return true; } -bool GetDefaultCrashDumpLocation(base::string16* crash_dir) { +bool GetDefaultCrashDumpLocation(std::wstring* crash_dir) { // In order to be able to start crash handling very early, we do not rely on // chrome's PathService entries (for DIR_CRASH_DUMPS) being available on // Windows. See https://crbug.com/564398. @@ -597,16 +512,15 @@ return true; } - std::string GetEnvironmentString(const std::string& variable_name) { return UTF16ToUTF8(GetEnvironmentString16(UTF8ToUTF16(variable_name))); } -base::string16 GetEnvironmentString16(const base::string16& variable_name) { +std::wstring GetEnvironmentString16(const std::wstring& variable_name) { DWORD value_length = ::GetEnvironmentVariable(variable_name.c_str(), nullptr, 0); if (value_length == 0) - return base::string16(); + return std::wstring(); std::unique_ptr<wchar_t[]> value(new wchar_t[value_length]); ::GetEnvironmentVariable(variable_name.c_str(), value.get(), value_length); return value.get(); @@ -618,8 +532,8 @@ UTF8ToUTF16(new_value)); } -bool SetEnvironmentString16(const base::string16& variable_name, - const base::string16& new_value) { +bool SetEnvironmentString16(const std::wstring& variable_name, + const std::wstring& new_value) { return !!SetEnvironmentVariable(variable_name.c_str(), new_value.c_str()); } @@ -627,15 +541,15 @@ return HasEnvironmentVariable16(UTF8ToUTF16(variable_name)); } -bool HasEnvironmentVariable16(const base::string16& variable_name) { +bool HasEnvironmentVariable16(const std::wstring& variable_name) { return !!::GetEnvironmentVariable(variable_name.c_str(), nullptr, 0); } -bool GetExecutableVersionDetails(const base::string16& exe_path, - base::string16* product_name, - base::string16* version, - base::string16* special_build, - base::string16* channel_name) { +bool GetExecutableVersionDetails(const std::wstring& exe_path, + std::wstring* product_name, + std::wstring* version, + std::wstring* special_build, + std::wstring* channel_name) { assert(product_name); assert(version); assert(special_build); @@ -651,11 +565,10 @@ DWORD length = ::GetFileVersionInfoSize(exe_path.c_str(), &dummy); if (length) { std::unique_ptr<char> data(new char[length]); - if (::GetFileVersionInfo(exe_path.c_str(), dummy, length, - data.get())) { + if (::GetFileVersionInfo(exe_path.c_str(), dummy, length, data.get())) { GetValueFromVersionResource(data.get(), L"ProductVersion", version); - base::string16 official_build; + std::wstring official_build; GetValueFromVersionResource(data.get(), L"Official Build", &official_build); if (official_build != L"1") @@ -671,7 +584,7 @@ void GetChromeChannelName(bool is_per_user_install, bool add_modifier, - base::string16* channel_name) { + std::wstring* channel_name) { channel_name->clear(); // TODO(ananta) // http://crbug.com/604923 @@ -679,21 +592,23 @@ if (IsSxSChrome(GetCurrentProcessExePath().c_str())) { *channel_name = L"canary"; } else { - base::string16 value; + std::wstring value; bool channel_available = false; bool is_multi_install = IsMultiInstall(!is_per_user_install); if (is_multi_install) { - channel_available = ReadKeyValueString(!is_per_user_install, - kRegPathClientState, - kAppGuidGoogleBinaries, - kRegApField, - &value); + std::wstring full_key_path(kRegPathClientState); + full_key_path.append(1, L'\\'); + full_key_path.append(kAppGuidGoogleBinaries); + channel_available = + nt::QueryRegValueSZ(is_per_user_install ? nt::HKCU : nt::HKLM, + full_key_path.c_str(), kRegApField, &value); } else { - channel_available = ReadKeyValueString(!is_per_user_install, - kRegPathClientState, - kAppGuidGoogleChrome, - kRegApField, - &value); + std::wstring full_key_path(kRegPathClientState); + full_key_path.append(1, L'\\'); + full_key_path.append(kAppGuidGoogleChrome); + channel_available = + nt::QueryRegValueSZ(is_per_user_install ? nt::HKCU : nt::HKLM, + full_key_path.c_str(), kRegApField, &value); } if (channel_available) { static const wchar_t kChromeChannelBetaPattern[] = L"1?1-*"; @@ -706,8 +621,8 @@ // Empty channel names or those containing "stable" should be reported as // an empty string. Exceptions being if |add_modifier| is true and this // is a multi install. In that case we report the channel name as "-m". - if (value.empty() || (value.find(kChromeChannelStableExplicit) - != base::string16::npos)) { + if (value.empty() || + (value.find(kChromeChannelStableExplicit) != std::wstring::npos)) { if (add_modifier && is_multi_install) channel_name->append(L"-m"); return; @@ -741,44 +656,40 @@ // TODO(ananta) // Consider whether Chromium should connect to Google update to manage // updates. Should this be returning an empty string for Chromium builds?. - base::string16 update_version; - if (ReadKeyValueString(IsSystemInstall(GetCurrentProcessExePath().c_str()), - kRegPathGoogleUpdate, - nullptr, - kRegGoogleUpdateVersion, - &update_version)) { + std::wstring update_version; + if (nt::QueryRegValueSZ(nt::AUTO, kRegPathGoogleUpdate, + kRegGoogleUpdateVersion, &update_version)) return UTF16ToUTF8(update_version); - } + return std::string(); } -base::string16 GetChromeInstallSubDirectory() { +std::wstring GetChromeInstallSubDirectory() { #if defined(GOOGLE_CHROME_BUILD) - base::string16 result = kGoogleChromeInstallSubDir1; + std::wstring result = kGoogleChromeInstallSubDir1; result += L"\\"; result += kGoogleChromeInstallSubDir2; if (IsSxSChrome(GetCurrentProcessExePath().c_str())) result += kSxSSuffix; return result; #else - return base::string16(kChromiumInstallSubDir); + return std::wstring(kChromiumInstallSubDir); #endif } -base::string16 GetBrowserCrashDumpAttemptsRegistryPath() { - base::string16 registry_path = L"Software\\"; +std::wstring GetBrowserCrashDumpAttemptsRegistryPath() { + std::wstring registry_path = L"Software\\"; registry_path += GetChromeInstallSubDirectory(); registry_path += kBrowserCrashDumpMetricsSubKey; return registry_path; } -bool MatchPattern(const base::string16& source, - const base::string16& pattern) { - assert(pattern.find(L"**") == base::string16::npos); +bool MatchPattern(const std::wstring& source, const std::wstring& pattern) { + assert(pattern.find(L"**") == std::wstring::npos); return MatchPatternImpl(source, pattern, 0, 0); } -std::string UTF16ToUTF8(const base::string16& source) { +std::string UTF16ToUTF8(const std::wstring& source) { if (source.empty() || static_cast<int>(source.size()) > std::numeric_limits<int>::max()) { return std::string(); @@ -796,19 +707,19 @@ return result; } -base::string16 UTF8ToUTF16(const std::string& source) { +std::wstring UTF8ToUTF16(const std::string& source) { if (source.empty() || static_cast<int>(source.size()) > std::numeric_limits<int>::max()) { - return base::string16(); + return std::wstring(); } int size = ::MultiByteToWideChar(CP_UTF8, 0, &source[0], static_cast<int>(source.size()), nullptr, 0); - base::string16 result(size, L'\0'); + std::wstring result(size, L'\0'); if (::MultiByteToWideChar(CP_UTF8, 0, &source[0], static_cast<int>(source.size()), &result[0], size) != size) { assert(false); - return base::string16(); + return std::wstring(); } return result; } @@ -819,10 +730,10 @@ return TokenizeStringT<std::string>(str, delimiter, trim_spaces); } -std::vector<base::string16> TokenizeString16(const base::string16& str, - base::char16 delimiter, - bool trim_spaces) { - return TokenizeStringT<base::string16>(str, delimiter, trim_spaces); +std::vector<std::wstring> TokenizeString16(const std::wstring& str, + wchar_t delimiter, + bool trim_spaces) { + return TokenizeStringT<std::wstring>(str, delimiter, trim_spaces); } bool CompareVersionStrings(const std::string& version1,
diff --git a/chrome/install_static/install_util.h b/chrome/install_static/install_util.h index 102378fd..be2a99d4 100644 --- a/chrome/install_static/install_util.h +++ b/chrome/install_static/install_util.h
@@ -12,8 +12,6 @@ #include <string> #include <vector> -#include "base/strings/string16.h" - namespace install_static { enum class ProcessType { @@ -78,7 +76,7 @@ // Returns true if usage stats collecting is enabled for this user for the // executable passed in as |exe_path|. // Only used by tests. -bool GetCollectStatsConsentForTesting(const base::string16& exe_path); +bool GetCollectStatsConsentForTesting(const std::wstring& exe_path); // Returns true if if usage stats reporting is controlled by a mandatory // policy. |metrics_is_enforced_by_policy| will be set to true accordingly. @@ -100,32 +98,32 @@ // TODO(ananta) // http://crbug.com/604923 // Unify this with the Browser Distribution code. -bool GetDefaultUserDataDirectory(base::string16* result); +bool GetDefaultUserDataDirectory(std::wstring* result); // Populates |crash_dir| with the default crash dump location regardless of // whether DIR_USER_DATA or DIR_CRASH_DUMPS has been overridden. // TODO(ananta) // http://crbug.com/604923 // Unify this with the Browser Distribution code. -bool GetDefaultCrashDumpLocation(base::string16* crash_dir); +bool GetDefaultCrashDumpLocation(std::wstring* crash_dir); // Returns the contents of the specified |variable_name| from the environment // block of the calling process. Returns an empty string if the variable does // not exist. std::string GetEnvironmentString(const std::string& variable_name); -base::string16 GetEnvironmentString16(const base::string16& variable_name); +std::wstring GetEnvironmentString16(const std::wstring& variable_name); // Sets the environment variable identified by |variable_name| to the value // identified by |new_value|. bool SetEnvironmentString(const std::string& variable_name, const std::string& new_value); -bool SetEnvironmentString16(const base::string16& variable_name, - const base::string16& new_value); +bool SetEnvironmentString16(const std::wstring& variable_name, + const std::wstring& new_value); // Returns true if the environment variable identified by |variable_name| // exists. bool HasEnvironmentVariable(const std::string& variable_name); -bool HasEnvironmentVariable16(const base::string16& variable_name); +bool HasEnvironmentVariable16(const std::wstring& variable_name); // Gets the exe version details like the |product_name|, |version|, // |special_build|, |channel_name|, etc. Most of this information is read @@ -133,11 +131,11 @@ // TODO(ananta) // http://crbug.com/604923 // Unify this with the Browser Distribution code. -bool GetExecutableVersionDetails(const base::string16& exe_path, - base::string16* product_name, - base::string16* version, - base::string16* special_build, - base::string16* channel_name); +bool GetExecutableVersionDetails(const std::wstring& exe_path, + std::wstring* product_name, + std::wstring* version, + std::wstring* special_build, + std::wstring* channel_name); // Gets the channel name for the current Chrome process. // If |add_modifier| is true the channel name is returned with the modifier @@ -148,8 +146,7 @@ // Unify this with the Browser Distribution code. void GetChromeChannelName(bool is_per_user_install, bool add_modifier, - base::string16* channel_name); - + std::wstring* channel_name); // Returns the version of Google Update that is installed. // TODO(ananta) @@ -162,7 +159,7 @@ // TODO(ananta) // http://crbug.com/604923 // Unify this with the Browser Distribution code. -base::string16 GetChromeInstallSubDirectory(); +std::wstring GetChromeInstallSubDirectory(); // Returns the registry path where the browser crash dumps metrics need to be // written to. @@ -170,7 +167,7 @@ // http://crbug.com/604923 // Unify this with the version in // chrome\common\metrics_constants_util_win.cc -base::string16 GetBrowserCrashDumpAttemptsRegistryPath(); +std::wstring GetBrowserCrashDumpAttemptsRegistryPath(); // Returns true if the |source| string matches the |pattern|. The pattern // may contain wildcards like '?', which matches one character or a '*' @@ -178,12 +175,12 @@ // Please note that pattern matches the whole string. If you want to find // something in the middle of the string then you need to specify the pattern // as '*xyz*'. -bool MatchPattern(const base::string16& source, const base::string16& pattern); +bool MatchPattern(const std::wstring& source, const std::wstring& pattern); // UTF8 to UTF16 and vice versa conversion helpers. -base::string16 UTF8ToUTF16(const std::string& source); +std::wstring UTF8ToUTF16(const std::string& source); -std::string UTF16ToUTF8(const base::string16& source); +std::string UTF16ToUTF8(const std::wstring& source); // Tokenizes a string |str| based on single character delimiter. // The tokens are returned in a vector. The |trim_spaces| parameter indicates @@ -191,9 +188,9 @@ std::vector<std::string> TokenizeString(const std::string& str, char delimiter, bool trim_spaces); -std::vector<base::string16> TokenizeString16(const base::string16& str, - base::char16 delimiter, - bool trim_spaces); +std::vector<std::wstring> TokenizeString16(const std::wstring& str, + wchar_t delimiter, + bool trim_spaces); // Compares version strings of the form "X.X.X.X" and returns the result of the // comparison in the |result| parameter. The result is as below:
diff --git a/chrome/install_static/install_util_unittest.cc b/chrome/install_static/install_util_unittest.cc index 13131d1..ebb7a802 100644 --- a/chrome/install_static/install_util_unittest.cc +++ b/chrome/install_static/install_util_unittest.cc
@@ -70,7 +70,7 @@ // TokenizeString16 tests. // Test if the string is tokenized correctly with all tokens stripped of // leading and trailing spaces. - std::vector<base::string16> results16 = + std::vector<std::wstring> results16 = TokenizeString16(L"un |deux\t|trois\n|quatre", L'|', true); ASSERT_EQ(4u, results16.size()); EXPECT_THAT(results16, ElementsAre(L"un", L"deux", L"trois", L"quatre")); @@ -194,4 +194,4 @@ EXPECT_EQ(value, "bar"); } -} // namespace install_static \ No newline at end of file +} // namespace install_static
diff --git a/chrome/installer/gcapi_mac/gcapi.mm b/chrome/installer/gcapi_mac/gcapi.mm index 798a539..25e0497c 100644 --- a/chrome/installer/gcapi_mac/gcapi.mm +++ b/chrome/installer/gcapi_mac/gcapi.mm
@@ -312,10 +312,6 @@ int GoogleChromeCompatibilityCheck(unsigned* reasons) { unsigned local_reasons = 0; @autoreleasepool { - passwd* user = GetRealUserId(); - if (!user) - return GCCC_ERROR_ACCESSDENIED; - if (!IsOSXVersionSupported()) local_reasons |= GCCC_ERROR_OSNOTSUPPORTED; @@ -326,7 +322,10 @@ local_reasons |= GCCC_ERROR_ACCESSDENIED; } - if (FindChromeTicket(kUserTicket, user, NULL)) + passwd* user = GetRealUserId(); + if (!user) + local_reasons |= GCCC_ERROR_ACCESSDENIED; + else if (FindChromeTicket(kUserTicket, user, NULL)) local_reasons |= GCCC_ERROR_ALREADYPRESENT; if ([[NSFileManager defaultManager] fileExistsAtPath:kChromeInstallPath]) @@ -337,8 +336,8 @@ isWritableFileAtPath:@"/Applications"]) local_reasons |= GCCC_ERROR_ACCESSDENIED; } - } + if (reasons != NULL) *reasons = local_reasons; return local_reasons == 0;
diff --git a/chrome/installer/mac/BUILD.gn b/chrome/installer/mac/BUILD.gn index 837f538..022ee64 100644 --- a/chrome/installer/mac/BUILD.gn +++ b/chrome/installer/mac/BUILD.gn
@@ -10,6 +10,7 @@ public_deps = [ ":copies", ":make_signers", + "app:downloader", ] }
diff --git a/chrome/installer/mac/app/BUILD.gn b/chrome/installer/mac/app/BUILD.gn new file mode 100644 index 0000000..aa2123f --- /dev/null +++ b/chrome/installer/mac/app/BUILD.gn
@@ -0,0 +1,17 @@ +# 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. + +executable("downloader") { + sources = [ + "DownloadDelegate.m", + "Downloader.m", + "NetworkCommunication.m", + "OmahaCommunication.m", + "OmahaXMLParser.m", + "OmahaXMLRequest.m", + "SystemInfo.m", + "main.m", + ] + libs = [ "Foundation.framework" ] +}
diff --git a/chrome/installer/mac/app/DownloadDelegate.h b/chrome/installer/mac/app/DownloadDelegate.h new file mode 100644 index 0000000..23cd5fe --- /dev/null +++ b/chrome/installer/mac/app/DownloadDelegate.h
@@ -0,0 +1,14 @@ +// 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_INSTALLER_MAC_APP_DOWNLOADDELEGATE_H_ +#define CHROME_INSTALLER_MAC_APP_DOWNLOADDELEGATE_H_ + +#import <Foundation/Foundation.h> + +@interface DownloadDelegate : NSObject<NSURLSessionDownloadDelegate> + +@end + +#endif // CHROME_INSTALLER_MAC_APP_DOWNLOADDELEGATE_H_
diff --git a/chrome/installer/mac/app/DownloadDelegate.m b/chrome/installer/mac/app/DownloadDelegate.m new file mode 100644 index 0000000..ff41c1f7 --- /dev/null +++ b/chrome/installer/mac/app/DownloadDelegate.m
@@ -0,0 +1,42 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <assert.h> + +#import "DownloadDelegate.h" +#import "Downloader.h" + +@implementation DownloadDelegate : NSObject + +// Skeleton of delegate method to provide download progress updates. +// TODO: Make use of (totalBytesWritten/totalBytesExpectedToWrite)*100 +// to generate download progress percentage. +- (void)URLSession:(NSURLSession*)session + downloadTask:(NSURLSessionDownloadTask*)downloadTask + didWriteData:(int64_t)bytesWritten + totalBytesWritten:(int64_t)totalBytesWritten + totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { +} + +// Delegate method to move downloaded disk image to user's Download directory. +- (void)URLSession:(NSURLSession*)session + downloadTask:(NSURLSessionDownloadTask*)downloadTask + didFinishDownloadingToURL:(NSURL*)location { + assert([location isFileURL]); + NSFileManager* manager = [[NSFileManager alloc] init]; + NSURL* downloadsDirectory = + [[NSURL alloc] initFileURLWithPath:[Downloader getDownloadsFilePath]]; + if ([manager fileExistsAtPath:location.path]) { + [manager copyItemAtURL:location toURL:downloadsDirectory error:nil]; + } else { + // TODO: Error Handling + } +} + +- (void)URLSession:(NSURLSession*)session + task:(NSURLSessionTask*)task + didCompleteWithError:(NSError*)error { + // TODO: Error Handling +} +@end
diff --git a/chrome/installer/mac/app/Downloader.h b/chrome/installer/mac/app/Downloader.h new file mode 100644 index 0000000..03c84fa7 --- /dev/null +++ b/chrome/installer/mac/app/Downloader.h
@@ -0,0 +1,24 @@ +// 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_INSTALLER_MAC_APP_DOWNLOADER_H_ +#define CHROME_INSTALLER_MAC_APP_DOWNLOADER_H_ + +#import <Foundation/Foundation.h> + +@interface Downloader : NSObject<NSXMLParserDelegate> + +// Returns a path to a user's home download folder. ++ (NSString*)getDownloadsFilePath; + +- (NSMutableArray*)appendFilename:(NSString*)filename + toURLs:(NSArray*)incompleteURLs; + +// Takes an NSData with a response XML from Omaha and writes the latest +// version of chrome to the user's download directory. +- (BOOL)downloadChromeImageToDownloadsDirectory:(NSData*)omahaResponseXML; + +@end + +#endif // CHROME_INSTALLER_MAC_APP_DOWNLOADER_H_
diff --git a/chrome/installer/mac/app/Downloader.m b/chrome/installer/mac/app/Downloader.m new file mode 100644 index 0000000..857897a --- /dev/null +++ b/chrome/installer/mac/app/Downloader.m
@@ -0,0 +1,84 @@ +// 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 <Foundation/Foundation.h> + +#import "DownloadDelegate.h" +#import "Downloader.h" +#import "NetworkCommunication.h" +#import "OmahaXMLParser.h" + +@implementation Downloader + +// TODO: make this overrideable with commandline argument? or enviro variable ++ (NSString*)getDownloadsFilePath { + NSArray* downloadPaths = NSSearchPathForDirectoriesInDomains( + NSDownloadsDirectory, NSUserDomainMask, YES); + NSString* filePathToDownloads = [downloadPaths objectAtIndex:0]; + NSArray* filenameComposition = @[ filePathToDownloads, @"GoogleChrome.dmg" ]; + NSString* completeFilePath = + [NSString pathWithComponents:filenameComposition]; + return completeFilePath; +} + +// The URLs extracted from parseXML are incomplete and need the filename (which +// is the same for all the links) appended to the end. Iterates through +// chromeIncompleteDownloadURLs_ and appends chromeImageFilename_ to each URL. +- (NSMutableArray*)appendFilename:(NSString*)filename + toURLs:(NSArray*)incompleteURLs { + NSMutableArray* completeURLs = [[NSMutableArray alloc] init]; + + for (NSString* URL in incompleteURLs) { + [completeURLs addObject:[NSURL URLWithString:filename + relativeToURL:[NSURL URLWithString:URL]]]; + } + return completeURLs; +} + +// Extract URLs and the filename from the omahaResponseXML. Then complete the +// URLs by appending filename and returns the first complete URL. +- (NSURL*)getChromeImageURLFromOmahaResponse:(NSData*)omahaResponseXML { + NSError* err = nil; + + OmahaXMLParser* parser = [[OmahaXMLParser alloc] init]; + NSArray* incompleteURLs = [parser parseXML:omahaResponseXML error:&err]; + + if ([incompleteURLs count] < 1) { + // TODO: Error handling and implement way to verify URL is working. Error + // information saved in "err". + } + + NSMutableArray* completeURLs = + [self appendFilename:parser.chromeImageFilename toURLs:incompleteURLs]; + + NSURL* chromeURL = [completeURLs firstObject]; + return chromeURL; +} + +// Downloads contents of chromeURL to downloads folders and delegates the work +// to the DownloadDelegate class. +- (BOOL)writeChromeImageToDownloadsDirectory:(NSURL*)chromeURL { + DownloadDelegate* delegate = [[DownloadDelegate alloc] init]; + NetworkCommunication* downloadTask = + [[NetworkCommunication alloc] initWithDelegate:delegate]; + + // TODO: What if file already exists? + [downloadTask createRequestWithUrlAsString:[chromeURL absoluteString] + andXMLBody:nil]; + [downloadTask sendDownloadRequest]; + + NSFileManager* manager = [[NSFileManager alloc] init]; + return [manager fileExistsAtPath:[Downloader getDownloadsFilePath]]; +} + +// Pieces together the getting the URL portion and downloading the contents of +// URL portion. +- (BOOL)downloadChromeImageToDownloadsDirectory:(NSData*)omahaResponseXML { + NSURL* chromeURL = [self getChromeImageURLFromOmahaResponse:omahaResponseXML]; + BOOL writeWasSuccessful = + [self writeChromeImageToDownloadsDirectory:chromeURL]; + return writeWasSuccessful; +} + +@end
diff --git a/chrome/installer/mac/app/NetworkCommunication.h b/chrome/installer/mac/app/NetworkCommunication.h new file mode 100644 index 0000000..803c2db25 --- /dev/null +++ b/chrome/installer/mac/app/NetworkCommunication.h
@@ -0,0 +1,36 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_INSTALLER_MAC_APP_NETWORKCOMMUNICATION_H_ +#define CHROME_INSTALLER_MAC_APP_NETWORKCOMMUNICATION_H_ + +#import <Foundation/Foundation.h> + +typedef void (^DataTaskCompletionHandler)(NSData*, NSURLResponse*, NSError*); +typedef void (^DownloadTaskCompletionHandler)(NSURL*, NSURLResponse*, NSError*); + +@interface NetworkCommunication : NSObject + +@property(nonatomic, copy) NSMutableURLRequest* request; +@property(nonatomic, copy) NSURLSession* session; +@property(nonatomic, copy) DataTaskCompletionHandler dataResponseHandler; +@property(nonatomic, copy) + DownloadTaskCompletionHandler downloadResponseHandler; + +- (id)init; +- (id)initWithDelegate:(id)delegate; + +// Creates a mutable URLRequest object as an instance variable, then returns it +// so the caller has a chance to edit it before sending the request out. +- (NSMutableURLRequest*)createRequestWithUrlAsString:(NSString*)urlString + andXMLBody:(NSXMLDocument*)body; +// Adds a data task to the run loop using the request instance variable. +- (void)sendDataRequestWithCompletionHandler: + (DataTaskCompletionHandler)completionHandler; +// Adds a download task to the run loop using the request instance variable. +- (void)sendDownloadRequest; + +@end + +#endif // CHROME_INSTALLER_MAC_APP_NETWORKCOMMUNICATION_H_
diff --git a/chrome/installer/mac/app/NetworkCommunication.m b/chrome/installer/mac/app/NetworkCommunication.m new file mode 100644 index 0000000..fdee745 --- /dev/null +++ b/chrome/installer/mac/app/NetworkCommunication.m
@@ -0,0 +1,78 @@ +// 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 <Foundation/Foundation.h> + +#import "NetworkCommunication.h" + +@interface NSURLSession (PartialAvailability) +- (NSURLSessionDataTask*)dataTaskWithRequest:(NSURLRequest*)request + completionHandler: + (void (^)(NSData* data, + NSURLResponse* response, + NSError* error))completionHandler; +- (NSURLSessionDownloadTask*) +downloadTaskWithRequest:(NSURLRequest*)request + completionHandler:(void (^)(NSURL* location, + NSURLResponse* response, + NSError* error))completionHandler; +@end + +@implementation NetworkCommunication : NSObject + +@synthesize session = session_; +@synthesize request = request_; +@synthesize dataResponseHandler = dataResponseHandler_; +@synthesize downloadResponseHandler = downloadResponseHandler_; + +- (id)init { + return [self initWithDelegate:nil]; +} + +- (id)initWithDelegate:(id)delegate { + if ((self = [super init])) { + NSURLSessionConfiguration* sessionConfig = + [NSURLSessionConfiguration defaultSessionConfiguration]; + session_ = [NSURLSession sessionWithConfiguration:sessionConfig + delegate:delegate + delegateQueue:nil]; + } + return self; +} + +- (NSMutableURLRequest*)createRequestWithUrlAsString:(NSString*)urlString + andXMLBody:(NSXMLDocument*)body { + NSURL* requestURL = [NSURL URLWithString:urlString]; + request_ = [NSMutableURLRequest requestWithURL:requestURL]; + if (body) { + [request_ addValue:@"text/xml" forHTTPHeaderField:@"Content-Type"]; + NSData* requestBody = + [[body XMLString] dataUsingEncoding:NSUTF8StringEncoding]; + request_.HTTPBody = requestBody; + } + return request_; +} + +- (void)sendDataRequestWithCompletionHandler: + (DataTaskCompletionHandler)completionHandler { + dataResponseHandler_ = completionHandler; + NSURLSessionDataTask* dataTask = + [session_ dataTaskWithRequest:request_ + completionHandler:dataResponseHandler_]; + + [dataTask resume]; +} + +- (void)sendDownloadRequest { + NSURLSessionDownloadTask* downloadTask; + if (downloadResponseHandler_) { + downloadTask = [session_ downloadTaskWithRequest:request_ + completionHandler:downloadResponseHandler_]; + } else { + downloadTask = [session_ downloadTaskWithRequest:request_]; + } + [downloadTask resume]; +} + +@end
diff --git a/chrome/installer/mac/app/OWNERS b/chrome/installer/mac/app/OWNERS new file mode 100644 index 0000000..6694e7b --- /dev/null +++ b/chrome/installer/mac/app/OWNERS
@@ -0,0 +1,4 @@ +ellyjones@chromium.org +ivanhernandez@google.com +mark@chromium.org +zengster@google.com \ No newline at end of file
diff --git a/chrome/installer/mac/app/OmahaCommunication.h b/chrome/installer/mac/app/OmahaCommunication.h new file mode 100644 index 0000000..54a377f --- /dev/null +++ b/chrome/installer/mac/app/OmahaCommunication.h
@@ -0,0 +1,27 @@ +// 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_INSTALLER_MAC_APP_OMAHACOMMUNICATION_H_ +#define CHROME_INSTALLER_MAC_APP_OMAHACOMMUNICATION_H_ + +#import <Foundation/Foundation.h> + +#include "NetworkCommunication.h" + +typedef void (^OmahaRequestCompletionHandler)(NSData*, NSError*); + +@interface OmahaCommunication : NSObject + +@property(nonatomic, copy) NSXMLDocument* requestXMLBody; +@property(nonatomic, copy) NetworkCommunication* sessionHelper; + +- (id)init; +- (id)initWithBody:(NSXMLDocument*)xmlBody; + +// Sends the request created using the session helper. +- (void)sendRequestWithBlock:(OmahaRequestCompletionHandler)block; + +@end + +#endif // CHROME_INSTALLER_MAC_APP_OMAHACOMMUNICATION_H_
diff --git a/chrome/installer/mac/app/OmahaCommunication.m b/chrome/installer/mac/app/OmahaCommunication.m new file mode 100644 index 0000000..4232890 --- /dev/null +++ b/chrome/installer/mac/app/OmahaCommunication.m
@@ -0,0 +1,59 @@ +// 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 <Foundation/Foundation.h> + +#include "OmahaCommunication.h" + +@implementation OmahaCommunication : NSObject + +@synthesize requestXMLBody = requestXMLBody_; +@synthesize sessionHelper = sessionHelper_; + +- (id)init { + return [self initWithBody:[[NSXMLDocument alloc] init]]; +} + +- (id)initWithBody:(NSXMLDocument*)xmlBody { + if ((self = [super init])) { + sessionHelper_ = [[NetworkCommunication alloc] init]; + requestXMLBody_ = xmlBody; + [self createOmahaRequest]; + } + return self; +} + +- (NSURLRequest*)createOmahaRequest { + // TODO: turn this string to a comand-line flag + NSMutableURLRequest* request = [sessionHelper_ + createRequestWithUrlAsString:@"https://tools.google.com/service/update2" + andXMLBody:requestXMLBody_]; + request.HTTPMethod = @"POST"; + return request; +} + +- (void)sendRequestWithBlock:(OmahaRequestCompletionHandler)block { + DataTaskCompletionHandler cHandler = + ^(NSData* _Nullable data, NSURLResponse* _Nullable response, + NSError* _Nullable error) { + if (error) { + NSLog(@"%@", error); + block(data, error); + return; + } + + NSHTTPURLResponse* HTTPResponse = (NSHTTPURLResponse*)response; + if (HTTPResponse.statusCode != 200) { + // TODO: make these logging statements more rare + NSLog(@"HTTP response: %ld", (unsigned long)HTTPResponse.statusCode); + } + + block(data, error); + + }; + + [sessionHelper_ sendDataRequestWithCompletionHandler:cHandler]; +} + +@end \ No newline at end of file
diff --git a/chrome/installer/mac/app/OmahaXMLParser.h b/chrome/installer/mac/app/OmahaXMLParser.h new file mode 100644 index 0000000..1d686db --- /dev/null +++ b/chrome/installer/mac/app/OmahaXMLParser.h
@@ -0,0 +1,25 @@ +// 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_INSTALLER_MAC_APP_OMAHAXMLPARSER_H_ +#define CHROME_INSTALLER_MAC_APP_OMAHAXMLPARSER_H_ + +#import <Foundation/Foundation.h> + +@interface OmahaXMLParser : NSObject<NSXMLParserDelegate> { + NSMutableArray* chromeIncompleteDownloadURLs_; + NSString* chromeImageFilename_; +} + +- (NSMutableArray*)chromeIncompleteDownloadURLs; + +- (NSString*)chromeImageFilename; + +// Parses an XML document and extracts all the URL's it finds as well as the +// filename. Adds each URL into the array chromeIncompleteDownloadURLs_. +- (NSArray*)parseXML:(NSData*)omahaResponseXML error:(NSError**)error; + +@end + +#endif // CHROME_INSTALLER_MAC_APP_OMAHAXMLPARSER_H_
diff --git a/chrome/installer/mac/app/OmahaXMLParser.m b/chrome/installer/mac/app/OmahaXMLParser.m new file mode 100644 index 0000000..4986e00 --- /dev/null +++ b/chrome/installer/mac/app/OmahaXMLParser.m
@@ -0,0 +1,54 @@ +// 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 "OmahaXMLParser.h" + +@implementation OmahaXMLParser + +- (NSMutableArray*)chromeIncompleteDownloadURLs { + return chromeIncompleteDownloadURLs_; +} + +- (NSString*)chromeImageFilename { + return chromeImageFilename_; +} + +// Sets up instance of NSXMLParser and calls on delegate methods to do actual +// parsing work. +- (NSArray*)parseXML:(NSData*)omahaResponseXML error:(NSError**)error { + NSXMLParser* parser = [[NSXMLParser alloc] initWithData:omahaResponseXML]; + [parser setDelegate:self]; + BOOL success = [parser parse]; + if (!success) { + *error = [parser parserError]; + } + + return chromeIncompleteDownloadURLs_; +} + +// Method implementation for XMLParserDelegate. +// Searches the XML data for the tag "URL" and the subsequent "codebase" +// attribute that indicates a URL follows. Copies each URL into an array. +// Note that the URLs in the XML file are incomplete. They need the filename +// appended to end. The second if statement checks for the tag "package" which +// contains the filename we need to complete the URLs. +- (void)parser:(NSXMLParser*)parser + didStartElement:(NSString*)elementName + namespaceURI:(NSString*)namespaceURI + qualifiedName:(NSString*)qName + attributes:(NSDictionary*)attributeDict { + if ([elementName isEqualToString:@"url"]) { + if (!chromeIncompleteDownloadURLs_) { + chromeIncompleteDownloadURLs_ = [[NSMutableArray alloc] init]; + } + NSString* extractedURL = [attributeDict objectForKey:@"codebase"]; + [chromeIncompleteDownloadURLs_ addObject:extractedURL]; + } + if ([elementName isEqualToString:@"package"]) { + chromeImageFilename_ = [[NSString alloc] + initWithFormat:@"%@", [attributeDict objectForKey:@"name"]]; + } +} + +@end
diff --git a/chrome/installer/mac/app/OmahaXMLRequest.h b/chrome/installer/mac/app/OmahaXMLRequest.h new file mode 100644 index 0000000..a70a4b2 --- /dev/null +++ b/chrome/installer/mac/app/OmahaXMLRequest.h
@@ -0,0 +1,17 @@ +// 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_INSTALLER_MAC_APP_OMAHAXMLREQUEST_H_ +#define CHROME_INSTALLER_MAC_APP_OMAHAXMLREQUEST_H_ + +#import <Foundation/Foundation.h> + +@interface OmahaXMLRequest : NSObject + +// Creates the body of the request being prepared to send to Omaha. ++ (NSXMLDocument*)createXMLRequestBody; + +@end + +#endif // CHROME_INSTALLER_MAC_APP_OMAHAXMLREQUEST_H_
diff --git a/chrome/installer/mac/app/OmahaXMLRequest.m b/chrome/installer/mac/app/OmahaXMLRequest.m new file mode 100644 index 0000000..8dad342 --- /dev/null +++ b/chrome/installer/mac/app/OmahaXMLRequest.m
@@ -0,0 +1,74 @@ +// 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 <Foundation/Foundation.h> + +#include "OmahaXMLRequest.h" +#include "SystemInfo.h" + +@implementation OmahaXMLRequest : NSObject + ++ (NSXMLElement*)createElementWithName:(NSString*)name { + return [[NSXMLElement alloc] initWithName:name]; +} + ++ (void)forElement:(NSXMLElement*)element + AddAttribute:(NSString*)attribute + WithValue:(NSString*)value { + [element + addAttribute:[NSXMLNode attributeWithName:attribute stringValue:value]]; +} + +// borisv@ indicated that the OS version, platform, appid, and version are the +// user attributes that Omaha actually looks at. The other parameters are useful +// for logging purposes but otherwise not directly used. ++ (NSXMLDocument*)createXMLRequestBody { + // NOTE: might be a good idea in the future to add a version# for this + // installer + NSString* protocol = @"3.0"; + + NSString* platform = @"mac"; + NSString* operatingSystem = [SystemInfo getOSVersion]; + NSString* architecture = [SystemInfo getArch]; + NSString* plat_arch = + [NSString stringWithFormat:@"%@_%@", operatingSystem, architecture]; + + NSString* appid = @"com.google.Chrome"; + NSString* version = @"0.0.0.0"; + NSString* language = @"en-us"; + + NSXMLElement* root = [OmahaXMLRequest createElementWithName:@"request"]; + [OmahaXMLRequest forElement:root AddAttribute:@"protocol" WithValue:protocol]; + + NSXMLElement* osChild = [OmahaXMLRequest createElementWithName:@"os"]; + [OmahaXMLRequest forElement:osChild + AddAttribute:@"platform" + WithValue:platform]; + [OmahaXMLRequest forElement:osChild + AddAttribute:@"version" + WithValue:operatingSystem]; + [OmahaXMLRequest forElement:osChild + AddAttribute:@"arch" + WithValue:architecture]; + [OmahaXMLRequest forElement:osChild AddAttribute:@"sp" WithValue:plat_arch]; + [root addChild:osChild]; + + NSXMLElement* appChild = [OmahaXMLRequest createElementWithName:@"app"]; + [OmahaXMLRequest forElement:appChild AddAttribute:@"appid" WithValue:appid]; + [OmahaXMLRequest forElement:appChild + AddAttribute:@"version" + WithValue:version]; + [OmahaXMLRequest forElement:appChild AddAttribute:@"lang" WithValue:language]; + [root addChild:appChild]; + + NSXMLElement* updateChildChild = + [OmahaXMLRequest createElementWithName:@"updatecheck"]; + [appChild addChild:updateChildChild]; + + NSXMLDocument* requestXMLDocument = + [[NSXMLDocument alloc] initWithRootElement:root]; + return requestXMLDocument; +} + +@end
diff --git a/chrome/installer/mac/app/SystemInfo.h b/chrome/installer/mac/app/SystemInfo.h new file mode 100644 index 0000000..431f9cde --- /dev/null +++ b/chrome/installer/mac/app/SystemInfo.h
@@ -0,0 +1,28 @@ +// 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_INSTALLER_MAC_APP_SYSTEMINFO_H_ +#define CHROME_INSTALLER_MAC_APP_SYSTEMINFO_H_ + +#if !defined(__x86_64__) +#error "Your machine's system architecture may not be compatible with Chrome." +#endif + +#import <Foundation/Foundation.h> + +@interface SystemInfo : NSObject +// Gets the CPU architecture type of the client's system, which will be used +// when crafting the query to Omaha. This will return either "x84_64h" for +// systems running on Intel Haswell chips, "x86_64" for other Intel machines, +// or strings representing other CPU types ("amd", "pentium", and "i686", for +// example, are all valid). ++ (NSString*)getArch; + +// Gets the operating system version of the client. This function may return +// values such as "10.11" or "10.10.5". ++ (NSString*)getOSVersion; + +@end + +#endif // CHROME_INSTALLER_MAC_APP_SYSTEMINFO_H_
diff --git a/chrome/installer/mac/app/SystemInfo.m b/chrome/installer/mac/app/SystemInfo.m new file mode 100644 index 0000000..66e3cf8 --- /dev/null +++ b/chrome/installer/mac/app/SystemInfo.m
@@ -0,0 +1,26 @@ +// 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 <mach-o/arch.h> + +#import "SystemInfo.h" + +@implementation SystemInfo + ++ (NSString*)getArch { + const NXArchInfo* arch = NXGetLocalArchInfo(); + NSString* archName = [NSString stringWithUTF8String:arch->name]; + return archName; +} + ++ (NSString*)getOSVersion { + NSDictionary* systemVersion = + [NSDictionary dictionaryWithContentsOfFile: + @"/System/Library/CoreServices/SystemVersion.plist"]; + NSString* versionNumber = [systemVersion objectForKey:@"ProductVersion"]; + + return versionNumber; +} + +@end
diff --git a/chrome/installer/mac/app/main.m b/chrome/installer/mac/app/main.m new file mode 100644 index 0000000..3f71813 --- /dev/null +++ b/chrome/installer/mac/app/main.m
@@ -0,0 +1,34 @@ +// 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 <Foundation/Foundation.h> + +#import "Downloader.h" +#import "OmahaCommunication.h" +#import "OmahaXMLRequest.h" +#import "SystemInfo.h" + +// TODO: add a class that takes care of what main is doing now +void talkToOmahaThenExecuteBlock(OmahaRequestCompletionHandler block) { + NSXMLDocument* requestBody = [OmahaXMLRequest createXMLRequestBody]; + OmahaCommunication* messenger = + [[OmahaCommunication alloc] initWithBody:requestBody]; + [messenger sendRequestWithBlock:block]; +} + +int main() { + talkToOmahaThenExecuteBlock(^(NSData* data, NSError* error) { + if (error) { + NSLog(@"%@", [error localizedDescription]); + return; + } + Downloader* download = [[Downloader alloc] init]; + [download downloadChromeImageToDownloadsDirectory:data]; + }); + + // [[NSRunLoop mainRunLoop] run]; + [[NSRunLoop mainRunLoop] + runUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]]; + return 1; +}
diff --git a/chrome/installer/mac/app/testing/requestSample.xml b/chrome/installer/mac/app/testing/requestSample.xml new file mode 100644 index 0000000..7e165e5a --- /dev/null +++ b/chrome/installer/mac/app/testing/requestSample.xml
@@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<request protocol="3.0" version="KeystoneAgent-1.99.4.0"> + + <os platform="mac" version="10.11" arch="x86_64h" sp="10.11.4_x86_64h"></os> + + <app appid="com.google.Chrome" version="1.1.1.1" lang="en-us"> + + <updatecheck></updatecheck> + + </app> + +</request> \ No newline at end of file
diff --git a/chrome/installer/mac/app/testing/responseExample.xml b/chrome/installer/mac/app/testing/responseExample.xml new file mode 100644 index 0000000..356ae3a --- /dev/null +++ b/chrome/installer/mac/app/testing/responseExample.xml
@@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8"?><response protocol="3.0" server="prod"><daystart elapsed_days="3461" elapsed_seconds="48105"/><app appid="com.google.Chrome" cohort="1:1y5:" cohortname="Stable" status="ok"><updatecheck status="ok"><urls><url codebase="http://redirector.gvt1.com/edgedl/release2/vqrm4ffupbfudxhoaio56oavtexllf94tladghchanr56wmkitmeucwtyehngk441aquxeu0pihv6q5zq1dbh5mk3zd2fnoqhqd/"/><url codebase="http://www.google.com/dl/release2/vqrm4ffupbfudxhoaio56oavtexllf94tladghchanr56wmkitmeucwtyehngk441aquxeu0pihv6q5zq1dbh5mk3zd2fnoqhqd/"/><url codebase="https://dl.google.com/release2/vqrm4ffupbfudxhoaio56oavtexllf94tladghchanr56wmkitmeucwtyehngk441aquxeu0pihv6q5zq1dbh5mk3zd2fnoqhqd/"/><url codebase="http://dl.google.com/release2/vqrm4ffupbfudxhoaio56oavtexllf94tladghchanr56wmkitmeucwtyehngk441aquxeu0pihv6q5zq1dbh5mk3zd2fnoqhqd/"/></urls><manifest version="51.0.2704.103"><packages><package fp="1.6849cf2bd473f9611fb14ea1cc35d588e8d4522721c1667cded77a4b999175e5" hash="NSh/iFTLYxKZslpgZBDY1cGcPeU=" hash_sha256="6849cf2bd473f9611fb14ea1cc35d588e8d4522721c1667cded77a4b999175e5" name="GoogleChrome-51.0.2704.103.dmg" required="true" size="68727751"/></packages><actions><action arguments="" event="install" run="GoogleChrome-51.0.2704.103.dmg"/><action DisplayVersion="51.0.2704.103" event="postinstall"/></actions></manifest></updatecheck></app></response> \ No newline at end of file
diff --git a/chrome/interactive_ui_tests.isolate b/chrome/interactive_ui_tests.isolate index 6395319..2d92f894 100644 --- a/chrome/interactive_ui_tests.isolate +++ b/chrome/interactive_ui_tests.isolate
@@ -55,6 +55,10 @@ '../third_party/pyftpdlib/', '../third_party/pywebsocket/', '../third_party/tlslite/', + '<(PRODUCT_DIR)/test_case.html', + '<(PRODUCT_DIR)/test_case.html.mock-http-headers', + '<(PRODUCT_DIR)/test_page.css', + '<(PRODUCT_DIR)/test_page.css.mock-http-headers', '<(PRODUCT_DIR)/ui_test.pak', 'test/data/', ],
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn index 309f710..fc1868e6e 100644 --- a/chrome/renderer/BUILD.gn +++ b/chrome/renderer/BUILD.gn
@@ -187,7 +187,7 @@ } # In GYP this is part of test_support_common. -source_set("test_support") { +static_library("test_support") { testonly = true visibility = [ "//chrome/test:test_support" ]
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 8999f1a..ec4c0d63 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -768,8 +768,15 @@ PowerSaverInfo power_saver_info = PowerSaverInfo::Get(render_frame, power_saver_setting_on, params, info, frame->document().url()); + // Prevent small plugins from loading by using a placeholder until + // we can determine the unobscured size of the object. + bool blocked_for_tinyness = + ChromePluginPlaceholder::IsSmallContentFilterEnabled() && + power_saver_info.power_saver_enabled; + if (power_saver_info.blocked_for_background_tab || is_prerendering || - !power_saver_info.poster_attribute.empty()) { + !power_saver_info.poster_attribute.empty() || + blocked_for_tinyness) { placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( render_frame, frame, params, info, identifier, group_name, power_saver_info.poster_attribute.empty() @@ -778,24 +785,12 @@ l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name), power_saver_info); placeholder->set_blocked_for_prerendering(is_prerendering); + placeholder->set_blocked_for_tinyness(blocked_for_tinyness); placeholder->AllowLoading(); break; } std::unique_ptr<content::PluginInstanceThrottler> throttler; - - // Small content filter requires routing through a placeholder. - if (ChromePluginPlaceholder::IsSmallContentFilterEnabled() && - power_saver_info.power_saver_enabled) { - // The feature only applies to flash plugins. - if (power_saver_info.is_eligible) { - placeholder = ChromePluginPlaceholder::CreateDelayedPlugin( - render_frame, frame, params, info, identifier, group_name, - power_saver_info); - break; - } - } - if (power_saver_info.power_saver_enabled) { throttler = PluginInstanceThrottler::Create(); // PluginPreroller manages its own lifetime.
diff --git a/chrome/renderer/extensions/cast_streaming_native_handler.cc b/chrome/renderer/extensions/cast_streaming_native_handler.cc index 4b20c600c..da8f742 100644 --- a/chrome/renderer/extensions/cast_streaming_native_handler.cc +++ b/chrome/renderer/extensions/cast_streaming_native_handler.cc
@@ -21,6 +21,7 @@ #include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" +#include "base/sys_info.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/common/extensions/api/cast_streaming_receiver_session.h" #include "chrome/common/extensions/api/cast_streaming_rtp_stream.h" @@ -33,6 +34,7 @@ #include "content/public/renderer/media_stream_utils.h" #include "extensions/renderer/script_context.h" #include "media/base/audio_parameters.h" +#include "media/base/limits.h" #include "net/base/host_port_pair.h" #include "net/base/ip_address.h" #include "third_party/WebKit/public/platform/WebMediaStream.h" @@ -43,10 +45,10 @@ #include "url/gurl.h" using content::V8ValueConverter; +using media::cast::FrameSenderConfig; // Extension types. using extensions::api::cast_streaming_receiver_session::RtpReceiverParams; -using extensions::api::cast_streaming_rtp_stream::CodecSpecificParams; using extensions::api::cast_streaming_rtp_stream::RtpParams; using extensions::api::cast_streaming_rtp_stream::RtpPayloadParams; using extensions::api::cast_streaming_udp_transport::IPEndPoint; @@ -54,36 +56,28 @@ namespace extensions { namespace { -const char kInvalidAesIvMask[] = "Invalid value for AES IV mask"; -const char kInvalidAesKey[] = "Invalid value for AES key"; -const char kInvalidAudioParams[] = "Invalid audio params"; -const char kInvalidDestination[] = "Invalid destination"; -const char kInvalidFPS[] = "Invalid FPS"; -const char kInvalidMediaStreamURL[] = "Invalid MediaStream URL"; -const char kInvalidRtpParams[] = "Invalid value for RTP params"; -const char kInvalidLatency[] = "Invalid value for max_latency. (0-1000)"; -const char kInvalidRtpTimebase[] = "Invalid rtp_timebase. (1000-1000000)"; -const char kInvalidStreamArgs[] = "Invalid stream arguments"; -const char kRtpStreamNotFound[] = "The RTP stream cannot be found"; -const char kUdpTransportNotFound[] = "The UDP transport cannot be found"; -const char kUnableToConvertArgs[] = "Unable to convert arguments"; -const char kUnableToConvertParams[] = "Unable to convert params"; -// These helper methods are used to convert between Extension API -// types and Cast types. -void ToCastCodecSpecificParams(const CodecSpecificParams& ext_params, - CastCodecSpecificParams* cast_params) { - cast_params->key = ext_params.key; - cast_params->value = ext_params.value; -} +constexpr char kInvalidAesIvMask[] = "Invalid value for AES IV mask"; +constexpr char kInvalidAesKey[] = "Invalid value for AES key"; +constexpr char kInvalidAudioParams[] = "Invalid audio params"; +constexpr char kInvalidDestination[] = "Invalid destination"; +constexpr char kInvalidFPS[] = "Invalid FPS"; +constexpr char kInvalidMediaStreamURL[] = "Invalid MediaStream URL"; +constexpr char kInvalidRtpParams[] = "Invalid value for RTP params"; +constexpr char kInvalidLatency[] = "Invalid value for max_latency. (0-1000)"; +constexpr char kInvalidRtpTimebase[] = "Invalid rtp_timebase. (1000-1000000)"; +constexpr char kInvalidStreamArgs[] = "Invalid stream arguments"; +constexpr char kRtpStreamNotFound[] = "The RTP stream cannot be found"; +constexpr char kUdpTransportNotFound[] = "The UDP transport cannot be found"; +constexpr char kUnableToConvertArgs[] = "Unable to convert arguments"; +constexpr char kUnableToConvertParams[] = "Unable to convert params"; +constexpr char kCodecNameOpus[] = "OPUS"; +constexpr char kCodecNameVp8[] = "VP8"; +constexpr char kCodecNameH264[] = "H264"; -void FromCastCodecSpecificParams(const CastCodecSpecificParams& cast_params, - CodecSpecificParams* ext_params) { - ext_params->key = cast_params.key; - ext_params->value = cast_params.value; -} +// To convert from kilobits per second to bits per second. +constexpr int kBitsPerKilobit = 1000; -namespace { bool HexDecode(const std::string& input, std::string* output) { std::vector<uint8_t> bytes; if (!base::HexStringToBytes(input, &bytes)) @@ -91,107 +85,189 @@ output->assign(reinterpret_cast<const char*>(&bytes[0]), bytes.size()); return true; } -} // namespace -bool ToCastRtpPayloadParamsOrThrow(v8::Isolate* isolate, - const RtpPayloadParams& ext_params, - CastRtpPayloadParams* cast_params) { - cast_params->max_latency_ms = ext_params.max_latency; - cast_params->min_latency_ms = - ext_params.min_latency ? *ext_params.min_latency : ext_params.max_latency; - cast_params->animated_latency_ms = ext_params.animated_latency - ? *ext_params.animated_latency - : ext_params.max_latency; - cast_params->codec_name = ext_params.codec_name; - if (cast_params->codec_name == "OPUS") { - cast_params->payload_type = media::cast::RtpPayloadType::AUDIO_OPUS; - } else if (cast_params->codec_name == "PCM16") { - cast_params->payload_type = media::cast::RtpPayloadType::AUDIO_PCM16; - } else if (cast_params->codec_name == "AAC") { - cast_params->payload_type = media::cast::RtpPayloadType::AUDIO_AAC; - } else if (cast_params->codec_name == "VP8") { - cast_params->payload_type = media::cast::RtpPayloadType::VIDEO_VP8; - } else if (cast_params->codec_name == "H264") { - cast_params->payload_type = media::cast::RtpPayloadType::VIDEO_H264; +int NumberOfEncodeThreads() { + // Do not saturate CPU utilization just for encoding. On a lower-end system + // with only 1 or 2 cores, use only one thread for encoding. On systems with + // more cores, allow half of the cores to be used for encoding. + return std::min(8, (base::SysInfo::NumberOfProcessors() + 1) / 2); +} + +bool ToFrameSenderConfigOrThrow(v8::Isolate* isolate, + const RtpPayloadParams& ext_params, + FrameSenderConfig* config) { + config->sender_ssrc = ext_params.ssrc; + config->receiver_ssrc = ext_params.feedback_ssrc; + if (config->sender_ssrc == config->receiver_ssrc) { + DVLOG(1) << "sender_ssrc " << config->sender_ssrc + << " cannot be equal to receiver_ssrc"; + isolate->ThrowException(v8::Exception::Error( + v8::String::NewFromUtf8(isolate, kInvalidRtpParams))); + return false; } - cast_params->ssrc = ext_params.ssrc; - cast_params->feedback_ssrc = ext_params.feedback_ssrc; - cast_params->clock_rate = ext_params.clock_rate ? *ext_params.clock_rate : 0; - cast_params->min_bitrate = - ext_params.min_bitrate ? *ext_params.min_bitrate : 0; - cast_params->max_bitrate = - ext_params.max_bitrate ? *ext_params.max_bitrate : 0; - cast_params->channels = ext_params.channels ? *ext_params.channels : 0; - cast_params->max_frame_rate = - ext_params.max_frame_rate ? *ext_params.max_frame_rate : 0.0; - if (ext_params.aes_key && - !HexDecode(*ext_params.aes_key, &cast_params->aes_key)) { + config->min_playout_delay = base::TimeDelta::FromMilliseconds( + ext_params.min_latency ? *ext_params.min_latency + : ext_params.max_latency); + config->max_playout_delay = + base::TimeDelta::FromMilliseconds(ext_params.max_latency); + config->animated_playout_delay = base::TimeDelta::FromMilliseconds( + ext_params.animated_latency ? *ext_params.animated_latency + : ext_params.max_latency); + if (config->min_playout_delay <= base::TimeDelta()) { + DVLOG(1) << "min_playout_delay " << config->min_playout_delay + << " must be greater than zero"; + isolate->ThrowException(v8::Exception::Error( + v8::String::NewFromUtf8(isolate, kInvalidRtpParams))); + return false; + } + if (config->min_playout_delay > config->max_playout_delay) { + DVLOG(1) << "min_playout_delay " << config->min_playout_delay + << " must be less than or equal to max_palyout_delay"; + isolate->ThrowException(v8::Exception::Error( + v8::String::NewFromUtf8(isolate, kInvalidRtpParams))); + return false; + } + if (config->animated_playout_delay < config->min_playout_delay || + config->animated_playout_delay > config->max_playout_delay) { + DVLOG(1) << "animated_playout_delay " << config->animated_playout_delay + << " must be between (inclusive) the min and max playout delay"; + isolate->ThrowException(v8::Exception::Error( + v8::String::NewFromUtf8(isolate, kInvalidRtpParams))); + return false; + } + if (ext_params.codec_name == kCodecNameOpus) { + config->rtp_payload_type = media::cast::RtpPayloadType::AUDIO_OPUS; + config->use_external_encoder = false; + config->rtp_timebase = ext_params.clock_rate + ? *ext_params.clock_rate + : media::cast::kDefaultAudioSamplingRate; + // Sampling rate must be one of the Opus-supported values. + switch (config->rtp_timebase) { + case 48000: + case 24000: + case 16000: + case 12000: + case 8000: + break; + default: + DVLOG(1) << "rtp_timebase " << config->rtp_timebase << " is invalid"; + isolate->ThrowException(v8::Exception::Error( + v8::String::NewFromUtf8(isolate, kInvalidRtpParams))); + return false; + } + config->channels = ext_params.channels ? *ext_params.channels : 2; + if (config->channels != 1 && config->channels != 2) { + isolate->ThrowException(v8::Exception::Error( + v8::String::NewFromUtf8(isolate, kInvalidRtpParams))); + DVLOG(1) << "channels " << config->channels << " is invalid"; + return false; + } + config->min_bitrate = config->start_bitrate = config->max_bitrate = + ext_params.max_bitrate ? (*ext_params.max_bitrate) * kBitsPerKilobit + : media::cast::kDefaultAudioEncoderBitrate; + config->max_frame_rate = 100; // 10ms audio frames. + config->codec = media::cast::CODEC_AUDIO_OPUS; + } else if (ext_params.codec_name == kCodecNameVp8 || + ext_params.codec_name == kCodecNameH264) { + config->rtp_timebase = media::cast::kVideoFrequency; + config->channels = ext_params.channels ? *ext_params.channels : 1; + if (config->channels != 1) { + isolate->ThrowException(v8::Exception::Error( + v8::String::NewFromUtf8(isolate, kInvalidRtpParams))); + DVLOG(1) << "channels " << config->channels << " is invalid"; + return false; + } + config->min_bitrate = ext_params.min_bitrate + ? (*ext_params.min_bitrate) * kBitsPerKilobit + : media::cast::kDefaultMinVideoBitrate; + config->max_bitrate = ext_params.max_bitrate + ? (*ext_params.max_bitrate) * kBitsPerKilobit + : media::cast::kDefaultMaxVideoBitrate; + if (config->min_bitrate > config->max_bitrate) { + DVLOG(1) << "min_bitrate " << config->min_bitrate << " is larger than " + << "max_bitrate " << config->max_bitrate; + isolate->ThrowException(v8::Exception::Error( + v8::String::NewFromUtf8(isolate, kInvalidRtpParams))); + return false; + } + config->start_bitrate = config->min_bitrate; + config->max_frame_rate = std::max( + 1.0, ext_params.max_frame_rate ? *ext_params.max_frame_rate : 0.0); + if (config->max_frame_rate > media::limits::kMaxFramesPerSecond) { + DVLOG(1) << "max_frame_rate " << config->max_frame_rate << " is invalid"; + isolate->ThrowException(v8::Exception::Error( + v8::String::NewFromUtf8(isolate, kInvalidRtpParams))); + return false; + } + if (ext_params.codec_name == kCodecNameVp8) { + config->rtp_payload_type = media::cast::RtpPayloadType::VIDEO_VP8; + config->codec = media::cast::CODEC_VIDEO_VP8; + config->use_external_encoder = + CastRtpStream::IsHardwareVP8EncodingSupported(); + } else { + config->rtp_payload_type = media::cast::RtpPayloadType::VIDEO_H264; + config->codec = media::cast::CODEC_VIDEO_H264; + config->use_external_encoder = + CastRtpStream::IsHardwareH264EncodingSupported(); + } + if (!config->use_external_encoder) + config->video_codec_params.number_of_encode_threads = + NumberOfEncodeThreads(); + } else { + DVLOG(1) << "codec_name " << ext_params.codec_name << " is invalid"; + isolate->ThrowException(v8::Exception::Error( + v8::String::NewFromUtf8(isolate, kInvalidRtpParams))); + return false; + } + if (ext_params.aes_key && !HexDecode(*ext_params.aes_key, &config->aes_key)) { isolate->ThrowException(v8::Exception::Error( v8::String::NewFromUtf8(isolate, kInvalidAesKey))); return false; } if (ext_params.aes_iv_mask && - !HexDecode(*ext_params.aes_iv_mask, &cast_params->aes_iv_mask)) { + !HexDecode(*ext_params.aes_iv_mask, &config->aes_iv_mask)) { isolate->ThrowException(v8::Exception::Error( v8::String::NewFromUtf8(isolate, kInvalidAesIvMask))); return false; } - for (size_t i = 0; i < ext_params.codec_specific_params.size(); ++i) { - CastCodecSpecificParams cast_codec_params; - ToCastCodecSpecificParams(ext_params.codec_specific_params[i], - &cast_codec_params); - cast_params->codec_specific_params.push_back(cast_codec_params); - } return true; } -void FromCastRtpPayloadParams(const CastRtpPayloadParams& cast_params, - RtpPayloadParams* ext_params) { - ext_params->payload_type = static_cast<int>(cast_params.payload_type); - ext_params->max_latency = cast_params.max_latency_ms; - ext_params->min_latency.reset(new int(cast_params.min_latency_ms)); - ext_params->animated_latency.reset(new int(cast_params.animated_latency_ms)); - ext_params->codec_name = cast_params.codec_name; - ext_params->ssrc = cast_params.ssrc; - ext_params->feedback_ssrc = cast_params.feedback_ssrc; - if (cast_params.clock_rate) - ext_params->clock_rate.reset(new int(cast_params.clock_rate)); - if (cast_params.min_bitrate) - ext_params->min_bitrate.reset(new int(cast_params.min_bitrate)); - if (cast_params.max_bitrate) - ext_params->max_bitrate.reset(new int(cast_params.max_bitrate)); - if (cast_params.channels) - ext_params->channels.reset(new int(cast_params.channels)); - if (cast_params.max_frame_rate > 0.0) - ext_params->max_frame_rate.reset(new double(cast_params.max_frame_rate)); - for (size_t i = 0; i < cast_params.codec_specific_params.size(); ++i) { - CodecSpecificParams ext_codec_params; - FromCastCodecSpecificParams(cast_params.codec_specific_params[i], - &ext_codec_params); - ext_params->codec_specific_params.push_back(std::move(ext_codec_params)); +void FromFrameSenderConfig(const FrameSenderConfig& config, + RtpPayloadParams* ext_params) { + ext_params->payload_type = static_cast<int>(config.rtp_payload_type); + ext_params->max_latency = config.max_playout_delay.InMilliseconds(); + ext_params->min_latency.reset( + new int(config.min_playout_delay.InMilliseconds())); + ext_params->animated_latency.reset( + new int(config.animated_playout_delay.InMilliseconds())); + switch (config.codec) { + case media::cast::CODEC_AUDIO_OPUS: + ext_params->codec_name = kCodecNameOpus; + break; + case media::cast::CODEC_VIDEO_VP8: + ext_params->codec_name = kCodecNameVp8; + break; + case media::cast::CODEC_VIDEO_H264: + ext_params->codec_name = kCodecNameH264; + break; + default: + NOTREACHED(); } -} - -void FromCastRtpParams(const CastRtpParams& cast_params, - RtpParams* ext_params) { - std::copy(cast_params.rtcp_features.begin(), - cast_params.rtcp_features.end(), - std::back_inserter(ext_params->rtcp_features)); - FromCastRtpPayloadParams(cast_params.payload, &ext_params->payload); -} - -bool ToCastRtpParamsOrThrow(v8::Isolate* isolate, - const RtpParams& ext_params, - CastRtpParams* cast_params) { - std::copy(ext_params.rtcp_features.begin(), - ext_params.rtcp_features.end(), - std::back_inserter(cast_params->rtcp_features)); - if (!ToCastRtpPayloadParamsOrThrow(isolate, - ext_params.payload, - &cast_params->payload)) { - return false; - } - return true; + ext_params->ssrc = config.sender_ssrc; + ext_params->feedback_ssrc = config.receiver_ssrc; + if (config.rtp_timebase) + ext_params->clock_rate.reset(new int(config.rtp_timebase)); + if (config.min_bitrate) + ext_params->min_bitrate.reset( + new int(config.min_bitrate / kBitsPerKilobit)); + if (config.max_bitrate) + ext_params->max_bitrate.reset( + new int(config.max_bitrate / kBitsPerKilobit)); + if (config.channels) + ext_params->channels.reset(new int(config.channels)); + if (config.max_frame_rate > 0.0) + ext_params->max_frame_rate.reset(new double(config.max_frame_rate)); } } // namespace @@ -399,13 +475,12 @@ return; std::unique_ptr<V8ValueConverter> converter(V8ValueConverter::create()); - std::vector<CastRtpParams> cast_params = transport->GetSupportedParams(); + std::vector<FrameSenderConfig> configs = transport->GetSupportedConfigs(); v8::Local<v8::Array> result = - v8::Array::New(args.GetIsolate(), - static_cast<int>(cast_params.size())); - for (size_t i = 0; i < cast_params.size(); ++i) { + v8::Array::New(args.GetIsolate(), static_cast<int>(configs.size())); + for (size_t i = 0; i < configs.size(); ++i) { RtpParams params; - FromCastRtpParams(cast_params[i], ¶ms); + FromFrameSenderConfig(configs[i], ¶ms.payload); std::unique_ptr<base::DictionaryValue> params_value = params.ToValue(); result->Set( static_cast<int>(i), @@ -440,9 +515,9 @@ return; } - CastRtpParams cast_params; + FrameSenderConfig config; v8::Isolate* isolate = context()->v8_context()->GetIsolate(); - if (!ToCastRtpParamsOrThrow(isolate, *params, &cast_params)) + if (!ToFrameSenderConfigOrThrow(isolate, params->payload, &config)) return; base::Closure start_callback = @@ -457,7 +532,7 @@ base::Bind(&CastStreamingNativeHandler::CallErrorCallback, weak_factory_.GetWeakPtr(), transport_id); - transport->Start(cast_params, start_callback, stop_callback, error_callback); + transport->Start(config, start_callback, stop_callback, error_callback); } void CastStreamingNativeHandler::StopCastRtpStream( @@ -816,7 +891,8 @@ media::AudioParameters::AUDIO_PCM_LINEAR, media::GuessChannelLayout(audio_config.channels), audio_config.rtp_timebase, // sampling rate - 16, audio_config.rtp_timebase / audio_config.target_frame_rate); + 16, static_cast<int>(audio_config.rtp_timebase / + audio_config.target_frame_rate)); if (!params.IsValid()) { args.GetIsolate()->ThrowException(v8::Exception::TypeError(
diff --git a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc index 6494172..a018de7 100644 --- a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc +++ b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
@@ -12,7 +12,6 @@ #include "chrome/common/channel_info.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/crash_keys.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/common/extensions/features/feature_util.h" #include "chrome/common/url_constants.h" #include "chrome/grit/renderer_resources.h" @@ -34,6 +33,7 @@ #include "extensions/common/constants.h" #include "extensions/common/extension.h" #include "extensions/common/feature_switch.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/permissions/manifest_permission_set.h" #include "extensions/common/permissions/permission_set.h" #include "extensions/common/permissions/permissions_data.h"
diff --git a/chrome/renderer/media/cast_rtp_stream.cc b/chrome/renderer/media/cast_rtp_stream.cc index 305cd0b..01d0fce1 100644 --- a/chrome/renderer/media/cast_rtp_stream.cc +++ b/chrome/renderer/media/cast_rtp_stream.cc
@@ -19,7 +19,6 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/strings/stringprintf.h" -#include "base/sys_info.h" #include "base/threading/thread_task_runner_handle.h" #include "base/timer/timer.h" #include "base/trace_event/trace_event.h" @@ -44,18 +43,10 @@ #include "third_party/WebKit/public/platform/WebMediaStreamSource.h" #include "ui/gfx/geometry/size.h" -using media::cast::AudioSenderConfig; -using media::cast::VideoSenderConfig; +using media::cast::FrameSenderConfig; namespace { -const char kCodecNameOpus[] = "OPUS"; -const char kCodecNameVp8[] = "VP8"; -const char kCodecNameH264[] = "H264"; - -// To convert from kilobits per second to bits to per second. -const int kBitrateMultiplier = 1000; - // The maximum number of milliseconds that should elapse since the last video // frame was received from the video source, before requesting refresh frames. const int kRefreshIntervalMilliseconds = 250; @@ -64,253 +55,69 @@ // limit (60 * 250ms = 15 seconds), refresh frame requests will stop being made. const int kMaxConsecutiveRefreshFrames = 60; -CastRtpPayloadParams DefaultOpusPayload() { - CastRtpPayloadParams payload; - payload.payload_type = media::cast::RtpPayloadType::AUDIO_OPUS; - payload.max_latency_ms = media::cast::kDefaultRtpMaxDelayMs; - payload.ssrc = 1; - payload.feedback_ssrc = 2; - payload.clock_rate = media::cast::kDefaultAudioSamplingRate; +FrameSenderConfig DefaultOpusConfig() { + FrameSenderConfig config; + config.rtp_payload_type = media::cast::RtpPayloadType::AUDIO_OPUS; + config.sender_ssrc = 1; + config.receiver_ssrc = 2; + config.rtp_timebase = media::cast::kDefaultAudioSamplingRate; + config.channels = 2; // The value is 0 which means VBR. - payload.min_bitrate = payload.max_bitrate = + config.min_bitrate = config.max_bitrate = config.start_bitrate = media::cast::kDefaultAudioEncoderBitrate; - payload.channels = 2; - payload.max_frame_rate = 100; // 10 ms audio frames - payload.codec_name = kCodecNameOpus; - return payload; + config.max_frame_rate = 100; // 10 ms audio frames + config.codec = media::cast::CODEC_AUDIO_OPUS; + return config; } -CastRtpPayloadParams DefaultVp8Payload() { - CastRtpPayloadParams payload; - payload.payload_type = media::cast::RtpPayloadType::VIDEO_VP8; - payload.max_latency_ms = media::cast::kDefaultRtpMaxDelayMs; - payload.ssrc = 11; - payload.feedback_ssrc = 12; - payload.clock_rate = media::cast::kVideoFrequency; - payload.max_bitrate = media::cast::kDefaultMaxVideoKbps; - payload.min_bitrate = media::cast::kDefaultMinVideoKbps; - payload.channels = 1; - payload.max_frame_rate = media::cast::kDefaultMaxFrameRate; - payload.codec_name = kCodecNameVp8; - return payload; +FrameSenderConfig DefaultVp8Config() { + FrameSenderConfig config; + config.rtp_payload_type = media::cast::RtpPayloadType::VIDEO_VP8; + config.sender_ssrc = 11; + config.receiver_ssrc = 12; + config.rtp_timebase = media::cast::kVideoFrequency; + config.channels = 1; + config.max_bitrate = media::cast::kDefaultMaxVideoBitrate; + config.min_bitrate = media::cast::kDefaultMinVideoBitrate; + config.max_frame_rate = media::cast::kDefaultMaxFrameRate; + config.codec = media::cast::CODEC_VIDEO_VP8; + return config; } -CastRtpPayloadParams DefaultH264Payload() { - CastRtpPayloadParams payload; - payload.payload_type = media::cast::RtpPayloadType::VIDEO_H264; - payload.max_latency_ms = media::cast::kDefaultRtpMaxDelayMs; - payload.ssrc = 11; - payload.feedback_ssrc = 12; - payload.clock_rate = media::cast::kVideoFrequency; - payload.max_bitrate = media::cast::kDefaultMaxVideoKbps; - payload.min_bitrate = media::cast::kDefaultMinVideoKbps; - payload.channels = 1; - payload.max_frame_rate = media::cast::kDefaultMaxFrameRate; - payload.codec_name = kCodecNameH264; - return payload; +FrameSenderConfig DefaultH264Config() { + FrameSenderConfig config; + config.rtp_payload_type = media::cast::RtpPayloadType::VIDEO_H264; + config.sender_ssrc = 11; + config.receiver_ssrc = 12; + config.rtp_timebase = media::cast::kVideoFrequency; + config.channels = 1; + config.max_bitrate = media::cast::kDefaultMaxVideoBitrate; + config.min_bitrate = media::cast::kDefaultMinVideoBitrate; + config.max_frame_rate = media::cast::kDefaultMaxFrameRate; + config.codec = media::cast::CODEC_VIDEO_H264; + return config; } -bool IsHardwareVP8EncodingSupported() { - const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); - if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) { - DVLOG(1) << "Disabled hardware VP8 support for Cast Streaming."; - return false; - } - - // Query for hardware VP8 encoder support. - const std::vector<media::VideoEncodeAccelerator::SupportedProfile> - vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles(); - for (const auto& vea_profile : vea_profiles) { - if (vea_profile.profile >= media::VP8PROFILE_MIN && - vea_profile.profile <= media::VP8PROFILE_MAX) { - return true; - } - } - return false; -} - -bool IsHardwareH264EncodingSupported() { - const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); - if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) { - DVLOG(1) << "Disabled hardware h264 support for Cast Streaming."; - return false; - } - - // Query for hardware H.264 encoder support. - // - // TODO(miu): Look into why H.264 hardware encoder on MacOS is broken. - // http://crbug.com/596674 -#if !defined(OS_MACOSX) - const std::vector<media::VideoEncodeAccelerator::SupportedProfile> - vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles(); - for (const auto& vea_profile : vea_profiles) { - if (vea_profile.profile >= media::H264PROFILE_MIN && - vea_profile.profile <= media::H264PROFILE_MAX) { - return true; - } - } -#endif // !defined(OS_MACOSX) - return false; -} - -int NumberOfEncodeThreads() { - // Do not saturate CPU utilization just for encoding. On a lower-end system - // with only 1 or 2 cores, use only one thread for encoding. On systems with - // more cores, allow half of the cores to be used for encoding. - return std::min(8, (base::SysInfo::NumberOfProcessors() + 1) / 2); -} - -std::vector<CastRtpParams> SupportedAudioParams() { +std::vector<FrameSenderConfig> SupportedAudioConfigs() { // TODO(hclam): Fill in more codecs here. - return std::vector<CastRtpParams>(1, CastRtpParams(DefaultOpusPayload())); + return std::vector<FrameSenderConfig>(1, DefaultOpusConfig()); } -std::vector<CastRtpParams> SupportedVideoParams() { - std::vector<CastRtpParams> supported_params; +std::vector<FrameSenderConfig> SupportedVideoConfigs() { + std::vector<FrameSenderConfig> supported_configs; // Prefer VP8 over H.264 for hardware encoder. - if (IsHardwareVP8EncodingSupported()) - supported_params.push_back(CastRtpParams(DefaultVp8Payload())); - if (IsHardwareH264EncodingSupported()) - supported_params.push_back(CastRtpParams(DefaultH264Payload())); + if (CastRtpStream::IsHardwareVP8EncodingSupported()) + supported_configs.push_back(DefaultVp8Config()); + if (CastRtpStream::IsHardwareH264EncodingSupported()) + supported_configs.push_back(DefaultH264Config()); // Propose the default software VP8 encoder, if no hardware encoders are // available. - if (supported_params.empty()) - supported_params.push_back(CastRtpParams(DefaultVp8Payload())); + if (supported_configs.empty()) + supported_configs.push_back(DefaultVp8Config()); - return supported_params; -} - -bool ToAudioSenderConfig(const CastRtpParams& params, - AudioSenderConfig* config) { - config->ssrc = params.payload.ssrc; - config->receiver_ssrc = params.payload.feedback_ssrc; - if (config->ssrc == config->receiver_ssrc) { - DVLOG(1) << "ssrc " << config->ssrc << " cannot be equal to receiver_ssrc"; - return false; - } - config->min_playout_delay = base::TimeDelta::FromMilliseconds( - params.payload.min_latency_ms ? - params.payload.min_latency_ms : - params.payload.max_latency_ms); - config->max_playout_delay = - base::TimeDelta::FromMilliseconds(params.payload.max_latency_ms); - config->animated_playout_delay = base::TimeDelta::FromMilliseconds( - params.payload.animated_latency_ms ? params.payload.animated_latency_ms - : params.payload.max_latency_ms); - if (config->min_playout_delay <= base::TimeDelta()) { - DVLOG(1) << "min_playout_delay " << config->min_playout_delay - << " is too small"; - return false; - } - if (config->min_playout_delay > config->max_playout_delay) { - DVLOG(1) << "min_playout_delay " << config->min_playout_delay - << " is too big"; - return false; - } - if (config->animated_playout_delay < config->min_playout_delay || - config->animated_playout_delay > config->max_playout_delay) { - DVLOG(1) << "animated_playout_delay " << config->animated_playout_delay - << " is out of range"; - return false; - } - config->rtp_payload_type = params.payload.payload_type; - config->use_external_encoder = false; - config->frequency = params.payload.clock_rate; - // Sampling rate must be one of the Opus-supported values. - switch (config->frequency) { - case 48000: - case 24000: - case 16000: - case 12000: - case 8000: - break; - default: - DVLOG(1) << "frequency " << config->frequency << " is invalid"; - return false; - } - config->channels = params.payload.channels; - if (config->channels < 1) { - DVLOG(1) << "channels " << config->channels << " is invalid"; - return false; - } - config->bitrate = params.payload.max_bitrate * kBitrateMultiplier; - if (params.payload.codec_name == kCodecNameOpus) { - config->codec = media::cast::CODEC_AUDIO_OPUS; - } else { - DVLOG(1) << "codec_name " << params.payload.codec_name << " is invalid"; - return false; - } - config->aes_key = params.payload.aes_key; - config->aes_iv_mask = params.payload.aes_iv_mask; - return true; -} - -bool ToVideoSenderConfig(const CastRtpParams& params, - VideoSenderConfig* config) { - config->ssrc = params.payload.ssrc; - config->receiver_ssrc = params.payload.feedback_ssrc; - if (config->ssrc == config->receiver_ssrc) { - DVLOG(1) << "ssrc " << config->ssrc << " cannot be equal to receiver_ssrc"; - return false; - } - config->min_playout_delay = base::TimeDelta::FromMilliseconds( - params.payload.min_latency_ms ? - params.payload.min_latency_ms : - params.payload.max_latency_ms); - config->max_playout_delay = - base::TimeDelta::FromMilliseconds(params.payload.max_latency_ms); - config->animated_playout_delay = base::TimeDelta::FromMilliseconds( - params.payload.animated_latency_ms ? params.payload.animated_latency_ms - : params.payload.max_latency_ms); - if (config->min_playout_delay <= base::TimeDelta()) { - DVLOG(1) << "min_playout_delay " << config->min_playout_delay - << " is too small"; - return false; - } - if (config->min_playout_delay > config->max_playout_delay) { - DVLOG(1) << "min_playout_delay " << config->min_playout_delay - << " is too big"; - return false; - } - if (config->animated_playout_delay < config->min_playout_delay || - config->animated_playout_delay > config->max_playout_delay) { - DVLOG(1) << "animated_playout_delay " << config->animated_playout_delay - << " is out of range"; - return false; - } - config->rtp_payload_type = params.payload.payload_type; - config->min_bitrate = config->start_bitrate = - params.payload.min_bitrate * kBitrateMultiplier; - config->max_bitrate = params.payload.max_bitrate * kBitrateMultiplier; - if (config->min_bitrate > config->max_bitrate) { - DVLOG(1) << "min_bitrate " << config->min_bitrate << " is larger than " - << "max_bitrate " << config->max_bitrate; - return false; - } - config->start_bitrate = config->min_bitrate; - config->max_frame_rate = static_cast<int>( - std::max(1.0, params.payload.max_frame_rate) + 0.5); - if (config->max_frame_rate > media::limits::kMaxFramesPerSecond) { - DVLOG(1) << "max_frame_rate " << config->max_frame_rate << " is invalid"; - return false; - } - if (params.payload.codec_name == kCodecNameVp8) { - config->use_external_encoder = IsHardwareVP8EncodingSupported(); - config->codec = media::cast::CODEC_VIDEO_VP8; - } else if (params.payload.codec_name == kCodecNameH264) { - config->use_external_encoder = IsHardwareH264EncodingSupported(); - config->codec = media::cast::CODEC_VIDEO_H264; - } else { - DVLOG(1) << "codec_name " << params.payload.codec_name << " is invalid"; - return false; - } - if (!config->use_external_encoder) - config->number_of_encode_threads = NumberOfEncodeThreads(); - config->aes_key = params.payload.aes_key; - config->aes_iv_mask = params.payload.aes_iv_mask; - return true; + return supported_configs; } } // namespace @@ -595,35 +402,48 @@ DISALLOW_COPY_AND_ASSIGN(CastAudioSink); }; -CastRtpParams::CastRtpParams(const CastRtpPayloadParams& payload_params) - : payload(payload_params) {} +bool CastRtpStream::IsHardwareVP8EncodingSupported() { + const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); + if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) { + DVLOG(1) << "Disabled hardware VP8 support for Cast Streaming."; + return false; + } -CastCodecSpecificParams::CastCodecSpecificParams() {} + // Query for hardware VP8 encoder support. + const std::vector<media::VideoEncodeAccelerator::SupportedProfile> + vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles(); + for (const auto& vea_profile : vea_profiles) { + if (vea_profile.profile >= media::VP8PROFILE_MIN && + vea_profile.profile <= media::VP8PROFILE_MAX) { + return true; + } + } + return false; +} -CastCodecSpecificParams::~CastCodecSpecificParams() {} +bool CastRtpStream::IsHardwareH264EncodingSupported() { + const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); + if (cmd_line->HasSwitch(switches::kDisableCastStreamingHWEncoding)) { + DVLOG(1) << "Disabled hardware h264 support for Cast Streaming."; + return false; + } -CastRtpPayloadParams::CastRtpPayloadParams() - : payload_type(media::cast::RtpPayloadType::UNKNOWN), - max_latency_ms(0), - min_latency_ms(0), - ssrc(0), - feedback_ssrc(0), - clock_rate(0), - max_bitrate(0), - min_bitrate(0), - channels(0), - max_frame_rate(0.0) {} - -CastRtpPayloadParams::CastRtpPayloadParams(const CastRtpPayloadParams& other) = - default; - -CastRtpPayloadParams::~CastRtpPayloadParams() {} - -CastRtpParams::CastRtpParams() {} - -CastRtpParams::CastRtpParams(const CastRtpParams& other) = default; - -CastRtpParams::~CastRtpParams() {} +// Query for hardware H.264 encoder support. +// +// TODO(miu): Look into why H.264 hardware encoder on MacOS is broken. +// http://crbug.com/596674 +#if !defined(OS_MACOSX) + const std::vector<media::VideoEncodeAccelerator::SupportedProfile> + vea_profiles = content::GetSupportedVideoEncodeAcceleratorProfiles(); + for (const auto& vea_profile : vea_profiles) { + if (vea_profile.profile >= media::H264PROFILE_MIN && + vea_profile.profile <= media::H264PROFILE_MAX) { + return true; + } + } +#endif // !defined(OS_MACOSX) + return false; +} CastRtpStream::CastRtpStream(const blink::WebMediaStreamTrack& track, const scoped_refptr<CastSession>& session) @@ -633,16 +453,14 @@ Stop(); } -std::vector<CastRtpParams> CastRtpStream::GetSupportedParams() { +std::vector<FrameSenderConfig> CastRtpStream::GetSupportedConfigs() { if (IsAudio()) - return SupportedAudioParams(); + return SupportedAudioConfigs(); else - return SupportedVideoParams(); + return SupportedVideoConfigs(); } -CastRtpParams CastRtpStream::GetParams() { return params_; } - -void CastRtpStream::Start(const CastRtpParams& params, +void CastRtpStream::Start(const FrameSenderConfig& config, const base::Closure& start_callback, const base::Closure& stop_callback, const ErrorCallback& error_callback) { @@ -655,18 +473,10 @@ error_callback_ = error_callback; if (IsAudio()) { - AudioSenderConfig config; - if (!ToAudioSenderConfig(params, &config)) { - DidEncounterError("Invalid parameters for audio."); - return; - } - // In case of error we have to go through DidEncounterError() to stop // the streaming after reporting the error. - audio_sink_.reset(new CastAudioSink( - track_, - params.payload.channels, - params.payload.clock_rate)); + audio_sink_.reset( + new CastAudioSink(track_, config.channels, config.rtp_timebase)); cast_session_->StartAudio( config, base::Bind(&CastAudioSink::AddToTrack, audio_sink_->AsWeakPtr()), @@ -674,11 +484,6 @@ weak_factory_.GetWeakPtr())); start_callback.Run(); } else { - VideoSenderConfig config; - if (!ToVideoSenderConfig(params, &config)) { - DidEncounterError("Invalid parameters for video."); - return; - } // See the code for audio above for explanation of callbacks. video_sink_.reset(new CastVideoSink( track_, @@ -686,7 +491,7 @@ weak_factory_.GetWeakPtr())))); cast_session_->StartVideo( config, base::Bind(&CastVideoSink::AddToTrack, video_sink_->AsWeakPtr(), - !params.payload.aes_key.empty()), + !config.aes_key.empty()), base::Bind(&CastRtpStream::DidEncounterError, weak_factory_.GetWeakPtr())); start_callback.Run();
diff --git a/chrome/renderer/media/cast_rtp_stream.h b/chrome/renderer/media/cast_rtp_stream.h index 456463e..01c3da8 100644 --- a/chrome/renderer/media/cast_rtp_stream.h +++ b/chrome/renderer/media/cast_rtp_stream.h
@@ -26,86 +26,6 @@ class CastSession; class CastVideoSink; -// A key value pair structure for codec specific parameters. -struct CastCodecSpecificParams { - std::string key; - std::string value; - - CastCodecSpecificParams(); - ~CastCodecSpecificParams(); -}; - -// Defines the basic properties of a payload supported by cast transport. -struct CastRtpPayloadParams { - // RTP specific field that identifies the content type. - media::cast::RtpPayloadType payload_type = - media::cast::RtpPayloadType::VIDEO_VP8; - - // Maximum latency in milliseconds. Implemetation tries to keep latency - // under this threshold. - int max_latency_ms = media::cast::kDefaultRtpMaxDelayMs; - - // Minimum latency. - // Default value (0) means use max_latency_ms. - int min_latency_ms = 0; - - // Starting latency on animated content. - // Default value (0) means use max_latency_ms. - int animated_latency_ms = 0; - - // RTP specific field to identify a stream. - int ssrc = 1; - - // RTP specific field to idenfity the feedback stream. - int feedback_ssrc = 2; - - // Update frequency of payload sample. - int clock_rate = media::cast::kVideoFrequency; - - // Maximum bitrate in kilobits per second. - int max_bitrate = media::cast::kDefaultMaxVideoKbps; - - // Minimum bitrate in kilobits per second. - int min_bitrate = media::cast::kDefaultMinVideoKbps; - - // Number of audio channels. - int channels = 1; - - // The maximum frame rate. - double max_frame_rate = media::cast::kDefaultMaxFrameRate; - - // Name of the codec used. - std::string codec_name; - - // AES encryption key. - std::string aes_key; - - // AES encryption IV mask. - std::string aes_iv_mask; - - // List of codec specific parameters. - std::vector<CastCodecSpecificParams> codec_specific_params; - - CastRtpPayloadParams(); - CastRtpPayloadParams(const CastRtpPayloadParams& other); - ~CastRtpPayloadParams(); -}; - -// Defines the parameters of a RTP stream. -struct CastRtpParams { - explicit CastRtpParams(const CastRtpPayloadParams& payload_params); - - // Payload parameters. - CastRtpPayloadParams payload; - - // Names of supported RTCP features. - std::vector<std::string> rtcp_features; - - CastRtpParams(); - CastRtpParams(const CastRtpParams& other); - ~CastRtpParams(); -}; - // This object represents a RTP stream that encodes and optionally // encrypt audio or video data from a WebMediaStreamTrack. // Note that this object does not actually output packets. It allows @@ -115,22 +35,23 @@ public: typedef base::Callback<void(const std::string&)> ErrorCallback; + static bool IsHardwareVP8EncodingSupported(); + + static bool IsHardwareH264EncodingSupported(); + CastRtpStream(const blink::WebMediaStreamTrack& track, const scoped_refptr<CastSession>& session); ~CastRtpStream(); // Return parameters currently supported by this stream. - std::vector<CastRtpParams> GetSupportedParams(); - - // Return parameters set to this stream. - CastRtpParams GetParams(); + std::vector<media::cast::FrameSenderConfig> GetSupportedConfigs(); // Begin encoding of media stream and then submit the encoded streams // to underlying transport. // When the stream is started |start_callback| is called. // When the stream is stopped |stop_callback| is called. // When there is an error |error_callback| is called with a message. - void Start(const CastRtpParams& params, + void Start(const media::cast::FrameSenderConfig& config, const base::Closure& start_callback, const base::Closure& stop_callback, const ErrorCallback& error_callback); @@ -163,7 +84,6 @@ const scoped_refptr<CastSession> cast_session_; std::unique_ptr<CastAudioSink> audio_sink_; std::unique_ptr<CastVideoSink> video_sink_; - CastRtpParams params_; base::Closure stop_callback_; ErrorCallback error_callback_;
diff --git a/chrome/renderer/media/cast_session.cc b/chrome/renderer/media/cast_session.cc index 61ce4379..c9fc3a6 100644 --- a/chrome/renderer/media/cast_session.cc +++ b/chrome/renderer/media/cast_session.cc
@@ -53,7 +53,7 @@ CHECK(io_task_runner_->DeleteSoon(FROM_HERE, delegate_.release())); } -void CastSession::StartAudio(const media::cast::AudioSenderConfig& config, +void CastSession::StartAudio(const media::cast::FrameSenderConfig& config, const AudioFrameInputAvailableCallback& callback, const ErrorCallback& error_callback) { DCHECK(content::RenderThread::Get()); @@ -67,7 +67,7 @@ media::BindToCurrentLoop(error_callback))); } -void CastSession::StartVideo(const media::cast::VideoSenderConfig& config, +void CastSession::StartVideo(const media::cast::FrameSenderConfig& config, const VideoFrameInputAvailableCallback& callback, const ErrorCallback& error_callback) { DCHECK(content::RenderThread::Get());
diff --git a/chrome/renderer/media/cast_session.h b/chrome/renderer/media/cast_session.h index 658e2e7d..2ccbc747 100644 --- a/chrome/renderer/media/cast_session.h +++ b/chrome/renderer/media/cast_session.h
@@ -60,10 +60,10 @@ // error message. Both |callback| and |error_callback| will be made on // the main thread. // |StartUDP()| must be called before these methods. - void StartAudio(const media::cast::AudioSenderConfig& config, + void StartAudio(const media::cast::FrameSenderConfig& config, const AudioFrameInputAvailableCallback& callback, const ErrorCallback& error_callback); - void StartVideo(const media::cast::VideoSenderConfig& config, + void StartVideo(const media::cast::FrameSenderConfig& config, const VideoFrameInputAvailableCallback& callback, const ErrorCallback& error_callback);
diff --git a/chrome/renderer/media/cast_session_delegate.cc b/chrome/renderer/media/cast_session_delegate.cc index 90d98957..5596d5d 100644 --- a/chrome/renderer/media/cast_session_delegate.cc +++ b/chrome/renderer/media/cast_session_delegate.cc
@@ -29,10 +29,9 @@ #include "media/cast/net/cast_transport.h" #include "media/cast/net/cast_transport_config.h" -using media::cast::AudioSenderConfig; using media::cast::CastEnvironment; using media::cast::CastSender; -using media::cast::VideoSenderConfig; +using media::cast::FrameSenderConfig; static base::LazyInstance<CastThreads> g_cast_threads = LAZY_INSTANCE_INITIALIZER; @@ -116,7 +115,7 @@ } void CastSessionDelegate::StartAudio( - const AudioSenderConfig& config, + const FrameSenderConfig& config, const AudioFrameInputAvailableCallback& callback, const ErrorCallback& error_callback) { DCHECK(io_task_runner_->BelongsToCurrentThread()); @@ -134,7 +133,7 @@ } void CastSessionDelegate::StartVideo( - const VideoSenderConfig& config, + const FrameSenderConfig& config, const VideoFrameInputAvailableCallback& callback, const ErrorCallback& error_callback, const media::cast::CreateVideoEncodeAcceleratorCallback& create_vea_cb,
diff --git a/chrome/renderer/media/cast_session_delegate.h b/chrome/renderer/media/cast_session_delegate.h index dbe7626..54cf520b 100644 --- a/chrome/renderer/media/cast_session_delegate.h +++ b/chrome/renderer/media/cast_session_delegate.h
@@ -104,17 +104,17 @@ // deliver any data between calling the two methods. // It's OK to call only one of the two methods. // StartUDP must be called before these methods. - void StartAudio(const media::cast::AudioSenderConfig& config, + void StartAudio(const media::cast::FrameSenderConfig& config, const AudioFrameInputAvailableCallback& callback, const ErrorCallback& error_callback); - void StartVideo(const media::cast::VideoSenderConfig& config, - const VideoFrameInputAvailableCallback& callback, - const ErrorCallback& error_callback, - const media::cast::CreateVideoEncodeAcceleratorCallback& - create_vea_cb, - const media::cast::CreateVideoEncodeMemoryCallback& - create_video_encode_mem_cb); + void StartVideo( + const media::cast::FrameSenderConfig& config, + const VideoFrameInputAvailableCallback& callback, + const ErrorCallback& error_callback, + const media::cast::CreateVideoEncodeAcceleratorCallback& create_vea_cb, + const media::cast::CreateVideoEncodeMemoryCallback& + create_video_encode_mem_cb); void ToggleLogging(bool is_audio, bool enable); void GetEventLogsAndReset(bool is_audio,
diff --git a/chrome/renderer/pepper/pepper_uma_host.cc b/chrome/renderer/pepper/pepper_uma_host.cc index 6a1e5a3..56ef732 100644 --- a/chrome/renderer/pepper/pepper_uma_host.cc +++ b/chrome/renderer/pepper/pepper_uma_host.cc
@@ -10,6 +10,7 @@ #include "base/metrics/histogram.h" #include "base/sha1.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "chrome/common/chrome_content_client.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/render_messages.h" @@ -113,7 +114,8 @@ } bool PepperUMAHost::IsHistogramAllowed(const std::string& histogram) { - if (is_plugin_in_process_ && histogram.find("NaCl.") == 0) { + if (is_plugin_in_process_ && + base::StartsWith(histogram, "NaCl.", base::CompareCase::SENSITIVE)) { return true; }
diff --git a/chrome/renderer/plugins/OWNERS b/chrome/renderer/plugins/OWNERS index 00985a81..21efaa10 100644 --- a/chrome/renderer/plugins/OWNERS +++ b/chrome/renderer/plugins/OWNERS
@@ -1 +1,2 @@ bauerb@chromium.org +tommycli@chromium.org
diff --git a/chrome/renderer/plugins/chrome_plugin_placeholder.cc b/chrome/renderer/plugins/chrome_plugin_placeholder.cc index 59397979..575aeda 100644 --- a/chrome/renderer/plugins/chrome_plugin_placeholder.cc +++ b/chrome/renderer/plugins/chrome_plugin_placeholder.cc
@@ -65,7 +65,7 @@ status_(ChromeViewHostMsg_GetPluginInfo_Status::kAllowed), title_(title), context_menu_request_id_(0), - ignore_updates_(false) { + did_send_blocked_content_notification_(false) { RenderThread::Get()->AddObserver(this); } @@ -170,39 +170,6 @@ return blocked_plugin; } -// static -ChromePluginPlaceholder* ChromePluginPlaceholder::CreateDelayedPlugin( - content::RenderFrame* render_frame, - blink::WebLocalFrame* frame, - const blink::WebPluginParams& params, - const content::WebPluginInfo& info, - const std::string& identifier, - const base::string16& name, - const PowerSaverInfo& power_saver_info) { - // Can never be called with an actual poster. - DCHECK(power_saver_info.poster_attribute.empty()); - - // Can never be called when blocked for background tab. - DCHECK(!power_saver_info.blocked_for_background_tab); - - const base::StringPiece template_html( - ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_PLUGIN_DELAY_HTML)); - base::DictionaryValue values; - std::string html_data = webui::GetI18nTemplateHtml(template_html, &values); - - // |delay_plugin| will destroy itself when its WebViewPlugin is going away. - ChromePluginPlaceholder* delay_plugin = - new ChromePluginPlaceholder(render_frame, frame, params, html_data, name); - - delay_plugin->set_delayed(true); - delay_plugin->SetPluginInfo(info); - delay_plugin->SetIdentifier(identifier); - delay_plugin->set_power_saver_enabled(power_saver_info.power_saver_enabled); - - return delay_plugin; -} - void ChromePluginPlaceholder::SetStatus( ChromeViewHostMsg_GetPluginInfo_Status status) { status_ = status; @@ -408,33 +375,13 @@ GetPluginParams(), std::move(throttler)); } -void ChromePluginPlaceholder::OnLoadedRectUpdate( - const gfx::Rect& unobscured_rect, - content::RenderFrame::PeripheralContentStatus status) { - // If the placeholder is in the blocked state, do nothing. - if (ignore_updates_) +void ChromePluginPlaceholder::OnBlockedTinyContent() { + if (did_send_blocked_content_notification_) return; - // This should only be called once. - set_delayed(false); - - // block tiny cross-origin - simply by not continuing the load chain. - if (status == - content::RenderFrame::CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_TINY) { - ContentSettingsObserver* observer = - ContentSettingsObserver::Get(render_frame()); - observer->DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS, title_); - AllowLoading(); - ignore_updates_ = true; - return; - } - - // For essential content, powersaver can be turned off. - if (status != content::RenderFrame::CONTENT_STATUS_PERIPHERAL) - set_power_saver_enabled(false); - - AllowLoading(); - LoadPlugin(); + did_send_blocked_content_notification_ = true; + ContentSettingsObserver::Get(render_frame()) + ->DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS, title_); } gin::ObjectTemplateBuilder ChromePluginPlaceholder::GetObjectTemplateBuilder(
diff --git a/chrome/renderer/plugins/chrome_plugin_placeholder.h b/chrome/renderer/plugins/chrome_plugin_placeholder.h index 78348cf2..e174f6c 100644 --- a/chrome/renderer/plugins/chrome_plugin_placeholder.h +++ b/chrome/renderer/plugins/chrome_plugin_placeholder.h
@@ -37,16 +37,6 @@ const base::string16& message, const PowerSaverInfo& power_saver_info); - // Create a plugin placeholder that delays until sizing is known. - static ChromePluginPlaceholder* CreateDelayedPlugin( - content::RenderFrame* render_frame, - blink::WebLocalFrame* frame, - const blink::WebPluginParams& params, - const content::WebPluginInfo& info, - const std::string& identifier, - const base::string16& name, - const PowerSaverInfo& power_saver_info); - // Creates a new WebViewPlugin with a MissingPlugin as a delegate. static ChromePluginPlaceholder* CreateLoadableMissingPlugin( content::RenderFrame* render_frame, @@ -69,9 +59,7 @@ // content::LoadablePluginPlaceholder overrides. blink::WebPlugin* CreatePlugin() override; - void OnLoadedRectUpdate( - const gfx::Rect& unobscured_rect, - content::RenderFrame::PeripheralContentStatus status) override; + void OnBlockedTinyContent() override; // gin::Wrappable (via PluginPlaceholder) method gin::ObjectTemplateBuilder GetObjectTemplateBuilder( @@ -120,7 +108,7 @@ int context_menu_request_id_; // Nonzero when request pending. base::string16 plugin_name_; - bool ignore_updates_; + bool did_send_blocked_content_notification_; DISALLOW_COPY_AND_ASSIGN(ChromePluginPlaceholder); };
diff --git a/chrome/renderer/plugins/power_saver_info.cc b/chrome/renderer/plugins/power_saver_info.cc index 9de969413..6209b64 100644 --- a/chrome/renderer/plugins/power_saver_info.cc +++ b/chrome/renderer/plugins/power_saver_info.cc
@@ -71,9 +71,7 @@ } // namespace PowerSaverInfo::PowerSaverInfo() - : is_eligible(false), - power_saver_enabled(false), - blocked_for_background_tab(false) {} + : power_saver_enabled(false), blocked_for_background_tab(false) {} PowerSaverInfo::PowerSaverInfo(const PowerSaverInfo& other) = default; @@ -92,10 +90,10 @@ plugin_info.name == base::ASCIIToUTF16(content::kFlashPluginName); PowerSaverInfo info; - info.is_eligible = power_saver_setting_on && + bool is_eligible = power_saver_setting_on && (is_flash || override_for_testing == "ignore-list"); info.power_saver_enabled = override_for_testing == "always" || - (power_saver_setting_on && info.is_eligible); + (power_saver_setting_on && is_eligible); if (info.power_saver_enabled) { // Even if we disable PPS in the next block because content is same-origin,
diff --git a/chrome/renderer/plugins/power_saver_info.h b/chrome/renderer/plugins/power_saver_info.h index bbcd7ac..ec1c5de 100644 --- a/chrome/renderer/plugins/power_saver_info.h +++ b/chrome/renderer/plugins/power_saver_info.h
@@ -31,8 +31,6 @@ const blink::WebPluginParams& params, const content::WebPluginInfo& plugin_info, const GURL& document_url); - // Whether this plugin is eligible for power saver. - bool is_eligible; // Whether power saver should be enabled. bool power_saver_enabled;
diff --git a/chrome/renderer/resources/plugins/blocked_plugin.html b/chrome/renderer/resources/plugins/blocked_plugin.html index 89de1eb..94313a1 100644 --- a/chrome/renderer/resources/plugins/blocked_plugin.html +++ b/chrome/renderer/resources/plugins/blocked_plugin.html
@@ -11,6 +11,9 @@ function notifyDidFinishLoading() { if (plugin.didFinishLoading) plugin.didFinishLoading(); + + if (plugin.didFinishIconRepositionForTesting) + plugin.didFinishIconRepositionForTesting(); } </script> </if>
diff --git a/chrome/renderer/resources/plugins/plugin_delay.html b/chrome/renderer/resources/plugins/plugin_delay.html deleted file mode 100644 index 2414abf2..0000000 --- a/chrome/renderer/resources/plugins/plugin_delay.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!doctype html> -<html> -<head> -<meta charset="utf-8"> -<meta name="viewport" content="width=device-width, user-scalable=no"> -<script> - window.onload = function() { - if (plugin.didFinishLoading) - plugin.didFinishLoading(); - if (plugin.didFinishIconRepositionForTesting) { - // Defer until reflow complete. - window.setTimeout(function() { - plugin.didFinishIconRepositionForTesting(); - }); - }}; -</script> -<body> - <div></div> -</body> -</html> -
diff --git a/chrome/renderer/resources/renderer_resources.grd b/chrome/renderer/resources/renderer_resources.grd index ed40ef9..732d4c6 100644 --- a/chrome/renderer/resources/renderer_resources.grd +++ b/chrome/renderer/resources/renderer_resources.grd
@@ -19,7 +19,6 @@ </if> <include name="IDR_BLOCKED_PLUGIN_HTML" file="plugins/blocked_plugin.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_DISABLED_PLUGIN_HTML" file="plugins/disabled_plugin.html" flattenhtml="true" type="BINDATA" /> - <include name="IDR_PLUGIN_DELAY_HTML" file="plugins/plugin_delay.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_PLUGIN_POSTER_HTML" file="plugins/plugin_poster.html" flattenhtml="true" type="BINDATA" /> <!-- Searchbox API -->
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 1e608bbd..62ae088 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -375,6 +375,10 @@ "//third_party/zlib/google/test/data/", "//tools/metrics/histograms/histograms.xml", "$root_out_dir/pyproto/google/", + "$root_out_dir/test_case.html", + "$root_out_dir/test_case.html.mock-http-headers", + "$root_out_dir/test_page.css", + "$root_out_dir/test_page.css.mock-http-headers", "$root_out_dir/ui_test.pak", ] if (is_linux || is_win) { @@ -662,7 +666,7 @@ } if (enable_app_list && use_ash) { - source_set("test_support_applist_ash") { + static_library("test_support_applist_ash") { defines = [] testonly = true @@ -678,7 +682,7 @@ } } - source_set("sync_integration_test_support") { + static_library("sync_integration_test_support") { testonly = true sources = rebase_path( chrome_tests_gypi_values.test_support_sync_integration_sources, @@ -2288,6 +2292,9 @@ ".", "//chrome") } + if (enable_supervised_users && !is_android && !is_chromeos) { + sources += [ "../browser/ui/webui/signin/signin_supervised_user_import_handler_unittest.cc" ] + } if (safe_browsing_mode == 1 && enable_extensions) { sources += [ "../browser/extensions/blacklist_unittest.cc" ] } @@ -2431,7 +2438,7 @@ } } -source_set("test_support_unit") { +static_library("test_support_unit") { testonly = true sources = [ "../browser/sync/glue/session_sync_test_helper.cc",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn index ece3423..54b23515 100644 --- a/chrome/test/android/BUILD.gn +++ b/chrome/test/android/BUILD.gn
@@ -55,11 +55,13 @@ "javatests/src/org/chromium/chrome/test/util/PrerenderTestHelper.java", "javatests/src/org/chromium/chrome/test/util/TabStripUtils.java", "javatests/src/org/chromium/chrome/test/util/TranslateUtil.java", + "javatests/src/org/chromium/chrome/test/webapk/TestWebApkServiceImplWrapper.java", ] deps = [ "//base:base_java", "//base:base_java_test_support", "//chrome/android:chrome_java", + "//chrome/android/webapk/libs/runtime_library:runtime_library_java", "//components/bookmarks/common/android:bookmarks_java", "//components/invalidation/impl:java", "//components/location/android:location_java",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/webapk/TestWebApkServiceImplWrapper.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/webapk/TestWebApkServiceImplWrapper.java new file mode 100644 index 0000000..71ae8d2f2 --- /dev/null +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/webapk/TestWebApkServiceImplWrapper.java
@@ -0,0 +1,28 @@ +// 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. + +package org.chromium.chrome.test.webapk; + +import android.app.Service; +import android.content.Intent; +import android.os.Bundle; +import android.os.IBinder; + +import org.chromium.webapk.lib.runtime_library.WebApkServiceImpl; + +/** + * Simple service which uses {@link WebApkServiceImpl} for testing. + */ +public class TestWebApkServiceImplWrapper extends Service { + @Override + public IBinder onBind(Intent intent) { + int smallIconId = intent.getIntExtra(WebApkServiceImpl.KEY_SMALL_ICON_ID, -1); + int authorizedAppUid = intent.getIntExtra(WebApkServiceImpl.KEY_HOST_BROWSER_UID, -1); + + Bundle bundle = new Bundle(); + bundle.putInt(WebApkServiceImpl.KEY_SMALL_ICON_ID, smallIconId); + bundle.putInt(WebApkServiceImpl.KEY_HOST_BROWSER_UID, authorizedAppUid); + return (IBinder) new WebApkServiceImpl(this, bundle); + } +}
diff --git a/chrome/test/base/menu_model_test.cc b/chrome/test/base/menu_model_test.cc index 4b1b25b..63b113e 100644 --- a/chrome/test/base/menu_model_test.cc +++ b/chrome/test/base/menu_model_test.cc
@@ -17,7 +17,7 @@ bool MenuModelTest::Delegate::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; }
diff --git a/chrome/test/base/menu_model_test.h b/chrome/test/base/menu_model_test.h index 8133485..f321f46 100644 --- a/chrome/test/base/menu_model_test.h +++ b/chrome/test/base/menu_model_test.h
@@ -25,8 +25,9 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; - bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + bool GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; int execute_count_;
diff --git a/chrome/test/base/web_ui_browser_test.cc b/chrome/test/base/web_ui_browser_test.cc index 4a55e86..5dd1111 100644 --- a/chrome/test/base/web_ui_browser_test.cc +++ b/chrome/test/base/web_ui_browser_test.cc
@@ -459,7 +459,12 @@ test_handler_->RunJavaScript(content); if (error_messages_.Get().size() > 0) { - LOG(ERROR) << "Encountered javascript console error(s)"; + LOG(ERROR) << "CONDITION FAILURE: encountered javascript console error(s):"; + for (const auto& msg : error_messages_.Get()) { + LOG(ERROR) << "JS ERROR: '" << msg << "'"; + } + LOG(ERROR) << "JS call assumed failed, because JS console error(s) found."; + result = false; error_messages_.Get().clear(); }
diff --git a/chrome/test/chromedriver/chrome/browser_info.cc b/chrome/test/chromedriver/chrome/browser_info.cc index 6938c38..c790bfd5d 100644 --- a/chrome/test/chromedriver/chrome/browser_info.cc +++ b/chrome/test/chromedriver/chrome/browser_info.cc
@@ -16,7 +16,8 @@ namespace { -const std::string kVersionPrefix = "Chrome/"; +const char kVersionPrefix[] = "Chrome/"; +const size_t kVersionPrefixLen = sizeof(kVersionPrefix) - 1; } // namespace @@ -86,8 +87,9 @@ } int build_no = 0; - if (browser_string.find(kVersionPrefix) == 0u) { - std::string version = browser_string.substr(kVersionPrefix.length()); + if (base::StartsWith(browser_string, kVersionPrefix, + base::CompareCase::SENSITIVE)) { + std::string version = browser_string.substr(kVersionPrefixLen); Status status = ParseBrowserVersionString( version, &browser_info->major_version, &build_no); @@ -108,7 +110,7 @@ if (pos != std::string::npos) { browser_info->browser_name = "webview"; browser_info->browser_version = - browser_string.substr(pos + kVersionPrefix.length()); + browser_string.substr(pos + kVersionPrefixLen); browser_info->is_android = true; return ParseBrowserVersionString(browser_info->browser_version, &browser_info->major_version, &build_no);
diff --git a/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc b/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc index a9685328..65784da8 100644 --- a/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc +++ b/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc
@@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/posix/eintr_wrapper.h" #include "base/process/kill.h" +#include "base/strings/string_util.h" #include "base/sys_info.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" @@ -122,7 +123,7 @@ for (size_t i = 0; i < views_info.GetSize(); ++i) { const WebViewInfo& view_info = views_info.Get(i); - if (view_info.url.find(url) == 0) { + if (base::StartsWith(view_info.url, url, base::CompareCase::SENSITIVE)) { id = view_info.id; type = view_info.type; break;
diff --git a/chrome/test/chromedriver/chrome/devtools_http_client.cc b/chrome/test/chromedriver/chrome/devtools_http_client.cc index eb83d768..5174512 100644 --- a/chrome/test/chromedriver/chrome/devtools_http_client.cc +++ b/chrome/test/chromedriver/chrome/devtools_http_client.cc
@@ -9,6 +9,8 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/json/json_reader.h" +#include "base/stl_util.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" @@ -32,7 +34,8 @@ WebViewInfo::~WebViewInfo() {} bool WebViewInfo::IsFrontend() const { - return url.find("chrome-devtools://") == 0u; + return base::StartsWith(url, "chrome-devtools://", + base::CompareCase::SENSITIVE); } bool WebViewInfo::IsInactiveBackgroundPage() const { @@ -153,11 +156,12 @@ } bool DevToolsHttpClient::IsBrowserWindow(const WebViewInfo& view) const { - return window_types_->find(view.type) != window_types_->end() || - (view.type == WebViewInfo::kOther && - (view.url.find("chrome-extension://") == 0 || - view.url == "chrome://print/" || - view.url == "chrome://media-router/")); + return ContainsKey(*window_types_, view.type) || + (view.type == WebViewInfo::kOther && + (base::StartsWith(view.url, "chrome-extension://", + base::CompareCase::SENSITIVE) || + view.url == "chrome://print/" || + view.url == "chrome://media-router/")); } Status DevToolsHttpClient::CloseFrontends(const std::string& for_client_id) {
diff --git a/chrome/test/data/android/payments/fail_complete.js b/chrome/test/data/android/payments/fail_complete.js new file mode 100644 index 0000000..4635f65 --- /dev/null +++ b/chrome/test/data/android/payments/fail_complete.js
@@ -0,0 +1,33 @@ +/* + * 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. + */ + +/* global PaymentRequest:false */ + +/** + * Launches the PaymentRequest UI and always fails to complete the transaction. + */ +function buy() { // eslint-disable-line no-unused-vars + try { + new PaymentRequest( + [{supportedMethods: ['visa']}], + {total: {label: 'Total', amount: {currency: 'USD', value: '5.00'}}}) + .show() + .then(function(resp) { + resp.complete('fail') + .then(function() { + print('Transaction failed'); + }) + .catch(function(error) { + print(error.message); + }); + }) + .catch(function(error) { + print(error.message); + }); + } catch (error) { + print(error.message); + } +}
diff --git a/chrome/test/data/android/payments/payment_request_fail_complete_test.html b/chrome/test/data/android/payments/payment_request_fail_complete_test.html new file mode 100644 index 0000000..9e7dcd9 --- /dev/null +++ b/chrome/test/data/android/payments/payment_request_fail_complete_test.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<!-- +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. +--> +<html> +<head> +<title>No Shipping 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">Fail Complete Test</button> +<pre id="result"></pre> +<script src="util.js"></script> +<script src="fail_complete.js"></script> +</body> +</html>
diff --git a/chrome/test/data/extensions/api_test/cast_streaming/rtp_stream_error.js b/chrome/test/data/extensions/api_test/cast_streaming/rtp_stream_error.js index 9db1949..b67ddf6a 100644 --- a/chrome/test/data/extensions/api_test/cast_streaming/rtp_stream_error.js +++ b/chrome/test/data/extensions/api_test/cast_streaming/rtp_stream_error.js
@@ -31,19 +31,21 @@ pass(function(stream, audioId, videoId, udpId) { var audioParams = rtpStream.getSupportedParams(audioId)[0]; var videoParams = rtpStream.getSupportedParams(videoId)[0]; - rtpStream.onError.addListener( - pass(function(audioId, videoId, id, msg) { - chrome.test.assertEq(videoId, id); - rtpStream.destroy(audioId); - rtpStream.destroy(videoId); - udpTransport.destroy(udpId); - console.log(msg); - }.bind(null, audioId, videoId))); // Specify invalid value to trigger error. videoParams.payload.codecName = "Animated WebP"; udpTransport.setDestination(udpId, {address: "127.0.0.1", port: 2344}); - rtpStream.start(videoId, videoParams); + try { + rtpStream.start(videoId, videoParams); + chrome.test.fail(); + } catch (e) { + rtpStream.stop(audioId); + rtpStream.stop(videoId); + rtpStream.destroy(audioId); + rtpStream.destroy(videoId); + udpTransport.destroy(udpId); + chrome.test.succeed(); + } }.bind(null, stream))); })); },
diff --git a/chrome/test/data/pdf/test-link.pdf b/chrome/test/data/pdf/test-link.pdf new file mode 100644 index 0000000..d9e8737 --- /dev/null +++ b/chrome/test/data/pdf/test-link.pdf Binary files differ
diff --git a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js index 4e13fcd..eb6b320 100644 --- a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js +++ b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
@@ -96,3 +96,22 @@ cr_slider.registerTests(); mocha.run(); }); + +function CrElementsSharedMenuTest() {} + +CrElementsSharedMenuTest.prototype = { + __proto__: CrElementsBrowserTest.prototype, + + /** @override */ + browsePreload: + 'chrome://resources/cr_elements/cr_shared_menu/cr_shared_menu.html', + + /** @override */ + extraLibraries: CrElementsBrowserTest.prototype.extraLibraries.concat([ + 'cr_shared_menu_tests.js' + ]), +}; + +TEST_F('CrElementsSharedMenuTest', 'All', function() { + mocha.run(); +});
diff --git a/chrome/test/data/webui/cr_elements/cr_shared_menu_tests.js b/chrome/test/data/webui/cr_elements/cr_shared_menu_tests.js new file mode 100644 index 0000000..59747fa8 --- /dev/null +++ b/chrome/test/data/webui/cr_elements/cr_shared_menu_tests.js
@@ -0,0 +1,122 @@ +// 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. + +/** @fileoverview Suite of tests for cr-shared-menu. */ +suite('cr-shared-menu', function() { + var menu; + + var button; + + var item1; + var item2; + var item3; + + function afterOpen(callback) { + menu.addEventListener('iron-overlay-opened', function f() { + menu.removeEventListener('iron-overlay-opened', f); + callback(); + }); + } + + suiteSetup(function() { + return PolymerTest.importHtml( + 'chrome://resources/polymer/v1_0/paper-item/paper-item.html'); + }); + + setup(function() { + PolymerTest.clearBody(); + // Basic wiring to set up a menu which opens when a button is pressed. + menu = document.createElement('cr-shared-menu'); + menu.$$('#dropdown').noAnimations = true; + + item1 = document.createElement('paper-item'); + menu.appendChild(item1); + item2 = document.createElement('paper-item'); + menu.appendChild(item2); + item3 = document.createElement('paper-item'); + menu.appendChild(item3); + + button = document.createElement('button'); + button.addEventListener('tap', function() { + menu.toggleMenu(button, {}); + }); + + document.body.appendChild(menu); + document.body.appendChild(button); + }); + + test('opening and closing menu', function(done) { + MockInteractions.tap(button); + assertTrue(menu.menuOpen); + + afterOpen(function() { + // Using tap to close the menu requires that the iron-overlay-behavior + // has finished initializing, which happens asynchronously between + // tapping the button and firing iron-overlay-opened. + MockInteractions.tap(document.body); + assertFalse(menu.menuOpen); + + MockInteractions.tap(button); + assertTrue(menu.menuOpen); + + // Pressing escape should close the menu. + MockInteractions.pressAndReleaseKeyOn(menu, 27); + assertTrue(menu.menuOpen); + done(); + }); + }); + + test('refocus button on close', function(done) { + button.focus(); + MockInteractions.tap(button); + + afterOpen(function() { + assertTrue(menu.menuOpen); + // Focus is applied asynchronously after the menu is opened. + assertEquals(item1, menu.shadowRoot.activeElement); + + menu.closeMenu(); + assertFalse(menu.menuOpen); + + // Button should regain focus after closing the menu. + assertEquals(button, document.activeElement); + + done(); + }); + }); + + test('closeMenu does not refocus button when focus moves', function(done) { + var input = document.createElement('input'); + document.body.appendChild(input); + + button.focus(); + MockInteractions.tap(button); + + afterOpen(function() { + input.focus(); + menu.closeMenu(); + assertEquals(input, document.activeElement); + + done(); + }); + }); + + test('focus is trapped inside the menu', function(done) { + button.focus(); + MockInteractions.tap(button); + + afterOpen(function() { + // Simulate shift-tab on first element. + assertEquals(item1, menu.shadowRoot.activeElement); + MockInteractions.pressAndReleaseKeyOn(item1, 9, ['shift']); + assertEquals(item3, menu.shadowRoot.activeElement); + + // Simulate tab on last element. + MockInteractions.pressAndReleaseKeyOn(item3, 9); + assertEquals(item1, menu.shadowRoot.activeElement); + + done(); + }); + }); +});
diff --git a/chrome/test/data/webui/md_history/history_overflow_menu_test.js b/chrome/test/data/webui/md_history/history_overflow_menu_test.js index 01836a7f..b7ca2ee 100644 --- a/chrome/test/data/webui/md_history/history_overflow_menu_test.js +++ b/chrome/test/data/webui/md_history/history_overflow_menu_test.js
@@ -61,15 +61,6 @@ element.$.sharedMenu.lastAnchor_); }); - test('keyboard input for closing menu', function() { - // Test that pressing escape on the document closes the menu. In the - // actual page, it will take two presses to close the menu due to focus. - // TODO(yingran): Fix this behavior to only require one key press. - element.toggleMenu_(MENU_EVENT); - MockInteractions.pressAndReleaseKeyOn(document.body, 27); - assertEquals(false, element.$.sharedMenu.menuOpen); - }); - teardown(function() { element.$.sharedMenu.lastAnchor_ = null; });
diff --git a/chrome/test/data/webui/md_history/history_toolbar_test.js b/chrome/test/data/webui/md_history/history_toolbar_test.js index 6eb61f6..5383fd1d 100644 --- a/chrome/test/data/webui/md_history/history_toolbar_test.js +++ b/chrome/test/data/webui/md_history/history_toolbar_test.js
@@ -45,7 +45,7 @@ test('search term gathered correctly from toolbar', function(done) { app.queryState_.queryingDisabled = false; registerMessageCallback('queryHistory', this, function (info) { - assertEquals(info[0], 'Test'); + assertEquals('Test', info[0]); done(); }); @@ -70,7 +70,19 @@ document.body, 70, 'ctrl', 'f'); assertTrue(field.showingSearch); assertEquals(field.$.searchInput, field.root.activeElement); - }); + }); + + test('spinner is active on search' , function(done) { + app.queryState_.queryingDisabled = false; + registerMessageCallback('queryHistory', this, function (info) { + assertTrue(toolbar.spinnerActive); + app.historyResult(createHistoryInfo(), TEST_HISTORY_RESULTS); + assertFalse(toolbar.spinnerActive); + done(); + }); + + toolbar.$$('cr-toolbar').fire('search-changed', 'Test2'); + }); teardown(function() { element.historyData_ = [];
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js index d794223..0825574 100644 --- a/chrome/test/data/webui/settings/cr_settings_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -639,9 +639,30 @@ * @constructor * @extends {CrSettingsBrowserTest} */ -function CrSettingsRouterTest() {} +function CrSettingsRouteTest() {} -CrSettingsRouterTest.prototype = { +CrSettingsRouteTest.prototype = { + __proto__: CrSettingsBrowserTest.prototype, + + /** @override */ + browsePreload: 'chrome://md-settings/route.html', + + extraLibraries: CrSettingsBrowserTest.prototype.extraLibraries.concat([ + 'route_tests.js', + ]), +}; + +TEST_F('CrSettingsRouteTest', 'All', function() { + mocha.run(); +}); + +/** + * @constructor + * @extends {CrSettingsBrowserTest} + */ +function CrSettingsRouterElementTest() {} + +CrSettingsRouterElementTest.prototype = { __proto__: CrSettingsBrowserTest.prototype, /** @override */ @@ -652,6 +673,6 @@ ]), }; -TEST_F('CrSettingsRouterTest', 'All', function() { +TEST_F('CrSettingsRouterElementTest', 'All', function() { mocha.run(); });
diff --git a/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js b/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js index e9f83d36..08b926a0 100644 --- a/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js +++ b/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js
@@ -44,17 +44,25 @@ }; /** + * Creates a new fake address entry for testing. + * @return {!chrome.autofillPrivate.AddressEntry} + */ +FakeDataMaker.emptyAddressEntry = function() { + return {}; +} + +/** * Creates a fake address entry for testing. * @return {!chrome.autofillPrivate.AddressEntry} */ FakeDataMaker.addressEntry = function() { var ret = {}; ret.guid = FakeDataMaker.makeGuid_(); - ret.fullNames = ['John', 'Doe']; + ret.fullNames = ['John Doe']; ret.companyName = 'Google'; ret.addressLines = FakeDataMaker.patternMaker_('xxxx Main St', 10); - ret.addressLevel1 = "CA"; - ret.addressLevel2 = "Venice"; + ret.addressLevel1 = 'CA'; + ret.addressLevel2 = 'Venice'; ret.postalCode = FakeDataMaker.patternMaker_('xxxxx', 10); ret.countryCode = 'US'; ret.phoneNumbers = [FakeDataMaker.patternMaker_('(xxx) xxx-xxxx', 10)];
diff --git a/chrome/test/data/webui/settings/route_tests.js b/chrome/test/data/webui/settings/route_tests.js new file mode 100644 index 0000000..728ddfe9 --- /dev/null +++ b/chrome/test/data/webui/settings/route_tests.js
@@ -0,0 +1,49 @@ +// 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. + +suite('route', function() { + test('tree structure', function() { + // Set up root page routes. + var BASIC = new settings.Route('/'); + BASIC.page = 'basic'; + var ADVANCED = new settings.Route('/advanced'); + ADVANCED.page = 'advanced'; + assertDeepEquals([], ADVANCED.subpage); + + // Test a section route. + var PRIVACY = ADVANCED.createChild('/privacy'); + PRIVACY.section = 'privacy'; + assertEquals('advanced', PRIVACY.page); + assertDeepEquals([], PRIVACY.subpage); + assertFalse(PRIVACY.isDescendantOf(BASIC)); + assertTrue(PRIVACY.isDescendantOf(ADVANCED)); + assertFalse(PRIVACY.isDescendantOf(PRIVACY)); + assertFalse(ADVANCED.isDescendantOf(PRIVACY)); + + // Test a subpage route. + var SITE_SETTINGS = PRIVACY.createChild('/siteSettings', 'site-settings'); + assertFalse(SITE_SETTINGS.dialog); + assertDeepEquals(['site-settings'], SITE_SETTINGS.subpage); + assertEquals('advanced', SITE_SETTINGS.page); + assertEquals('privacy', SITE_SETTINGS.section); + assertFalse(SITE_SETTINGS.isDescendantOf(BASIC)); + assertTrue(SITE_SETTINGS.isDescendantOf(ADVANCED)); + assertTrue(SITE_SETTINGS.isDescendantOf(PRIVACY)); + + // Test a sub-subpage route. + var SITE_SETTINGS_ALL = + SITE_SETTINGS.createChild('/siteSettings/all', 'all-sites'); + assertDeepEquals(['site-settings', 'all-sites'], SITE_SETTINGS_ALL.subpage); + + // Test a dialog route. + var CLEAR_BROWSING_DATA = PRIVACY.createDialog('/clearBrowsingData'); + assertTrue(CLEAR_BROWSING_DATA.dialog); + assertEquals('privacy', CLEAR_BROWSING_DATA.section); + assertEquals('advanced', CLEAR_BROWSING_DATA.page); + assertEquals('privacy', CLEAR_BROWSING_DATA.section); + assertFalse(CLEAR_BROWSING_DATA.isDescendantOf(BASIC)); + assertTrue(CLEAR_BROWSING_DATA.isDescendantOf(ADVANCED)); + assertTrue(CLEAR_BROWSING_DATA.isDescendantOf(PRIVACY)); + }); +});
diff --git a/chrome/test/data/webui/settings/search_engines_page_test.js b/chrome/test/data/webui/settings/search_engines_page_test.js index a96ecee..599043e 100644 --- a/chrome/test/data/webui/settings/search_engines_page_test.js +++ b/chrome/test/data/webui/settings/search_engines_page_test.js
@@ -16,7 +16,7 @@ canBeEdited: canBeEdited, canBeRemoved: canBeRemoved, default: false, - displayName: "Google", + displayName: "Google displayName", iconURL: "http://www.google.com/favicon.ico", isOmniboxExtension: false, keyword: "google.com", @@ -34,7 +34,7 @@ canBeEdited: false, canBeRemoved: false, default: false, - displayName: "Omnibox extension", + displayName: "Omnibox extension displayName", extension: { icon: "chrome://extension-icon/some-extension-icon", id: "dummyextensionid", @@ -143,19 +143,39 @@ /** @type {?SettingsSearchEngineEntryElement} */ var entry = null; + /** @type {!settings_search.TestSearchEnginesBrowserProxy} */ var browserProxy = null; + /** @type {!SearchEngine} */ + var searchEngine = createSampleSearchEngine(true, true, true); + setup(function() { browserProxy = new settings_search.TestSearchEnginesBrowserProxy(); settings.SearchEnginesBrowserProxyImpl.instance_ = browserProxy; PolymerTest.clearBody(); entry = document.createElement('settings-search-engine-entry'); - entry.set('engine', createSampleSearchEngine(true, true, true)); + entry.set('engine', searchEngine); document.body.appendChild(entry); }); teardown(function() { entry.remove(); }); + // Test that the <search-engine-entry> is populated according to its + // underlying SearchEngine model. + test('Initialization', function() { + var nameElement = entry.$$('.name'); + assertTrue(!!nameElement); + assertEquals(searchEngine.displayName, nameElement.textContent); + + var keywordElement = entry.$$('.keyword-column'); + assertTrue(!!keywordElement); + assertEquals(searchEngine.keyword, keywordElement.textContent); + + var urlElement = entry.$$('.url-column'); + assertTrue(!!urlElement); + assertEquals(searchEngine.url, urlElement.textContent); + }); + test('Remove_Enabled', function() { var deleteButton = entry.$.delete; assertTrue(!!deleteButton); @@ -191,7 +211,7 @@ assertTrue(!!dialog); // Check that the paper-input fields are pre-populated. - assertEquals(engine.displayName, dialog.$.searchEngine.value); + assertEquals(engine.name, dialog.$.searchEngine.value); assertEquals(engine.keyword, dialog.$.keyword.value); assertEquals(engine.url, dialog.$.queryUrl.value);
diff --git a/chrome/test/data/webui/settings/settings_autofill_section_browsertest.js b/chrome/test/data/webui/settings/settings_autofill_section_browsertest.js index e4bc701..ab017ba 100644 --- a/chrome/test/data/webui/settings/settings_autofill_section_browsertest.js +++ b/chrome/test/data/webui/settings/settings_autofill_section_browsertest.js
@@ -16,6 +16,75 @@ ]); /** + * Test implementation. + * @implements {settings.address.CountryDetailManager} + * @constructor + */ +function CountryDetailManagerTestImpl() {} +CountryDetailManagerTestImpl.prototype = { + /** @override */ + getCountryList: function() { + return new Promise(function(resolve) { + resolve([ + {name: 'United States', countryCode: 'US'}, // Default test country. + {name: 'Israel', countryCode: 'IL'}, + {name: 'United Kingdom', countryCode: 'GB'}, + ]); + }); + }, + + /** @override */ + getAddressFormat: function(countryCode) { + return new Promise(function(resolve) { + chrome.autofillPrivate.getAddressComponents(countryCode, resolve); + }); + }, +}; + +/** + * Will call |loopBody| for each item in |items|. Will only move to the next + * item after the promise from |loopBody| resolves. + * @param {!Array<Object>} items + * @param {!function(!Object):!Promise} loopBody + * @return {!Promise} + */ +function asyncForEach(items, loopBody) { + return new Promise(function(finish) { + var index = 0; + + function loop() { + var item = items[index++]; + if (item) + loopBody(item).then(loop); + else + finish(); + }; + + loop(); + }); +} + +/** + * Resolves the promise after the element fires the expected event. Will add and + * remove the listener so it is only triggered once. |causeEvent| is called + * after adding a listener to make sure that the event is captured. + * @param {!Element} element + * @param {string} eventName + * @param {function():void} causeEvent + * @return {!Promise} + */ +function expectEvent(element, eventName, causeEvent) { + return new Promise(function(resolve) { + var callback = function() { + element.removeEventListener(eventName, callback); + resolve.apply(this, arguments); + }; + element.addEventListener(eventName, callback); + causeEvent(); + }); +} + +/** * @constructor * @extends {PolymerTest} */ @@ -31,6 +100,20 @@ /** @override */ extraLibraries: PolymerTest.getLibraries(ROOT_PATH), + /** + * TODO(hcarmona): Increases speed, but disables A11y checks. Enable checks + * when we "accessibilityIssuesAreErrors: true" for all tests. + * @override + */ + runAccessibilityChecks: false, + + i18nStrings: { + addAddressTitle: 'add-title', + addCreditCardTitle: 'add-title', + editAddressTitle: 'edit-title', + editCreditCardTitle: 'edit-title', + }, + /** @override */ setUp: function() { PolymerTest.prototype.setUp.call(this); @@ -39,10 +122,10 @@ this.accessibilityAuditConfig.auditRulesToIgnore.push('humanLangMissing'); // Faking 'strings.js' for this test. - loadTimeData.data = { - editCreditCardTitle: 'edit-title', - addCreditCardTitle: 'add-title' - }; + loadTimeData.data = this.i18nStrings; + + settings.address.CountryDetailManagerImpl.instance_ = + new CountryDetailManagerTestImpl(); }, /** @@ -73,6 +156,30 @@ }, /** + * Creates the Edit Address dialog and fulfills the promise when the dialog + * has actually opened. + * @param {!chrome.autofillPrivate.AddressEntry} address + * @return {!Promise<Object>} + */ + createAddressDialog_: function(address) { + return new Promise(function(resolve) { + var section = document.createElement('settings-address-edit-dialog'); + document.body.appendChild(section); + var onOpen = function() { + resolve(section); + }; + section.addEventListener('iron-overlay-opened', onOpen); + + // |setTimeout| allows the dialog to async get the list of countries + // before running any tests. + window.setTimeout(function() { + section.open(address); // Opening the dialog will add the item. + Polymer.dom.flush(); + }, 0); + }); + }, + + /** * Creates the Edit Credit Card dialog. * @param {!chrome.autofillPrivate.CreditCardEntry} creditCardItem * @return {!Object} @@ -86,10 +193,7 @@ }, }; -/** - * This test will validate that the section is loaded with data. - */ -TEST_F('SettingsAutofillSectionBrowserTest', 'uiTests', function() { +TEST_F('SettingsAutofillSectionBrowserTest', 'CreditCardTests', function() { var self = this; suite('AutofillSection', function() { @@ -135,7 +239,7 @@ assertNotEquals(oldCreditCardDialog.title_, newCreditCardDialog.title_); assertNotEquals('', newCreditCardDialog.title_); assertNotEquals('', oldCreditCardDialog.title_); - }), + }); test('verifyExpiredCreditCardYear', function() { var creditCard = FakeDataMaker.creditCardEntry(); @@ -154,7 +258,7 @@ assertEquals('2015', firstSelectableYear.textContent); assertEquals(maxYear.toString(), lastSelectableYear.textContent); - }), + }); test('verifyVeryFutureCreditCardYear', function() { var creditCard = FakeDataMaker.creditCardEntry(); @@ -172,7 +276,7 @@ assertEquals(now.getFullYear().toString(), firstSelectableYear.textContent); assertEquals(farFutureYear.toString(), lastSelectableYear.textContent); - }), + }); test('verifyVeryNormalCreditCardYear', function() { var creditCard = FakeDataMaker.creditCardEntry(); @@ -191,7 +295,7 @@ assertEquals(now.getFullYear().toString(), firstSelectableYear.textContent); assertEquals(maxYear.toString(), lastSelectableYear.textContent); - }), + }); // Test will timeout if event is not received. test('verifySaveCreditCardEdit', function(done) { @@ -204,28 +308,36 @@ }); MockInteractions.tap(creditCardDialog.$.saveButton); - }), + }); test('verifyCancelCreditCardEdit', function(done) { var creditCard = FakeDataMaker.emptyCreditCardEntry(); var creditCardDialog = self.createCreditCardDialog_(creditCard); - creditCardDialog.addEventListener('save-credit-card', function(event) { + creditCardDialog.addEventListener('save-credit-card', function() { // Fail the test because the save event should not be called when cancel // is clicked. assertTrue(false); done(); }); - creditCardDialog.addEventListener('iron-overlay-closed', function(event) { + creditCardDialog.addEventListener('iron-overlay-closed', function() { // Test is |done| in a timeout in order to ensure that // 'save-credit-card' is NOT fired after this test. window.setTimeout(done, 100); }); MockInteractions.tap(creditCardDialog.$.cancelButton); - }), + }); + }); + mocha.run(); +}); + +TEST_F('SettingsAutofillSectionBrowserTest', 'AddressTests', function() { + var self = this; + + suite('AutofillSection', function() { test('verifyAddressCount', function() { var addresses = [ FakeDataMaker.addressEntry(), @@ -258,6 +370,381 @@ assertEquals(addressSummary, row.querySelector('#addressSummary').textContent); }); + + test('verifyAddAddressDialog', function() { + return self.createAddressDialog_( + FakeDataMaker.emptyAddressEntry()).then(function(dialog) { + var title = dialog.$$('.title'); + assertEquals(self.i18nStrings.addAddressTitle, title.textContent); + // Shouldn't be possible to save until something is typed in. + assertTrue(dialog.$.saveButton.disabled); + }); + }); + + test('verifyEditAddressDialog', function() { + return self.createAddressDialog_( + FakeDataMaker.addressEntry()).then(function(dialog) { + var title = dialog.$$('.title'); + assertEquals(self.i18nStrings.editAddressTitle, title.textContent); + // Should be possible to save when editing because fields are populated. + assertFalse(dialog.$.saveButton.disabled); + }); + }); + + test('verifyCountryIsSaved', function() { + var address = FakeDataMaker.emptyAddressEntry(); + return self.createAddressDialog_(address).then(function(dialog) { + assertEquals(undefined, dialog.$.countryList.selected); + assertEquals(undefined, address.countryCode); + dialog.$.countryList.selected = 'US'; + Polymer.dom.flush(); + assertEquals('US', dialog.$.countryList.selected); + assertEquals('US', address.countryCode); + }); + }); + + test('verifyPhoneAndEmailAreSaved', function() { + var address = FakeDataMaker.emptyAddressEntry(); + return self.createAddressDialog_(address).then(function(dialog) { + assertEquals('', dialog.$.phoneInput.value); + assertFalse(!!(address.phoneNumbers && address.phoneNumbers[0])); + + assertEquals('', dialog.$.emailInput.value); + assertFalse(!!(address.emailAddresses && address.emailAddresses[0])); + + var phoneNumber = '(555) 555-5555'; + var emailAddress = 'no-reply@chromium.org'; + + dialog.$.phoneInput.value = phoneNumber; + dialog.$.emailInput.value = emailAddress; + + Polymer.dom.flush(); + + assertEquals(phoneNumber, dialog.$.phoneInput.value); + assertEquals(phoneNumber, address.phoneNumbers[0]); + + assertEquals(emailAddress, dialog.$.emailInput.value); + assertEquals(emailAddress, address.emailAddresses[0]); + }); + }); + + // Test will set a value of 'foo' in each text field and verify that the + // save button is enabled, then it will clear the field and verify that the + // save button is disabled. Test passes after all elements have been tested. + test('verifySaveIsNotClickableIfAllInputFieldsAreEmpty', function() { + return self.createAddressDialog_( + FakeDataMaker.emptyAddressEntry()).then(function(dialog) { + var saveButton = dialog.$.saveButton; + var testElements = + dialog.$.dialog.querySelectorAll('paper-input,paper-textarea'); + + // Default country is 'US' expecting: Name, Organization, + // Street address, City, State, ZIP code, Phone, and Email. + assertEquals(8, testElements.length); + + return asyncForEach(testElements, function(element) { + return expectEvent(dialog, 'on-update-can-save', function() { + assertTrue(saveButton.disabled); + element.value = 'foo'; + }).then(function() { + return expectEvent(dialog, 'on-update-can-save', function() { + assertFalse(saveButton.disabled); + element.value = ''; + }); + }).then(function() { + assertTrue(saveButton.disabled); + }); + }); + }); + }); + + // Setting the country should allow the address to be saved. + test('verifySaveIsNotClickableIfCountryNotSet', function() { + return self.createAddressDialog_( + FakeDataMaker.emptyAddressEntry()).then(function(dialog) { + var saveButton = dialog.$.saveButton; + var countries = dialog.$.countryList; + + return expectEvent(dialog, 'on-update-can-save', function() { + assertTrue(saveButton.disabled); + countries.selected = 'US'; + }).then(function() { + assertFalse(saveButton.disabled); + countries.selected = ''; + }).then(function() { + assertTrue(saveButton.disabled); + }); + }); + }); + + // Test will timeout if save-address event is not fired. + test('verifyDefaultCountryIsAppliedWhenSaving', function() { + var address = FakeDataMaker.emptyAddressEntry(); + address.companyName = 'Google'; + return self.createAddressDialog_(address).then(function(dialog) { + return expectEvent(dialog, 'save-address', function() { + // Verify |countryCode| is not set. + assertEquals(undefined, address.countryCode); + MockInteractions.tap(dialog.$.saveButton); + }).then(function(event) { + // 'US' is the default country for these tests. + assertEquals('US', event.detail.countryCode); + }); + }); + }); + + test('verifyCancelDoesNotSaveAddress', function(done) { + self.createAddressDialog_( + FakeDataMaker.addressEntry()).then(function(dialog) { + dialog.addEventListener('save-address', function() { + // Fail the test because the save event should not be called when + // cancel is clicked. + assertTrue(false); + done(); + }); + + dialog.addEventListener('iron-overlay-closed', function() { + // Test is |done| in a timeout in order to ensure that + // 'save-address' is NOT fired after this test. + window.setTimeout(done, 100); + }); + + MockInteractions.tap(dialog.$.cancelButton); + }); + }); + }); + + mocha.run(); +}); + +TEST_F('SettingsAutofillSectionBrowserTest', 'AddressLocaleTests', function() { + var self = this; + + suite('AutofillSection', function() { + // US address has 3 fields on the same line. + test('verifyEditingUSAddress', function() { + var address = FakeDataMaker.emptyAddressEntry(); + + address.fullNames = [ 'Name' ]; + address.companyName = 'Organization'; + address.addressLines = 'Street address'; + address.addressLevel2 = 'City'; + address.addressLevel1 = 'State'; + address.postalCode = 'ZIP code'; + address.countryCode = 'US'; + address.phoneNumbers = [ 'Phone' ]; + address.emailAddresses = [ 'Email' ]; + + return self.createAddressDialog_(address).then(function(dialog) { + var rows = dialog.$.dialog.querySelectorAll('.address-row'); + assertEquals(6, rows.length); + + // Name + var row = rows[0]; + var cols = row.querySelectorAll('.address-column'); + assertEquals(1, cols.length); + assertEquals(address.fullNames[0], cols[0].value); + // Organization + row = rows[1]; + cols = row.querySelectorAll('.address-column'); + assertEquals(1, cols.length); + assertEquals(address.companyName, cols[0].value); + // Street address + row = rows[2]; + cols = row.querySelectorAll('.address-column'); + assertEquals(1, cols.length); + assertEquals(address.addressLines, cols[0].value); + // City, State, ZIP code + row = rows[3]; + cols = row.querySelectorAll('.address-column'); + assertEquals(3, cols.length); + assertEquals(address.addressLevel2, cols[0].value); + assertEquals(address.addressLevel1, cols[1].value); + assertEquals(address.postalCode, cols[2].value); + // Country + row = rows[4]; + cols = row.querySelectorAll('.address-column'); + assertEquals(1, cols.length); + assertEquals('United States', cols[0].value); + // Phone, Email + row = rows[5]; + cols = row.querySelectorAll('.address-column'); + assertEquals(2, cols.length); + assertEquals(address.phoneNumbers[0], cols[0].value); + assertEquals(address.emailAddresses[0], cols[1].value); + }); + }); + + // GB address has 1 field per line for all lines that change. + test('verifyEditingGBAddress', function() { + var address = FakeDataMaker.emptyAddressEntry(); + + address.fullNames = [ 'Name' ]; + address.companyName = 'Organization'; + address.addressLines = 'Street address'; + address.addressLevel2 = 'Post town'; + address.addressLevel1 = 'County'; + address.postalCode = 'Postal code'; + address.countryCode = 'GB'; + address.phoneNumbers = [ 'Phone' ]; + address.emailAddresses = [ 'Email' ]; + + return self.createAddressDialog_(address).then(function(dialog) { + var rows = dialog.$.dialog.querySelectorAll('.address-row'); + assertEquals(8, rows.length); + + // Name + var row = rows[0]; + var cols = row.querySelectorAll('.address-column'); + assertEquals(1, cols.length); + assertEquals(address.fullNames[0], cols[0].value); + // Organization + row = rows[1]; + cols = row.querySelectorAll('.address-column'); + assertEquals(1, cols.length); + assertEquals(address.companyName, cols[0].value); + // Street address + row = rows[2]; + cols = row.querySelectorAll('.address-column'); + assertEquals(1, cols.length); + assertEquals(address.addressLines, cols[0].value); + // Post Town + row = rows[3]; + cols = row.querySelectorAll('.address-column'); + assertEquals(1, cols.length); + assertEquals(address.addressLevel2, cols[0].value); + // County + row = rows[4]; + cols = row.querySelectorAll('.address-column'); + assertEquals(1, cols.length); + assertEquals(address.addressLevel1, cols[0].value); + // Postal code + row = rows[5]; + cols = row.querySelectorAll('.address-column'); + assertEquals(1, cols.length); + assertEquals(address.postalCode, cols[0].value); + // Country + row = rows[6]; + cols = row.querySelectorAll('.address-column'); + assertEquals(1, cols.length); + assertEquals('United Kingdom', cols[0].value); + // Phone, Email + row = rows[7]; + cols = row.querySelectorAll('.address-column'); + assertEquals(2, cols.length); + assertEquals(address.phoneNumbers[0], cols[0].value); + assertEquals(address.emailAddresses[0], cols[1].value); + }); + }); + + // IL address has 2 fields on the same line and is an RTL locale. + // RTL locale shouldn't affect this test. + test('verifyEditingILAddress', function() { + var address = FakeDataMaker.emptyAddressEntry(); + + address.fullNames = [ 'Name' ]; + address.companyName = 'Organization'; + address.addressLines = 'Street address'; + address.addressLevel2 = 'City'; + address.postalCode = 'Postal code'; + address.countryCode = 'IL'; + address.phoneNumbers = [ 'Phone' ]; + address.emailAddresses = [ 'Email' ]; + + return self.createAddressDialog_(address).then(function(dialog) { + var rows = dialog.$.dialog.querySelectorAll('.address-row'); + assertEquals(6, rows.length); + + // Name + var row = rows[0]; + var cols = row.querySelectorAll('.address-column'); + assertEquals(1, cols.length); + assertEquals(address.fullNames[0], cols[0].value); + // Organization + row = rows[1]; + cols = row.querySelectorAll('.address-column'); + assertEquals(1, cols.length); + assertEquals(address.companyName, cols[0].value); + // Street address + row = rows[2]; + cols = row.querySelectorAll('.address-column'); + assertEquals(1, cols.length); + assertEquals(address.addressLines, cols[0].value); + // City, Postal code + row = rows[3]; + cols = row.querySelectorAll('.address-column'); + assertEquals(2, cols.length); + assertEquals(address.addressLevel2, cols[0].value); + assertEquals(address.postalCode, cols[1].value); + // Country + row = rows[4]; + cols = row.querySelectorAll('.address-column'); + assertEquals(1, cols.length); + assertEquals('Israel', cols[0].value); + // Phone, Email + row = rows[5]; + cols = row.querySelectorAll('.address-column'); + assertEquals(2, cols.length); + assertEquals(address.phoneNumbers[0], cols[0].value); + assertEquals(address.emailAddresses[0], cols[1].value); + }); + }); + + // US has an extra field 'State'. Validate that this field is + // persisted when switching to IL then back to US. + test('verifyAddressPersistanceWhenSwitchingCountries', function() { + var address = FakeDataMaker.emptyAddressEntry(); + address.countryCode = 'US'; + + return self.createAddressDialog_(address).then(function(dialog) { + var city = 'Los Angeles'; + var state = 'CA'; + var zip = '90291'; + + return expectEvent(dialog, 'on-update-address-wrapper', function() { + // US: + var rows = dialog.$.dialog.querySelectorAll('.address-row'); + assertEquals(6, rows.length); + + // City, State, ZIP code + var row = rows[3]; + var cols = row.querySelectorAll('.address-column'); + assertEquals(3, cols.length); + cols[0].value = city; + cols[1].value = state; + cols[2].value = zip; + + dialog.$.countryList.selected = 'IL'; + }).then(function() { + return expectEvent(dialog, 'on-update-address-wrapper', function() { + // IL: + rows = dialog.$.dialog.querySelectorAll('.address-row'); + assertEquals(6, rows.length); + + // City, Postal code + row = rows[3]; + cols = row.querySelectorAll('.address-column'); + assertEquals(2, cols.length); + assertEquals(city, cols[0].value); + assertEquals(zip, cols[1].value); + + dialog.$.countryList.selected = 'US'; + }); + }).then(function() { + // US: + var rows = dialog.$.dialog.querySelectorAll('.address-row'); + assertEquals(6, rows.length); + + // City, State, ZIP code + row = rows[3]; + cols = row.querySelectorAll('.address-column'); + assertEquals(3, cols.length); + assertEquals(city, cols[0].value); + assertEquals(state, cols[1].value); + assertEquals(zip, cols[2].value); + }); + }); + }); }); mocha.run();
diff --git a/chrome/test/data/webui_test_resources.grd b/chrome/test/data/webui_test_resources.grd index 6f8530d..3c269a9 100644 --- a/chrome/test/data/webui_test_resources.grd +++ b/chrome/test/data/webui_test_resources.grd
@@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1"> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="chrome/test/data/grit/webui_test_resources.h" type="rc_header"> <emit emit_type='prepend'></emit>
diff --git a/chrome/test/ppapi/ppapi_filechooser_browsertest.cc b/chrome/test/ppapi/ppapi_filechooser_browsertest.cc index 90816e9..b57a91ea 100644 --- a/chrome/test/ppapi/ppapi_filechooser_browsertest.cc +++ b/chrome/test/ppapi/ppapi_filechooser_browsertest.cc
@@ -8,6 +8,7 @@ #include "base/command_line.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" +#include "base/strings/string_util.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/ppapi/ppapi_test.h" @@ -147,7 +148,8 @@ bool MatchDownloadWhitelistUrl(const GURL& url) override { // This matches the behavior in RunTestViaHTTP(). return url.SchemeIsHTTPOrHTTPS() && url.has_path() && - url.path().find("/test_case.html") == 0; + base::StartsWith(url.path(), "/test_case.html", + base::CompareCase::SENSITIVE); } protected:
diff --git a/chrome/utility/importer/bookmark_html_reader.cc b/chrome/utility/importer/bookmark_html_reader.cc index f23183c0..8e524b83 100644 --- a/chrome/utility/importer/bookmark_html_reader.cc +++ b/chrome/utility/importer/bookmark_html_reader.cc
@@ -297,19 +297,20 @@ namespace internal { bool ParseCharsetFromLine(const std::string& line, std::string* charset) { - const char kCharset[] = "charset="; - if (base::StartsWith(line, "<META", base::CompareCase::INSENSITIVE_ASCII) && - (line.find("CONTENT=\"") != std::string::npos || - line.find("content=\"") != std::string::npos)) { - size_t begin = line.find(kCharset); - if (begin == std::string::npos) - return false; - begin += std::string(kCharset).size(); - size_t end = line.find_first_of('\"', begin); - *charset = line.substr(begin, end - begin); - return true; + if (!base::StartsWith(line, "<META", base::CompareCase::INSENSITIVE_ASCII) || + (line.find("CONTENT=\"") == std::string::npos && + line.find("content=\"") == std::string::npos)) { + return false; } - return false; + + const char kCharset[] = "charset="; + size_t begin = line.find(kCharset); + if (begin == std::string::npos) + return false; + begin += sizeof(kCharset) - 1; + size_t end = line.find_first_of('\"', begin); + *charset = line.substr(begin, end - begin); + return true; } bool ParseFolderNameFromLine(const std::string& lineDt,
diff --git a/chrome/utility/importer/nss_decryptor.cc b/chrome/utility/importer/nss_decryptor.cc index af7e847..be88f05 100644 --- a/chrome/utility/importer/nss_decryptor.cc +++ b/chrome/utility/importer/nss_decryptor.cc
@@ -206,7 +206,7 @@ if (lines[begin].find(kRealmBracketBegin) != std::string::npos) { size_t start = lines[begin].find(kRealmBracketBegin); raw_password_info.host = lines[begin].substr(0, start); - start += std::string(kRealmBracketBegin).size(); + start += sizeof(kRealmBracketBegin) - 1; size_t end = lines[begin].rfind(kRealmBracketEnd); raw_password_info.realm = lines[begin].substr(start, end - start); } else {
diff --git a/chrome/utility/media_galleries/picasa_albums_indexer.cc b/chrome/utility/media_galleries/picasa_albums_indexer.cc index 7eded27..c6b88bc 100644 --- a/chrome/utility/media_galleries/picasa_albums_indexer.cc +++ b/chrome/utility/media_galleries/picasa_albums_indexer.cc
@@ -10,6 +10,7 @@ #include "base/logging.h" #include "base/strings/string_split.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "chrome/common/ini_parser.h" @@ -38,7 +39,8 @@ return; // [.album:*] sections ignored as we get that data from the PMP files. - if (section.find(kAlbumSectionHeader) == 0) + if (base::StartsWith(section, kAlbumSectionHeader, + base::CompareCase::SENSITIVE)) return; for (const std::string& album : base::SplitString(
diff --git a/chrome/utility/safe_browsing/mac/udif.cc b/chrome/utility/safe_browsing/mac/udif.cc index d3cadf8..2a51bdb 100644 --- a/chrome/utility/safe_browsing/mac/udif.cc +++ b/chrome/utility/safe_browsing/mac/udif.cc
@@ -70,16 +70,21 @@ uint64_t plist_offset; // Offset and length of the blkx plist. uint64_t plist_length; - uint8_t reserved1[120]; + uint8_t reserved1[64]; + + uint64_t code_signature_offset; + uint64_t code_signature_length; + + uint8_t reserved2[40]; UDIFChecksum master_checksum; uint32_t image_variant; uint64_t sector_count; - uint32_t reserved2; uint32_t reserved3; uint32_t reserved4; + uint32_t reserved5; }; static void ConvertBigEndian(uuid_t* uuid) { @@ -102,6 +107,8 @@ ConvertBigEndian(&file->data_checksum); ConvertBigEndian(&file->plist_offset); ConvertBigEndian(&file->plist_length); + ConvertBigEndian(&file->code_signature_offset); + ConvertBigEndian(&file->code_signature_length); ConvertBigEndian(&file->master_checksum); ConvertBigEndian(&file->image_variant); ConvertBigEndian(&file->sector_count);
diff --git a/chrome_elf/BUILD.gn b/chrome_elf/BUILD.gn index a3ba1b42..87c14a5 100644 --- a/chrome_elf/BUILD.gn +++ b/chrome_elf/BUILD.gn
@@ -2,10 +2,17 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +# Chrome elf targets (excepting tests) should only link in kernel32. +# Please don't add dependencies on any other system libraries. + import("//build/config/win/manifest.gni") import("//chrome/version.gni") import("//testing/test.gni") +##------------------------------------------------------------------------------ +## chrome_elf +##------------------------------------------------------------------------------ + process_version("chrome_elf_resources") { template_file = chrome_version_rc_template sources = [ @@ -38,10 +45,11 @@ ":breakpad", ":chrome_elf_manifest", ":chrome_elf_resources", - ":common", + ":hook_util", "//base", "//build/config/sanitizers:deps", "//chrome/install_static:install_static_util", + "//chrome_elf/nt_registry:nt_registry", "//components/crash/content/app", "//components/crash/core/common", "//content/public/common:result_codes", @@ -66,6 +74,10 @@ } } +##------------------------------------------------------------------------------ +## source sets +##------------------------------------------------------------------------------ + source_set("constants") { sources = [ "chrome_elf_constants.cc", @@ -73,35 +85,6 @@ ] } -source_set("common") { - public_deps = [ - ":constants", - ] - deps = [ - "//base", - "//sandbox", - ] - sources = [ - "thunk_getter.cc", - "thunk_getter.h", - ] -} - -source_set("breakpad") { - include_dirs = [ "$target_gen_dir" ] - sources = [ - "breakpad.cc", - "breakpad.h", - ] - deps = [ - ":common", - "//base", - "//breakpad:breakpad_handler", - "//chrome/common:version_header", - "//chrome/install_static:install_static_util", - ] -} - source_set("dll_hash") { deps = [ "//base", @@ -112,6 +95,10 @@ ] } +##------------------------------------------------------------------------------ +## chrome_elf sub targets +##------------------------------------------------------------------------------ + executable("dll_hash_main") { sources = [ "dll_hash/dll_hash_main.cc", @@ -135,13 +122,44 @@ ] deps = [ ":breakpad", - ":common", ":constants", - "//base", + ":hook_util", "//chrome/install_static:install_static_util", + "//chrome_elf/nt_registry:nt_registry", + + # Still uses base/win/pe_image.h + "//base", ] } +static_library("breakpad") { + include_dirs = [ "$target_gen_dir" ] + sources = [ + "breakpad/breakpad.cc", + "breakpad/breakpad.h", + ] + deps = [ + "//breakpad:breakpad_handler", + "//chrome/common:version_header", + "//chrome/install_static:install_static_util", + "//chrome_elf/nt_registry:nt_registry", + ] +} + +static_library("hook_util") { + sources = [ + "hook_util/thunk_getter.cc", + "hook_util/thunk_getter.h", + ] + deps = [ + "//sandbox", + ] +} + +##------------------------------------------------------------------------------ +## tests +##------------------------------------------------------------------------------ + test("chrome_elf_unittests") { output_name = "chrome_elf_unittests" sources = [ @@ -154,12 +172,14 @@ deps = [ ":blacklist", ":blacklist_test_main_dll", - ":common", + ":constants", + ":hook_util", "//base", "//base/test:test_support", "//chrome", "//chrome/common:version_header", "//chrome/install_static:install_static_util", + "//chrome_elf/nt_registry:nt_registry", "//sandbox", "//testing/gtest", ] @@ -198,10 +218,10 @@ ] deps = [ ":blacklist", - ":common", "//base", "//build/config/sanitizers:deps", "//chrome/install_static:install_static_util", + "//chrome_elf/nt_registry:nt_registry", ] }
diff --git a/chrome_elf/OWNERS b/chrome_elf/OWNERS index 1056485..b90211b 100644 --- a/chrome_elf/OWNERS +++ b/chrome_elf/OWNERS
@@ -1,2 +1,4 @@ caitkp@chromium.org robertshield@chromium.org +# For early browser process security and nt_registry: +pennymac@chromium.org
diff --git a/chrome_elf/blacklist.gypi b/chrome_elf/blacklist.gypi index f552186..5f05425 100644 --- a/chrome_elf/blacklist.gypi +++ b/chrome_elf/blacklist.gypi
@@ -18,8 +18,11 @@ ], 'dependencies': [ '../base/base.gyp:base', + '../chrome/chrome.gyp:install_static_util', '../chrome_elf/chrome_elf.gyp:chrome_elf_breakpad', '../chrome_elf/chrome_elf.gyp:chrome_elf_constants', + '../chrome_elf/chrome_elf.gyp:chrome_elf_hook_util', + '../chrome_elf/nt_registry/nt_registry.gyp:chrome_elf_nt_registry', '../sandbox/sandbox.gyp:sandbox', ], }, @@ -32,6 +35,8 @@ ], 'dependencies': [ '../base/base.gyp:base', + '../chrome/chrome.gyp:install_static_util', + '../chrome_elf/nt_registry/nt_registry.gyp:chrome_elf_nt_registry', 'blacklist', ], },
diff --git a/chrome_elf/blacklist/blacklist.cc b/chrome_elf/blacklist/blacklist.cc index d370793..0fdf91d2 100644 --- a/chrome_elf/blacklist/blacklist.cc +++ b/chrome_elf/blacklist/blacklist.cc
@@ -12,7 +12,8 @@ #include "chrome/install_static/install_util.h" #include "chrome_elf/blacklist/blacklist_interceptions.h" #include "chrome_elf/chrome_elf_constants.h" -#include "chrome_elf/thunk_getter.h" +#include "chrome_elf/hook_util/thunk_getter.h" +#include "chrome_elf/nt_registry/nt_registry.h" #include "sandbox/win/src/interception_internal.h" #include "sandbox/win/src/internal_types.h" #include "sandbox/win/src/service_resolver.h" @@ -20,7 +21,7 @@ // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx extern "C" IMAGE_DOS_HEADER __ImageBase; -namespace blacklist{ +namespace blacklist { // The DLLs listed here are known (or under strong suspicion) of causing crashes // when they are loaded in the browser. DLLs should only be added to this list @@ -31,45 +32,45 @@ // NOTE: Please remember to update the DllHash enum in histograms.xml when // adding a new value to the blacklist. const wchar_t* g_troublesome_dlls[kTroublesomeDllsMaxCount] = { - L"949ba8b6a9.dll", // Coupon Time. - L"activedetect32.dll", // Lenovo One Key Theater. - // See crbug.com/379218. - L"activedetect64.dll", // Lenovo One Key Theater. - L"bitguard.dll", // Unknown (suspected malware). - L"bsvc.dll", // Unknown (suspected adware). - L"chrmxtn.dll", // Unknown (keystroke logger). - L"cplushook.dll", // Unknown (suspected malware). - L"crdli.dll", // Linkury Inc. - L"crdli64.dll", // Linkury Inc. - L"datamngr.dll", // Unknown (suspected adware). - L"dpinterface32.dll", // Unknown (suspected adware). - L"explorerex.dll", // Unknown (suspected adware). - L"hk.dll", // Unknown (keystroke logger). - L"libapi2hook.dll", // V-Bates. - L"libinject.dll", // V-Bates. - L"libinject2.dll", // V-Bates. - L"libredir2.dll", // V-Bates. - L"libsvn_tsvn32.dll", // TortoiseSVN. - L"libwinhook.dll", // V-Bates. - L"lmrn.dll", // Unknown. - L"minisp.dll", // Unknown (suspected malware). - L"minisp32.dll", // Unknown (suspected malware). - L"offerswizarddll.dll", // Unknown (suspected adware). - L"safetynut.dll", // Unknown (suspected adware). - L"smdmf.dll", // Unknown (suspected adware). - L"spappsv32.dll", // Unknown (suspected adware). - L"systemk.dll", // Unknown (suspected adware). - L"vntsrv.dll", // Virtual New Tab by APN LLC. - L"wajam_goblin_64.dll", // Wajam Internet Technologies. - L"wajam_goblin.dll", // Wajam Internet Technologies. - L"windowsapihookdll32.dll", // Lenovo One Key Theater. - // See crbug.com/379218. - L"windowsapihookdll64.dll", // Lenovo One Key Theater. - L"virtualcamera.ax", // %PROGRAMFILES%\ASUS\VirtualCamera. - // See crbug.com/422522. - L"ycwebcamerasource.ax", // CyberLink Youcam, crbug.com/424159 - // Keep this null pointer here to mark the end of the list. - NULL, + L"949ba8b6a9.dll", // Coupon Time. + L"activedetect32.dll", // Lenovo One Key Theater. + // See crbug.com/379218. + L"activedetect64.dll", // Lenovo One Key Theater. + L"bitguard.dll", // Unknown (suspected malware). + L"bsvc.dll", // Unknown (suspected adware). + L"chrmxtn.dll", // Unknown (keystroke logger). + L"cplushook.dll", // Unknown (suspected malware). + L"crdli.dll", // Linkury Inc. + L"crdli64.dll", // Linkury Inc. + L"datamngr.dll", // Unknown (suspected adware). + L"dpinterface32.dll", // Unknown (suspected adware). + L"explorerex.dll", // Unknown (suspected adware). + L"hk.dll", // Unknown (keystroke logger). + L"libapi2hook.dll", // V-Bates. + L"libinject.dll", // V-Bates. + L"libinject2.dll", // V-Bates. + L"libredir2.dll", // V-Bates. + L"libsvn_tsvn32.dll", // TortoiseSVN. + L"libwinhook.dll", // V-Bates. + L"lmrn.dll", // Unknown. + L"minisp.dll", // Unknown (suspected malware). + L"minisp32.dll", // Unknown (suspected malware). + L"offerswizarddll.dll", // Unknown (suspected adware). + L"safetynut.dll", // Unknown (suspected adware). + L"smdmf.dll", // Unknown (suspected adware). + L"spappsv32.dll", // Unknown (suspected adware). + L"systemk.dll", // Unknown (suspected adware). + L"vntsrv.dll", // Virtual New Tab by APN LLC. + L"wajam_goblin_64.dll", // Wajam Internet Technologies. + L"wajam_goblin.dll", // Wajam Internet Technologies. + L"windowsapihookdll32.dll", // Lenovo One Key Theater. + // See crbug.com/379218. + L"windowsapihookdll64.dll", // Lenovo One Key Theater. + L"virtualcamera.ax", // %PROGRAMFILES%\ASUS\VirtualCamera. + // See crbug.com/422522. + L"ycwebcamerasource.ax", // CyberLink Youcam, crbug.com/424159 + // Keep this null pointer here to mark the end of the list. + NULL, }; bool g_blocked_dlls[kTroublesomeDllsMaxCount] = {}; @@ -79,7 +80,7 @@ // Allocate storage for thunks in a page of this module to save on doing // an extra allocation at run time. -#pragma section(".crthunk",read,execute) +#pragma section(".crthunk", read, execute) __declspec(allocate(".crthunk")) sandbox::ThunkData g_thunk_storage; namespace { @@ -88,151 +89,97 @@ // determine if the blacklist is enabled for them. bool g_blacklist_initialized = false; -// Helper to set DWORD registry values. -DWORD SetDWValue(HKEY* key, const wchar_t* property, DWORD value) { - return ::RegSetValueEx(*key, - property, - 0, - REG_DWORD, - reinterpret_cast<LPBYTE>(&value), - sizeof(value)); -} - -bool GenerateStateFromBeaconAndAttemptCount(HKEY* key, DWORD blacklist_state) { - LONG result = 0; - if (blacklist_state == blacklist::BLACKLIST_ENABLED) { - // If the blacklist succeeded on the previous run reset the failure - // counter. - return (SetDWValue(key, - blacklist::kBeaconAttemptCount, - static_cast<DWORD>(0)) == ERROR_SUCCESS); - } else { - // Some part of the blacklist setup failed last time. If this has occured - // blacklist::kBeaconMaxAttempts times in a row we switch the state to - // failed and skip setting up the blacklist. - DWORD attempt_count = 0; - DWORD attempt_count_size = sizeof(attempt_count); - result = ::RegQueryValueEx(*key, - blacklist::kBeaconAttemptCount, - 0, - NULL, - reinterpret_cast<LPBYTE>(&attempt_count), - &attempt_count_size); - - if (result == ERROR_FILE_NOT_FOUND) - attempt_count = 0; - else if (result != ERROR_SUCCESS) - return false; - - ++attempt_count; - SetDWValue(key, blacklist::kBeaconAttemptCount, attempt_count); - - if (attempt_count >= blacklist::kBeaconMaxAttempts) { - blacklist_state = blacklist::BLACKLIST_SETUP_FAILED; - SetDWValue(key, blacklist::kBeaconState, blacklist_state); - } - - return false; - } -} - } // namespace namespace blacklist { #if defined(_WIN64) - // Allocate storage for the pointer to the old NtMapViewOfSectionFunction. -#pragma section(".oldntmap",write,read) - __declspec(allocate(".oldntmap")) +// Allocate storage for the pointer to the old NtMapViewOfSectionFunction. +#pragma section(".oldntmap", write, read) +__declspec(allocate(".oldntmap")) NtMapViewOfSectionFunction g_nt_map_view_of_section_func = NULL; #endif bool LeaveSetupBeacon() { - HKEY key = NULL; - DWORD disposition = 0; - LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER, - kRegistryBeaconPath, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_QUERY_VALUE | KEY_SET_VALUE, - NULL, - &key, - &disposition); - if (result != ERROR_SUCCESS) + HANDLE key_handle = INVALID_HANDLE_VALUE; + + if (!nt::CreateRegKey(nt::HKCU, kRegistryBeaconPath, + KEY_QUERY_VALUE | KEY_SET_VALUE, &key_handle)) return false; - // Retrieve the current blacklist state. DWORD blacklist_state = BLACKLIST_STATE_MAX; - DWORD blacklist_state_size = sizeof(blacklist_state); - DWORD type = 0; - result = ::RegQueryValueEx(key, - kBeaconState, - 0, - &type, - reinterpret_cast<LPBYTE>(&blacklist_state), - &blacklist_state_size); - - if (result != ERROR_SUCCESS || blacklist_state == BLACKLIST_DISABLED || - type != REG_DWORD) { - ::RegCloseKey(key); + if (!nt::QueryRegValueDWORD(key_handle, kBeaconState, &blacklist_state) || + blacklist_state == BLACKLIST_DISABLED) { + nt::CloseRegKey(key_handle); return false; } - if (!GenerateStateFromBeaconAndAttemptCount(&key, blacklist_state)) { - ::RegCloseKey(key); - return false; + // Handle attempt count. + // Only return true if BL is enabled and succeeded on previous run. + bool success = false; + if (blacklist_state == BLACKLIST_ENABLED) { + // If the blacklist succeeded on the previous run reset the failure + // counter. Then update the beacon state. + if (nt::SetRegValueDWORD(key_handle, kBeaconAttemptCount, + static_cast<DWORD>(0))) { + if (nt::SetRegValueDWORD(key_handle, kBeaconState, + BLACKLIST_SETUP_RUNNING)) + success = true; + } + } else { + // Some part of the blacklist setup failed last time. If this has occured + // blacklist::kBeaconMaxAttempts times in a row we switch the state to + // failed and skip setting up the blacklist. + DWORD attempt_count = 0; + + nt::QueryRegValueDWORD(key_handle, blacklist::kBeaconAttemptCount, + &attempt_count); + ++attempt_count; + nt::SetRegValueDWORD(key_handle, blacklist::kBeaconAttemptCount, + attempt_count); + + if (attempt_count >= blacklist::kBeaconMaxAttempts) { + blacklist_state = blacklist::BLACKLIST_SETUP_FAILED; + nt::SetRegValueDWORD(key_handle, blacklist::kBeaconState, + blacklist_state); + } } - result = SetDWValue(&key, kBeaconState, BLACKLIST_SETUP_RUNNING); - ::RegCloseKey(key); - - return (result == ERROR_SUCCESS); + nt::CloseRegKey(key_handle); + return success; } bool ResetBeacon() { - HKEY key = NULL; - DWORD disposition = 0; - LONG result = ::RegCreateKeyEx(HKEY_CURRENT_USER, - kRegistryBeaconPath, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_QUERY_VALUE | KEY_SET_VALUE, - NULL, - &key, - &disposition); - if (result != ERROR_SUCCESS) + HANDLE key_handle = INVALID_HANDLE_VALUE; + + if (!nt::CreateRegKey(nt::HKCU, kRegistryBeaconPath, + KEY_QUERY_VALUE | KEY_SET_VALUE, &key_handle)) return false; DWORD blacklist_state = BLACKLIST_STATE_MAX; - DWORD blacklist_state_size = sizeof(blacklist_state); - DWORD type = 0; - result = ::RegQueryValueEx(key, - kBeaconState, - 0, - &type, - reinterpret_cast<LPBYTE>(&blacklist_state), - &blacklist_state_size); - - if (result != ERROR_SUCCESS || type != REG_DWORD) { - ::RegCloseKey(key); + if (!nt::QueryRegValueDWORD(key_handle, kBeaconState, &blacklist_state)) { + nt::CloseRegKey(key_handle); return false; } // Reaching this point with the setup running state means the setup did not // crash, so we reset to enabled. Any other state indicates that setup was // skipped; in that case we leave the state alone for later recording. - if (blacklist_state == BLACKLIST_SETUP_RUNNING) - result = SetDWValue(&key, kBeaconState, BLACKLIST_ENABLED); + if (blacklist_state == BLACKLIST_SETUP_RUNNING) { + if (!nt::SetRegValueDWORD(key_handle, kBeaconState, BLACKLIST_ENABLED)) { + nt::CloseRegKey(key_handle); + return false; + } + } - ::RegCloseKey(key); - return (result == ERROR_SUCCESS); + nt::CloseRegKey(key_handle); + return true; } int BlacklistSize() { int size = -1; - while (blacklist::g_troublesome_dlls[++size] != NULL) {} + while (blacklist::g_troublesome_dlls[++size] != NULL) { + } return size; } @@ -355,10 +302,8 @@ // Mark the thunk storage as readable and writeable, since we // ready to write to it. DWORD old_protect = 0; - if (!VirtualProtect(&g_thunk_storage, - sizeof(g_thunk_storage), - PAGE_EXECUTE_READWRITE, - &old_protect)) { + if (!VirtualProtect(&g_thunk_storage, sizeof(g_thunk_storage), + PAGE_EXECUTE_READWRITE, &old_protect)) { return false; } @@ -368,36 +313,29 @@ // still work on 32-bit build when referenced at the end of the function. BOOL page_executable = false; - // Replace the default NtMapViewOfSection with our patched version. +// Replace the default NtMapViewOfSection with our patched version. #if defined(_WIN64) - NTSTATUS ret = thunk->Setup(::GetModuleHandle(sandbox::kNtdllName), - reinterpret_cast<void*>(&__ImageBase), - "NtMapViewOfSection", - NULL, - &blacklist::BlNtMapViewOfSection64, - thunk_storage, - sizeof(sandbox::ThunkData), - NULL); + NTSTATUS ret = + thunk->Setup(::GetModuleHandle(sandbox::kNtdllName), + reinterpret_cast<void*>(&__ImageBase), "NtMapViewOfSection", + NULL, &blacklist::BlNtMapViewOfSection64, thunk_storage, + sizeof(sandbox::ThunkData), NULL); // Keep a pointer to the original code, we don't have enough space to // add it directly to the call. - g_nt_map_view_of_section_func = reinterpret_cast<NtMapViewOfSectionFunction>( - thunk_storage); + g_nt_map_view_of_section_func = + reinterpret_cast<NtMapViewOfSectionFunction>(thunk_storage); // Ensure that the pointer to the old function can't be changed. - page_executable = VirtualProtect(&g_nt_map_view_of_section_func, - sizeof(g_nt_map_view_of_section_func), - PAGE_EXECUTE_READ, - &old_protect); + page_executable = VirtualProtect(&g_nt_map_view_of_section_func, + sizeof(g_nt_map_view_of_section_func), + PAGE_EXECUTE_READ, &old_protect); #else - NTSTATUS ret = thunk->Setup(::GetModuleHandle(sandbox::kNtdllName), - reinterpret_cast<void*>(&__ImageBase), - "NtMapViewOfSection", - NULL, - &blacklist::BlNtMapViewOfSection, - thunk_storage, - sizeof(sandbox::ThunkData), - NULL); + NTSTATUS ret = + thunk->Setup(::GetModuleHandle(sandbox::kNtdllName), + reinterpret_cast<void*>(&__ImageBase), "NtMapViewOfSection", + NULL, &blacklist::BlNtMapViewOfSection, thunk_storage, + sizeof(sandbox::ThunkData), NULL); #endif delete thunk; @@ -405,10 +343,9 @@ g_blacklist_initialized = NT_SUCCESS(ret); // Mark the thunk storage as executable and prevent any future writes to it. - page_executable = page_executable && VirtualProtect(&g_thunk_storage, - sizeof(g_thunk_storage), - PAGE_EXECUTE_READ, - &old_protect); + page_executable = page_executable && + VirtualProtect(&g_thunk_storage, sizeof(g_thunk_storage), + PAGE_EXECUTE_READ, &old_protect); AddDllsFromRegistryToBlacklist(); @@ -416,41 +353,18 @@ } void AddDllsFromRegistryToBlacklist() { - HKEY key = NULL; - LONG result = ::RegOpenKeyEx(HKEY_CURRENT_USER, - kRegistryFinchListPath, - 0, - KEY_QUERY_VALUE | KEY_SET_VALUE, - &key); + std::vector<std::wstring> dlls; - if (result != ERROR_SUCCESS) + if (!nt::QueryRegValueMULTISZ(nt::HKCU, kRegistryFinchListPath, + kRegistryFinchListValueName, &dlls) || + dlls.empty()) return; - // We add dlls from the registry to the blacklist. - DWORD value_len; - DWORD name_len = MAX_PATH; - std::vector<wchar_t> name_buffer(name_len); - for (int i = 0; result == ERROR_SUCCESS; ++i) { - name_len = MAX_PATH; - value_len = 0; - result = ::RegEnumValue( - key, i, &name_buffer[0], &name_len, NULL, NULL, NULL, &value_len); - if (result != ERROR_SUCCESS) - break; - - name_len = name_len + 1; - value_len = value_len + 1; - std::vector<wchar_t> value_buffer(value_len); - result = ::RegEnumValue(key, i, &name_buffer[0], &name_len, NULL, NULL, - reinterpret_cast<BYTE*>(&value_buffer[0]), - &value_len); - if (result != ERROR_SUCCESS) - break; - value_buffer[value_len - 1] = L'\0'; - AddDllToBlacklist(&value_buffer[0]); + // Add each DLL to the BL in memory + for (auto name : dlls) { + AddDllToBlacklist(name.c_str()); } - ::RegCloseKey(key); return; }
diff --git a/chrome_elf/blacklist/blacklist_interceptions.cc b/chrome_elf/blacklist/blacklist_interceptions.cc index f4c7344..48699b1c 100644 --- a/chrome_elf/blacklist/blacklist_interceptions.cc +++ b/chrome_elf/blacklist/blacklist_interceptions.cc
@@ -16,10 +16,9 @@ // Note that only #includes from base that are either header-only or built into // base_static (see base/base.gyp) are allowed here. -#include "base/strings/string16.h" #include "base/win/pe_image.h" #include "chrome_elf/blacklist/blacklist.h" -#include "chrome_elf/breakpad.h" +#include "chrome_elf/breakpad/breakpad.h" #include "sandbox/win/src/internal_types.h" #include "sandbox/win/src/nt_internals.h" #include "sandbox/win/src/sandbox_nt_util.h" @@ -37,7 +36,7 @@ return ::GetProcAddress(ntdll, export_name); } -int DllMatch(const base::string16& module_name) { +int DllMatch(const std::wstring& module_name) { if (module_name.empty()) return -1; @@ -52,7 +51,7 @@ // code in sandbox_nt_util.cc. See if they can be unified. // Native reimplementation of PSAPIs GetMappedFileName. -base::string16 GetBackingModuleFilePath(PVOID address) { +std::wstring GetBackingModuleFilePath(PVOID address) { DCHECK_NT(g_nt_query_virtual_memory_func); // We'll start with something close to max_path characters for the name. @@ -83,11 +82,11 @@ UNICODE_STRING* section_string = reinterpret_cast<UNICODE_STRING*>(section_name); - return base::string16(section_string->Buffer, - section_string->Length / sizeof(wchar_t)); + return std::wstring(section_string->Buffer, + section_string->Length / sizeof(wchar_t)); } - return base::string16(); + return std::wstring(); } bool IsModuleValidImageSection(HANDLE section, @@ -114,12 +113,12 @@ return true; } -base::string16 ExtractLoadedModuleName(const base::string16& module_path) { +std::wstring ExtractLoadedModuleName(const std::wstring& module_path) { if (module_path.empty() || module_path.back() == L'\\') - return base::string16(); + return std::wstring(); size_t sep = module_path.find_last_of(L'\\'); - if (sep == base::string16::npos) + if (sep == std::wstring::npos) return module_path; return module_path.substr(sep + 1); } @@ -161,11 +160,11 @@ } } -base::string16 GetImageInfoFromLoadedModule(HMODULE module, uint32_t* flags) { +std::wstring GetImageInfoFromLoadedModule(HMODULE module, uint32_t* flags) { std::string out_name; base::win::PEImage pe(module); SafeGetImageInfo(pe, &out_name, flags); - return base::string16(out_name.begin(), out_name.end()); + return std::wstring(out_name.begin(), out_name.end()); } bool IsSameAsCurrentProcess(HANDLE process) { @@ -198,7 +197,7 @@ if (module) { UINT image_flags; - base::string16 module_name_from_image(GetImageInfoFromLoadedModule( + std::wstring module_name_from_image(GetImageInfoFromLoadedModule( reinterpret_cast<HMODULE>(*base), &image_flags)); int blocked_index = DllMatch(module_name_from_image); @@ -206,8 +205,8 @@ // If the module name isn't blacklisted, see if the file name is different // and blacklisted. if (blocked_index == -1) { - base::string16 file_name(GetBackingModuleFilePath(*base)); - base::string16 module_name_from_file = ExtractLoadedModuleName(file_name); + std::wstring file_name(GetBackingModuleFilePath(*base)); + std::wstring module_name_from_file = ExtractLoadedModuleName(file_name); if (module_name_from_image != module_name_from_file) blocked_index = DllMatch(module_name_from_file);
diff --git a/chrome_elf/blacklist/test/blacklist_test.cc b/chrome_elf/blacklist/test/blacklist_test.cc index 7eb18f2..a0c55f2f 100644 --- a/chrome_elf/blacklist/test/blacklist_test.cc +++ b/chrome_elf/blacklist/test/blacklist_test.cc
@@ -7,6 +7,7 @@ #include <memory> #include "base/environment.h" +#include "base/files/file.h" #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" #include "base/i18n/case_conversion.h" @@ -20,8 +21,8 @@ #include "base/win/registry.h" #include "chrome/common/chrome_version.h" #include "chrome_elf/blacklist/blacklist.h" -#include "chrome_elf/blacklist/test/blacklist_test_main_dll.h" #include "chrome_elf/chrome_elf_constants.h" +#include "chrome_elf/nt_registry/nt_registry.h" #include "testing/gtest/include/gtest/gtest.h" const wchar_t kTestDllName1[] = L"blacklist_test_dll_1.dll"; @@ -33,24 +34,31 @@ extern const wchar_t* kEnvVars[]; -extern "C" { -// When modifying the blacklist in the test process, use the exported test dll -// functions on the test blacklist dll, not the ones linked into the test -// executable itself. -__declspec(dllimport) void TestDll_AddDllsFromRegistryToBlacklist(); -__declspec(dllimport) bool TestDll_AddDllToBlacklist(const wchar_t* dll_name); -__declspec(dllimport) int TestDll_BlacklistSize(); -__declspec(dllimport) void TestDll_BlockedDll(size_t blocked_index); -__declspec(dllimport) int TestDll_GetBlacklistIndex(const wchar_t* dll_name); -__declspec(dllimport) bool TestDll_IsBlacklistInitialized(); -__declspec(dllimport) bool TestDll_RemoveDllFromBlacklist( - const wchar_t* dll_name); -__declspec(dllimport) bool TestDll_SuccessfullyBlocked( +namespace { + +// Functions we need from blacklist_test_main_dll.dll +typedef void (*TestDll_AddDllsFromRegistryToBlacklistFunction)(); +typedef bool (*TestDll_AddDllToBlacklistFunction)(const wchar_t* dll_name); +typedef int (*TestDll_BlacklistSizeFunction)(); +typedef void (*TestDll_BlockedDllFunction)(size_t blocked_index); +typedef int (*TestDll_GetBlacklistIndexFunction)(const wchar_t* dll_name); +typedef bool (*TestDll_IsBlacklistInitializedFunction)(); +typedef bool (*TestDll_RemoveDllFromBlacklistFunction)(const wchar_t* dll_name); +typedef bool (*TestDll_SuccessfullyBlockedFunction)( const wchar_t** blocked_dlls, int* size); -} +typedef void (*InitTestDllFunction)(); -namespace { +TestDll_AddDllsFromRegistryToBlacklistFunction + TestDll_AddDllsFromRegistryToBlacklist = nullptr; +TestDll_AddDllToBlacklistFunction TestDll_AddDllToBlacklist = nullptr; +TestDll_BlacklistSizeFunction TestDll_BlacklistSize = nullptr; +TestDll_BlockedDllFunction TestDll_BlockedDll = nullptr; +TestDll_GetBlacklistIndexFunction TestDll_GetBlacklistIndex = nullptr; +TestDll_IsBlacklistInitializedFunction TestDll_IsBlacklistInitialized = nullptr; +TestDll_RemoveDllFromBlacklistFunction TestDll_RemoveDllFromBlacklist = nullptr; +TestDll_SuccessfullyBlockedFunction TestDll_SuccessfullyBlocked = nullptr; +InitTestDllFunction InitTestDll = nullptr; struct TestData { const wchar_t* dll_name; @@ -63,7 +71,6 @@ class BlacklistTest : public testing::Test { protected: BlacklistTest() : override_manager_(), num_initially_blocked_(0) { - override_manager_.OverrideRegistry(HKEY_CURRENT_USER); } void CheckBlacklistedDllsNotLoaded() { @@ -125,9 +132,71 @@ int num_initially_blocked_; private: + // This function puts registry-key redirection paths into + // process-specific environment variables, for our test DLLs to access. + // This will only work as long as the IPC is within the same process. + void IpcOverrides() { + if (::wcslen(nt::HKCU_override) != 0) { + ASSERT_TRUE( + ::SetEnvironmentVariableW(L"hkcu_override", nt::HKCU_override)); + } + if (::wcslen(nt::HKLM_override) != 0) { + ASSERT_TRUE( + ::SetEnvironmentVariableW(L"hklm_override", nt::HKLM_override)); + } + } + void SetUp() override { - // Force an import from blacklist_test_main_dll. - InitBlacklistTestDll(); + base::string16 temp; + override_manager_.OverrideRegistry(HKEY_CURRENT_USER, &temp); + ::wcsncpy(nt::HKCU_override, temp.c_str(), nt::g_kRegMaxPathLen - 1); + + // Make the override path available to our test DLL. + IpcOverrides(); + + // Load the main test Dll now. + // Note: this has to happen after we set up the registry overrides. + HMODULE dll = nullptr; + dll = ::LoadLibraryW(L"blacklist_test_main_dll.dll"); + if (!dll) + return; + TestDll_AddDllsFromRegistryToBlacklist = + reinterpret_cast<TestDll_AddDllsFromRegistryToBlacklistFunction>( + ::GetProcAddress(dll, "TestDll_AddDllsFromRegistryToBlacklist")); + TestDll_AddDllToBlacklist = + reinterpret_cast<TestDll_AddDllToBlacklistFunction>( + ::GetProcAddress(dll, "TestDll_AddDllToBlacklist")); + TestDll_BlacklistSize = reinterpret_cast<TestDll_BlacklistSizeFunction>( + ::GetProcAddress(dll, "TestDll_BlacklistSize")); + TestDll_BlockedDll = reinterpret_cast<TestDll_BlockedDllFunction>( + ::GetProcAddress(dll, "TestDll_BlockedDll")); + TestDll_GetBlacklistIndex = + reinterpret_cast<TestDll_GetBlacklistIndexFunction>( + ::GetProcAddress(dll, "TestDll_GetBlacklistIndex")); + TestDll_IsBlacklistInitialized = + reinterpret_cast<TestDll_IsBlacklistInitializedFunction>( + ::GetProcAddress(dll, "TestDll_IsBlacklistInitialized")); + TestDll_RemoveDllFromBlacklist = + reinterpret_cast<TestDll_RemoveDllFromBlacklistFunction>( + ::GetProcAddress(dll, "TestDll_RemoveDllFromBlacklist")); + TestDll_SuccessfullyBlocked = + reinterpret_cast<TestDll_SuccessfullyBlockedFunction>( + ::GetProcAddress(dll, "TestDll_SuccessfullyBlocked")); + InitTestDll = reinterpret_cast<InitTestDllFunction>( + ::GetProcAddress(dll, "InitTestDll")); + if (!TestDll_AddDllsFromRegistryToBlacklist || !TestDll_AddDllToBlacklist || + !TestDll_BlacklistSize || !TestDll_BlockedDll || + !TestDll_GetBlacklistIndex || !TestDll_IsBlacklistInitialized || + !TestDll_RemoveDllFromBlacklist || !TestDll_SuccessfullyBlocked || + !InitTestDll) + return; + + // We have to call this exported function every time this test setup runs. + // If the tests are running in single process mode, the test DLL does not + // get reloaded everytime - but we need to make sure it updates + // appropriately. + InitTestDll(); + blacklist_registry_key_.reset( new base::win::RegKey(HKEY_CURRENT_USER, blacklist::kRegistryBeaconPath, @@ -142,6 +211,9 @@ TestDll_RemoveDllFromBlacklist(kTestDllName2); TestDll_RemoveDllFromBlacklist(kTestDllName3); } + + // A scoped temporary directory to be destroyed with this test. + base::ScopedTempDir reg_override_dir_; }; TEST_F(BlacklistTest, Beacon) { @@ -254,15 +326,27 @@ KEY_QUERY_VALUE | KEY_SET_VALUE); key.DeleteKey(L""); - // Add the test dlls to the registry (with their name as both key and value). + // Add the test dlls to the registry. + // (REG_MULTI_SZ: eos separated, double null terminated.) base::win::RegKey finch_blacklist_registry_key( HKEY_CURRENT_USER, blacklist::kRegistryFinchListPath, KEY_QUERY_VALUE | KEY_SET_VALUE); + + std::vector<wchar_t>(reg_buffer); for (size_t i = 0; i < arraysize(test_data); ++i) { - finch_blacklist_registry_key.WriteValue(test_data[i].dll_name, - test_data[i].dll_name); + if (reg_buffer.size() > 0) + reg_buffer.push_back(L'\0'); + const wchar_t* dll = test_data[i].dll_name; + // Append the name, not including terminator. + reg_buffer.insert(reg_buffer.end(), dll, dll + ::wcslen(dll)); } + reg_buffer.push_back(L'\0'); + reg_buffer.push_back(L'\0'); + + finch_blacklist_registry_key.WriteValue( + blacklist::kRegistryFinchListValueName, reg_buffer.data(), + (DWORD)(reg_buffer.size() * sizeof(wchar_t)), REG_MULTI_SZ); TestDll_AddDllsFromRegistryToBlacklist(); CheckBlacklistedDllsNotLoaded();
diff --git a/chrome_elf/blacklist/test/blacklist_test_main.cc b/chrome_elf/blacklist/test/blacklist_test_main.cc deleted file mode 100644 index c84b5ad..0000000 --- a/chrome_elf/blacklist/test/blacklist_test_main.cc +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/at_exit.h" -#include "chrome_elf/blacklist/test/blacklist_test_main_dll.h" -#include "testing/gtest/include/gtest/gtest.h" - -int main(int argc, char** argv) { - testing::InitGoogleTest(&argc, argv); - - base::AtExitManager at_exit_manager; - - InitBlacklistTestDll(); - - RUN_ALL_TESTS(); -}
diff --git a/chrome_elf/blacklist/test/blacklist_test_main_dll.cc b/chrome_elf/blacklist/test/blacklist_test_main_dll.cc index 8dd16a6..3b2c4d7 100644 --- a/chrome_elf/blacklist/test/blacklist_test_main_dll.cc +++ b/chrome_elf/blacklist/test/blacklist_test_main_dll.cc
@@ -2,16 +2,49 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chrome_elf/blacklist/blacklist.h" + #include <windows.h> #include "chrome/install_static/install_util.h" -#include "chrome_elf/blacklist/blacklist.h" +#include "chrome_elf/nt_registry/nt_registry.h" -extern "C" void InitBlacklistTestDll() { +namespace { + +void GetIpcOverrides() { + DWORD buffer_size = ::GetEnvironmentVariableW(L"hkcu_override", nullptr, 0); + if (buffer_size > 0) { + wchar_t* content = new wchar_t[buffer_size]; + buffer_size = + ::GetEnvironmentVariableW(L"hkcu_override", content, buffer_size); + if (buffer_size) + ::wcsncpy(nt::HKCU_override, content, nt::g_kRegMaxPathLen - 1); + delete[] content; + } + + buffer_size = ::GetEnvironmentVariableW(L"hklm_override", nullptr, 0); + if (buffer_size > 0) { + wchar_t* content = new wchar_t[buffer_size]; + buffer_size = + ::GetEnvironmentVariableW(L"hklm_override", content, buffer_size); + if (buffer_size) + ::wcsncpy(nt::HKLM_override, content, nt::g_kRegMaxPathLen - 1); + delete[] content; + } + + return; +} + +} // namespace + +extern "C" __declspec(dllexport) void InitTestDll() { + // Make sure we've got the latest registry overrides. + GetIpcOverrides(); } BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) { if (reason == DLL_PROCESS_ATTACH) { + GetIpcOverrides(); install_static::InitializeProcessType(); blacklist::Initialize(true); // force always on, no beacon }
diff --git a/chrome_elf/blacklist/test/blacklist_test_main_dll.def b/chrome_elf/blacklist/test/blacklist_test_main_dll.def index 70a872a..0a6efab 100644 --- a/chrome_elf/blacklist/test/blacklist_test_main_dll.def +++ b/chrome_elf/blacklist/test/blacklist_test_main_dll.def
@@ -13,4 +13,3 @@ TestDll_IsBlacklistInitialized=IsBlacklistInitialized TestDll_SuccessfullyBlocked=SuccessfullyBlocked TestDll_RemoveDllFromBlacklist=RemoveDllFromBlacklist - InitBlacklistTestDll \ No newline at end of file
diff --git a/chrome_elf/breakpad.cc b/chrome_elf/breakpad.cc deleted file mode 100644 index 226ebf8..0000000 --- a/chrome_elf/breakpad.cc +++ /dev/null
@@ -1,196 +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. - -// This module contains the necessary code to register the Breakpad exception -// handler. This implementation is based on Chrome's crash reporting code. - -#include "chrome_elf/breakpad.h" - -#include <sddl.h> - -#include "base/macros.h" -#include "base/strings/string16.h" -#include "breakpad/src/client/windows/handler/exception_handler.h" -#include "chrome/common/chrome_version.h" -#include "chrome/install_static/install_util.h" - -google_breakpad::ExceptionHandler* g_elf_breakpad = NULL; - -namespace { - -const wchar_t kBreakpadProductName[] = L"Chrome"; -const wchar_t kBreakpadVersionEntry[] = L"ver"; -const wchar_t kBreakpadProdEntry[] = L"prod"; -const wchar_t kBreakpadPlatformEntry[] = L"plat"; -const wchar_t kBreakpadPlatformWin32[] = L"Win32"; -const wchar_t kBreakpadProcessEntry[] = L"ptype"; -const wchar_t kBreakpadChannelEntry[] = L"channel"; - -// The protocol for connecting to the out-of-process Breakpad crash -// reporter is different for x86-32 and x86-64: the message sizes -// are different because the message struct contains a pointer. As -// a result, there are two different named pipes to connect to. The -// 64-bit one is distinguished with an "-x64" suffix. -const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices\\"; -const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; -const wchar_t kSystemPrincipalSid[] = L"S-1-5-18"; - -const wchar_t kNoErrorDialogs[] = L"noerrdialogs"; - -google_breakpad::CustomClientInfo* GetCustomInfo() { - base::string16 process = - install_static::IsNonBrowserProcess() ? L"renderer" : L"browser"; - - wchar_t exe_path[MAX_PATH] = {}; - base::string16 channel; - if (GetModuleFileName(NULL, exe_path, arraysize(exe_path)) && - install_static::IsSxSChrome(exe_path)) { - channel = L"canary"; - } - - static google_breakpad::CustomInfoEntry ver_entry( - kBreakpadVersionEntry, TEXT(CHROME_VERSION_STRING)); - static google_breakpad::CustomInfoEntry prod_entry( - kBreakpadProdEntry, kBreakpadProductName); - static google_breakpad::CustomInfoEntry plat_entry( - kBreakpadPlatformEntry, kBreakpadPlatformWin32); - static google_breakpad::CustomInfoEntry proc_entry( - kBreakpadProcessEntry, process.c_str()); - static google_breakpad::CustomInfoEntry channel_entry( - kBreakpadChannelEntry, channel.c_str()); - static google_breakpad::CustomInfoEntry entries[] = { - ver_entry, prod_entry, plat_entry, proc_entry, channel_entry}; - static google_breakpad::CustomClientInfo custom_info = { - entries, arraysize(entries) }; - return &custom_info; -} - -base::string16 GetUserSidString() { - // Get the current token. - HANDLE token = NULL; - base::string16 user_sid; - if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &token)) - return user_sid; - - DWORD size = sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE; - BYTE user_bytes[sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE] = {}; - TOKEN_USER* user = reinterpret_cast<TOKEN_USER*>(user_bytes); - - wchar_t* sid_string = NULL; - if (::GetTokenInformation(token, TokenUser, user, size, &size) && - user->User.Sid && - ::ConvertSidToStringSid(user->User.Sid, &sid_string)) { - user_sid = sid_string; - ::LocalFree(sid_string); - } - - CloseHandle(token); - return user_sid; -} - -bool IsHeadless() { - DWORD ret = ::GetEnvironmentVariable(L"CHROME_HEADLESS", NULL, 0); - if (ret != 0) - return true; - - wchar_t* command_line = ::GetCommandLine(); - - // Note: Since this is a pure substring search rather than a check for a - // switch, there is a small chance that this code will match things that the - // Chrome code (which executes a similar check) does not. However, as long as - // no other switches contain the string "noerrdialogs", it should not be an - // issue. - return (command_line && wcsstr(command_line, kNoErrorDialogs)); -} - -} // namespace - -int GenerateCrashDump(EXCEPTION_POINTERS* exinfo) { - DWORD code = exinfo->ExceptionRecord->ExceptionCode; - if (code == EXCEPTION_BREAKPOINT || code == EXCEPTION_SINGLE_STEP) - return EXCEPTION_CONTINUE_SEARCH; - - if (g_elf_breakpad != NULL) - g_elf_breakpad->WriteMinidumpForException(exinfo); - return EXCEPTION_CONTINUE_SEARCH; -} - -void InitializeCrashReporting() { - wchar_t exe_path[MAX_PATH] = {}; - if (!::GetModuleFileName(NULL, exe_path, arraysize(exe_path))) - return; - - // Disable the message box for assertions. - _CrtSetReportMode(_CRT_ASSERT, 0); - - // Get the alternate dump directory. We use the temp path. - // N.B. We don't use base::GetTempDir() here to avoid running more code then - // necessary before crashes can be properly reported. - wchar_t temp_directory[MAX_PATH + 1] = {}; - DWORD length = GetTempPath(MAX_PATH, temp_directory); - if (length == 0) - return; - - // Minidump with stacks, PEB, TEBs and unloaded module list. - MINIDUMP_TYPE dump_type = static_cast<MINIDUMP_TYPE>( - MiniDumpWithProcessThreadData | // Get PEB and TEB. - MiniDumpWithUnloadedModules | // Get unloaded modules when available. - MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by - // stack. - -#if defined(GOOGLE_CHROME_BUILD) && defined(OFFICIAL_BUILD) - bool is_official_chrome_build = true; -#else - bool is_official_chrome_build = false; -#endif - - base::string16 pipe_name; - - bool enabled_by_policy = false; - bool use_policy = - install_static::ReportingIsEnforcedByPolicy(&enabled_by_policy); - - if (!use_policy && IsHeadless()) { - pipe_name = kChromePipeName; - } else if (use_policy ? enabled_by_policy - : (is_official_chrome_build && - install_static::GetCollectStatsConsent())) { - // Build the pipe name. It can be one of: - // 32-bit system: \\.\pipe\GoogleCrashServices\S-1-5-18 - // 32-bit user: \\.\pipe\GoogleCrashServices\<user SID> - // 64-bit system: \\.\pipe\GoogleCrashServices\S-1-5-18-x64 - // 64-bit user: \\.\pipe\GoogleCrashServices\<user SID>-x64 - base::string16 user_sid = install_static::IsSystemInstall(exe_path) - ? kSystemPrincipalSid - : GetUserSidString(); - if (user_sid.empty()) - return; - - pipe_name = kGoogleUpdatePipeName; - pipe_name += user_sid; - -#if defined(_WIN64) - pipe_name += L"-x64"; -#endif - } else { - // Either this is a Chromium build, reporting is disabled by policy or the - // user has not given consent. - return; - } - - g_elf_breakpad = new google_breakpad::ExceptionHandler( - temp_directory, - NULL, - NULL, - NULL, - google_breakpad::ExceptionHandler::HANDLER_ALL, - dump_type, - pipe_name.c_str(), - GetCustomInfo()); - - if (g_elf_breakpad->IsOutOfProcess()) { - // Tells breakpad to handle breakpoint and single step exceptions. - g_elf_breakpad->set_handle_debug_exceptions(true); - } -}
diff --git a/chrome_elf/breakpad.h b/chrome_elf/breakpad.h deleted file mode 100644 index 8067708..0000000 --- a/chrome_elf/breakpad.h +++ /dev/null
@@ -1,34 +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 CHROME_ELF_BREAKPAD_H_ -#define CHROME_ELF_BREAKPAD_H_ - -#include <windows.h> - -namespace google_breakpad { -class ExceptionHandler; -} - -// Initializes collection and upload of crash reports. This will only be done if -// the user has agreed to crash dump reporting. -// -// Crash reporting has to be initialized as early as possible (e.g., the first -// thing in main()) to catch crashes occuring during process startup. -// Crashes which occur during the global static construction phase will not -// be caught and reported. This should not be a problem as static non-POD -// objects are not allowed by the style guide and exceptions to this rule are -// rare. -void InitializeCrashReporting(); - -// Generates a crashdump for the provided |exinfo|. This crashdump will be -// either be saved locally, or uploaded, depending on how the ExceptionHandler -// has been configured. -int GenerateCrashDump(EXCEPTION_POINTERS* exinfo); - -// Global pointer to the ExceptionHandler. This is initialized by -// InitializeCrashReporting() and used by GenerateCrashDump() to record dumps. -extern google_breakpad::ExceptionHandler* g_elf_breakpad; - -#endif // CHROME_ELF_BREAKPAD_H_
diff --git a/chrome_elf/breakpad/breakpad.cc b/chrome_elf/breakpad/breakpad.cc new file mode 100644 index 0000000..f33c9fef --- /dev/null +++ b/chrome_elf/breakpad/breakpad.cc
@@ -0,0 +1,165 @@ +// 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. + +// This module contains the necessary code to register the Breakpad exception +// handler. This implementation is based on Chrome's crash reporting code. + +#include "chrome_elf/breakpad/breakpad.h" + +#include "breakpad/src/client/windows/handler/exception_handler.h" +#include "chrome/common/chrome_version.h" +#include "chrome/install_static/install_util.h" +#include "chrome_elf/nt_registry/nt_registry.h" + +google_breakpad::ExceptionHandler* g_elf_breakpad = NULL; + +namespace { + +const wchar_t kBreakpadProductName[] = L"Chrome"; +const wchar_t kBreakpadVersionEntry[] = L"ver"; +const wchar_t kBreakpadProdEntry[] = L"prod"; +const wchar_t kBreakpadPlatformEntry[] = L"plat"; +const wchar_t kBreakpadPlatformWin32[] = L"Win32"; +const wchar_t kBreakpadProcessEntry[] = L"ptype"; +const wchar_t kBreakpadChannelEntry[] = L"channel"; + +// The protocol for connecting to the out-of-process Breakpad crash +// reporter is different for x86-32 and x86-64: the message sizes +// are different because the message struct contains a pointer. As +// a result, there are two different named pipes to connect to. The +// 64-bit one is distinguished with an "-x64" suffix. +const wchar_t kChromePipeName[] = L"\\\\.\\pipe\\ChromeCrashServices\\"; +const wchar_t kGoogleUpdatePipeName[] = L"\\\\.\\pipe\\GoogleCrashServices\\"; +const wchar_t kSystemPrincipalSid[] = L"S-1-5-18"; + +const wchar_t kNoErrorDialogs[] = L"noerrdialogs"; + +google_breakpad::CustomClientInfo* GetCustomInfo() { + std::wstring process = + install_static::IsNonBrowserProcess() ? L"renderer" : L"browser"; + + wchar_t exe_path[MAX_PATH] = {}; + std::wstring channel; + if (GetModuleFileName(NULL, exe_path, MAX_PATH) && + install_static::IsSxSChrome(exe_path)) { + channel = L"canary"; + } + + static google_breakpad::CustomInfoEntry ver_entry( + kBreakpadVersionEntry, TEXT(CHROME_VERSION_STRING)); + static google_breakpad::CustomInfoEntry prod_entry(kBreakpadProdEntry, + kBreakpadProductName); + static google_breakpad::CustomInfoEntry plat_entry(kBreakpadPlatformEntry, + kBreakpadPlatformWin32); + static google_breakpad::CustomInfoEntry proc_entry(kBreakpadProcessEntry, + process.c_str()); + static google_breakpad::CustomInfoEntry channel_entry(kBreakpadChannelEntry, + channel.c_str()); + static google_breakpad::CustomInfoEntry entries[] = { + ver_entry, prod_entry, plat_entry, proc_entry, channel_entry}; + static google_breakpad::CustomClientInfo custom_info = { + entries, (sizeof(entries) / sizeof(google_breakpad::CustomInfoEntry))}; + return &custom_info; +} + +bool IsHeadless() { + DWORD ret = ::GetEnvironmentVariable(L"CHROME_HEADLESS", NULL, 0); + if (ret != 0) + return true; + + wchar_t* command_line = ::GetCommandLine(); + + // Note: Since this is a pure substring search rather than a check for a + // switch, there is a small chance that this code will match things that the + // Chrome code (which executes a similar check) does not. However, as long as + // no other switches contain the string "noerrdialogs", it should not be an + // issue. + return (command_line && wcsstr(command_line, kNoErrorDialogs)); +} + +} // namespace + +int GenerateCrashDump(EXCEPTION_POINTERS* exinfo) { + DWORD code = exinfo->ExceptionRecord->ExceptionCode; + if (code == EXCEPTION_BREAKPOINT || code == EXCEPTION_SINGLE_STEP) + return EXCEPTION_CONTINUE_SEARCH; + + if (g_elf_breakpad != NULL) + g_elf_breakpad->WriteMinidumpForException(exinfo); + return EXCEPTION_CONTINUE_SEARCH; +} + +void InitializeCrashReporting() { + wchar_t exe_path[MAX_PATH] = {}; + if (!::GetModuleFileName(NULL, exe_path, MAX_PATH)) + return; + + // Disable the message box for assertions. + _CrtSetReportMode(_CRT_ASSERT, 0); + + // Get the alternate dump directory. We use the temp path. + // N.B. We don't use base::GetTempDir() here to avoid running more code then + // necessary before crashes can be properly reported. + wchar_t temp_directory[MAX_PATH + 1] = {}; + DWORD length = GetTempPath(MAX_PATH, temp_directory); + if (length == 0) + return; + + // Minidump with stacks, PEB, TEBs and unloaded module list. + MINIDUMP_TYPE dump_type = static_cast<MINIDUMP_TYPE>( + MiniDumpWithProcessThreadData | // Get PEB and TEB. + MiniDumpWithUnloadedModules | // Get unloaded modules when available. + MiniDumpWithIndirectlyReferencedMemory); // Get memory referenced by + // stack. + +#if defined(GOOGLE_CHROME_BUILD) && defined(OFFICIAL_BUILD) + bool is_official_chrome_build = true; +#else + bool is_official_chrome_build = false; +#endif + + std::wstring pipe_name; + + bool enabled_by_policy = false; + bool use_policy = + install_static::ReportingIsEnforcedByPolicy(&enabled_by_policy); + + if (!use_policy && IsHeadless()) { + pipe_name = kChromePipeName; + } else if (use_policy ? enabled_by_policy + : (is_official_chrome_build && + install_static::GetCollectStatsConsent())) { + // Build the pipe name. It can be one of: + // 32-bit system: \\.\pipe\GoogleCrashServices\S-1-5-18 + // 32-bit user: \\.\pipe\GoogleCrashServices\<user SID> + // 64-bit system: \\.\pipe\GoogleCrashServices\S-1-5-18-x64 + // 64-bit user: \\.\pipe\GoogleCrashServices\<user SID>-x64 + std::wstring user_sid = install_static::IsSystemInstall(exe_path) + ? kSystemPrincipalSid + : nt::GetCurrentUserSidString(); + if (user_sid.empty()) + return; + + pipe_name = kGoogleUpdatePipeName; + pipe_name += user_sid; + +#if defined(_WIN64) + pipe_name += L"-x64"; +#endif + } else { + // Either this is a Chromium build, reporting is disabled by policy or the + // user has not given consent. + return; + } + + g_elf_breakpad = new google_breakpad::ExceptionHandler( + temp_directory, NULL, NULL, NULL, + google_breakpad::ExceptionHandler::HANDLER_ALL, dump_type, + pipe_name.c_str(), GetCustomInfo()); + + if (g_elf_breakpad->IsOutOfProcess()) { + // Tells breakpad to handle breakpoint and single step exceptions. + g_elf_breakpad->set_handle_debug_exceptions(true); + } +}
diff --git a/chrome_elf/breakpad/breakpad.h b/chrome_elf/breakpad/breakpad.h new file mode 100644 index 0000000..72783247 --- /dev/null +++ b/chrome_elf/breakpad/breakpad.h
@@ -0,0 +1,34 @@ +// 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 CHROME_ELF_BREAKPAD_BREAKPAD_H_ +#define CHROME_ELF_BREAKPAD_BREAKPAD_H_ + +#include <windows.h> + +namespace google_breakpad { +class ExceptionHandler; +} + +// Initializes collection and upload of crash reports. This will only be done if +// the user has agreed to crash dump reporting. +// +// Crash reporting has to be initialized as early as possible (e.g., the first +// thing in main()) to catch crashes occuring during process startup. +// Crashes which occur during the global static construction phase will not +// be caught and reported. This should not be a problem as static non-POD +// objects are not allowed by the style guide and exceptions to this rule are +// rare. +void InitializeCrashReporting(); + +// Generates a crashdump for the provided |exinfo|. This crashdump will be +// either be saved locally, or uploaded, depending on how the ExceptionHandler +// has been configured. +int GenerateCrashDump(EXCEPTION_POINTERS* exinfo); + +// Global pointer to the ExceptionHandler. This is initialized by +// InitializeCrashReporting() and used by GenerateCrashDump() to record dumps. +extern google_breakpad::ExceptionHandler* g_elf_breakpad; + +#endif // CHROME_ELF_BREAKPAD_BREAKPAD_H_
diff --git a/chrome_elf/chrome_elf.gyp b/chrome_elf/chrome_elf.gyp index 7a49fe8..420ee05 100644 --- a/chrome_elf/chrome_elf.gyp +++ b/chrome_elf/chrome_elf.gyp
@@ -12,6 +12,9 @@ 'dll_hash.gypi', ], 'targets': [ + ##-------------------------------------------------------------------------- + ## chrome_elf + ##-------------------------------------------------------------------------- { 'target_name': 'chrome_elf_resources', 'type': 'none', @@ -42,9 +45,12 @@ '<(SHARED_INTERMEDIATE_DIR)/chrome_elf/chrome_elf_version.rc', ], 'dependencies': [ + '../chrome/chrome.gyp:install_static_util', 'blacklist', 'chrome_elf_breakpad', + 'chrome_elf_hook_util', 'chrome_elf_resources', + 'nt_registry/nt_registry.gyp:chrome_elf_nt_registry', '../chrome/chrome.gyp:install_static_util', '../components/components.gyp:crash_component', '../components/components.gyp:crash_core_common', @@ -68,6 +74,52 @@ }, }, }, + ##-------------------------------------------------------------------------- + ## chrome_elf sub targets + ##-------------------------------------------------------------------------- + { + 'target_name': 'chrome_elf_constants', + 'type': 'static_library', + 'include_dirs': [ + '..', + ], + 'sources': [ + 'chrome_elf_constants.cc', + 'chrome_elf_constants.h', + ], + }, + { + 'target_name': 'chrome_elf_breakpad', + 'type': 'static_library', + 'include_dirs': [ + '..', + '<(SHARED_INTERMEDIATE_DIR)', + ], + 'sources': [ + 'breakpad/breakpad.cc', + 'breakpad/breakpad.h', + ], + 'dependencies': [ + '../breakpad/breakpad.gyp:breakpad_handler', + '../chrome/chrome.gyp:install_static_util', + '../chrome/common_constants.gyp:version_header', + 'nt_registry/nt_registry.gyp:chrome_elf_nt_registry', + ], + }, + { + 'target_name': 'chrome_elf_hook_util', + 'type': 'static_library', + 'include_dirs': [ + '..', + ], + 'sources': [ + 'hook_util/thunk_getter.cc', + 'hook_util/thunk_getter.h', + ], + }, + ##-------------------------------------------------------------------------- + ## tests + ##-------------------------------------------------------------------------- { 'target_name': 'chrome_elf_unittests_exe', 'product_name': 'chrome_elf_unittests', @@ -94,6 +146,8 @@ 'blacklist_test_dll_2', 'blacklist_test_dll_3', 'blacklist_test_main_dll', + 'chrome_elf_hook_util', + 'nt_registry/nt_registry.gyp:chrome_elf_nt_registry', ], 'msvs_settings': { 'VCLinkerTool': { @@ -125,50 +179,10 @@ 'chrome_elf_unittests_exe', ], }, - { - 'target_name': 'chrome_elf_constants', - 'type': 'static_library', - 'include_dirs': [ - '..', - ], - 'sources': [ - 'chrome_elf_constants.cc', - 'chrome_elf_constants.h', - ], - }, - { - 'target_name': 'chrome_elf_common', - 'type': 'static_library', - 'dependencies': [ - 'chrome_elf_constants', - ], - 'include_dirs': [ - '..', - ], - 'sources': [ - 'thunk_getter.cc', - 'thunk_getter.h', - ], - }, - { - 'target_name': 'chrome_elf_breakpad', - 'type': 'static_library', - 'include_dirs': [ - '..', - '<(SHARED_INTERMEDIATE_DIR)', - ], - 'sources': [ - 'breakpad.cc', - 'breakpad.h', - ], - 'dependencies': [ - 'chrome_elf_common', - '../breakpad/breakpad.gyp:breakpad_handler', - '../chrome/common_constants.gyp:version_header', - '../chrome/chrome.gyp:install_static_util', - ], - }, ], # targets + ##---------------------------------------------------------------------------- + ## conditionals + ##---------------------------------------------------------------------------- 'conditions': [ ['test_isolation_mode != "noop"', { 'targets': [
diff --git a/chrome_elf/chrome_elf_constants.cc b/chrome_elf/chrome_elf_constants.cc index 76560228..9b9e944 100644 --- a/chrome_elf/chrome_elf_constants.cc +++ b/chrome_elf/chrome_elf_constants.cc
@@ -21,6 +21,8 @@ L"SOFTWARE\\" PRODUCT_STRING_PATH L"\\BLBeacon"; const wchar_t kRegistryFinchListPath[] = L"SOFTWARE\\" PRODUCT_STRING_PATH L"\\BLFinchList"; +const char kRegistryFinchListValueNameStr[] = "BLDlls"; +const wchar_t kRegistryFinchListValueName[] = L"BLDlls"; const wchar_t kBeaconVersion[] = L"version"; const wchar_t kBeaconState[] = L"state"; const wchar_t kBeaconAttemptCount[] = L"failed_count"; @@ -28,3 +30,13 @@ const DWORD kBeaconMaxAttempts = 2; } // namespace blacklist + +namespace elf_sec { + +const wchar_t kRegSecurityFinchPath[] = + L"SOFTWARE\\" PRODUCT_STRING_PATH L"\\BrowserSboxFinch"; + +const wchar_t kRegSecurityPath[] = + L"SOFTWARE\\" PRODUCT_STRING_PATH L"\\BrowserSec"; + +} // namespace elf_sec
diff --git a/chrome_elf/chrome_elf_constants.h b/chrome_elf/chrome_elf_constants.h index a989eeb..58c635b 100644 --- a/chrome_elf/chrome_elf_constants.h +++ b/chrome_elf/chrome_elf_constants.h
@@ -17,6 +17,13 @@ // The registry path of the finch blacklist dlls. extern const wchar_t kRegistryFinchListPath[]; +// The registry value name for the REG_MULTI_SZ list of blacklist dlls. +// Note the char version is handy for use as the param name when +// appending dll names to the base::FieldTrial. Can be removed +// if no longer used. +extern const char kRegistryFinchListValueNameStr[]; +extern const wchar_t kRegistryFinchListValueName[]; + // The properties for the blacklist beacon. extern const wchar_t kBeaconVersion[]; extern const wchar_t kBeaconState[]; @@ -41,4 +48,14 @@ } // namespace blacklist +namespace elf_sec { + +// The registry path of the finch "emergency-off" +// switch for sandbox::MITIGATION_EXTENSION_POINT_DISABLE. +extern const wchar_t kRegSecurityFinchPath[]; + +// The registry path for any early-browser security settings. +extern const wchar_t kRegSecurityPath[]; +} + #endif // CHROME_ELF_CHROME_ELF_CONSTANTS_H_
diff --git a/chrome_elf/chrome_elf_main.cc b/chrome_elf/chrome_elf_main.cc index 8ee176f..7a1a92d 100644 --- a/chrome_elf/chrome_elf_main.cc +++ b/chrome_elf/chrome_elf_main.cc
@@ -8,8 +8,7 @@ #include "chrome/install_static/install_util.h" #include "chrome_elf/blacklist/blacklist.h" -#include "chrome_elf/breakpad.h" - +#include "chrome_elf/breakpad/breakpad.h" void SignalChromeElf() { blacklist::ResetBeacon();
diff --git a/chrome_elf/chrome_elf_util_unittest.cc b/chrome_elf/chrome_elf_util_unittest.cc index 210901e..dc4f1e1 100644 --- a/chrome_elf/chrome_elf_util_unittest.cc +++ b/chrome_elf/chrome_elf_util_unittest.cc
@@ -3,10 +3,14 @@ // found in the LICENSE file. #include <tuple> +#include <windows.h> +#include <versionhelpers.h> // windows.h must be before. #include "base/test/test_reg_util_win.h" #include "base/win/registry.h" #include "chrome/install_static/install_util.h" +#include "chrome_elf/chrome_elf_constants.h" +#include "chrome_elf/nt_registry/nt_registry.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -41,18 +45,130 @@ EXPECT_FALSE(IsNonBrowserProcess()); } +//------------------------------------------------------------------------------ +// NT registry API tests (chrome_elf_reg) +//------------------------------------------------------------------------------ + +TEST(ChromeElfUtilTest, NTRegistry) { + HANDLE key_handle; + const wchar_t* dword_val_name = L"DwordTestValue"; + DWORD dword_val = 1234; + const wchar_t* sz_val_name = L"SzTestValue"; + base::string16 sz_val = L"blah de blah de blahhhhh."; + const wchar_t* sz_val_name2 = L"SzTestValueEmpty"; + base::string16 sz_val2 = L""; + const wchar_t* multisz_val_name = L"SzmultiTestValue"; + std::vector<base::string16> multisz_val; + base::string16 multi1 = L"one"; + base::string16 multi2 = L"two"; + base::string16 multi3 = L"three"; + const wchar_t* multisz_val_name2 = L"SzmultiTestValueBad"; + base::string16 multi_empty = L""; + const wchar_t* sz_new_key_1 = L"test\\new\\subkey"; + const wchar_t* sz_new_key_2 = L"test\\new\\subkey\\blah\\"; + const wchar_t* sz_new_key_3 = L"\\test\\new\\subkey\\\\blah2"; + + // Set up registry override for this test. + base::string16 temp; + registry_util::RegistryOverrideManager override_manager; + override_manager.OverrideRegistry(HKEY_CURRENT_USER, &temp); + ::wcsncpy(nt::HKCU_override, temp.c_str(), nt::g_kRegMaxPathLen - 1); + + // Create a temp key to play under. + ASSERT_TRUE(nt::CreateRegKey(nt::HKCU, elf_sec::kRegSecurityPath, + KEY_ALL_ACCESS, &key_handle)); + + // Exercise the supported getter & setter functions. + EXPECT_TRUE(nt::SetRegValueDWORD(key_handle, dword_val_name, dword_val)); + EXPECT_TRUE(nt::SetRegValueSZ(key_handle, sz_val_name, sz_val)); + EXPECT_TRUE(nt::SetRegValueSZ(key_handle, sz_val_name2, sz_val2)); + + DWORD get_dword = 0; + base::string16 get_sz; + EXPECT_TRUE(nt::QueryRegValueDWORD(key_handle, dword_val_name, &get_dword) && + get_dword == dword_val); + EXPECT_TRUE(nt::QueryRegValueSZ(key_handle, sz_val_name, &get_sz) && + get_sz.compare(sz_val) == 0); + EXPECT_TRUE(nt::QueryRegValueSZ(key_handle, sz_val_name2, &get_sz) && + get_sz.compare(sz_val2) == 0); + + multisz_val.push_back(multi1); + multisz_val.push_back(multi2); + multisz_val.push_back(multi3); + EXPECT_TRUE( + nt::SetRegValueMULTISZ(key_handle, multisz_val_name, multisz_val)); + multisz_val.clear(); + multisz_val.push_back(multi_empty); + EXPECT_TRUE( + nt::SetRegValueMULTISZ(key_handle, multisz_val_name2, multisz_val)); + multisz_val.clear(); + + EXPECT_TRUE( + nt::QueryRegValueMULTISZ(key_handle, multisz_val_name, &multisz_val)); + if (multisz_val.size() == 3) { + EXPECT_TRUE(multi1.compare(multisz_val.at(0)) == 0); + EXPECT_TRUE(multi2.compare(multisz_val.at(1)) == 0); + EXPECT_TRUE(multi3.compare(multisz_val.at(2)) == 0); + } else { + EXPECT_TRUE(false); + } + multisz_val.clear(); + + EXPECT_TRUE( + nt::QueryRegValueMULTISZ(key_handle, multisz_val_name2, &multisz_val)); + if (multisz_val.size() == 1) { + EXPECT_TRUE(multi_empty.compare(multisz_val.at(0)) == 0); + } else { + EXPECT_TRUE(false); + } + multisz_val.clear(); + + // Clean up + EXPECT_TRUE(nt::DeleteRegKey(key_handle)); + nt::CloseRegKey(key_handle); + + // More tests for CreateRegKey recursion. + ASSERT_TRUE( + nt::CreateRegKey(nt::HKCU, sz_new_key_1, KEY_ALL_ACCESS, nullptr)); + EXPECT_TRUE(nt::OpenRegKey(nt::HKCU, sz_new_key_1, KEY_ALL_ACCESS, + &key_handle, nullptr)); + EXPECT_TRUE(nt::DeleteRegKey(key_handle)); + nt::CloseRegKey(key_handle); + + ASSERT_TRUE( + nt::CreateRegKey(nt::HKCU, sz_new_key_2, KEY_ALL_ACCESS, nullptr)); + EXPECT_TRUE(nt::OpenRegKey(nt::HKCU, sz_new_key_2, KEY_ALL_ACCESS, + &key_handle, nullptr)); + EXPECT_TRUE(nt::DeleteRegKey(key_handle)); + nt::CloseRegKey(key_handle); + + ASSERT_TRUE( + nt::CreateRegKey(nt::HKCU, sz_new_key_3, KEY_ALL_ACCESS, nullptr)); + EXPECT_TRUE(nt::OpenRegKey(nt::HKCU, L"test\\new\\subkey\\blah2", + KEY_ALL_ACCESS, &key_handle, nullptr)); + EXPECT_TRUE(nt::DeleteRegKey(key_handle)); + nt::CloseRegKey(key_handle); + + ASSERT_TRUE(nt::CreateRegKey(nt::HKCU, nullptr, KEY_ALL_ACCESS, &key_handle)); + nt::CloseRegKey(key_handle); +} + // Parameterized test with paramters: // 1: product: "canary" or "google" // 2: install level: "user" or "system" // 3: install mode: "single" or "multi" -class ChromeElfUtilTest : - public testing::TestWithParam<std::tuple<const char*, - const char*, - const char*> > { +class ChromeElfUtilTest + : public testing::TestWithParam< + std::tuple<const char*, const char*, const char*>> { protected: void SetUp() override { - override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE); - override_manager_.OverrideRegistry(HKEY_CURRENT_USER); + base::string16 temp; + override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE, &temp); + ::wcsncpy(nt::HKLM_override, temp.c_str(), nt::g_kRegMaxPathLen - 1); + temp.clear(); + override_manager_.OverrideRegistry(HKEY_CURRENT_USER, &temp); + ::wcsncpy(nt::HKCU_override, temp.c_str(), nt::g_kRegMaxPathLen - 1); + const char* app; const char* level; const char* mode; @@ -67,8 +183,8 @@ chrome_path_ = kCanaryExePath; } else { app_guid_ = kAppGuidGoogleChrome; - chrome_path_ = (system_level_ ? kChromeSystemExePath : - kChromeUserExePath); + chrome_path_ = + (system_level_ ? kChromeSystemExePath : kChromeUserExePath); } if (multi_install_) { SetMultiInstallStateInRegistry(system_level_, true); @@ -85,10 +201,13 @@ void SetUsageStat(DWORD value, bool state_medium) { LONG result = base::win::RegKey( - system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, - BuildKey(state_medium ? kRegPathClientStateMedium : kRegPathClientState, - app_guid_).c_str(), - KEY_SET_VALUE).WriteValue(kRegValueUsageStats, value); + system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, + BuildKey(state_medium ? kRegPathClientStateMedium + : kRegPathClientState, + app_guid_) + .c_str(), + KEY_SET_VALUE) + .WriteValue(kRegValueUsageStats, value); ASSERT_EQ(ERROR_SUCCESS, result); } @@ -108,10 +227,11 @@ } void SetChannelName(const base::string16& channel_name) { - LONG result = base::win::RegKey( - system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, - BuildKey(kRegPathClientState, app_guid_).c_str(), - KEY_SET_VALUE).WriteValue(kRegApField, channel_name.c_str()); + LONG result = + base::win::RegKey( + system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, + BuildKey(kRegPathClientState, app_guid_).c_str(), KEY_SET_VALUE) + .WriteValue(kRegApField, channel_name.c_str()); ASSERT_EQ(ERROR_SUCCESS, result); } @@ -130,195 +250,195 @@ install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"-m", channel); + EXPECT_STREQ(L"-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelStable, channel); + EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str()); } SetChannelName(L"-full"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"-m", channel); + EXPECT_STREQ(L"-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelStable, channel); + EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str()); } SetChannelName(L"1.1-beta"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"beta-m", channel); + EXPECT_STREQ(L"beta-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelBeta, channel); + EXPECT_STREQ(install_static::kChromeChannelBeta, channel.c_str()); } SetChannelName(L"1.1-beta"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"beta-m", channel); + EXPECT_STREQ(L"beta-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelBeta, channel); + EXPECT_STREQ(install_static::kChromeChannelBeta, channel.c_str()); } SetChannelName(L"1.1-bar"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"beta-m", channel); + EXPECT_STREQ(L"beta-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelBeta, channel); + EXPECT_STREQ(install_static::kChromeChannelBeta, channel.c_str()); } SetChannelName(L"1n1-foobar"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"beta-m", channel); + EXPECT_STREQ(L"beta-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelBeta, channel); + EXPECT_STREQ(install_static::kChromeChannelBeta, channel.c_str()); } SetChannelName(L"foo-1.1-beta"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"-m", channel); + EXPECT_STREQ(L"-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelStable, channel); + EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str()); } SetChannelName(L"2.0-beta"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"-m", channel); + EXPECT_STREQ(L"-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelStable, channel); + EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str()); } SetChannelName(L"2.0-dev"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"dev-m", channel); + EXPECT_STREQ(L"dev-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelDev, channel); + EXPECT_STREQ(install_static::kChromeChannelDev, channel.c_str()); } SetChannelName(L"2.0-DEV"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"dev-m", channel); + EXPECT_STREQ(L"dev-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelDev, channel); + EXPECT_STREQ(install_static::kChromeChannelDev, channel.c_str()); } SetChannelName(L"2.0-dev-eloper"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"dev-m", channel); + EXPECT_STREQ(L"dev-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelDev, channel); + EXPECT_STREQ(install_static::kChromeChannelDev, channel.c_str()); } SetChannelName(L"2.0-doom"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"dev-m", channel); + EXPECT_STREQ(L"dev-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelDev, channel); + EXPECT_STREQ(install_static::kChromeChannelDev, channel.c_str()); } SetChannelName(L"250-doom"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"dev-m", channel); + EXPECT_STREQ(L"dev-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelDev, channel); + EXPECT_STREQ(install_static::kChromeChannelDev, channel.c_str()); } SetChannelName(L"bar-2.0-dev"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"-m", channel); + EXPECT_STREQ(L"-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelStable, channel); + EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str()); } SetChannelName(L"1.0-dev"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"-m", channel); + EXPECT_STREQ(L"-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelStable, channel); + EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str()); } SetChannelName(L"x64-beta"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"beta-m", channel); + EXPECT_STREQ(L"beta-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelBeta, channel); + EXPECT_STREQ(install_static::kChromeChannelBeta, channel.c_str()); } SetChannelName(L"bar-x64-beta"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"beta-m", channel); + EXPECT_STREQ(L"beta-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelBeta, channel); + EXPECT_STREQ(install_static::kChromeChannelBeta, channel.c_str()); } SetChannelName(L"x64-Beta"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"beta-m", channel); + EXPECT_STREQ(L"beta-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelBeta, channel); + EXPECT_STREQ(install_static::kChromeChannelBeta, channel.c_str()); } SetChannelName(L"x64-stable"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"-m", channel); + EXPECT_STREQ(L"-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelStable, channel); + EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str()); } SetChannelName(L"baz-x64-stable"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"-m", channel); + EXPECT_STREQ(L"-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelStable, channel); + EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str()); } SetChannelName(L"x64-Stable"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"-m", channel); + EXPECT_STREQ(L"-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelStable, channel); + EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str()); } SetChannelName(L"fuzzy"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"-m", channel); + EXPECT_STREQ(L"-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelStable, channel); + EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str()); } SetChannelName(L"foo"); install_static::GetChromeChannelName(!system_level_, add_modifier, &channel); if (multi_install_ && add_modifier) { - EXPECT_EQ(L"-m", channel); + EXPECT_STREQ(L"-m", channel.c_str()); } else { - EXPECT_EQ(install_static::kChromeChannelStable, channel); + EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str()); } } @@ -386,15 +506,17 @@ // This test tests the install_static::GetChromeChannelName function and is // based on the ChannelInfoTest.Channels in channel_info_unittest.cc TEST_P(ChromeElfUtilTest, InstallStaticGetChannelNameTest) { - PerformChannelNameTests(true); // add_modifier - PerformChannelNameTests(false); // !add_modifier + PerformChannelNameTests(true); // add_modifier + PerformChannelNameTests(false); // !add_modifier } -INSTANTIATE_TEST_CASE_P(Canary, ChromeElfUtilTest, +INSTANTIATE_TEST_CASE_P(Canary, + ChromeElfUtilTest, testing::Combine(testing::Values("canary"), testing::Values("user"), testing::Values("single"))); -INSTANTIATE_TEST_CASE_P(GoogleChrome, ChromeElfUtilTest, +INSTANTIATE_TEST_CASE_P(GoogleChrome, + ChromeElfUtilTest, testing::Combine(testing::Values("google"), testing::Values("user", "system"), testing::Values("single", "multi")));
diff --git a/chrome_elf/hook_util/thunk_getter.cc b/chrome_elf/hook_util/thunk_getter.cc new file mode 100644 index 0000000..5d15ea0 --- /dev/null +++ b/chrome_elf/hook_util/thunk_getter.cc
@@ -0,0 +1,152 @@ +// 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. + +#include <stdint.h> +#include <windows.h> + +#include "sandbox/win/src/interception_internal.h" +#include "sandbox/win/src/internal_types.h" +#include "sandbox/win/src/sandbox_utils.h" +#include "sandbox/win/src/service_resolver.h" + +namespace { +enum Version { + VERSION_PRE_XP_SP2 = 0, // Not supported. + VERSION_XP_SP2, + VERSION_SERVER_2003, // Also includes XP Pro x64 and Server 2003 R2. + VERSION_VISTA, // Also includes Windows Server 2008. + VERSION_WIN7, // Also includes Windows Server 2008 R2. + VERSION_WIN8, // Also includes Windows Server 2012. + VERSION_WIN8_1, + VERSION_WIN10, + VERSION_WIN_LAST, // Indicates error condition. +}; + +#if !defined(_WIN64) +// Whether a process is running under WOW64 (the wrapper that allows 32-bit +// processes to run on 64-bit versions of Windows). This will return +// WOW64_DISABLED for both "32-bit Chrome on 32-bit Windows" and "64-bit +// Chrome on 64-bit Windows". WOW64_UNKNOWN means "an error occurred", e.g. +// the process does not have sufficient access rights to determine this. +enum WOW64Status { + WOW64_DISABLED, + WOW64_ENABLED, + WOW64_UNKNOWN, +}; + +WOW64Status GetWOW64StatusForCurrentProcess() { + typedef BOOL(WINAPI * IsWow64ProcessFunc)(HANDLE, PBOOL); + IsWow64ProcessFunc is_wow64_process = reinterpret_cast<IsWow64ProcessFunc>( + GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process")); + if (!is_wow64_process) + return WOW64_DISABLED; + BOOL is_wow64 = FALSE; + if (!is_wow64_process(GetCurrentProcess(), &is_wow64)) + return WOW64_UNKNOWN; + return is_wow64 ? WOW64_ENABLED : WOW64_DISABLED; +} +#endif // !defined(_WIN64) + +class OSInfo { + public: + struct VersionNumber { + int major; + int minor; + int build; + }; + + struct ServicePack { + int major; + int minor; + }; + + OSInfo() { + OSVERSIONINFOEX version_info = {sizeof(version_info)}; + GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info)); + version_number_.major = version_info.dwMajorVersion; + version_number_.minor = version_info.dwMinorVersion; + version_number_.build = version_info.dwBuildNumber; + if ((version_number_.major == 5) && (version_number_.minor > 0)) { + // Treat XP Pro x64, Home Server, and Server 2003 R2 as Server 2003. + version_ = + (version_number_.minor == 1) ? VERSION_XP_SP2 : VERSION_SERVER_2003; + if (version_ == VERSION_XP_SP2 && version_info.wServicePackMajor < 2) + version_ = VERSION_PRE_XP_SP2; + } else if (version_number_.major == 6) { + switch (version_number_.minor) { + case 0: + // Treat Windows Server 2008 the same as Windows Vista. + version_ = VERSION_VISTA; + break; + case 1: + // Treat Windows Server 2008 R2 the same as Windows 7. + version_ = VERSION_WIN7; + break; + case 2: + // Treat Windows Server 2012 the same as Windows 8. + version_ = VERSION_WIN8; + break; + default: + version_ = VERSION_WIN8_1; + break; + } + } else if (version_number_.major == 10) { + version_ = VERSION_WIN10; + } else if (version_number_.major > 6) { + version_ = VERSION_WIN_LAST; + } else { + version_ = VERSION_PRE_XP_SP2; + } + + service_pack_.major = version_info.wServicePackMajor; + service_pack_.minor = version_info.wServicePackMinor; + } + + Version version() const { return version_; } + VersionNumber version_number() const { return version_number_; } + ServicePack service_pack() const { return service_pack_; } + + private: + Version version_; + VersionNumber version_number_; + ServicePack service_pack_; + + DISALLOW_COPY_AND_ASSIGN(OSInfo); +}; + +} // namespace + +sandbox::ServiceResolverThunk* GetThunk(bool relaxed) { + // Create a thunk via the appropriate ServiceResolver instance. + sandbox::ServiceResolverThunk* thunk = NULL; + + // No thunks for unsupported OS versions. + OSInfo os_info; + if (os_info.version() <= VERSION_PRE_XP_SP2) + return thunk; + + // Pseudo-handle, no need to close. + HANDLE current_process = ::GetCurrentProcess(); + +#if defined(_WIN64) + // ServiceResolverThunk can handle all the formats in 64-bit (instead only + // handling one like it does in 32-bit versions). + thunk = new sandbox::ServiceResolverThunk(current_process, relaxed); +#else + if (GetWOW64StatusForCurrentProcess() == WOW64_ENABLED) { + if (os_info.version() >= VERSION_WIN10) + thunk = new sandbox::Wow64W10ResolverThunk(current_process, relaxed); + else if (os_info.version() >= VERSION_WIN8) + thunk = new sandbox::Wow64W8ResolverThunk(current_process, relaxed); + else + thunk = new sandbox::Wow64ResolverThunk(current_process, relaxed); + } else if (os_info.version() >= VERSION_WIN8) { + thunk = new sandbox::Win8ResolverThunk(current_process, relaxed); + } else { + thunk = new sandbox::ServiceResolverThunk(current_process, relaxed); + } +#endif + + return thunk; +}
diff --git a/chrome_elf/hook_util/thunk_getter.h b/chrome_elf/hook_util/thunk_getter.h new file mode 100644 index 0000000..68db8f8 --- /dev/null +++ b/chrome_elf/hook_util/thunk_getter.h
@@ -0,0 +1,16 @@ +// 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 CHROME_ELF_HOOK_UTIL_THUNK_GETTER_H_ +#define CHROME_ELF_HOOK_UTIL_THUNK_GETTER_H_ + +namespace sandbox { +class ServiceResolverThunk; +} + +// Creates a |ServiceResolverThunk| based on the OS version. Ownership of the +// resulting thunk is passed to the caller. +sandbox::ServiceResolverThunk* GetThunk(bool relaxed); + +#endif // CHROME_ELF_HOOK_UTIL_THUNK_GETTER_H_
diff --git a/chrome_elf/nt_registry/BUILD.gn b/chrome_elf/nt_registry/BUILD.gn new file mode 100644 index 0000000..e58bac7 --- /dev/null +++ b/chrome_elf/nt_registry/BUILD.gn
@@ -0,0 +1,20 @@ +# 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("//build/config/chrome_build.gni") +import("//testing/test.gni") + +assert(is_win) + +# This target only contains utility functions which must only depend on +# kernel32. Please don't add dependencies on other system libraries. +static_library("nt_registry") { + sources = [ + "../../sandbox/win/src/nt_internals.h", + "nt_registry.cc", + "nt_registry.h", + ] + + libs = [ "kernel32.lib" ] +}
diff --git a/chrome_elf/nt_registry/DEPS b/chrome_elf/nt_registry/DEPS new file mode 100644 index 0000000..e54eb13 --- /dev/null +++ b/chrome_elf/nt_registry/DEPS
@@ -0,0 +1,8 @@ +include_rules = [ + # Nothing from base. + "-base", + # Nothing from chrome. + "-chrome", + "-chrome_elf", + "+chrome_elf/nt_registry/nt_registry.h", +]
diff --git a/chrome_elf/nt_registry/nt_registry.cc b/chrome_elf/nt_registry/nt_registry.cc new file mode 100644 index 0000000..373f009 --- /dev/null +++ b/chrome_elf/nt_registry/nt_registry.cc
@@ -0,0 +1,685 @@ +// 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_elf/nt_registry/nt_registry.h" + +namespace { + +// Function pointers used for registry access. +RtlInitUnicodeStringFunction g_rtl_init_unicode_string = nullptr; +NtCreateKeyFunction g_nt_create_key = nullptr; +NtDeleteKeyFunction g_nt_delete_key = nullptr; +NtOpenKeyExFunction g_nt_open_key_ex = nullptr; +NtCloseFunction g_nt_close = nullptr; +NtQueryValueKeyFunction g_nt_query_value_key = nullptr; +NtSetValueKeyFunction g_nt_set_value_key = nullptr; + +// Lazy init. No concern about concurrency in chrome_elf. +bool g_initialized = false; +bool g_system_install = false; +bool g_reg_redirection = false; +const size_t g_kMaxPathLen = 255; +wchar_t g_kRegPathHKLM[] = L"\\Registry\\Machine\\"; +wchar_t g_kRegPathHKCU[g_kMaxPathLen] = L""; +wchar_t g_current_user_sid_string[g_kMaxPathLen] = L""; +wchar_t g_override_path[g_kMaxPathLen] = L""; + +// Not using install_util, to prevent circular dependency. +bool IsThisProcSystem() { + wchar_t program_dir[MAX_PATH] = {}; + wchar_t* cmd_line = GetCommandLineW(); + // If our command line starts with the "Program Files" or + // "Program Files (x86)" path, we're system. + DWORD ret = ::GetEnvironmentVariable(L"PROGRAMFILES", program_dir, MAX_PATH); + if (ret && ret < MAX_PATH && !::wcsncmp(cmd_line, program_dir, ret)) + return true; + + ret = ::GetEnvironmentVariable(L"PROGRAMFILES(X86)", program_dir, MAX_PATH); + if (ret && ret < MAX_PATH && !::wcsncmp(cmd_line, program_dir, ret)) + return true; + + return false; +} + +bool InitNativeRegApi() { + HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll"); + + // Setup the global function pointers for registry access. + g_rtl_init_unicode_string = reinterpret_cast<RtlInitUnicodeStringFunction>( + ::GetProcAddress(ntdll, "RtlInitUnicodeString")); + + g_nt_create_key = reinterpret_cast<NtCreateKeyFunction>( + ::GetProcAddress(ntdll, "NtCreateKey")); + + g_nt_delete_key = reinterpret_cast<NtDeleteKeyFunction>( + ::GetProcAddress(ntdll, "NtDeleteKey")); + + g_nt_open_key_ex = reinterpret_cast<NtOpenKeyExFunction>( + ::GetProcAddress(ntdll, "NtOpenKeyEx")); + + g_nt_close = + reinterpret_cast<NtCloseFunction>(::GetProcAddress(ntdll, "NtClose")); + + g_nt_query_value_key = reinterpret_cast<NtQueryValueKeyFunction>( + ::GetProcAddress(ntdll, "NtQueryValueKey")); + + g_nt_set_value_key = reinterpret_cast<NtSetValueKeyFunction>( + ::GetProcAddress(ntdll, "NtSetValueKey")); + + if (!g_rtl_init_unicode_string || !g_nt_create_key || !g_nt_open_key_ex || + !g_nt_delete_key || !g_nt_close || !g_nt_query_value_key || + !g_nt_set_value_key) + return false; + + // We need to set HKCU based on the sid of the current user account. + RtlFormatCurrentUserKeyPathFunction rtl_current_user_string = + reinterpret_cast<RtlFormatCurrentUserKeyPathFunction>( + ::GetProcAddress(ntdll, "RtlFormatCurrentUserKeyPath")); + + RtlFreeUnicodeStringFunction rtl_free_unicode_str = + reinterpret_cast<RtlFreeUnicodeStringFunction>( + ::GetProcAddress(ntdll, "RtlFreeUnicodeString")); + + if (!rtl_current_user_string || !rtl_free_unicode_str) + return false; + + UNICODE_STRING current_user_reg_path; + if (!NT_SUCCESS(rtl_current_user_string(¤t_user_reg_path))) + return false; + + // Finish setting up global HKCU path. + ::wcsncat(g_kRegPathHKCU, current_user_reg_path.Buffer, (g_kMaxPathLen - 1)); + ::wcsncat(g_kRegPathHKCU, L"\\", + (g_kMaxPathLen - ::wcslen(g_kRegPathHKCU) - 1)); + // Keep the sid string as well. + wchar_t* ptr = ::wcsrchr(current_user_reg_path.Buffer, L'\\'); + ptr++; + ::wcsncpy(g_current_user_sid_string, ptr, (g_kMaxPathLen - 1)); + rtl_free_unicode_str(¤t_user_reg_path); + + // Figure out if we're a system or user install. + g_system_install = IsThisProcSystem(); + + g_initialized = true; + return true; +} + +const wchar_t* ConvertRootKey(nt::ROOT_KEY root) { + nt::ROOT_KEY key = root; + + if (!root) { + // AUTO + key = g_system_install ? nt::HKLM : nt::HKCU; + } + + if ((key == nt::HKCU) && (::wcslen(nt::HKCU_override) != 0)) { + std::wstring temp(g_kRegPathHKCU); + temp.append(nt::HKCU_override); + temp.append(L"\\"); + ::wcsncpy(g_override_path, temp.c_str(), g_kMaxPathLen - 1); + g_reg_redirection = true; + return g_override_path; + } else if ((key == nt::HKLM) && (::wcslen(nt::HKLM_override) != 0)) { + std::wstring temp(g_kRegPathHKCU); + temp.append(nt::HKLM_override); + temp.append(L"\\"); + ::wcsncpy(g_override_path, temp.c_str(), g_kMaxPathLen - 1); + g_reg_redirection = true; + return g_override_path; + } + + g_reg_redirection = false; + if (key == nt::HKCU) + return g_kRegPathHKCU; + else + return g_kRegPathHKLM; +} + +// Turns a root and subkey path into the registry base hive and the rest of the +// subkey tokens. +// - |converted_root| should come directly out of ConvertRootKey function. +// - E.g. base hive: "\Registry\Machine\", "\Registry\User\<SID>\". +bool ParseFullRegPath(const wchar_t* converted_root, + const wchar_t* subkey_path, + std::wstring* out_base, + std::vector<std::wstring>* subkeys) { + out_base->clear(); + subkeys->clear(); + std::wstring temp = L""; + + if (g_reg_redirection) { + // Why process |converted_root|? To handle reg redirection used by tests. + // E.g.: + // |converted_root| = "\REGISTRY\USER\S-1-5-21-39260824-743453154-142223018- + // 716772\Software\Chromium\TempTestKeys\13110669370890870$94c6ed9d-bc34- + // 44f3-a0b3-9eee2d3f2f82\". + // |subkey_path| = "SOFTWARE\Google\Chrome\BrowserSec". + temp.append(converted_root); + } + if (subkey_path != nullptr) + temp.append(subkey_path); + + // Tokenize the full path. + size_t find_start = 0; + size_t delimiter = temp.find_first_of(L'\\'); + while (delimiter != std::wstring::npos) { + std::wstring token = temp.substr(find_start, delimiter - find_start); + if (!token.empty()) + subkeys->push_back(token); + find_start = delimiter + 1; + delimiter = temp.find_first_of(L'\\', find_start); + } + if (!temp.empty() && find_start < temp.length()) + // Get the last token. + subkeys->push_back(temp.substr(find_start)); + + if (g_reg_redirection) { + // The base hive for HKCU needs to include the user SID. + uint32_t num_base_tokens = 2; + const wchar_t* hkcu = L"\\REGISTRY\\USER\\"; + if (0 == ::wcsnicmp(converted_root, hkcu, ::wcslen(hkcu))) + num_base_tokens = 3; + + if (subkeys->size() < num_base_tokens) + return false; + + // Pull out the base hive tokens. + out_base->push_back(L'\\'); + for (size_t i = 0; i < num_base_tokens; i++) { + out_base->append((*subkeys)[i].c_str()); + out_base->push_back(L'\\'); + } + subkeys->erase(subkeys->begin(), subkeys->begin() + num_base_tokens); + } else { + out_base->assign(converted_root); + } + + return true; +} + +NTSTATUS CreateKeyWrapper(const std::wstring& key_path, + ACCESS_MASK access, + HANDLE* out_handle, + ULONG* create_or_open OPTIONAL) { + UNICODE_STRING key_path_uni = {}; + g_rtl_init_unicode_string(&key_path_uni, key_path.c_str()); + + OBJECT_ATTRIBUTES obj = {}; + InitializeObjectAttributes(&obj, &key_path_uni, OBJ_CASE_INSENSITIVE, NULL, + nullptr); + + return g_nt_create_key(out_handle, access, &obj, 0, nullptr, + REG_OPTION_NON_VOLATILE, create_or_open); +} + +} // namespace + +namespace nt { + +const size_t g_kRegMaxPathLen = 255; +wchar_t HKLM_override[g_kRegMaxPathLen] = L""; +wchar_t HKCU_override[g_kRegMaxPathLen] = L""; + +//------------------------------------------------------------------------------ +// Create, open, delete, close functions +//------------------------------------------------------------------------------ + +bool CreateRegKey(ROOT_KEY root, + const wchar_t* key_path, + ACCESS_MASK access, + HANDLE* out_handle OPTIONAL) { + if (!g_initialized) + InitNativeRegApi(); + + std::wstring current_path; + std::vector<std::wstring> subkeys; + if (!ParseFullRegPath(ConvertRootKey(root), key_path, ¤t_path, + &subkeys)) + return false; + + // Open the base hive first. It should always exist already. + HANDLE last_handle = INVALID_HANDLE_VALUE; + NTSTATUS status = + CreateKeyWrapper(current_path, access, &last_handle, nullptr); + if (!NT_SUCCESS(status)) + return false; + + size_t subkeys_size = subkeys.size(); + if (subkeys_size != 0) + g_nt_close(last_handle); + + // Recursively open/create each subkey. + std::vector<HANDLE> rollback; + bool success = true; + for (size_t i = 0; i < subkeys_size; i++) { + current_path.append(subkeys[i]); + current_path.push_back(L'\\'); + + // Process the latest subkey. + ULONG created = 0; + HANDLE key_handle = INVALID_HANDLE_VALUE; + status = + CreateKeyWrapper(current_path.c_str(), access, &key_handle, &created); + if (!NT_SUCCESS(status)) { + success = false; + break; + } + + if (i == subkeys_size - 1) { + last_handle = key_handle; + } else { + // Save any subkey handle created, in case of rollback. + if (created == REG_CREATED_NEW_KEY) + rollback.push_back(key_handle); + else + g_nt_close(key_handle); + } + } + + if (!success) { + // Delete any subkeys created. + for (HANDLE handle : rollback) { + g_nt_delete_key(handle); + } + } + for (HANDLE handle : rollback) { + // Close the rollback handles, on success or failure. + g_nt_close(handle); + } + if (!success) + return false; + + // See if caller wants the handle left open. + if (out_handle) + *out_handle = last_handle; + else + g_nt_close(last_handle); + + return true; +} + +bool OpenRegKey(ROOT_KEY root, + const wchar_t* key_path, + ACCESS_MASK access, + HANDLE* out_handle, + NTSTATUS* error_code OPTIONAL) { + if (!g_initialized) + InitNativeRegApi(); + + NTSTATUS status = STATUS_UNSUCCESSFUL; + UNICODE_STRING key_path_uni = {}; + OBJECT_ATTRIBUTES obj = {}; + *out_handle = INVALID_HANDLE_VALUE; + + std::wstring full_path(ConvertRootKey(root)); + full_path.append(key_path); + + g_rtl_init_unicode_string(&key_path_uni, full_path.c_str()); + InitializeObjectAttributes(&obj, &key_path_uni, OBJ_CASE_INSENSITIVE, NULL, + NULL); + + status = g_nt_open_key_ex(out_handle, access, &obj, 0); + // See if caller wants the NTSTATUS. + if (error_code) + *error_code = status; + + if (NT_SUCCESS(status)) + return true; + + return false; +} + +bool DeleteRegKey(HANDLE key) { + if (!g_initialized) + InitNativeRegApi(); + + NTSTATUS status = STATUS_UNSUCCESSFUL; + + status = g_nt_delete_key(key); + + if (NT_SUCCESS(status)) + return true; + + return false; +} + +// wrapper function +bool DeleteRegKey(ROOT_KEY root, const wchar_t* key_path) { + HANDLE key = INVALID_HANDLE_VALUE; + + if (!OpenRegKey(root, key_path, DELETE, &key, nullptr)) + return false; + + if (!DeleteRegKey(key)) { + CloseRegKey(key); + return false; + } + + CloseRegKey(key); + return true; +} + +void CloseRegKey(HANDLE key) { + if (!g_initialized) + InitNativeRegApi(); + g_nt_close(key); +} + +//------------------------------------------------------------------------------ +// Getter functions +//------------------------------------------------------------------------------ + +bool QueryRegKeyValue(HANDLE key, + const wchar_t* value_name, + ULONG* out_type, + BYTE** out_buffer, + DWORD* out_size) { + if (!g_initialized) + InitNativeRegApi(); + + NTSTATUS ntstatus = STATUS_UNSUCCESSFUL; + UNICODE_STRING value_uni = {}; + g_rtl_init_unicode_string(&value_uni, value_name); + DWORD size_needed = 0; + bool success = false; + + // First call to find out how much room we need for the value! + ntstatus = g_nt_query_value_key(key, &value_uni, KeyValueFullInformation, + nullptr, 0, &size_needed); + if (ntstatus != STATUS_BUFFER_TOO_SMALL) + return false; + + KEY_VALUE_FULL_INFORMATION* value_info = + reinterpret_cast<KEY_VALUE_FULL_INFORMATION*>(new BYTE[size_needed]); + + // Second call to get the value. + ntstatus = g_nt_query_value_key(key, &value_uni, KeyValueFullInformation, + value_info, size_needed, &size_needed); + if (NT_SUCCESS(ntstatus)) { + *out_type = value_info->Type; + *out_size = value_info->DataLength; + *out_buffer = new BYTE[*out_size]; + ::memcpy(*out_buffer, + (reinterpret_cast<BYTE*>(value_info) + value_info->DataOffset), + *out_size); + success = true; + } + + delete[] value_info; + return success; +} + +// wrapper function +bool QueryRegValueDWORD(HANDLE key, + const wchar_t* value_name, + DWORD* out_dword) { + ULONG type = REG_NONE; + BYTE* value_bytes = nullptr; + DWORD ret_size = 0; + + if (!QueryRegKeyValue(key, value_name, &type, &value_bytes, &ret_size) || + type != REG_DWORD) + return false; + + *out_dword = *(reinterpret_cast<DWORD*>(value_bytes)); + + delete[] value_bytes; + return true; +} + +// wrapper function +bool QueryRegValueDWORD(ROOT_KEY root, + const wchar_t* key_path, + const wchar_t* value_name, + DWORD* out_dword) { + HANDLE key = INVALID_HANDLE_VALUE; + + if (!OpenRegKey(root, key_path, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key, + NULL)) + return false; + + if (!QueryRegValueDWORD(key, value_name, out_dword)) { + CloseRegKey(key); + return false; + } + + CloseRegKey(key); + return true; +} + +// wrapper function +bool QueryRegValueSZ(HANDLE key, + const wchar_t* value_name, + std::wstring* out_sz) { + BYTE* value_bytes = nullptr; + DWORD ret_size = 0; + ULONG type = REG_NONE; + + if (!QueryRegKeyValue(key, value_name, &type, &value_bytes, &ret_size) || + type != REG_SZ) + return false; + + *out_sz = reinterpret_cast<wchar_t*>(value_bytes); + + delete[] value_bytes; + return true; +} + +// wrapper function +bool QueryRegValueSZ(ROOT_KEY root, + const wchar_t* key_path, + const wchar_t* value_name, + std::wstring* out_sz) { + HANDLE key = INVALID_HANDLE_VALUE; + + if (!OpenRegKey(root, key_path, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key, + NULL)) + return false; + + if (!QueryRegValueSZ(key, value_name, out_sz)) { + CloseRegKey(key); + return false; + } + + CloseRegKey(key); + return true; +} + +// wrapper function +bool QueryRegValueMULTISZ(HANDLE key, + const wchar_t* value_name, + std::vector<std::wstring>* out_multi_sz) { + BYTE* value_bytes = nullptr; + DWORD ret_size = 0; + ULONG type = REG_NONE; + + if (!QueryRegKeyValue(key, value_name, &type, &value_bytes, &ret_size) || + type != REG_MULTI_SZ) + return false; + + // Make sure the vector is empty to start. + (*out_multi_sz).resize(0); + + wchar_t* pointer = reinterpret_cast<wchar_t*>(value_bytes); + std::wstring temp = pointer; + // Loop. Each string is separated by '\0'. Another '\0' at very end (so 2 in + // a row). + while (temp.length() != 0) { + (*out_multi_sz).push_back(temp); + + pointer += temp.length() + 1; + temp = pointer; + } + + // Handle the case of "empty multi_sz". + if (out_multi_sz->size() == 0) + out_multi_sz->push_back(L""); + + delete[] value_bytes; + return true; +} + +// wrapper function +bool QueryRegValueMULTISZ(ROOT_KEY root, + const wchar_t* key_path, + const wchar_t* value_name, + std::vector<std::wstring>* out_multi_sz) { + HANDLE key = INVALID_HANDLE_VALUE; + + if (!OpenRegKey(root, key_path, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key, + NULL)) + return false; + + if (!QueryRegValueMULTISZ(key, value_name, out_multi_sz)) { + CloseRegKey(key); + return false; + } + + CloseRegKey(key); + return true; +} + +//------------------------------------------------------------------------------ +// Setter functions +//------------------------------------------------------------------------------ + +bool SetRegKeyValue(HANDLE key, + const wchar_t* value_name, + ULONG type, + const BYTE* data, + DWORD data_size) { + if (!g_initialized) + InitNativeRegApi(); + + NTSTATUS ntstatus = STATUS_UNSUCCESSFUL; + UNICODE_STRING value_uni = {}; + g_rtl_init_unicode_string(&value_uni, value_name); + + BYTE* non_const_data = const_cast<BYTE*>(data); + ntstatus = + g_nt_set_value_key(key, &value_uni, 0, type, non_const_data, data_size); + + if (NT_SUCCESS(ntstatus)) + return true; + + return false; +} + +// wrapper function +bool SetRegValueDWORD(HANDLE key, const wchar_t* value_name, DWORD value) { + return SetRegKeyValue(key, value_name, REG_DWORD, + reinterpret_cast<BYTE*>(&value), sizeof(value)); +} + +// wrapper function +bool SetRegValueDWORD(ROOT_KEY root, + const wchar_t* key_path, + const wchar_t* value_name, + DWORD value) { + HANDLE key = INVALID_HANDLE_VALUE; + + if (!OpenRegKey(root, key_path, KEY_SET_VALUE | KEY_WOW64_32KEY, &key, NULL)) + return false; + + if (!SetRegValueDWORD(key, value_name, value)) { + CloseRegKey(key); + return false; + } + + return true; +} + +// wrapper function +bool SetRegValueSZ(HANDLE key, + const wchar_t* value_name, + const std::wstring& value) { + // Make sure the number of bytes in |value|, including EoS, fits in a DWORD. + if (std::numeric_limits<DWORD>::max() < + ((value.length() + 1) * sizeof(wchar_t))) + return false; + + DWORD size = (static_cast<DWORD>((value.length() + 1) * sizeof(wchar_t))); + return SetRegKeyValue(key, value_name, REG_SZ, + reinterpret_cast<const BYTE*>(value.c_str()), size); +} + +// wrapper function +bool SetRegValueSZ(ROOT_KEY root, + const wchar_t* key_path, + const wchar_t* value_name, + const std::wstring& value) { + HANDLE key = INVALID_HANDLE_VALUE; + + if (!OpenRegKey(root, key_path, KEY_SET_VALUE | KEY_WOW64_32KEY, &key, NULL)) + return false; + + if (!SetRegValueSZ(key, value_name, value)) { + CloseRegKey(key); + return false; + } + + return true; +} + +// wrapper function +bool SetRegValueMULTISZ(HANDLE key, + const wchar_t* value_name, + const std::vector<std::wstring>& values) { + std::vector<wchar_t> builder; + + for (auto& string : values) { + // Just in case someone is passing in an illegal empty string + // (not allowed in REG_MULTI_SZ), ignore it. + if (!string.empty()) { + for (const wchar_t& w : string) { + builder.push_back(w); + } + builder.push_back(L'\0'); + } + } + // Add second null terminator to end REG_MULTI_SZ. + builder.push_back(L'\0'); + // Handle rare case where the vector passed in was empty, + // or only had an empty string. + if (builder.size() == 1) + builder.push_back(L'\0'); + + if (std::numeric_limits<DWORD>::max() < builder.size()) + return false; + + return SetRegKeyValue( + key, value_name, REG_MULTI_SZ, reinterpret_cast<BYTE*>(builder.data()), + (static_cast<DWORD>(builder.size()) + 1) * sizeof(wchar_t)); +} + +// wrapper function +bool SetRegValueMULTISZ(ROOT_KEY root, + const wchar_t* key_path, + const wchar_t* value_name, + const std::vector<std::wstring>& values) { + HANDLE key = INVALID_HANDLE_VALUE; + + if (!OpenRegKey(root, key_path, KEY_SET_VALUE | KEY_WOW64_32KEY, &key, NULL)) + return false; + + if (!SetRegValueMULTISZ(key, value_name, values)) { + CloseRegKey(key); + return false; + } + + return true; +} + +//------------------------------------------------------------------------------ +// Utils +//------------------------------------------------------------------------------ + +const wchar_t* GetCurrentUserSidString() { + if (!g_initialized) + InitNativeRegApi(); + + return g_current_user_sid_string; +} + +}; // namespace nt
diff --git a/chrome_elf/nt_registry/nt_registry.gyp b/chrome_elf/nt_registry/nt_registry.gyp new file mode 100644 index 0000000..ad5e1ed --- /dev/null +++ b/chrome_elf/nt_registry/nt_registry.gyp
@@ -0,0 +1,51 @@ +# 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. + +# The nt_registry target should only depend on functions in kernel32. +# Please don't add dependencies on other system libraries. +{ + 'target_defaults': { + # This part is shared between the two versions of the target. + 'type': 'static_library', + 'sources': [ + 'nt_registry.cc', + 'nt_registry.h', + ], + 'include_dirs': [ + '../..', + '<(SHARED_INTERMEDIATE_DIR)', + ], + 'msvs_settings': { + 'VCLinkerTool': { + # Please don't add dependencies on other system libraries. + 'AdditionalDependencies': [ + 'kernel32.lib', + ], + }, + }, + }, + 'conditions': [ + ['OS=="win"', { + 'targets': [ + { + # GN version: "//chrome_elf/nt_registry", + 'target_name': 'chrome_elf_nt_registry', + }, + ], + }], + ['OS=="win" and target_arch=="ia32"', { + 'targets': [ + { + # GN version: "//chrome_elf/nt_registry", + 'target_name': 'chrome_elf_nt_registry_nacl_win64', + 'configurations': { + 'Common_Base': { + 'msvs_target_platform': 'x64', + }, + }, + }, + ], + }], + ], +}
diff --git a/chrome_elf/nt_registry/nt_registry.h b/chrome_elf/nt_registry/nt_registry.h new file mode 100644 index 0000000..0451fc5 --- /dev/null +++ b/chrome_elf/nt_registry/nt_registry.h
@@ -0,0 +1,204 @@ +// 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. + +// This API is a usability layer for direct registry access via NTDLL. +// It allows for "advapi32-free" registry access, which is especially +// useful for accessing registy from DllMain (holding loader lock), +// or if a dependency on/linkage of ADVAPI32.dll is not desired. + +// The implementation of this API should only use ntdll and kernel32 system +// DLLs. + +// Note that this API is currently lazy initialized. Any function that is +// NOT merely a wrapper function (i.e. any function that directly interacts with +// NTDLL) will immediately check: +// if (!g_initialized) +// InitNativeRegApi(); +// There is currently no multi-threading lock around the lazy initialization, +// as the main client for this API (chrome_elf) does not introduce +// a multi-threading concern. This can easily be changed if needed. + +#ifndef CHROME_ELF_NT_REGISTRY_NT_REGISTRY_H_ +#define CHROME_ELF_NT_REGISTRY_NT_REGISTRY_H_ + +#include <vector> + +#include "sandbox/win/src/nt_internals.h" // NTSTATUS + +namespace nt { + +// These globals are only used in test suites that use reg redirection +// of HKLM and/or HKCU. +extern const size_t g_kRegMaxPathLen; +extern wchar_t HKLM_override[]; +extern wchar_t HKCU_override[]; + +// AUTO will choose depending on system install or not. +// Use HKLM or HKCU to override. +typedef enum _ROOT_KEY { AUTO = 0, HKLM, HKCU } ROOT_KEY; + +// Create and/or open a registry key. +// - This function will recursively create multiple sub-keys if required for +// |key_path|. +// - If the key doesn't need to be left open, pass in nullptr for |out_handle|. +// - This function will happily succeed if the key already exists. +// - Optional |out_handle|. If nullptr, function will close handle when done. +// Otherwise, will hold the open handle to the deepest subkey. +// - Caller must call CloseRegKey on returned handle (on success). +bool CreateRegKey(ROOT_KEY root, + const wchar_t* key_path, + ACCESS_MASK access, + HANDLE* out_handle OPTIONAL); + +// Open existing registry key. +// - Caller must call CloseRegKey on returned handle (on success). +// - Optional error code can be returned on failure for extra detail. +bool OpenRegKey(ROOT_KEY root, + const wchar_t* key_path, + ACCESS_MASK access, + HANDLE* out_handle, + NTSTATUS* error_code OPTIONAL); + +// Delete a registry key. +// - Caller must still call CloseRegKey after the delete. +bool DeleteRegKey(HANDLE key); + +// Delete a registry key. +// - WRAPPER: Function opens and closes the target key for caller. +bool DeleteRegKey(ROOT_KEY root, const wchar_t* key_path); + +// Close a registry key handle that was opened with CreateRegKey or OpenRegKey. +void CloseRegKey(HANDLE key); + +//------------------------------------------------------------------------------ +// Getter functions +//------------------------------------------------------------------------------ + +// Main function to query a registry value. +// - Key handle should have been opened with CreateRegKey or OpenRegKey. +// - Types defined in winnt.h. E.g.: REG_DWORD, REG_SZ. +// - Caller is responsible for calling "delete[] *out_buffer" (on success). +bool QueryRegKeyValue(HANDLE key, + const wchar_t* value_name, + ULONG* out_type, + BYTE** out_buffer, + DWORD* out_size); + +// Query DWORD value. +// - WRAPPER: Function works with DWORD data type. +// - Key handle should have been opened with CreateRegKey or OpenRegKey. +// - Handle will be left open. Caller must still call CloseRegKey when done. +bool QueryRegValueDWORD(HANDLE key, + const wchar_t* value_name, + DWORD* out_dword); + +// Query DWORD value. +// - WRAPPER: Function opens and closes the target key for caller, and works +// with DWORD data type. +bool QueryRegValueDWORD(ROOT_KEY root, + const wchar_t* key_path, + const wchar_t* value_name, + DWORD* out_dword); + +// Query SZ (string) value. +// - WRAPPER: Function works with SZ data type. +// - Key handle should have been opened with CreateRegKey or OpenRegKey. +// - Handle will be left open. Caller must still call CloseRegKey when done. +bool QueryRegValueSZ(HANDLE key, + const wchar_t* value_name, + std::wstring* out_sz); + +// Query SZ (string) value. +// - WRAPPER: Function opens and closes the target key for caller, and works +// with SZ data type. +bool QueryRegValueSZ(ROOT_KEY root, + const wchar_t* key_path, + const wchar_t* value_name, + std::wstring* out_sz); + +// Query MULTI_SZ (multiple strings) value. +// - WRAPPER: Function works with MULTI_SZ data type. +// - Key handle should have been opened with CreateRegKey or OpenRegKey. +// - Handle will be left open. Caller must still call CloseRegKey when done. +bool QueryRegValueMULTISZ(HANDLE key, + const wchar_t* value_name, + std::vector<std::wstring>* out_multi_sz); + +// Query MULTI_SZ (multiple strings) value. +// - WRAPPER: Function opens and closes the target key for caller, and works +// with MULTI_SZ data type. +bool QueryRegValueMULTISZ(ROOT_KEY root, + const wchar_t* key_path, + const wchar_t* value_name, + std::vector<std::wstring>* out_multi_sz); + +//------------------------------------------------------------------------------ +// Setter functions +//------------------------------------------------------------------------------ + +// Main function to set a registry value. +// - Key handle should have been opened with CreateRegKey or OpenRegKey. +// - Types defined in winnt.h. E.g.: REG_DWORD, REG_SZ. +bool SetRegKeyValue(HANDLE key, + const wchar_t* value_name, + ULONG type, + const BYTE* data, + DWORD data_size); + +// Set DWORD value. +// - WRAPPER: Function works with DWORD data type. +// - Key handle should have been opened with CreateRegKey or OpenRegKey. +// - Handle will be left open. Caller must still call CloseRegKey when done. +bool SetRegValueDWORD(HANDLE key, const wchar_t* value_name, DWORD value); + +// Set DWORD value. +// - WRAPPER: Function opens and closes the target key for caller, and works +// with DWORD data type. +bool SetRegValueDWORD(ROOT_KEY root, + const wchar_t* key_path, + const wchar_t* value_name, + DWORD value); + +// Set SZ (string) value. +// - WRAPPER: Function works with SZ data type. +// - Key handle should have been opened with CreateRegKey or OpenRegKey. +// - Handle will be left open. Caller must still call CloseRegKey when done. +bool SetRegValueSZ(HANDLE key, + const wchar_t* value_name, + const std::wstring& value); + +// Set SZ (string) value. +// - WRAPPER: Function opens and closes the target key for caller, and works +// with SZ data type. +bool SetRegValueSZ(ROOT_KEY root, + const wchar_t* key_path, + const wchar_t* value_name, + const std::wstring& value); + +// Set MULTI_SZ (multiple strings) value. +// - WRAPPER: Function works with MULTI_SZ data type. +// - Key handle should have been opened with CreateRegKey or OpenRegKey. +// - Handle will be left open. Caller must still call CloseRegKey when done. +bool SetRegValueMULTISZ(HANDLE key, + const wchar_t* value_name, + const std::vector<std::wstring>& values); + +// Set MULTI_SZ (multiple strings) value. +// - WRAPPER: Function opens and closes the target key for caller, and works +// with MULTI_SZ data type. +bool SetRegValueMULTISZ(ROOT_KEY root, + const wchar_t* key_path, + const wchar_t* value_name, + const std::vector<std::wstring>& values); + +//------------------------------------------------------------------------------ +// Utils +//------------------------------------------------------------------------------ + +// Returns the current user SID in string form. +const wchar_t* GetCurrentUserSidString(); + +}; // namespace nt + +#endif // CHROME_ELF_NT_REGISTRY_NT_REGISTRY_H_
diff --git a/chrome_elf/thunk_getter.cc b/chrome_elf/thunk_getter.cc deleted file mode 100644 index 64cb0b8..0000000 --- a/chrome_elf/thunk_getter.cc +++ /dev/null
@@ -1,149 +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. - -#include <stdint.h> -#include <windows.h> - -#include "base/macros.h" -#include "sandbox/win/src/interception_internal.h" -#include "sandbox/win/src/internal_types.h" -#include "sandbox/win/src/sandbox_utils.h" -#include "sandbox/win/src/service_resolver.h" - -namespace { -enum Version { - VERSION_PRE_XP_SP2 = 0, // Not supported. - VERSION_XP_SP2, - VERSION_SERVER_2003, // Also includes XP Pro x64 and Server 2003 R2. - VERSION_VISTA, // Also includes Windows Server 2008. - VERSION_WIN7, // Also includes Windows Server 2008 R2. - VERSION_WIN8, // Also includes Windows Server 2012. - VERSION_WIN8_1, - VERSION_WIN10, - VERSION_WIN_LAST, // Indicates error condition. -}; - -#if !defined(_WIN64) -// Whether a process is running under WOW64 (the wrapper that allows 32-bit -// processes to run on 64-bit versions of Windows). This will return -// WOW64_DISABLED for both "32-bit Chrome on 32-bit Windows" and "64-bit -// Chrome on 64-bit Windows". WOW64_UNKNOWN means "an error occurred", e.g. -// the process does not have sufficient access rights to determine this. -enum WOW64Status { WOW64_DISABLED, WOW64_ENABLED, WOW64_UNKNOWN, }; - -WOW64Status GetWOW64StatusForCurrentProcess() { - typedef BOOL(WINAPI * IsWow64ProcessFunc)(HANDLE, PBOOL); - IsWow64ProcessFunc is_wow64_process = reinterpret_cast<IsWow64ProcessFunc>( - GetProcAddress(GetModuleHandle(L"kernel32.dll"), "IsWow64Process")); - if (!is_wow64_process) - return WOW64_DISABLED; - BOOL is_wow64 = FALSE; - if (!is_wow64_process(GetCurrentProcess(), &is_wow64)) - return WOW64_UNKNOWN; - return is_wow64 ? WOW64_ENABLED : WOW64_DISABLED; -} -#endif // !defined(_WIN64) - -class OSInfo { - public: - struct VersionNumber { - int major; - int minor; - int build; - }; - - struct ServicePack { - int major; - int minor; - }; - - OSInfo() { - OSVERSIONINFOEX version_info = {sizeof(version_info)}; - GetVersionEx(reinterpret_cast<OSVERSIONINFO*>(&version_info)); - version_number_.major = version_info.dwMajorVersion; - version_number_.minor = version_info.dwMinorVersion; - version_number_.build = version_info.dwBuildNumber; - if ((version_number_.major == 5) && (version_number_.minor > 0)) { - // Treat XP Pro x64, Home Server, and Server 2003 R2 as Server 2003. - version_ = - (version_number_.minor == 1) ? VERSION_XP_SP2 : VERSION_SERVER_2003; - if (version_ == VERSION_XP_SP2 && version_info.wServicePackMajor < 2) - version_ = VERSION_PRE_XP_SP2; - } else if (version_number_.major == 6) { - switch (version_number_.minor) { - case 0: - // Treat Windows Server 2008 the same as Windows Vista. - version_ = VERSION_VISTA; - break; - case 1: - // Treat Windows Server 2008 R2 the same as Windows 7. - version_ = VERSION_WIN7; - break; - case 2: - // Treat Windows Server 2012 the same as Windows 8. - version_ = VERSION_WIN8; - break; - default: - version_ = VERSION_WIN8_1; - break; - } - } else if (version_number_.major == 10) { - version_ = VERSION_WIN10; - } else if (version_number_.major > 6) { - version_ = VERSION_WIN_LAST; - } else { - version_ = VERSION_PRE_XP_SP2; - } - - service_pack_.major = version_info.wServicePackMajor; - service_pack_.minor = version_info.wServicePackMinor; - } - - Version version() const { return version_; } - VersionNumber version_number() const { return version_number_; } - ServicePack service_pack() const { return service_pack_; } - - private: - Version version_; - VersionNumber version_number_; - ServicePack service_pack_; - - DISALLOW_COPY_AND_ASSIGN(OSInfo); -}; - -} // namespace - -sandbox::ServiceResolverThunk* GetThunk(bool relaxed) { - // Create a thunk via the appropriate ServiceResolver instance. - sandbox::ServiceResolverThunk* thunk = NULL; - - // No thunks for unsupported OS versions. - OSInfo os_info; - if (os_info.version() <= VERSION_PRE_XP_SP2) - return thunk; - - // Pseudo-handle, no need to close. - HANDLE current_process = ::GetCurrentProcess(); - -#if defined(_WIN64) - // ServiceResolverThunk can handle all the formats in 64-bit (instead only - // handling one like it does in 32-bit versions). - thunk = new sandbox::ServiceResolverThunk(current_process, relaxed); -#else - if (GetWOW64StatusForCurrentProcess() == WOW64_ENABLED) { - if (os_info.version() >= VERSION_WIN10) - thunk = new sandbox::Wow64W10ResolverThunk(current_process, relaxed); - else if (os_info.version() >= VERSION_WIN8) - thunk = new sandbox::Wow64W8ResolverThunk(current_process, relaxed); - else - thunk = new sandbox::Wow64ResolverThunk(current_process, relaxed); - } else if (os_info.version() >= VERSION_WIN8) { - thunk = new sandbox::Win8ResolverThunk(current_process, relaxed); - } else { - thunk = new sandbox::ServiceResolverThunk(current_process, relaxed); - } -#endif - - return thunk; -}
diff --git a/chrome_elf/thunk_getter.h b/chrome_elf/thunk_getter.h deleted file mode 100644 index 5bc20fe..0000000 --- a/chrome_elf/thunk_getter.h +++ /dev/null
@@ -1,16 +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 CHROME_ELF_THUNK_GETTER_H_ -#define CHROME_ELF_THUNK_GETTER_H_ - -namespace sandbox { -class ServiceResolverThunk; -} - -// Creates a |ServiceResolverThunk| based on the OS version. Ownership of the -// resulting thunk is passed to the caller. -sandbox::ServiceResolverThunk* GetThunk(bool relaxed); - -#endif // CHROME_ELF_THUNK_GETTER_H_
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc index 321755c..b1e6f55 100644 --- a/chromecast/browser/cast_content_browser_client.cc +++ b/chromecast/browser/cast_content_browser_client.cc
@@ -154,7 +154,8 @@ std::unique_ptr<media::MediaPipelineBackend> CastContentBrowserClient::CreateMediaPipelineBackend( - const media::MediaPipelineDeviceParams& params) { + const media::MediaPipelineDeviceParams& params, + const std::string& audio_device_id) { return media_pipeline_backend_manager()->CreateMediaPipelineBackend(params); }
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h index 15d68510..dffac91 100644 --- a/chromecast/browser/cast_content_browser_client.h +++ b/chromecast/browser/cast_content_browser_client.h
@@ -74,7 +74,8 @@ // Creates a MediaPipelineDevice (CMA backend) for media playback, called // once per media player instance. virtual std::unique_ptr<media::MediaPipelineBackend> - CreateMediaPipelineBackend(const media::MediaPipelineDeviceParams& params); + CreateMediaPipelineBackend(const media::MediaPipelineDeviceParams& params, + const std::string& audio_device_id); media::MediaResourceTracker* media_resource_tracker();
diff --git a/chromecast/browser/media/cast_mojo_media_client.cc b/chromecast/browser/media/cast_mojo_media_client.cc index 58dd5ca9..b530524 100644 --- a/chromecast/browser/media/cast_mojo_media_client.cc +++ b/chromecast/browser/media/cast_mojo_media_client.cc
@@ -10,35 +10,6 @@ #include "media/base/media_log.h" #include "media/base/renderer_factory.h" -namespace { - -class CastRendererFactory : public media::RendererFactory { - public: - CastRendererFactory( - const chromecast::media::CreateMediaPipelineBackendCB& create_backend_cb, - const scoped_refptr<media::MediaLog>& media_log) - : create_backend_cb_(create_backend_cb), media_log_(media_log) {} - ~CastRendererFactory() final {} - - std::unique_ptr<media::Renderer> CreateRenderer( - const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner, - const scoped_refptr<base::TaskRunner>& worker_task_runner, - media::AudioRendererSink* audio_renderer_sink, - media::VideoRendererSink* video_renderer_sink, - const media::RequestSurfaceCB& request_surface_cb) final { - DCHECK(!audio_renderer_sink && !video_renderer_sink); - return base::WrapUnique(new chromecast::media::CastRenderer( - create_backend_cb_, media_task_runner)); - } - - private: - const chromecast::media::CreateMediaPipelineBackendCB create_backend_cb_; - scoped_refptr<media::MediaLog> media_log_; - DISALLOW_COPY_AND_ASSIGN(CastRendererFactory); -}; - -} // namespace - namespace chromecast { namespace media { @@ -50,11 +21,12 @@ CastMojoMediaClient::~CastMojoMediaClient() {} -std::unique_ptr<::media::RendererFactory> -CastMojoMediaClient::CreateRendererFactory( - const scoped_refptr<::media::MediaLog>& media_log) { - return base::WrapUnique( - new CastRendererFactory(create_backend_cb_, media_log)); +std::unique_ptr<::media::Renderer> CastMojoMediaClient::CreateRenderer( + scoped_refptr<base::SingleThreadTaskRunner> media_task_runner, + scoped_refptr<::media::MediaLog> media_log, + const std::string& audio_device_id) { + return base::MakeUnique<chromecast::media::CastRenderer>( + create_backend_cb_, std::move(media_task_runner), audio_device_id); } std::unique_ptr<::media::CdmFactory> CastMojoMediaClient::CreateCdmFactory(
diff --git a/chromecast/browser/media/cast_mojo_media_client.h b/chromecast/browser/media/cast_mojo_media_client.h index cf2c8ac..a84ac3a7 100644 --- a/chromecast/browser/media/cast_mojo_media_client.h +++ b/chromecast/browser/media/cast_mojo_media_client.h
@@ -21,8 +21,10 @@ ~CastMojoMediaClient() override; // MojoMediaClient overrides. - std::unique_ptr<::media::RendererFactory> CreateRendererFactory( - const scoped_refptr<::media::MediaLog>& media_log) override; + std::unique_ptr<::media::Renderer> CreateRenderer( + scoped_refptr<base::SingleThreadTaskRunner> media_task_runner, + scoped_refptr<::media::MediaLog> media_log, + const std::string& audio_device_id) override; std::unique_ptr<::media::CdmFactory> CreateCdmFactory( ::shell::mojom::InterfaceProvider* interface_provider) override;
diff --git a/chromecast/browser/media/cast_renderer.cc b/chromecast/browser/media/cast_renderer.cc index 12fc872..a3cc8f5 100644 --- a/chromecast/browser/media/cast_renderer.cc +++ b/chromecast/browser/media/cast_renderer.cc
@@ -32,9 +32,11 @@ CastRenderer::CastRenderer( const CreateMediaPipelineBackendCB& create_backend_cb, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, + const std::string& audio_device_id) : create_backend_cb_(create_backend_cb), task_runner_(task_runner), + audio_device_id_(audio_device_id), client_(nullptr), cast_cdm_context_(nullptr), media_task_runner_factory_( @@ -65,7 +67,7 @@ : MediaPipelineDeviceParams::kModeSyncPts; MediaPipelineDeviceParams params(sync_type, backend_task_runner_.get()); std::unique_ptr<MediaPipelineBackend> backend = - create_backend_cb_.Run(params); + create_backend_cb_.Run(params, audio_device_id_); // Create pipeline. MediaPipelineClient pipeline_client;
diff --git a/chromecast/browser/media/cast_renderer.h b/chromecast/browser/media/cast_renderer.h index 0248884..65666ca5 100644 --- a/chromecast/browser/media/cast_renderer.h +++ b/chromecast/browser/media/cast_renderer.h
@@ -26,7 +26,8 @@ class CastRenderer : public ::media::Renderer { public: CastRenderer(const CreateMediaPipelineBackendCB& create_backend_cb, - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner); + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, + const std::string& audio_device_id); ~CastRenderer() final; // ::media::Renderer implementation. @@ -55,6 +56,7 @@ const CreateMediaPipelineBackendCB create_backend_cb_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + std::string audio_device_id_; ::media::RendererClient* client_; CastCdmContext* cast_cdm_context_; scoped_refptr<BalancedMediaTaskRunnerFactory> media_task_runner_factory_;
diff --git a/chromecast/browser/media/media_pipeline_backend_factory.h b/chromecast/browser/media/media_pipeline_backend_factory.h index 9f59bb9..8712a7f 100644 --- a/chromecast/browser/media/media_pipeline_backend_factory.h +++ b/chromecast/browser/media/media_pipeline_backend_factory.h
@@ -6,6 +6,7 @@ #define CHROMECAST_BROWSER_MEDIA_MEDIA_PIPELINE_BACKEND_FACTORY_H_ #include <memory> +#include <string> #include "base/callback.h" #include "chromecast/public/media/media_pipeline_backend.h" @@ -15,8 +16,8 @@ namespace media { typedef base::Callback<std::unique_ptr<MediaPipelineBackend>( - const MediaPipelineDeviceParams&)> - CreateMediaPipelineBackendCB; + const MediaPipelineDeviceParams&, + const std::string& audio_device_id)> CreateMediaPipelineBackendCB; } // media } // chromecast
diff --git a/chromecast/browser/media/media_pipeline_host.cc b/chromecast/browser/media/media_pipeline_host.cc index 7e0cd04a..19c8ae6 100644 --- a/chromecast/browser/media/media_pipeline_host.cc +++ b/chromecast/browser/media/media_pipeline_host.cc
@@ -25,6 +25,7 @@ #include "chromecast/media/cma/pipeline/video_pipeline_impl.h" #include "chromecast/public/media/media_pipeline_backend.h" #include "chromecast/public/media/media_pipeline_device_params.h" +#include "media/audio/audio_device_description.h" namespace chromecast { namespace media { @@ -70,8 +71,10 @@ MediaPipelineDeviceParams default_parameters(sync_type, task_runner_.get()); media_pipeline_->SetClient(client); - media_pipeline_->Initialize(load_type, - create_backend_cb.Run(default_parameters)); + media_pipeline_->Initialize( + load_type, + create_backend_cb.Run(default_parameters, + ::media::AudioDeviceDescription::kDefaultDeviceId)); } void MediaPipelineHost::SetAvPipe(
diff --git a/chromecast/media/audio/BUILD.gn b/chromecast/media/audio/BUILD.gn index e959969..cfead8c 100644 --- a/chromecast/media/audio/BUILD.gn +++ b/chromecast/media/audio/BUILD.gn
@@ -2,17 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/buildflag_header.gni") - -declare_args() { - enable_mixer = false -} - -buildflag_header("audio_features") { - header = "audio_features.h" - flags = [ "ENABLE_PCM_MIXING=$enable_mixer" ] -} - source_set("audio") { sources = [ "cast_audio_manager.cc", @@ -24,7 +13,6 @@ ] deps = [ - ":audio_features", "//base", "//chromecast/base", "//chromecast/media/base",
diff --git a/chromecast/media/audio/cast_audio_manager.cc b/chromecast/media/audio/cast_audio_manager.cc index af639bf..230a1f9 100644 --- a/chromecast/media/audio/cast_audio_manager.cc +++ b/chromecast/media/audio/cast_audio_manager.cc
@@ -8,7 +8,6 @@ #include <string> #include "base/bind.h" -#include "chromecast/media/audio/audio_features.h" #include "chromecast/media/audio/cast_audio_mixer.h" #include "chromecast/media/audio/cast_audio_output_stream.h" #include "chromecast/media/cma/backend/media_pipeline_backend_manager.h" @@ -33,17 +32,13 @@ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner, ::media::AudioLogFactory* audio_log_factory, MediaPipelineBackendManager* backend_manager) - : AudioManagerBase(std::move(task_runner), - std::move(worker_task_runner), - audio_log_factory), - backend_manager_(backend_manager) { -#if BUILDFLAG(ENABLE_PCM_MIXING) - // |this| is guaranteed to outlive |mixer_|, so it is safe to - // use base::Unretained here. - mixer_.reset(new CastAudioMixer(base::Bind( - &CastAudioManager::MakeMixerOutputStream, base::Unretained(this)))); -#endif -} + : CastAudioManager(task_runner, + worker_task_runner, + audio_log_factory, + backend_manager, + new CastAudioMixer( + base::Bind(&CastAudioManager::MakeMixerOutputStream, + base::Unretained(this)))) {} CastAudioManager::CastAudioManager( scoped_refptr<base::SingleThreadTaskRunner> task_runner,
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 4051b9b..9346351 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -8562.0.0 \ No newline at end of file +8584.0.0 \ No newline at end of file
diff --git a/chromeos/settings/cros_settings_names.cc b/chromeos/settings/cros_settings_names.cc index aae6f6df..88a8202 100644 --- a/chromeos/settings/cros_settings_names.cc +++ b/chromeos/settings/cros_settings_names.cc
@@ -110,6 +110,17 @@ const char kReportDeviceSessionStatus[] = "cros.device_status.report_session_status"; +// Determines whether the device reports os update status (update status, +// new platform version and new required platform version of the auto +// launched kiosk app). +const char kReportOsUpdateStatus[] = + "cros.device_status.report_os_update_status"; + +// Determines whether the device reports the current running kiosk app ( +// its app ID, version and required platform version). +const char kReportRunningKioskApp[] = + "cros.device_status.report_running_kiosk_app"; + // How frequently device status reports are uploaded, in milliseconds. const char kReportUploadFrequency[] = "cros.device_status.report_upload_frequency";
diff --git a/chromeos/settings/cros_settings_names.h b/chromeos/settings/cros_settings_names.h index 4f851d0..a6cd087 100644 --- a/chromeos/settings/cros_settings_names.h +++ b/chromeos/settings/cros_settings_names.h
@@ -59,6 +59,8 @@ CHROMEOS_EXPORT extern const char kReportDeviceUsers[]; CHROMEOS_EXPORT extern const char kReportDeviceHardwareStatus[]; CHROMEOS_EXPORT extern const char kReportDeviceSessionStatus[]; +CHROMEOS_EXPORT extern const char kReportOsUpdateStatus[]; +CHROMEOS_EXPORT extern const char kReportRunningKioskApp[]; CHROMEOS_EXPORT extern const char kReportUploadFrequency[]; CHROMEOS_EXPORT extern const char kHeartbeatEnabled[];
diff --git a/components/arc.gypi b/components/arc.gypi index 3aad39d..7f4eac80 100644 --- a/components/arc.gypi +++ b/components/arc.gypi
@@ -54,21 +54,24 @@ 'arc/ime/arc_ime_bridge_impl.h', 'arc/ime/arc_ime_service.cc', 'arc/ime/arc_ime_service.h', + 'arc/instance_holder.h', 'arc/intent_helper/activity_icon_loader.cc', 'arc/intent_helper/activity_icon_loader.h', 'arc/intent_helper/arc_intent_helper_bridge.cc', 'arc/intent_helper/arc_intent_helper_bridge.h', 'arc/intent_helper/font_size_util.cc', 'arc/intent_helper/font_size_util.h', + 'arc/intent_helper/intent_filter.cc', + 'arc/intent_helper/intent_filter.h', 'arc/intent_helper/link_handler_model_impl.cc', 'arc/intent_helper/link_handler_model_impl.h', 'arc/intent_helper/local_activity_resolver.cc', 'arc/intent_helper/local_activity_resolver.h', + 'arc/metrics/arc_metrics_service.cc', + 'arc/metrics/arc_metrics_service.h', 'arc/metrics/oom_kills_histogram.h', 'arc/metrics/oom_kills_monitor.cc', 'arc/metrics/oom_kills_monitor.h', - 'arc/metrics/arc_metrics_service.cc', - 'arc/metrics/arc_metrics_service.h', 'arc/net/arc_net_host_impl.cc', 'arc/net/arc_net_host_impl.h', 'arc/obb_mounter/arc_obb_mounter_bridge.cc',
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn index dfe4ee8d..745c0a8c 100644 --- a/components/arc/BUILD.gn +++ b/components/arc/BUILD.gn
@@ -34,6 +34,8 @@ "intent_helper/arc_intent_helper_bridge.h", "intent_helper/font_size_util.cc", "intent_helper/font_size_util.h", + "intent_helper/intent_filter.cc", + "intent_helper/intent_filter.h", "intent_helper/link_handler_model_impl.cc", "intent_helper/link_handler_model_impl.h", "intent_helper/local_activity_resolver.cc", @@ -98,6 +100,7 @@ "arc_bridge_service.h", "arc_service.cc", "arc_service.h", + "instance_holder.h", ] deps = [
diff --git a/components/arc/arc_bridge_bootstrap.cc b/components/arc/arc_bridge_bootstrap.cc index 77e15c42..c9cafb21 100644 --- a/components/arc/arc_bridge_bootstrap.cc +++ b/components/arc/arc_bridge_bootstrap.cc
@@ -73,11 +73,11 @@ // AcceptInstanceConnection() -> OnInstanceConnected() -> // READY // - // When Stop() is called from any state, either because an operation - // resulted in an error or because the user is logging out: + // When Stop() or AbortBoot() is called from any state, either because an + // operation resulted in an error or because the user is logging out: // // (any) - // Stop() -> + // Stop()/AbortBoot() -> // STOPPING // StopInstance() -> // STOPPED @@ -86,6 +86,9 @@ // READY -> STOPPING -> STOPPED // and then restarted: // STOPPED -> SOCKET_CREATING -> ... -> READY). + // + // Note: Order of constants below matters. Please make sure to sort them + // in chronological order. enum class State { // ARC is not currently running. STOPPED, @@ -114,6 +117,10 @@ void Stop() override; private: + // Aborts ARC instance boot. This is called from various state-machine + // functions when they encounter an error during boot. + void AbortBoot(ArcBridgeService::StopReason reason); + // Creates the UNIX socket on the bootstrap thread and then processes its // file descriptor. static base::ScopedFD CreateSocket(); @@ -135,6 +142,10 @@ // The state of the bootstrap connection. State state_ = State::STOPPED; + // The reason the ARC instance is stopped. + ArcBridgeService::StopReason stop_reason_ = + ArcBridgeService::StopReason::SHUTDOWN; + base::ThreadChecker thread_checker_; // WeakPtrFactory to use callbacks. @@ -168,6 +179,7 @@ VLOG(1) << "Start() called when instance is not stopped"; return; } + stop_reason_ = ArcBridgeService::StopReason::SHUTDOWN; SetState(State::SOCKET_CREATING); base::PostTaskAndReplyWithResult( base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE, @@ -236,7 +248,7 @@ if (!socket_fd.is_valid()) { LOG(ERROR) << "ARC: Error creating socket"; - Stop(); + AbortBoot(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE); return; } @@ -261,7 +273,7 @@ // Roll back the state to SOCKET_CREATING to avoid sending the D-Bus signal // to stop the failed instance. SetState(State::SOCKET_CREATING); - Stop(); + AbortBoot(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE); return; } if (state_ != State::STARTING) { @@ -318,12 +330,14 @@ } if (!fd.is_valid()) { LOG(ERROR) << "Invalid handle"; + AbortBoot(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE); return; } mojo::ScopedMessagePipeHandle server_pipe = mojo::edk::CreateMessagePipe( mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle(fd.release()))); if (!server_pipe.is_valid()) { LOG(ERROR) << "Invalid pipe"; + AbortBoot(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE); return; } SetState(State::READY); @@ -339,11 +353,10 @@ VLOG(1) << "Stop() called when ARC is not running"; return; } - if (state_ == State::SOCKET_CREATING) { + if (state_ < State::STARTING) { // This was stopped before the D-Bus command to start the instance. Skip // the D-Bus command to stop it. - SetState(State::STOPPING); - ArcInstanceStopped(true); + SetState(State::STOPPED); return; } SetState(State::STOPPING); @@ -354,13 +367,26 @@ base::Bind(&DoNothingInstanceStopped)); } +void ArcBridgeBootstrapImpl::AbortBoot(ArcBridgeService::StopReason reason) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(reason != ArcBridgeService::StopReason::SHUTDOWN); + // In case of multiple errors, report the first one. + if (stop_reason_ == ArcBridgeService::StopReason::SHUTDOWN) { + stop_reason_ = reason; + } + Stop(); +} + void ArcBridgeBootstrapImpl::ArcInstanceStopped(bool clean) { DCHECK(thread_checker_.CalledOnValidThread()); - if (!clean) + if (!clean) { LOG(ERROR) << "ARC instance crashed"; - DCHECK(delegate_); + // In case of multiple errors, report the first one. + if (stop_reason_ == ArcBridgeService::StopReason::SHUTDOWN) { + stop_reason_ = ArcBridgeService::StopReason::CRASH; + } + } SetState(State::STOPPED); - delegate_->OnStopped(); } void ArcBridgeBootstrapImpl::SetState(State state) { @@ -369,6 +395,10 @@ DCHECK(state_ != state); state_ = state; VLOG(2) << "State: " << static_cast<uint32_t>(state_); + if (state_ == State::STOPPED) { + DCHECK(delegate_); + delegate_->OnStopped(stop_reason_); + } } } // namespace
diff --git a/components/arc/arc_bridge_bootstrap.h b/components/arc/arc_bridge_bootstrap.h index 918c2c0..25a59f8 100644 --- a/components/arc/arc_bridge_bootstrap.h +++ b/components/arc/arc_bridge_bootstrap.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" +#include "components/arc/arc_bridge_service.h" #include "components/arc/common/arc_bridge.mojom.h" namespace arc { @@ -21,9 +22,12 @@ public: class Delegate { public: + // Called when the connection with ARC instance has been established. virtual void OnConnectionEstablished( mojom::ArcBridgeInstancePtr instance_ptr) = 0; - virtual void OnStopped() = 0; + + // Called when ARC instance is stopped. + virtual void OnStopped(ArcBridgeService::StopReason reason) = 0; }; // Creates a default instance of ArcBridgeBootstrap.
diff --git a/components/arc/arc_bridge_service.cc b/components/arc/arc_bridge_service.cc index bc864faf..ad8a7c4b 100644 --- a/components/arc/arc_bridge_service.cc +++ b/components/arc/arc_bridge_service.cc
@@ -17,8 +17,10 @@ ArcBridgeService* g_arc_bridge_service = nullptr; ArcBridgeService::ArcBridgeService() - : available_(false), state_(State::STOPPED), weak_factory_(this) { -} + : available_(false), + state_(State::STOPPED), + stop_reason_(StopReason::SHUTDOWN), + weak_factory_(this) {} ArcBridgeService::~ArcBridgeService() { DCHECK(CalledOnValidThread()); @@ -45,46 +47,6 @@ void ArcBridgeService::AddObserver(Observer* observer) { DCHECK(CalledOnValidThread()); observer_list_.AddObserver(observer); - - // If any of the instances were ready before the call to AddObserver(), the - // |observer| won't get any readiness events. For such cases, we have to call - // them explicitly now to avoid a race. - if (app_instance()) - observer->OnAppInstanceReady(); - if (audio_instance()) - observer->OnAudioInstanceReady(); - if (auth_instance()) - observer->OnAuthInstanceReady(); - if (bluetooth_instance()) - observer->OnBluetoothInstanceReady(); - if (clipboard_instance()) - observer->OnClipboardInstanceReady(); - if (crash_collector_instance()) - observer->OnCrashCollectorInstanceReady(); - if (file_system_instance()) - observer->OnFileSystemInstanceReady(); - if (ime_instance()) - observer->OnImeInstanceReady(); - if (metrics_instance()) - observer->OnMetricsInstanceReady(); - if (net_instance()) - observer->OnNetInstanceReady(); - if (notifications_instance()) - observer->OnNotificationsInstanceReady(); - if (obb_mounter_instance()) - observer->OnObbMounterInstanceReady(); - if (policy_instance()) - observer->OnPolicyInstanceReady(); - if (power_instance()) - observer->OnPowerInstanceReady(); - if (process_instance()) - observer->OnProcessInstanceReady(); - if (storage_manager_instance()) - observer->OnStorageManagerInstanceReady(); - if (video_instance()) - observer->OnVideoInstanceReady(); - if (window_manager_instance()) - observer->OnWindowManagerInstanceReady(); } void ArcBridgeService::RemoveObserver(Observer* observer) { @@ -94,484 +56,109 @@ void ArcBridgeService::OnAppInstanceReady(mojom::AppInstancePtr app_ptr) { DCHECK(CalledOnValidThread()); - temporary_app_ptr_ = std::move(app_ptr); - temporary_app_ptr_.QueryVersion(base::Bind( - &ArcBridgeService::OnAppVersionReady, weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnAppVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - app_ptr_ = std::move(temporary_app_ptr_); - app_ptr_.set_connection_error_handler(base::Bind( - &ArcBridgeService::CloseAppChannel, weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnAppInstanceReady()); -} - -void ArcBridgeService::CloseAppChannel() { - DCHECK(CalledOnValidThread()); - if (!app_ptr_) - return; - - app_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), OnAppInstanceClosed()); + app_.OnInstanceReady(std::move(app_ptr)); } void ArcBridgeService::OnAudioInstanceReady(mojom::AudioInstancePtr audio_ptr) { DCHECK(CalledOnValidThread()); - temporary_audio_ptr_ = std::move(audio_ptr); - temporary_audio_ptr_.QueryVersion(base::Bind( - &ArcBridgeService::OnAudioVersionReady, weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnAudioVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - audio_ptr_ = std::move(temporary_audio_ptr_); - audio_ptr_.set_connection_error_handler(base::Bind( - &ArcBridgeService::CloseAudioChannel, weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnAudioInstanceReady()); -} - -void ArcBridgeService::CloseAudioChannel() { - if (!audio_ptr_) - return; - - audio_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), OnAudioInstanceClosed()); + audio_.OnInstanceReady(std::move(audio_ptr)); } void ArcBridgeService::OnAuthInstanceReady(mojom::AuthInstancePtr auth_ptr) { DCHECK(CalledOnValidThread()); - temporary_auth_ptr_ = std::move(auth_ptr); - temporary_auth_ptr_.QueryVersion(base::Bind( - &ArcBridgeService::OnAuthVersionReady, weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnAuthVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - auth_ptr_ = std::move(temporary_auth_ptr_); - auth_ptr_.set_connection_error_handler(base::Bind( - &ArcBridgeService::CloseAuthChannel, weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnAuthInstanceReady()); -} - -void ArcBridgeService::CloseAuthChannel() { - DCHECK(CalledOnValidThread()); - if (!auth_ptr_) - return; - - auth_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), OnAuthInstanceClosed()); + auth_.OnInstanceReady(std::move(auth_ptr)); } void ArcBridgeService::OnBluetoothInstanceReady( mojom::BluetoothInstancePtr bluetooth_ptr) { DCHECK(CalledOnValidThread()); - temporary_bluetooth_ptr_ = std::move(bluetooth_ptr); - temporary_bluetooth_ptr_.QueryVersion(base::Bind( - &ArcBridgeService::OnBluetoothVersionReady, weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnBluetoothVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - bluetooth_ptr_ = std::move(temporary_bluetooth_ptr_); - bluetooth_ptr_.set_connection_error_handler(base::Bind( - &ArcBridgeService::CloseBluetoothChannel, weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnBluetoothInstanceReady()); -} - -void ArcBridgeService::CloseBluetoothChannel() { - DCHECK(CalledOnValidThread()); - if (!bluetooth_ptr_) - return; - - bluetooth_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), OnBluetoothInstanceClosed()); + bluetooth_.OnInstanceReady(std::move(bluetooth_ptr)); } void ArcBridgeService::OnClipboardInstanceReady( mojom::ClipboardInstancePtr clipboard_ptr) { DCHECK(CalledOnValidThread()); - temporary_clipboard_ptr_ = std::move(clipboard_ptr); - temporary_clipboard_ptr_.QueryVersion(base::Bind( - &ArcBridgeService::OnClipboardVersionReady, weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnClipboardVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - clipboard_ptr_ = std::move(temporary_clipboard_ptr_); - clipboard_ptr_.set_connection_error_handler(base::Bind( - &ArcBridgeService::CloseClipboardChannel, weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnClipboardInstanceReady()); -} - -void ArcBridgeService::CloseClipboardChannel() { - DCHECK(CalledOnValidThread()); - if (!clipboard_ptr_) - return; - - clipboard_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), OnClipboardInstanceClosed()); + clipboard_.OnInstanceReady(std::move(clipboard_ptr)); } void ArcBridgeService::OnCrashCollectorInstanceReady( mojom::CrashCollectorInstancePtr crash_collector_ptr) { DCHECK(CalledOnValidThread()); - temporary_crash_collector_ptr_ = std::move(crash_collector_ptr); - temporary_crash_collector_ptr_.QueryVersion( - base::Bind(&ArcBridgeService::OnCrashCollectorVersionReady, - weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnCrashCollectorVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - crash_collector_ptr_ = std::move(temporary_crash_collector_ptr_); - crash_collector_ptr_.set_connection_error_handler( - base::Bind(&ArcBridgeService::CloseCrashCollectorChannel, - weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnCrashCollectorInstanceReady()); -} - -void ArcBridgeService::CloseCrashCollectorChannel() { - DCHECK(CalledOnValidThread()); - if (!crash_collector_ptr_) - return; - - crash_collector_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), - OnCrashCollectorInstanceClosed()); + crash_collector_.OnInstanceReady(std::move(crash_collector_ptr)); } void ArcBridgeService::OnFileSystemInstanceReady( mojom::FileSystemInstancePtr file_system_ptr) { DCHECK(CalledOnValidThread()); - temporary_file_system_ptr_ = std::move(file_system_ptr); - temporary_file_system_ptr_.QueryVersion( - base::Bind(&ArcBridgeService::OnFileSystemVersionReady, - weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnFileSystemVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - file_system_ptr_ = std::move(temporary_file_system_ptr_); - file_system_ptr_.set_connection_error_handler( - base::Bind(&ArcBridgeService::CloseFileSystemChannel, - weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnFileSystemInstanceReady()); -} - -void ArcBridgeService::CloseFileSystemChannel() { - DCHECK(CalledOnValidThread()); - if (!file_system_ptr_) - return; - - file_system_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), - OnFileSystemInstanceClosed()); + file_system_.OnInstanceReady(std::move(file_system_ptr)); } void ArcBridgeService::OnImeInstanceReady(mojom::ImeInstancePtr ime_ptr) { DCHECK(CalledOnValidThread()); - temporary_ime_ptr_ = std::move(ime_ptr); - temporary_ime_ptr_.QueryVersion(base::Bind( - &ArcBridgeService::OnImeVersionReady, weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnImeVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - ime_ptr_ = std::move(temporary_ime_ptr_); - ime_ptr_.set_connection_error_handler(base::Bind( - &ArcBridgeService::CloseImeChannel, weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnImeInstanceReady()); -} - -void ArcBridgeService::CloseImeChannel() { - DCHECK(CalledOnValidThread()); - if (!ime_ptr_) - return; - - ime_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), OnImeInstanceClosed()); + ime_.OnInstanceReady(std::move(ime_ptr)); } void ArcBridgeService::OnIntentHelperInstanceReady( mojom::IntentHelperInstancePtr intent_helper_ptr) { DCHECK(CalledOnValidThread()); - temporary_intent_helper_ptr_ = std::move(intent_helper_ptr); - temporary_intent_helper_ptr_.QueryVersion( - base::Bind(&ArcBridgeService::OnIntentHelperVersionReady, - weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnIntentHelperVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - intent_helper_ptr_ = std::move(temporary_intent_helper_ptr_); - intent_helper_ptr_.set_connection_error_handler(base::Bind( - &ArcBridgeService::CloseIntentHelperChannel, weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnIntentHelperInstanceReady()); -} - -void ArcBridgeService::CloseIntentHelperChannel() { - DCHECK(CalledOnValidThread()); - if (!intent_helper_ptr_) - return; - - intent_helper_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), OnIntentHelperInstanceClosed()); + intent_helper_.OnInstanceReady(std::move(intent_helper_ptr)); } void ArcBridgeService::OnMetricsInstanceReady( mojom::MetricsInstancePtr metrics_ptr) { DCHECK(CalledOnValidThread()); - temporary_metrics_ptr_ = std::move(metrics_ptr); - temporary_metrics_ptr_.QueryVersion(base::Bind( - &ArcBridgeService::OnMetricsVersionReady, weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnMetricsVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - metrics_ptr_ = std::move(temporary_metrics_ptr_); - metrics_ptr_.set_connection_error_handler(base::Bind( - &ArcBridgeService::CloseMetricsChannel, weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnMetricsInstanceReady()); -} - -void ArcBridgeService::CloseMetricsChannel() { - DCHECK(CalledOnValidThread()); - if (!metrics_ptr_) - return; - - metrics_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), OnMetricsInstanceClosed()); + metrics_.OnInstanceReady(std::move(metrics_ptr)); } void ArcBridgeService::OnNetInstanceReady(mojom::NetInstancePtr net_ptr) { DCHECK(CalledOnValidThread()); - temporary_net_ptr_ = std::move(net_ptr); - temporary_net_ptr_.QueryVersion(base::Bind( - &ArcBridgeService::OnNetVersionReady, weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnNetVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - net_ptr_ = std::move(temporary_net_ptr_); - net_ptr_.set_connection_error_handler(base::Bind( - &ArcBridgeService::CloseNetChannel, weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnNetInstanceReady()); -} - -void ArcBridgeService::CloseNetChannel() { - DCHECK(CalledOnValidThread()); - if (!net_ptr_) - return; - - net_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), OnNetInstanceClosed()); + net_.OnInstanceReady(std::move(net_ptr)); } void ArcBridgeService::OnNotificationsInstanceReady( mojom::NotificationsInstancePtr notifications_ptr) { DCHECK(CalledOnValidThread()); - temporary_notifications_ptr_ = std::move(notifications_ptr); - temporary_notifications_ptr_.QueryVersion( - base::Bind(&ArcBridgeService::OnNotificationsVersionReady, - weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnNotificationsVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - notifications_ptr_ = std::move(temporary_notifications_ptr_); - notifications_ptr_.set_connection_error_handler( - base::Bind(&ArcBridgeService::CloseNotificationsChannel, - weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnNotificationsInstanceReady()); -} - -void ArcBridgeService::CloseNotificationsChannel() { - DCHECK(CalledOnValidThread()); - if (!notifications_ptr_) - return; - - notifications_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), OnNotificationsInstanceClosed()); + notifications_.OnInstanceReady(std::move(notifications_ptr)); } void ArcBridgeService::OnObbMounterInstanceReady( mojom::ObbMounterInstancePtr obb_mounter_ptr) { DCHECK(CalledOnValidThread()); - temporary_obb_mounter_ptr_ = std::move(obb_mounter_ptr); - temporary_obb_mounter_ptr_.QueryVersion(base::Bind( - &ArcBridgeService::OnObbMounterVersionReady, - weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnObbMounterVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - obb_mounter_ptr_ = std::move(temporary_obb_mounter_ptr_); - obb_mounter_ptr_.set_connection_error_handler(base::Bind( - &ArcBridgeService::CloseObbMounterChannel, - weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnObbMounterInstanceReady()); -} - -void ArcBridgeService::CloseObbMounterChannel() { - if (!obb_mounter_ptr_) - return; - - obb_mounter_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), OnObbMounterInstanceClosed()); + obb_mounter_.OnInstanceReady(std::move(obb_mounter_ptr)); } void ArcBridgeService::OnPolicyInstanceReady( mojom::PolicyInstancePtr policy_ptr) { DCHECK(CalledOnValidThread()); - temporary_policy_ptr_ = std::move(policy_ptr); - temporary_policy_ptr_.QueryVersion(base::Bind( - &ArcBridgeService::OnPolicyVersionReady, weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnPolicyVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - policy_ptr_ = std::move(temporary_policy_ptr_); - policy_ptr_.set_connection_error_handler(base::Bind( - &ArcBridgeService::ClosePolicyChannel, weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnPolicyInstanceReady()); -} - -void ArcBridgeService::ClosePolicyChannel() { - DCHECK(CalledOnValidThread()); - if (!policy_ptr_) - return; - - policy_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), OnPolicyInstanceClosed()); + policy_.OnInstanceReady(std::move(policy_ptr)); } void ArcBridgeService::OnPowerInstanceReady(mojom::PowerInstancePtr power_ptr) { DCHECK(CalledOnValidThread()); - temporary_power_ptr_ = std::move(power_ptr); - temporary_power_ptr_.QueryVersion(base::Bind( - &ArcBridgeService::OnPowerVersionReady, weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnPowerVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - power_ptr_ = std::move(temporary_power_ptr_); - power_ptr_.set_connection_error_handler(base::Bind( - &ArcBridgeService::ClosePowerChannel, weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnPowerInstanceReady()); -} - -void ArcBridgeService::ClosePowerChannel() { - DCHECK(CalledOnValidThread()); - if (!power_ptr_) - return; - - power_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), OnPowerInstanceClosed()); + power_.OnInstanceReady(std::move(power_ptr)); } void ArcBridgeService::OnProcessInstanceReady( mojom::ProcessInstancePtr process_ptr) { DCHECK(CalledOnValidThread()); - temporary_process_ptr_ = std::move(process_ptr); - temporary_process_ptr_.QueryVersion(base::Bind( - &ArcBridgeService::OnProcessVersionReady, weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnProcessVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - process_ptr_ = std::move(temporary_process_ptr_); - process_ptr_.set_connection_error_handler(base::Bind( - &ArcBridgeService::CloseProcessChannel, weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnProcessInstanceReady()); -} - -void ArcBridgeService::CloseProcessChannel() { - DCHECK(CalledOnValidThread()); - if (!process_ptr_) - return; - - process_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), OnProcessInstanceClosed()); + process_.OnInstanceReady(std::move(process_ptr)); } void ArcBridgeService::OnStorageManagerInstanceReady( mojom::StorageManagerInstancePtr storage_manager_ptr) { DCHECK(CalledOnValidThread()); - temporary_storage_manager_ptr_ = std::move(storage_manager_ptr); - temporary_storage_manager_ptr_.QueryVersion(base::Bind( - &ArcBridgeService::OnStorageManagerVersionReady, - weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnStorageManagerVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - storage_manager_ptr_ = std::move(temporary_storage_manager_ptr_); - storage_manager_ptr_.set_connection_error_handler(base::Bind( - &ArcBridgeService::CloseStorageManagerChannel, - weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER( - Observer, observer_list(), OnStorageManagerInstanceReady()); -} - -void ArcBridgeService::CloseStorageManagerChannel() { - DCHECK(CalledOnValidThread()); - if (!storage_manager_ptr_) - return; - - storage_manager_ptr_.reset(); - FOR_EACH_OBSERVER( - Observer, observer_list(), OnStorageManagerInstanceClosed()); + storage_manager_.OnInstanceReady(std::move(storage_manager_ptr)); } void ArcBridgeService::OnVideoInstanceReady(mojom::VideoInstancePtr video_ptr) { DCHECK(CalledOnValidThread()); - temporary_video_ptr_ = std::move(video_ptr); - temporary_video_ptr_.QueryVersion(base::Bind( - &ArcBridgeService::OnVideoVersionReady, weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnVideoVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - video_ptr_ = std::move(temporary_video_ptr_); - video_ptr_.set_connection_error_handler(base::Bind( - &ArcBridgeService::CloseVideoChannel, weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnVideoInstanceReady()); -} - -void ArcBridgeService::CloseVideoChannel() { - DCHECK(CalledOnValidThread()); - if (!video_ptr_) - return; - - video_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), OnVideoInstanceClosed()); + video_.OnInstanceReady(std::move(video_ptr)); } void ArcBridgeService::OnWindowManagerInstanceReady( mojom::WindowManagerInstancePtr window_manager_ptr) { DCHECK(CalledOnValidThread()); - temporary_window_manager_ptr_ = std::move(window_manager_ptr); - temporary_window_manager_ptr_.QueryVersion(base::Bind( - &ArcBridgeService::OnWindowManagerVersionReady, - weak_factory_.GetWeakPtr())); -} - -void ArcBridgeService::OnWindowManagerVersionReady(uint32_t version) { - DCHECK(CalledOnValidThread()); - window_manager_ptr_ = std::move(temporary_window_manager_ptr_); - window_manager_ptr_.set_connection_error_handler(base::Bind( - &ArcBridgeService::CloseWindowManagerChannel, - weak_factory_.GetWeakPtr())); - FOR_EACH_OBSERVER(Observer, observer_list(), OnWindowManagerInstanceReady()); -} - -void ArcBridgeService::CloseWindowManagerChannel() { - if (!window_manager_ptr_) - return; - - window_manager_ptr_.reset(); - FOR_EACH_OBSERVER(Observer, observer_list(), OnWindowManagerInstanceClosed()); + window_manager_.OnInstanceReady(std::move(window_manager_ptr)); } void ArcBridgeService::SetState(State state) { @@ -582,7 +169,7 @@ if (state_ == State::READY) FOR_EACH_OBSERVER(Observer, observer_list(), OnBridgeReady()); else if (state == State::STOPPED) - FOR_EACH_OBSERVER(Observer, observer_list(), OnBridgeStopped()); + FOR_EACH_OBSERVER(Observer, observer_list(), OnBridgeStopped(stop_reason_)); } void ArcBridgeService::SetAvailable(bool available) { @@ -592,6 +179,11 @@ FOR_EACH_OBSERVER(Observer, observer_list(), OnAvailableChanged(available_)); } +void ArcBridgeService::SetStopReason(StopReason stop_reason) { + DCHECK(CalledOnValidThread()); + stop_reason_ = stop_reason; +} + bool ArcBridgeService::CalledOnValidThread() { return thread_checker_.CalledOnValidThread(); } @@ -599,25 +191,25 @@ void ArcBridgeService::CloseAllChannels() { // Call all the error handlers of all the channels to both close the channel // and notify any observers that the channel is closed. - CloseAppChannel(); - CloseAudioChannel(); - CloseAuthChannel(); - CloseBluetoothChannel(); - CloseClipboardChannel(); - CloseCrashCollectorChannel(); - CloseFileSystemChannel(); - CloseImeChannel(); - CloseIntentHelperChannel(); - CloseMetricsChannel(); - CloseNetChannel(); - CloseNotificationsChannel(); - CloseObbMounterChannel(); - ClosePolicyChannel(); - ClosePowerChannel(); - CloseProcessChannel(); - CloseStorageManagerChannel(); - CloseVideoChannel(); - CloseWindowManagerChannel(); + app_.CloseChannel(); + audio_.CloseChannel(); + auth_.CloseChannel(); + bluetooth_.CloseChannel(); + clipboard_.CloseChannel(); + crash_collector_.CloseChannel(); + file_system_.CloseChannel(); + ime_.CloseChannel(); + intent_helper_.CloseChannel(); + metrics_.CloseChannel(); + net_.CloseChannel(); + notifications_.CloseChannel(); + obb_mounter_.CloseChannel(); + policy_.CloseChannel(); + power_.CloseChannel(); + process_.CloseChannel(); + storage_manager_.CloseChannel(); + video_.CloseChannel(); + window_manager_.CloseChannel(); } } // namespace arc
diff --git a/components/arc/arc_bridge_service.h b/components/arc/arc_bridge_service.h index bcd5b09..186800b 100644 --- a/components/arc/arc_bridge_service.h +++ b/components/arc/arc_bridge_service.h
@@ -14,6 +14,7 @@ #include "base/observer_list.h" #include "base/values.h" #include "components/arc/common/arc_bridge.mojom.h" +#include "components/arc/instance_holder.h" namespace base { class CommandLine; @@ -21,7 +22,6 @@ namespace arc { -class ArcBridgeBootstrap; class ArcBridgeTest; // The Chrome-side service that handles ARC instances and ARC bridge creation. @@ -29,92 +29,30 @@ // communication channel (the ARC bridge) used to send and receive messages. class ArcBridgeService : public mojom::ArcBridgeHost { public: + // Describes the reason the bridge is stopped. + enum class StopReason { + // ARC instance has been gracefully shut down. + SHUTDOWN, + + // Errors occurred during the ARC instance boot. This includes any failures + // before the instance is actually attempted to be started, and also + // failures on bootstrapping IPC channels with Android. + GENERIC_BOOT_FAILURE, + + // ARC instance has crashed. + CRASH, + }; + // Notifies life cycle events of ArcBridgeService. class Observer { public: // Called whenever the state of the bridge has changed. virtual void OnBridgeReady() {} - virtual void OnBridgeStopped() {} + virtual void OnBridgeStopped(StopReason reason) {} // Called whenever ARC's availability has changed for this system. virtual void OnAvailableChanged(bool available) {} - // Called whenever the ARC app interface state changes. - virtual void OnAppInstanceReady() {} - virtual void OnAppInstanceClosed() {} - - // Called whenever the ARC audio interface state changes. - virtual void OnAudioInstanceReady() {} - virtual void OnAudioInstanceClosed() {} - - // Called whenever the ARC auth interface state changes. - virtual void OnAuthInstanceReady() {} - virtual void OnAuthInstanceClosed() {} - - // Called whenever ARC Bluetooth instance is ready. - virtual void OnBluetoothInstanceReady() {} - virtual void OnBluetoothInstanceClosed() {} - - // Called whenever the ARC clipboard interface state changes. - virtual void OnClipboardInstanceReady() {} - virtual void OnClipboardInstanceClosed() {} - - // Called whenever the ARC crash collector interface state changes. - virtual void OnCrashCollectorInstanceReady() {} - virtual void OnCrashCollectorInstanceClosed() {} - - // Called whenever the ARC file system interface state changes. - virtual void OnFileSystemInstanceReady() {} - virtual void OnFileSystemInstanceClosed() {} - - // Called whenever the ARC IME interface state changes. - virtual void OnImeInstanceReady() {} - virtual void OnImeInstanceClosed() {} - - // Called whenever the ARC intent helper interface state changes. - virtual void OnIntentHelperInstanceReady() {} - virtual void OnIntentHelperInstanceClosed() {} - - // Called whenever the ARC metrics interface state changes. - virtual void OnMetricsInstanceReady() {} - virtual void OnMetricsInstanceClosed() {} - - // Called whenever the ARC notification interface state changes. - virtual void OnNotificationsInstanceReady() {} - virtual void OnNotificationsInstanceClosed() {} - - // Called whenever the ARC net interface state changes. - virtual void OnNetInstanceReady() {} - virtual void OnNetInstanceClosed() {} - - // Called whenever the ARC OBB mounter interface state changes. - virtual void OnObbMounterInstanceReady() {} - virtual void OnObbMounterInstanceClosed() {} - - // Called whenever the ARC policy interface state changes. - virtual void OnPolicyInstanceReady() {} - virtual void OnPolicyInstanceClosed() {} - - // Called whenever the ARC power interface state changes. - virtual void OnPowerInstanceReady() {} - virtual void OnPowerInstanceClosed() {} - - // Called whenever the ARC process interface state changes. - virtual void OnProcessInstanceReady() {} - virtual void OnProcessInstanceClosed() {} - - // Called whenever the ARC storage manager interface state changes. - virtual void OnStorageManagerInstanceReady() {} - virtual void OnStorageManagerInstanceClosed() {} - - // Called whenever the ARC video interface state changes. - virtual void OnVideoInstanceReady() {} - virtual void OnVideoInstanceClosed() {} - - // Called whenever the ARC window manager interface state changes. - virtual void OnWindowManagerInstanceReady() {} - virtual void OnWindowManagerInstanceClosed() {} - protected: virtual ~Observer() {} }; @@ -149,72 +87,38 @@ void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); - // Gets the Mojo interface for all the instance services. This will return - // nullptr if that particular service is not ready yet. Use an Observer if - // you want to be notified when this is ready. This can only be called on the - // thread that this class was created on. - mojom::AppInstance* app_instance() { return app_ptr_.get(); } - mojom::AudioInstance* audio_instance() { return audio_ptr_.get(); } - mojom::AuthInstance* auth_instance() { return auth_ptr_.get(); } - mojom::BluetoothInstance* bluetooth_instance() { - return bluetooth_ptr_.get(); + InstanceHolder<mojom::AppInstance>* app() { return &app_; } + InstanceHolder<mojom::AudioInstance>* audio() { return &audio_; } + InstanceHolder<mojom::AuthInstance>* auth() { return &auth_; } + InstanceHolder<mojom::BluetoothInstance>* bluetooth() { return &bluetooth_; } + InstanceHolder<mojom::ClipboardInstance>* clipboard() { return &clipboard_; } + InstanceHolder<mojom::CrashCollectorInstance>* crash_collector() { + return &crash_collector_; } - mojom::ClipboardInstance* clipboard_instance() { - return clipboard_ptr_.get(); + InstanceHolder<mojom::FileSystemInstance>* file_system() { + return &file_system_; } - mojom::CrashCollectorInstance* crash_collector_instance() { - return crash_collector_ptr_.get(); + InstanceHolder<mojom::ImeInstance>* ime() { return &ime_; } + InstanceHolder<mojom::IntentHelperInstance>* intent_helper() { + return &intent_helper_; } - mojom::FileSystemInstance* file_system_instance() { - return file_system_ptr_.get(); + InstanceHolder<mojom::MetricsInstance>* metrics() { return &metrics_; } + InstanceHolder<mojom::NetInstance>* net() { return &net_; } + InstanceHolder<mojom::NotificationsInstance>* notifications() { + return ¬ifications_; } - mojom::ImeInstance* ime_instance() { return ime_ptr_.get(); } - mojom::IntentHelperInstance* intent_helper_instance() { - return intent_helper_ptr_.get(); + InstanceHolder<mojom::ObbMounterInstance>* obb_mounter() { + return &obb_mounter_; } - mojom::MetricsInstance* metrics_instance() { return metrics_ptr_.get(); } - mojom::NetInstance* net_instance() { return net_ptr_.get(); } - mojom::NotificationsInstance* notifications_instance() { - return notifications_ptr_.get(); + InstanceHolder<mojom::PolicyInstance>* policy() { return &policy_; } + InstanceHolder<mojom::PowerInstance>* power() { return &power_; } + InstanceHolder<mojom::ProcessInstance>* process() { return &process_; } + InstanceHolder<mojom::StorageManagerInstance>* storage_manager() { + return &storage_manager_; } - mojom::ObbMounterInstance* obb_mounter_instance() { - return obb_mounter_ptr_.get(); - } - mojom::PolicyInstance* policy_instance() { return policy_ptr_.get(); } - mojom::PowerInstance* power_instance() { return power_ptr_.get(); } - mojom::ProcessInstance* process_instance() { return process_ptr_.get(); } - mojom::StorageManagerInstance* storage_manager_instance() { - return storage_manager_ptr_.get(); - } - mojom::VideoInstance* video_instance() { return video_ptr_.get(); } - mojom::WindowManagerInstance* window_manager_instance() { - return window_manager_ptr_.get(); - } - - int32_t app_version() const { return app_ptr_.version(); } - int32_t audio_version() const { return audio_ptr_.version(); } - int32_t bluetooth_version() const { return bluetooth_ptr_.version(); } - int32_t auth_version() const { return auth_ptr_.version(); } - int32_t clipboard_version() const { return clipboard_ptr_.version(); } - int32_t crash_collector_version() const { - return crash_collector_ptr_.version(); - } - int32_t file_system_version() const { return file_system_ptr_.version(); } - int32_t ime_version() const { return ime_ptr_.version(); } - int32_t intent_helper_version() const { return intent_helper_ptr_.version(); } - int32_t metrics_version() const { return metrics_ptr_.version(); } - int32_t net_version() const { return net_ptr_.version(); } - int32_t notifications_version() const { return notifications_ptr_.version(); } - int32_t obb_mounter_version() const { return obb_mounter_ptr_.version(); } - int32_t policy_version() const { return policy_ptr_.version(); } - int32_t power_version() const { return power_ptr_.version(); } - int32_t process_version() const { return process_ptr_.version(); } - int32_t storage_manager_version() const { - return storage_manager_ptr_.version(); - } - int32_t video_version() const { return video_ptr_.version(); } - int32_t window_manager_version() const { - return window_manager_ptr_.version(); + InstanceHolder<mojom::VideoInstance>* video() { return &video_; } + InstanceHolder<mojom::WindowManagerInstance>* window_manager() { + return &window_manager_; } // ArcHost: @@ -304,6 +208,11 @@ // Changes the current availability and notifies all observers. void SetAvailable(bool availability); + // Sets the reason the bridge is stopped. This function must be always called + // before SetState(State::STOPPED) to report a correct reason with + // Observer::OnBridgeStopped(). + void SetStopReason(StopReason stop_reason); + base::ObserverList<Observer>& observer_list() { return observer_list_; } bool CalledOnValidThread(); @@ -317,95 +226,28 @@ FRIEND_TEST_ALL_PREFIXES(ArcBridgeTest, Prerequisites); FRIEND_TEST_ALL_PREFIXES(ArcBridgeTest, ShutdownMidStartup); FRIEND_TEST_ALL_PREFIXES(ArcBridgeTest, Restart); + FRIEND_TEST_ALL_PREFIXES(ArcBridgeTest, OnBridgeStopped); - // Called when one of the individual channels is closed. - void CloseAppChannel(); - void CloseAudioChannel(); - void CloseAuthChannel(); - void CloseBluetoothChannel(); - void CloseClipboardChannel(); - void CloseCrashCollectorChannel(); - void CloseFileSystemChannel(); - void CloseImeChannel(); - void CloseIntentHelperChannel(); - void CloseMetricsChannel(); - void CloseNetChannel(); - void CloseNotificationsChannel(); - void CloseObbMounterChannel(); - void ClosePolicyChannel(); - void ClosePowerChannel(); - void CloseProcessChannel(); - void CloseStorageManagerChannel(); - void CloseVideoChannel(); - void CloseWindowManagerChannel(); - - // Callbacks for QueryVersion. - void OnAppVersionReady(uint32_t version); - void OnAudioVersionReady(uint32_t version); - void OnAuthVersionReady(uint32_t version); - void OnBluetoothVersionReady(uint32_t version); - void OnClipboardVersionReady(uint32_t version); - void OnCrashCollectorVersionReady(uint32_t version); - void OnFileSystemVersionReady(uint32_t version); - void OnImeVersionReady(uint32_t version); - void OnIntentHelperVersionReady(uint32_t version); - void OnMetricsVersionReady(uint32_t version); - void OnNetVersionReady(uint32_t version); - void OnNotificationsVersionReady(uint32_t version); - void OnObbMounterVersionReady(uint32_t version); - void OnPolicyVersionReady(uint32_t version); - void OnPowerVersionReady(uint32_t version); - void OnProcessVersionReady(uint32_t version); - void OnStorageManagerVersionReady(uint32_t version); - void OnVideoVersionReady(uint32_t version); - void OnWindowManagerVersionReady(uint32_t version); - - // Mojo interfaces. - mojom::AppInstancePtr app_ptr_; - mojom::AudioInstancePtr audio_ptr_; - mojom::AuthInstancePtr auth_ptr_; - mojom::BluetoothInstancePtr bluetooth_ptr_; - mojom::ClipboardInstancePtr clipboard_ptr_; - mojom::CrashCollectorInstancePtr crash_collector_ptr_; - mojom::FileSystemInstancePtr file_system_ptr_; - mojom::ImeInstancePtr ime_ptr_; - mojom::IntentHelperInstancePtr intent_helper_ptr_; - mojom::MetricsInstancePtr metrics_ptr_; - mojom::NetInstancePtr net_ptr_; - mojom::NotificationsInstancePtr notifications_ptr_; - mojom::ObbMounterInstancePtr obb_mounter_ptr_; - mojom::PolicyInstancePtr policy_ptr_; - mojom::PowerInstancePtr power_ptr_; - mojom::ProcessInstancePtr process_ptr_; - mojom::StorageManagerInstancePtr storage_manager_ptr_; - mojom::VideoInstancePtr video_ptr_; - mojom::WindowManagerInstancePtr window_manager_ptr_; - - // Temporary Mojo interfaces. After a Mojo interface pointer has been - // received from the other endpoint, we still need to asynchronously query - // its version. While that is going on, we should still return nullptr on - // the xxx_instance() functions. - // To keep the xxx_instance() functions being trivial, store the instance - // pointer in a temporary variable to avoid losing its reference. - mojom::AppInstancePtr temporary_app_ptr_; - mojom::AudioInstancePtr temporary_audio_ptr_; - mojom::AuthInstancePtr temporary_auth_ptr_; - mojom::BluetoothInstancePtr temporary_bluetooth_ptr_; - mojom::ClipboardInstancePtr temporary_clipboard_ptr_; - mojom::CrashCollectorInstancePtr temporary_crash_collector_ptr_; - mojom::FileSystemInstancePtr temporary_file_system_ptr_; - mojom::ImeInstancePtr temporary_ime_ptr_; - mojom::IntentHelperInstancePtr temporary_intent_helper_ptr_; - mojom::MetricsInstancePtr temporary_metrics_ptr_; - mojom::NetInstancePtr temporary_net_ptr_; - mojom::NotificationsInstancePtr temporary_notifications_ptr_; - mojom::ObbMounterInstancePtr temporary_obb_mounter_ptr_; - mojom::PolicyInstancePtr temporary_policy_ptr_; - mojom::PowerInstancePtr temporary_power_ptr_; - mojom::ProcessInstancePtr temporary_process_ptr_; - mojom::StorageManagerInstancePtr temporary_storage_manager_ptr_; - mojom::VideoInstancePtr temporary_video_ptr_; - mojom::WindowManagerInstancePtr temporary_window_manager_ptr_; + // Instance holders. + InstanceHolder<mojom::AppInstance> app_; + InstanceHolder<mojom::AudioInstance> audio_; + InstanceHolder<mojom::AuthInstance> auth_; + InstanceHolder<mojom::BluetoothInstance> bluetooth_; + InstanceHolder<mojom::ClipboardInstance> clipboard_; + InstanceHolder<mojom::CrashCollectorInstance> crash_collector_; + InstanceHolder<mojom::FileSystemInstance> file_system_; + InstanceHolder<mojom::ImeInstance> ime_; + InstanceHolder<mojom::IntentHelperInstance> intent_helper_; + InstanceHolder<mojom::MetricsInstance> metrics_; + InstanceHolder<mojom::NetInstance> net_; + InstanceHolder<mojom::NotificationsInstance> notifications_; + InstanceHolder<mojom::ObbMounterInstance> obb_mounter_; + InstanceHolder<mojom::PolicyInstance> policy_; + InstanceHolder<mojom::PowerInstance> power_; + InstanceHolder<mojom::ProcessInstance> process_; + InstanceHolder<mojom::StorageManagerInstance> storage_manager_; + InstanceHolder<mojom::VideoInstance> video_; + InstanceHolder<mojom::WindowManagerInstance> window_manager_; base::ObserverList<Observer> observer_list_; @@ -417,6 +259,9 @@ // The current state of the bridge. ArcBridgeService::State state_; + // The reason the bridge is stopped. + StopReason stop_reason_; + // WeakPtrFactory to use callbacks. base::WeakPtrFactory<ArcBridgeService> weak_factory_;
diff --git a/components/arc/arc_bridge_service_impl.cc b/components/arc/arc_bridge_service_impl.cc index a5c49456..52c9284 100644 --- a/components/arc/arc_bridge_service_impl.cc +++ b/components/arc/arc_bridge_service_impl.cc
@@ -78,6 +78,7 @@ if (!available() || !session_started_) return; VLOG(0) << "Prerequisites met, starting ARC"; + SetStopReason(StopReason::SHUTDOWN); SetState(State::CONNECTING); bootstrap_->Start(); } else { @@ -136,8 +137,9 @@ SetState(State::READY); } -void ArcBridgeServiceImpl::OnStopped() { +void ArcBridgeServiceImpl::OnStopped(StopReason stop_reason) { DCHECK(CalledOnValidThread()); + SetStopReason(stop_reason); SetState(State::STOPPED); VLOG(0) << "ARC stopped"; if (reconnect_) {
diff --git a/components/arc/arc_bridge_service_impl.h b/components/arc/arc_bridge_service_impl.h index 60e61627..93805405 100644 --- a/components/arc/arc_bridge_service_impl.h +++ b/components/arc/arc_bridge_service_impl.h
@@ -44,6 +44,7 @@ private: friend class ArcBridgeTest; FRIEND_TEST_ALL_PREFIXES(ArcBridgeTest, Restart); + FRIEND_TEST_ALL_PREFIXES(ArcBridgeTest, OnBridgeStopped); // If all pre-requisites are true (ARC is available, it has been enabled, and // the session has started), and ARC is stopped, start ARC. If ARC is running @@ -55,7 +56,7 @@ // ArcBridgeBootstrap::Delegate: void OnConnectionEstablished(mojom::ArcBridgeInstancePtr instance) override; - void OnStopped() override; + void OnStopped(StopReason reason) override; // Called when the bridge channel is closed. This typically only happens when // the ARC instance crashes. This is not called during shutdown.
diff --git a/components/arc/arc_bridge_service_unittest.cc b/components/arc/arc_bridge_service_unittest.cc index 52ad15fc..a4bff47 100644 --- a/components/arc/arc_bridge_service_unittest.cc +++ b/components/arc/arc_bridge_service_unittest.cc
@@ -34,8 +34,9 @@ ready_ = true; } - void OnBridgeStopped() override { + void OnBridgeStopped(ArcBridgeService::StopReason stop_reason) override { state_ = ArcBridgeService::State::STOPPED; + stop_reason_ = stop_reason; message_loop_.PostTask(FROM_HERE, message_loop_.QuitWhenIdleClosure()); } @@ -45,6 +46,7 @@ protected: std::unique_ptr<ArcBridgeServiceImpl> service_; std::unique_ptr<FakeArcBridgeInstance> instance_; + ArcBridgeService::StopReason stop_reason_; private: void SetUp() override { @@ -52,6 +54,7 @@ ready_ = false; state_ = ArcBridgeService::State::STOPPED; + stop_reason_ = ArcBridgeService::StopReason::SHUTDOWN; instance_.reset(new FakeArcBridgeInstance()); service_.reset(new ArcBridgeServiceImpl( @@ -129,7 +132,7 @@ // Simulate a connection loss. service_->DisableReconnectDelayForTesting(); service_->OnChannelClosed(); - instance_->SimulateCrash(); + instance_->Stop(ArcBridgeService::StopReason::CRASH); instance_->WaitForInitCall(); ASSERT_EQ(ArcBridgeService::State::READY, state()); ASSERT_EQ(2, instance_->init_calls()); @@ -138,6 +141,36 @@ ASSERT_EQ(ArcBridgeService::State::STOPPED, state()); } +// Makes sure OnBridgeStopped is called on stop. +TEST_F(ArcBridgeTest, OnBridgeStopped) { + ASSERT_FALSE(ready()); + + service_->DisableReconnectDelayForTesting(); + service_->SetAvailable(true); + service_->HandleStartup(); + instance_->WaitForInitCall(); + ASSERT_EQ(ArcBridgeService::State::READY, state()); + + // Simulate boot failure. + service_->OnChannelClosed(); + instance_->Stop(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE); + instance_->WaitForInitCall(); + ASSERT_EQ(ArcBridgeService::StopReason::GENERIC_BOOT_FAILURE, stop_reason_); + ASSERT_EQ(ArcBridgeService::State::READY, state()); + + // Simulate crash. + service_->OnChannelClosed(); + instance_->Stop(ArcBridgeService::StopReason::CRASH); + instance_->WaitForInitCall(); + ASSERT_EQ(ArcBridgeService::StopReason::CRASH, stop_reason_); + ASSERT_EQ(ArcBridgeService::State::READY, state()); + + // Graceful shutdown. + service_->Shutdown(); + ASSERT_EQ(ArcBridgeService::StopReason::SHUTDOWN, stop_reason_); + ASSERT_EQ(ArcBridgeService::State::STOPPED, state()); +} + // Removing the same observer more than once should be okay. TEST_F(ArcBridgeTest, RemoveObserverTwice) { ASSERT_FALSE(ready());
diff --git a/components/arc/audio/arc_audio_bridge.cc b/components/arc/audio/arc_audio_bridge.cc index 13625d4..222b5bc4 100644 --- a/components/arc/audio/arc_audio_bridge.cc +++ b/components/arc/audio/arc_audio_bridge.cc
@@ -13,7 +13,7 @@ ArcAudioBridge::ArcAudioBridge(ArcBridgeService* bridge_service) : ArcService(bridge_service), binding_(this) { - arc_bridge_service()->AddObserver(this); + arc_bridge_service()->audio()->AddObserver(this); if (chromeos::CrasAudioHandler::IsInitialized()) { cras_audio_handler_ = chromeos::CrasAudioHandler::Get(); cras_audio_handler_->AddAudioObserver(this); @@ -21,21 +21,21 @@ } ArcAudioBridge::~ArcAudioBridge() { - arc_bridge_service()->RemoveObserver(this); if (cras_audio_handler_ && chromeos::CrasAudioHandler::IsInitialized()) { cras_audio_handler_->RemoveAudioObserver(this); } + arc_bridge_service()->audio()->RemoveObserver(this); } -void ArcAudioBridge::OnAudioInstanceReady() { +void ArcAudioBridge::OnInstanceReady() { mojom::AudioInstance* audio_instance = - arc_bridge_service()->audio_instance(); + arc_bridge_service()->audio()->instance(); if (!audio_instance) { LOG(ERROR) << "OnAudioInstanceReady called, " << "but no audio instance found"; return; } - if (arc_bridge_service()->audio_version() < 1) { + if (arc_bridge_service()->audio()->version() < 1) { LOG(WARNING) << "Audio instance is too old and does not support Init()"; return; } @@ -44,8 +44,8 @@ void ArcAudioBridge::ShowVolumeControls() { VLOG(2) << "ArcAudioBridge::ShowVolumeControls"; - ash::WmShell::Get()->system_tray_notifier()-> - NotifyAudioOutputVolumeChanged(0, 0); + ash::WmShell::Get()->system_tray_notifier()->NotifyAudioOutputVolumeChanged( + 0, 0); } void ArcAudioBridge::OnAudioNodesChanged() { @@ -53,18 +53,18 @@ const chromeos::AudioDevice* output_device = cras_audio_handler_->GetDeviceFromId(output_id); bool headphone_inserted = - (output_device && - output_device->type == chromeos::AudioDeviceType::AUDIO_TYPE_HEADPHONE); + (output_device && + output_device->type == chromeos::AudioDeviceType::AUDIO_TYPE_HEADPHONE); uint64_t input_id = cras_audio_handler_->GetPrimaryActiveInputNode(); const chromeos::AudioDevice* input_device = cras_audio_handler_->GetDeviceFromId(input_id); bool microphone_inserted = - (input_device && - input_device->type == chromeos::AudioDeviceType::AUDIO_TYPE_MIC); + (input_device && + input_device->type == chromeos::AudioDeviceType::AUDIO_TYPE_MIC); - VLOG(1) << "HEADPHONE " << headphone_inserted - << " MICROPHONE " << microphone_inserted; + VLOG(1) << "HEADPHONE " << headphone_inserted << " MICROPHONE " + << microphone_inserted; SendSwitchState(headphone_inserted, microphone_inserted); } @@ -81,7 +81,8 @@ } VLOG(1) << "Send switch state " << switch_state; - mojom::AudioInstance* audio_instance = arc_bridge_service()->audio_instance(); + mojom::AudioInstance* audio_instance = + arc_bridge_service()->audio()->instance(); if (audio_instance) audio_instance->NotifySwitchState(switch_state); }
diff --git a/components/arc/audio/arc_audio_bridge.h b/components/arc/audio/arc_audio_bridge.h index 5f88b1ab..34cf4f1 100644 --- a/components/arc/audio/arc_audio_bridge.h +++ b/components/arc/audio/arc_audio_bridge.h
@@ -11,20 +11,21 @@ #include "chromeos/audio/cras_audio_handler.h" #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/instance_holder.h" #include "mojo/public/cpp/bindings/binding.h" namespace arc { class ArcAudioBridge : public ArcService, - public ArcBridgeService::Observer, + public InstanceHolder<mojom::AudioInstance>::Observer, public mojom::AudioHost, public chromeos::CrasAudioHandler::AudioObserver { public: explicit ArcAudioBridge(ArcBridgeService* bridge_service); ~ArcAudioBridge() override; - // ArcBridgeService::Observer overrides. - void OnAudioInstanceReady() override; + // InstanceHolder<mojom::AudioInstance>::Observer overrides. + void OnInstanceReady() override; // mojom::AudioHost overrides. void ShowVolumeControls() override;
diff --git a/components/arc/bluetooth/arc_bluetooth_bridge.cc b/components/arc/bluetooth/arc_bluetooth_bridge.cc index 5ba17cc..3437480 100644 --- a/components/arc/bluetooth/arc_bluetooth_bridge.cc +++ b/components/arc/bluetooth/arc_bluetooth_bridge.cc
@@ -71,11 +71,11 @@ VLOG(1) << "no bluetooth adapter available"; } - arc_bridge_service()->AddObserver(this); + arc_bridge_service()->bluetooth()->AddObserver(this); } ArcBluetoothBridge::~ArcBluetoothBridge() { - arc_bridge_service()->RemoveObserver(this); + arc_bridge_service()->bluetooth()->RemoveObserver(this); if (bluetooth_adapter_) bluetooth_adapter_->RemoveObserver(this); @@ -90,17 +90,15 @@ bluetooth_adapter_->AddObserver(this); } -void ArcBluetoothBridge::OnBluetoothInstanceReady() { +void ArcBluetoothBridge::OnInstanceReady() { mojom::BluetoothInstance* bluetooth_instance = - arc_bridge_service()->bluetooth_instance(); + arc_bridge_service()->bluetooth()->instance(); if (!bluetooth_instance) { LOG(ERROR) << "OnBluetoothInstanceReady called, " << "but no bluetooth instance found"; return; } - - arc_bridge_service()->bluetooth_instance()->Init( - binding_.CreateInterfacePtrAndBind()); + bluetooth_instance->Init(binding_.CreateInterfacePtrAndBind()); } void ArcBluetoothBridge::AdapterPresentChanged(BluetoothAdapter* adapter, @@ -132,7 +130,7 @@ mojo::Array<mojom::BluetoothPropertyPtr> properties = GetDeviceProperties(mojom::BluetoothPropertyType::ALL, device); - arc_bridge_service()->bluetooth_instance()->OnDeviceFound( + arc_bridge_service()->bluetooth()->instance()->OnDeviceFound( std::move(properties)); if (!CheckBluetoothInstanceVersion(kMinBtleVersion)) @@ -143,7 +141,7 @@ int rssi = device->GetInquiryRSSI(); mojo::Array<mojom::BluetoothAdvertisingDataPtr> adv_data = GetAdvertisingData(device); - arc_bridge_service()->bluetooth_instance()->OnLEDeviceFound( + arc_bridge_service()->bluetooth()->instance()->OnLEDeviceFound( std::move(addr), rssi, std::move(adv_data)); } @@ -213,7 +211,7 @@ mojom::BluetoothAddressPtr addr = mojom::BluetoothAddress::From(device->GetAddress()); - arc_bridge_service()->bluetooth_instance()->OnSearchComplete( + arc_bridge_service()->bluetooth()->instance()->OnSearchComplete( std::move(addr), mojom::BluetoothGattStatus::GATT_SUCCESS); } @@ -278,7 +276,7 @@ char_id->inst_id = ConvertGattIdentifierToId(characteristic->GetIdentifier()); char_id->uuid = mojom::BluetoothUUID::From(characteristic->GetUUID()); - arc_bridge_service()->bluetooth_instance()->OnGattNotify( + arc_bridge_service()->bluetooth()->instance()->OnGattNotify( std::move(address), std::move(service_id), std::move(char_id), true /* is_notify */, mojo::Array<uint8_t>::From(value)); } @@ -322,7 +320,7 @@ mojo::Array<mojom::BluetoothPropertyPtr> properties = GetAdapterProperties(type); - arc_bridge_service()->bluetooth_instance()->OnAdapterProperties( + arc_bridge_service()->bluetooth()->instance()->OnAdapterProperties( mojom::BluetoothStatus::SUCCESS, std::move(properties)); } @@ -333,7 +331,7 @@ return; // TODO(smbarber): Implement SetAdapterProperty - arc_bridge_service()->bluetooth_instance()->OnAdapterProperties( + arc_bridge_service()->bluetooth()->instance()->OnAdapterProperties( mojom::BluetoothStatus::FAIL, mojo::Array<mojom::BluetoothPropertyPtr>::New(0)); } @@ -357,7 +355,7 @@ status = mojom::BluetoothStatus::FAIL; } - arc_bridge_service()->bluetooth_instance()->OnRemoteDeviceProperties( + arc_bridge_service()->bluetooth()->instance()->OnRemoteDeviceProperties( status, std::move(remote_addr), std::move(properties)); } @@ -369,7 +367,7 @@ return; // TODO(smbarber): Implement SetRemoteDeviceProperty - arc_bridge_service()->bluetooth_instance()->OnRemoteDeviceProperties( + arc_bridge_service()->bluetooth()->instance()->OnRemoteDeviceProperties( mojom::BluetoothStatus::FAIL, std::move(remote_addr), mojo::Array<mojom::BluetoothPropertyPtr>::New(0)); } @@ -439,7 +437,7 @@ discovery_session_ = std::move(session); - arc_bridge_service()->bluetooth_instance()->OnDiscoveryStateChanged( + arc_bridge_service()->bluetooth()->instance()->OnDiscoveryStateChanged( mojom::BluetoothDiscoveryState::STARTED); SendCachedDevicesFound(); @@ -451,7 +449,7 @@ discovery_session_.reset(); - arc_bridge_service()->bluetooth_instance()->OnDiscoveryStateChanged( + arc_bridge_service()->bluetooth()->instance()->OnDiscoveryStateChanged( mojom::BluetoothDiscoveryState::STOPPED); } @@ -565,7 +563,7 @@ DCHECK(addr); - arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange( + arc_bridge_service()->bluetooth()->instance()->OnLEConnectionStateChange( std::move(addr), connected); } @@ -596,7 +594,7 @@ DCHECK(device); if (device->IsConnected()) { - arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange( + arc_bridge_service()->bluetooth()->instance()->OnLEConnectionStateChange( std::move(remote_addr), true); return; } @@ -621,7 +619,7 @@ DCHECK(device); if (!device->IsConnected()) { - arc_bridge_service()->bluetooth_instance()->OnLEConnectionStateChange( + arc_bridge_service()->bluetooth()->instance()->OnLEConnectionStateChange( std::move(remote_addr), false); return; } @@ -644,7 +642,7 @@ // Call the callback if discovery is completed if (device->IsGattServicesDiscoveryComplete()) { - arc_bridge_service()->bluetooth_instance()->OnSearchComplete( + arc_bridge_service()->bluetooth()->instance()->OnSearchComplete( std::move(remote_addr), mojom::BluetoothGattStatus::GATT_SUCCESS); return; } @@ -770,7 +768,7 @@ } } - arc_bridge_service()->bluetooth_instance()->OnGetGattDB( + arc_bridge_service()->bluetooth()->instance()->OnGetGattDB( std::move(remote_addr), std::move(db)); } @@ -1032,7 +1030,7 @@ if (!HasBluetoothInstance()) return; - arc_bridge_service()->bluetooth_instance()->OnBondStateChanged( + arc_bridge_service()->bluetooth()->instance()->OnBondStateChanged( mojom::BluetoothStatus::SUCCESS, std::move(addr), mojom::BluetoothBondState::BONDING); } @@ -1041,7 +1039,7 @@ if (!HasBluetoothInstance()) return; - arc_bridge_service()->bluetooth_instance()->OnBondStateChanged( + arc_bridge_service()->bluetooth()->instance()->OnBondStateChanged( mojom::BluetoothStatus::SUCCESS, std::move(addr), mojom::BluetoothBondState::BONDED); } @@ -1052,7 +1050,7 @@ if (!HasBluetoothInstance()) return; - arc_bridge_service()->bluetooth_instance()->OnBondStateChanged( + arc_bridge_service()->bluetooth()->instance()->OnBondStateChanged( mojom::BluetoothStatus::FAIL, std::move(addr), mojom::BluetoothBondState::NONE); } @@ -1061,7 +1059,7 @@ if (!HasBluetoothInstance()) return; - arc_bridge_service()->bluetooth_instance()->OnBondStateChanged( + arc_bridge_service()->bluetooth()->instance()->OnBondStateChanged( mojom::BluetoothStatus::SUCCESS, std::move(addr), mojom::BluetoothBondState::NONE); } @@ -1076,7 +1074,7 @@ if (device && device->IsPaired()) { bond_state = mojom::BluetoothBondState::BONDED; } - arc_bridge_service()->bluetooth_instance()->OnBondStateChanged( + arc_bridge_service()->bluetooth()->instance()->OnBondStateChanged( mojom::BluetoothStatus::FAIL, std::move(addr), bond_state); } @@ -1290,23 +1288,23 @@ mojo::Array<mojom::BluetoothPropertyPtr> properties = GetDeviceProperties(mojom::BluetoothPropertyType::ALL, device); - arc_bridge_service()->bluetooth_instance()->OnDeviceFound( + arc_bridge_service()->bluetooth()->instance()->OnDeviceFound( std::move(properties)); - if (arc_bridge_service()->bluetooth_version() >= kMinBtleVersion) { + if (arc_bridge_service()->bluetooth()->version() >= kMinBtleVersion) { mojom::BluetoothAddressPtr addr = mojom::BluetoothAddress::From(device->GetAddress()); int rssi = device->GetInquiryRSSI(); mojo::Array<mojom::BluetoothAdvertisingDataPtr> adv_data = GetAdvertisingData(device); - arc_bridge_service()->bluetooth_instance()->OnLEDeviceFound( + arc_bridge_service()->bluetooth()->instance()->OnLEDeviceFound( std::move(addr), rssi, std::move(adv_data)); } } } bool ArcBluetoothBridge::HasBluetoothInstance() const { - if (!arc_bridge_service()->bluetooth_instance()) { + if (!arc_bridge_service()->bluetooth()->instance()) { LOG(WARNING) << "no Bluetooth instance available"; return false; } @@ -1327,17 +1325,17 @@ mojo::Array<mojom::BluetoothPropertyPtr> properties = GetDeviceProperties(mojom::BluetoothPropertyType::ALL, device); - arc_bridge_service()->bluetooth_instance()->OnDeviceFound( + arc_bridge_service()->bluetooth()->instance()->OnDeviceFound( std::move(properties)); mojom::BluetoothAddressPtr addr = mojom::BluetoothAddress::From(device->GetAddress()); - if (arc_bridge_service()->bluetooth_version() >= kMinBtleVersion) { + if (arc_bridge_service()->bluetooth()->version() >= kMinBtleVersion) { int rssi = device->GetInquiryRSSI(); mojo::Array<mojom::BluetoothAdvertisingDataPtr> adv_data = GetAdvertisingData(device); - arc_bridge_service()->bluetooth_instance()->OnLEDeviceFound( + arc_bridge_service()->bluetooth()->instance()->OnLEDeviceFound( addr->Clone(), rssi, std::move(adv_data)); } @@ -1352,8 +1350,8 @@ } bool ArcBluetoothBridge::CheckBluetoothInstanceVersion( - int32_t version_need) const { - int32_t version = arc_bridge_service()->bluetooth_version(); + uint32_t version_need) const { + uint32_t version = arc_bridge_service()->bluetooth()->version(); if (version >= version_need) return true; LOG(WARNING) << "Bluetooth instance is too old (version " << version
diff --git a/components/arc/bluetooth/arc_bluetooth_bridge.h b/components/arc/bluetooth/arc_bluetooth_bridge.h index cebf74f7..c305661c 100644 --- a/components/arc/bluetooth/arc_bluetooth_bridge.h +++ b/components/arc/bluetooth/arc_bluetooth_bridge.h
@@ -16,6 +16,7 @@ #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" #include "components/arc/common/bluetooth.mojom.h" +#include "components/arc/instance_holder.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/bluetooth_device.h" @@ -32,7 +33,7 @@ class ArcBluetoothBridge : public ArcService, - public ArcBridgeService::Observer, + public InstanceHolder<mojom::BluetoothInstance>::Observer, public device::BluetoothAdapter::Observer, public device::BluetoothAdapterFactory::AdapterCallback, public mojom::BluetoothHost { @@ -40,8 +41,9 @@ explicit ArcBluetoothBridge(ArcBridgeService* bridge_service); ~ArcBluetoothBridge() override; - // Overridden from ArcBridgeService::Observer: - void OnBluetoothInstanceReady() override; + // Overridden from + // InstanceHolder<mojom::BluetoothInstance>::Observer: + void OnInstanceReady() override; void OnAdapterInitialized(scoped_refptr<device::BluetoothAdapter> adapter); @@ -264,7 +266,7 @@ void SendCachedDevicesFound() const; bool HasBluetoothInstance() const; - bool CheckBluetoothInstanceVersion(int32_t version_need) const; + bool CheckBluetoothInstanceVersion(uint32_t version_need) const; template <class T> T* FindGattObjectFromUuid(const std::vector<T*> objs,
diff --git a/components/arc/clipboard/arc_clipboard_bridge.cc b/components/arc/clipboard/arc_clipboard_bridge.cc index aa0dbe4..2a6d735 100644 --- a/components/arc/clipboard/arc_clipboard_bridge.cc +++ b/components/arc/clipboard/arc_clipboard_bridge.cc
@@ -29,23 +29,22 @@ ArcClipboardBridge::ArcClipboardBridge(ArcBridgeService* bridge_service) : ArcService(bridge_service), binding_(this) { - arc_bridge_service()->AddObserver(this); + arc_bridge_service()->clipboard()->AddObserver(this); } ArcClipboardBridge::~ArcClipboardBridge() { DCHECK(CalledOnValidThread()); - arc_bridge_service()->RemoveObserver(this); + arc_bridge_service()->clipboard()->RemoveObserver(this); } -void ArcClipboardBridge::OnClipboardInstanceReady() { +void ArcClipboardBridge::OnInstanceReady() { mojom::ClipboardInstance* clipboard_instance = - arc_bridge_service()->clipboard_instance(); + arc_bridge_service()->clipboard()->instance(); if (!clipboard_instance) { LOG(ERROR) << "OnClipboardInstanceReady called, " << "but no clipboard instance found"; return; } - clipboard_instance->Init(binding_.CreateInterfacePtrAndBind()); } @@ -63,7 +62,7 @@ clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &text); mojom::ClipboardInstance* clipboard_instance = - arc_bridge_service()->clipboard_instance(); + arc_bridge_service()->clipboard()->instance(); clipboard_instance->OnGetTextContent(ConvertString16ToMojoString(text)); }
diff --git a/components/arc/clipboard/arc_clipboard_bridge.h b/components/arc/clipboard/arc_clipboard_bridge.h index 1980b69..97a569d 100644 --- a/components/arc/clipboard/arc_clipboard_bridge.h +++ b/components/arc/clipboard/arc_clipboard_bridge.h
@@ -10,19 +10,21 @@ #include "base/macros.h" #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/instance_holder.h" #include "mojo/public/cpp/bindings/binding.h" namespace arc { -class ArcClipboardBridge : public ArcService, - public ArcBridgeService::Observer, - public mojom::ClipboardHost { +class ArcClipboardBridge + : public ArcService, + public InstanceHolder<mojom::ClipboardInstance>::Observer, + public mojom::ClipboardHost { public: explicit ArcClipboardBridge(ArcBridgeService* bridge_service); ~ArcClipboardBridge() override; - // ArcBridgeService::Observer overrides. - void OnClipboardInstanceReady() override; + // InstanceHolder<mojom::ClipboardInstance>::Observer overrides. + void OnInstanceReady() override; // mojom::ClipboardHost overrides. void SetTextContent(const mojo::String& text) override;
diff --git a/components/arc/common/intent_helper.mojom b/components/arc/common/intent_helper.mojom index b8fb48ae..17d12e2 100644 --- a/components/arc/common/intent_helper.mojom +++ b/components/arc/common/intent_helper.mojom
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Next MinVersion: 10 +// Next MinVersion: 11 module arc.mojom; @@ -15,10 +15,30 @@ SEND_MULTIPLE, }; +[Extensible] +enum PatternType { + PATTERN_LITERAL, + PATTERN_PREFIX, + PATTERN_SIMPLE_GLOB, +}; + +struct PatternMatcher { + string pattern; + PatternType type; +}; + +struct AuthorityEntry { + string host; + int32 port; +}; + struct IntentFilter { array<string> actions; array<string> categories; array<string> data_schemes; + [MinVersion=10] array<AuthorityEntry>? data_authorities; + [MinVersion=10] array<PatternMatcher>? data_paths; + [MinVersion=10] array<PatternMatcher>? data_scheme_specific_parts; }; // Describes a package that can handle a URL.
diff --git a/components/arc/crash_collector/arc_crash_collector_bridge.cc b/components/arc/crash_collector/arc_crash_collector_bridge.cc index 3095304..8557308a 100644 --- a/components/arc/crash_collector/arc_crash_collector_bridge.cc +++ b/components/arc/crash_collector/arc_crash_collector_bridge.cc
@@ -14,26 +14,25 @@ #include "mojo/edk/embedder/embedder.h" namespace { - const char kCrashReporterPath[] = "/sbin/crash_reporter"; - } namespace arc { ArcCrashCollectorBridge::ArcCrashCollectorBridge(ArcBridgeService* bridge) : ArcService(bridge), binding_(this) { - arc_bridge_service()->AddObserver(this); + arc_bridge_service()->crash_collector()->AddObserver(this); } ArcCrashCollectorBridge::~ArcCrashCollectorBridge() { - arc_bridge_service()->RemoveObserver(this); + arc_bridge_service()->crash_collector()->RemoveObserver(this); } -void ArcCrashCollectorBridge::OnCrashCollectorInstanceReady() { +void ArcCrashCollectorBridge::OnInstanceReady() { mojom::CrashCollectorHostPtr host_ptr; binding_.Bind(mojo::GetProxy(&host_ptr)); - arc_bridge_service()->crash_collector_instance()->Init(std::move(host_ptr)); + arc_bridge_service()->crash_collector()->instance()->Init( + std::move(host_ptr)); } void ArcCrashCollectorBridge::DumpCrash(const mojo::String& type, @@ -42,19 +41,16 @@ mojo::edk::PassWrappedPlatformHandle(pipe.get().value(), &handle); base::FileHandleMappingVector fd_map = { - std::make_pair(handle.get().handle, STDIN_FILENO) - }; + std::make_pair(handle.get().handle, STDIN_FILENO)}; base::LaunchOptions options; options.fds_to_remap = &fd_map; - auto process = base::LaunchProcess({ - kCrashReporterPath, - "--arc_java_crash=" + type.get(), - "--arc_device=" + device_, - "--arc_board=" + board_, - "--arc_cpu_abi=" + cpu_abi_ - }, options); + auto process = + base::LaunchProcess({kCrashReporterPath, "--arc_java_crash=" + type.get(), + "--arc_device=" + device_, "--arc_board=" + board_, + "--arc_cpu_abi=" + cpu_abi_}, + options); int exit_code; if (!process.WaitForExit(&exit_code)) {
diff --git a/components/arc/crash_collector/arc_crash_collector_bridge.h b/components/arc/crash_collector/arc_crash_collector_bridge.h index 4446bd3..cb23475 100644 --- a/components/arc/crash_collector/arc_crash_collector_bridge.h +++ b/components/arc/crash_collector/arc_crash_collector_bridge.h
@@ -10,20 +10,22 @@ #include "base/macros.h" #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/instance_holder.h" #include "mojo/public/cpp/bindings/binding.h" namespace arc { // Relays dumps for non-native ARC crashes to the crash reporter in Chrome OS. -class ArcCrashCollectorBridge : public ArcService, - public ArcBridgeService::Observer, - public mojom::CrashCollectorHost { +class ArcCrashCollectorBridge + : public ArcService, + public InstanceHolder<mojom::CrashCollectorInstance>::Observer, + public mojom::CrashCollectorHost { public: explicit ArcCrashCollectorBridge(ArcBridgeService* bridge); ~ArcCrashCollectorBridge() override; - // ArcBridgeService::Observer overrides. - void OnCrashCollectorInstanceReady() override; + // InstanceHolder<mojom::CrashCollectorInstance>::Observer overrides. + void OnInstanceReady() override; // mojom::CrashCollectorHost overrides. void DumpCrash(const mojo::String& type, mojo::ScopedHandle pipe) override;
diff --git a/components/arc/ime/arc_ime_bridge_impl.cc b/components/arc/ime/arc_ime_bridge_impl.cc index b575a4a..001f26e 100644 --- a/components/arc/ime/arc_ime_bridge_impl.cc +++ b/components/arc/ime/arc_ime_bridge_impl.cc
@@ -64,9 +64,10 @@ arc::mojom::CompositionSegment::New(); segment->start_offset = underline.start_offset; segment->end_offset = underline.end_offset; - segment->emphasized = (underline.thick || - (composition.selection.start() == underline.start_offset && - composition.selection.end() == underline.end_offset)); + segment->emphasized = + (underline.thick || + (composition.selection.start() == underline.start_offset && + composition.selection.end() == underline.end_offset)); segments.push_back(std::move(segment)); } return segments; @@ -77,20 +78,21 @@ ArcImeBridgeImpl::ArcImeBridgeImpl(Delegate* delegate, ArcBridgeService* bridge_service) : binding_(this), delegate_(delegate), bridge_service_(bridge_service) { - bridge_service_->AddObserver(this); + bridge_service_->ime()->AddObserver(this); } ArcImeBridgeImpl::~ArcImeBridgeImpl() { - bridge_service_->RemoveObserver(this); + bridge_service_->ime()->RemoveObserver(this); } -void ArcImeBridgeImpl::OnImeInstanceReady() { - bridge_service_->ime_instance()->Init(binding_.CreateInterfacePtrAndBind()); +void ArcImeBridgeImpl::OnInstanceReady() { + bridge_service_->ime()->instance()->Init( + binding_.CreateInterfacePtrAndBind()); } void ArcImeBridgeImpl::SendSetCompositionText( const ui::CompositionText& composition) { - mojom::ImeInstance* ime_instance = bridge_service_->ime_instance(); + mojom::ImeInstance* ime_instance = bridge_service_->ime()->instance(); if (!ime_instance) { LOG(ERROR) << "ArcImeInstance method called before being ready."; return; @@ -101,7 +103,7 @@ } void ArcImeBridgeImpl::SendConfirmCompositionText() { - mojom::ImeInstance* ime_instance = bridge_service_->ime_instance(); + mojom::ImeInstance* ime_instance = bridge_service_->ime()->instance(); if (!ime_instance) { LOG(ERROR) << "ArcImeInstance method called before being ready."; return; @@ -111,7 +113,7 @@ } void ArcImeBridgeImpl::SendInsertText(const base::string16& text) { - mojom::ImeInstance* ime_instance = bridge_service_->ime_instance(); + mojom::ImeInstance* ime_instance = bridge_service_->ime()->instance(); if (!ime_instance) { LOG(ERROR) << "ArcImeInstance method called before being ready."; return; @@ -122,12 +124,12 @@ void ArcImeBridgeImpl::SendOnKeyboardBoundsChanging( const gfx::Rect& new_bounds) { - mojom::ImeInstance* ime_instance = bridge_service_->ime_instance(); + mojom::ImeInstance* ime_instance = bridge_service_->ime()->instance(); if (!ime_instance) { LOG(ERROR) << "ArcImeInstance method called before being ready."; return; } - if (bridge_service_->ime_version() < + if (bridge_service_->ime()->version() < kMinVersionForOnKeyboardsBoundsChanging) { LOG(ERROR) << "ArcImeInstance is too old for OnKeyboardsBoundsChanging."; return; @@ -138,12 +140,12 @@ void ArcImeBridgeImpl::SendExtendSelectionAndDelete( size_t before, size_t after) { - mojom::ImeInstance* ime_instance = bridge_service_->ime_instance(); + mojom::ImeInstance* ime_instance = bridge_service_->ime()->instance(); if (!ime_instance) { LOG(ERROR) << "ArcImeInstance method called before being ready."; return; } - if (bridge_service_->ime_version() < + if (bridge_service_->ime()->version() < kMinVersionForExtendSelectionAndDelete) { LOG(ERROR) << "ArcImeInstance is too old for ExtendSelectionAndDelete."; return; @@ -157,11 +159,9 @@ } void ArcImeBridgeImpl::OnCursorRectChanged(arc::mojom::CursorRectPtr rect) { - delegate_->OnCursorRectChanged(gfx::Rect( - rect->left, - rect->top, - rect->right - rect->left, - rect->bottom - rect->top)); + delegate_->OnCursorRectChanged(gfx::Rect(rect->left, rect->top, + rect->right - rect->left, + rect->bottom - rect->top)); } void ArcImeBridgeImpl::OnCancelComposition() {
diff --git a/components/arc/ime/arc_ime_bridge_impl.h b/components/arc/ime/arc_ime_bridge_impl.h index 046cfb8..2246e52 100644 --- a/components/arc/ime/arc_ime_bridge_impl.h +++ b/components/arc/ime/arc_ime_bridge_impl.h
@@ -10,6 +10,7 @@ #include "components/arc/arc_bridge_service.h" #include "components/arc/common/ime.mojom.h" #include "components/arc/ime/arc_ime_bridge.h" +#include "components/arc/instance_holder.h" #include "mojo/public/cpp/bindings/binding.h" #include "ui/base/ime/text_input_type.h" #include "ui/gfx/geometry/rect.h" @@ -24,13 +25,13 @@ // Chromium and the ARC container. class ArcImeBridgeImpl : public ArcImeBridge, public mojom::ImeHost, - public ArcBridgeService::Observer { + public InstanceHolder<mojom::ImeInstance>::Observer { public: ArcImeBridgeImpl(Delegate* delegate, ArcBridgeService* bridge_service); ~ArcImeBridgeImpl() override; - // arc::ArcBridgeService::Observer overrides: - void OnImeInstanceReady() override; + // arc::InstanceHolder<mojom::ImeInstance>::Observer overrides: + void OnInstanceReady() override; // ArcImeBridge overrides: void SendSetCompositionText(const ui::CompositionText& composition) override;
diff --git a/components/arc/instance_holder.h b/components/arc/instance_holder.h new file mode 100644 index 0000000..2d22f759b --- /dev/null +++ b/components/arc/instance_holder.h
@@ -0,0 +1,127 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_ARC_INSTANCE_HOLDER_H_ +#define COMPONENTS_ARC_INSTANCE_HOLDER_H_ + +#include <utility> + +#include "base/bind.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "base/threading/thread_checker.h" +#include "mojo/public/cpp/bindings/interface_ptr.h" + +namespace arc { + +// Holds a Mojo instance+version pair. This also allows for listening for state +// changes for the particular instance. T should be a Mojo interface type +// (arc::mojom::XxxInstance). +template <typename T> +class InstanceHolder { + public: + // Notifies about connection events for individual instances. + class Observer { + public: + // Called once the instance is ready. + virtual void OnInstanceReady() {} + + // Called when the connection to the instance is closed. + virtual void OnInstanceClosed() {} + + protected: + virtual ~Observer() = default; + }; + + InstanceHolder() : weak_factory_(this) {} + + // Gets the Mojo interface for all the instance services. This will return + // nullptr if that particular service is not ready yet. Use an Observer if you + // want to be notified when this is ready. This can only be called on the + // thread that this class was created on. + T* instance() const { return raw_ptr_; } + uint32_t version() const { return version_; } + + // Adds or removes observers. This can only be called on the thread that this + // class was created on. RemoveObserver does nothing if |observer| is not in + // the list. + void AddObserver(Observer* observer) { + DCHECK(thread_checker_.CalledOnValidThread()); + observer_list_.AddObserver(observer); + + if (instance()) + observer->OnInstanceReady(); + } + + void RemoveObserver(Observer* observer) { + DCHECK(thread_checker_.CalledOnValidThread()); + observer_list_.RemoveObserver(observer); + } + + // Called when the channel is closed. + void CloseChannel() { + if (!ptr_) + return; + + ptr_.reset(); + raw_ptr_ = nullptr; + version_ = 0; + FOR_EACH_OBSERVER(Observer, observer_list_, OnInstanceClosed()); + } + + // Sets the interface pointer to |ptr|, once the version is determined. This + // will eventually invoke SetInstance(), which will notify the observers. + void OnInstanceReady(mojo::InterfacePtr<T> ptr) { + temporary_ptr_ = std::move(ptr); + temporary_ptr_.QueryVersion(base::Bind(&InstanceHolder<T>::OnVersionReady, + weak_factory_.GetWeakPtr())); + } + + // This method is not intended to be called directly. Normally it is called by + // OnInstanceReady once the version of the instance is determined, but it is + // also exposed so that tests can directly inject a raw pointer+version + // combination. + void SetInstance(T* raw_ptr, uint32_t raw_version = T::Version_) { + raw_ptr_ = raw_ptr; + version_ = raw_version; + FOR_EACH_OBSERVER(Observer, observer_list_, OnInstanceReady()); + } + + private: + void OnVersionReady(uint32_t version) { + ptr_ = std::move(temporary_ptr_); + ptr_.set_connection_error_handler(base::Bind( + &InstanceHolder<T>::CloseChannel, weak_factory_.GetWeakPtr())); + SetInstance(ptr_.get(), version); + } + + // These two are copies of the contents of ptr_. They are provided here just + // so that tests can provide non-mojo implementations. + T* raw_ptr_ = nullptr; + uint32_t version_ = 0; + + mojo::InterfacePtr<T> ptr_; + + // Temporary Mojo interfaces. After a Mojo interface pointer has been + // received from the other endpoint, we still need to asynchronously query its + // version. While that is going on, we should still return nullptr on the + // instance() function. + // To keep the instance() functions being trivial, store the instance pointer + // in a temporary variable to avoid losing its reference. + mojo::InterfacePtr<T> temporary_ptr_; + + base::ThreadChecker thread_checker_; + base::ObserverList<Observer> observer_list_; + + // This needs to be the last member in order to cancel all inflight callbacks + // before destroying any other members. + base::WeakPtrFactory<InstanceHolder<T>> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(InstanceHolder<T>); +}; + +} // namespace arc + +#endif // COMPONENTS_ARC_INSTANCE_HOLDER_H_
diff --git a/components/arc/intent_helper/activity_icon_loader.cc b/components/arc/intent_helper/activity_icon_loader.cc index 8a24fe1..5248f759 100644 --- a/components/arc/intent_helper/activity_icon_loader.cc +++ b/components/arc/intent_helper/activity_icon_loader.cc
@@ -37,13 +37,13 @@ return nullptr; } mojom::IntentHelperInstance* intent_helper_instance = - bridge_service->intent_helper_instance(); + bridge_service->intent_helper()->instance(); if (!intent_helper_instance) { VLOG(2) << "ARC intent helper instance is not ready."; *out_error_code = ActivityIconLoader::GetResult::FAILED_ARC_NOT_READY; return nullptr; } - if (bridge_service->intent_helper_version() < kMinInstanceVersion) { + if (bridge_service->intent_helper()->version() < kMinInstanceVersion) { VLOG(1) << "ARC intent helper instance is too old."; *out_error_code = ActivityIconLoader::GetResult::FAILED_ARC_NOT_SUPPORTED; return nullptr;
diff --git a/components/arc/intent_helper/arc_intent_helper_bridge.cc b/components/arc/intent_helper/arc_intent_helper_bridge.cc index e4a2660..4709817 100644 --- a/components/arc/intent_helper/arc_intent_helper_bridge.cc +++ b/components/arc/intent_helper/arc_intent_helper_bridge.cc
@@ -39,22 +39,22 @@ set_wallpaper_delegate_(std::move(set_wallpaper_delegate)), activity_resolver_(activity_resolver) { DCHECK(thread_checker_.CalledOnValidThread()); - arc_bridge_service()->AddObserver(this); + arc_bridge_service()->intent_helper()->AddObserver(this); } ArcIntentHelperBridge::~ArcIntentHelperBridge() { DCHECK(thread_checker_.CalledOnValidThread()); - arc_bridge_service()->RemoveObserver(this); + arc_bridge_service()->intent_helper()->RemoveObserver(this); } -void ArcIntentHelperBridge::OnIntentHelperInstanceReady() { +void ArcIntentHelperBridge::OnInstanceReady() { DCHECK(thread_checker_.CalledOnValidThread()); ash::Shell::GetInstance()->set_link_handler_model_factory(this); - arc_bridge_service()->intent_helper_instance()->Init( + arc_bridge_service()->intent_helper()->instance()->Init( binding_.CreateInterfacePtrAndBind()); } -void ArcIntentHelperBridge::OnIntentHelperInstanceClosed() { +void ArcIntentHelperBridge::OnInstanceClosed() { DCHECK(thread_checker_.CalledOnValidThread()); ash::Shell::GetInstance()->set_link_handler_model_factory(nullptr); }
diff --git a/components/arc/intent_helper/arc_intent_helper_bridge.h b/components/arc/intent_helper/arc_intent_helper_bridge.h index 4adbe47..a48e90e 100644 --- a/components/arc/intent_helper/arc_intent_helper_bridge.h +++ b/components/arc/intent_helper/arc_intent_helper_bridge.h
@@ -15,6 +15,7 @@ #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" #include "components/arc/common/intent_helper.mojom.h" +#include "components/arc/instance_holder.h" #include "mojo/public/cpp/bindings/binding.h" namespace ash { @@ -30,10 +31,11 @@ class SetWallpaperDelegate; // Receives intents from ARC. -class ArcIntentHelperBridge : public ArcService, - public ArcBridgeService::Observer, - public mojom::IntentHelperHost, - public ash::LinkHandlerModelFactory { +class ArcIntentHelperBridge + : public ArcService, + public InstanceHolder<mojom::IntentHelperInstance>::Observer, + public mojom::IntentHelperHost, + public ash::LinkHandlerModelFactory { public: ArcIntentHelperBridge( ArcBridgeService* bridge_service, @@ -42,9 +44,9 @@ const scoped_refptr<LocalActivityResolver>& activity_resolver); ~ArcIntentHelperBridge() override; - // ArcBridgeService::Observer - void OnIntentHelperInstanceReady() override; - void OnIntentHelperInstanceClosed() override; + // InstanceHolder<mojom::IntentHelperInstance>::Observer + void OnInstanceReady() override; + void OnInstanceClosed() override; // arc::mojom::IntentHelperHost void OnIconInvalidated(const mojo::String& package_name) override;
diff --git a/components/arc/intent_helper/intent_filter.cc b/components/arc/intent_helper/intent_filter.cc new file mode 100644 index 0000000..1a0f79c --- /dev/null +++ b/components/arc/intent_helper/intent_filter.cc
@@ -0,0 +1,226 @@ +// 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 "components/arc/intent_helper/intent_filter.h" + +#include "base/compiler_specific.h" +#include "base/strings/string_util.h" +#include "url/gurl.h" + +namespace arc { + +IntentFilter::IntentFilter(const mojom::IntentFilterPtr& mojo_intent_filter) { + for (const mojom::AuthorityEntryPtr& authorityptr : + mojo_intent_filter->data_authorities) { + authorities_.emplace_back(authorityptr); + } + for (const mojom::PatternMatcherPtr& pattern : + mojo_intent_filter->data_paths) { + paths_.emplace_back(pattern); + } + for (const mojom::PatternMatcherPtr& pattern : + mojo_intent_filter->data_scheme_specific_parts) { + scheme_specific_parts_.emplace_back(pattern); + } +} + +IntentFilter::IntentFilter(const IntentFilter& other) = default; + +IntentFilter::~IntentFilter() = default; + +// Logically, this maps to IntentFilter#match, but this code only deals with +// view intents for http/https URLs and so it really only implements the +// #matchData part of the match code. +bool IntentFilter::match(const GURL& url) const { + // Chrome-side code only receives view intents for http/https URLs, so this + // match code really only implements the matchData part of the android + // IntentFilter class. + if (!url.SchemeIsHTTPOrHTTPS()) { + return false; + } + + if (!scheme_specific_parts_.empty() && hasDataSchemeSpecificPart(url)) { + return true; + } + + // If there isn't any matching ssp, we need to match an authority. + if (!authorities_.empty()) { + return matchDataAuthority(url) && (paths_.empty() || hasDataPath(url)); + } + + return false; +} + +// Transcribed from android's IntentFilter#hasDataSchemeSpecificPart. +bool IntentFilter::hasDataSchemeSpecificPart(const GURL& url) const { + // The scheme-specific-part is the content of the URL minus the ref fragment. + GURL::Replacements replacements; + replacements.ClearRef(); + const std::string ssp = url.ReplaceComponents(replacements).GetContent(); + + for (const PatternMatcher& pattern : scheme_specific_parts_) { + if (pattern.match(ssp)) { + return true; + } + } + return false; +} + +// Transcribed from android's IntentFilter#hasDataPath. +bool IntentFilter::hasDataPath(const GURL& url) const { + const std::string path = url.path(); + for (const PatternMatcher& pattern : paths_) { + if (pattern.match(path)) { + return true; + } + } + return false; +} + +// Transcribed from android's IntentFilter#matchDataAuthority. +bool IntentFilter::matchDataAuthority(const GURL& url) const { + for (const AuthorityEntry& authority : authorities_) { + if (authority.match(url)) { + return true; + } + } + return false; +} + +IntentFilter::AuthorityEntry::AuthorityEntry( + const mojom::AuthorityEntryPtr& entry) + : host_(entry->host.get()), port_(entry->port) { + // Wildcards are only allowed at the front of the host string. + wild_ = !host_.empty() && host_[0] == '*'; + if (wild_) { + host_ = host_.substr(1); + } + + // TODO: Not i18n-friendly. Figure out how to correctly deal with IDNs. + host_ = base::ToLowerASCII(host_); +} + +// Transcribed from android's IntentFilter.AuthorityEntry#match. +bool IntentFilter::AuthorityEntry::match(const GURL& url) const { + if (!url.has_host()) + return false; + + if (port_ >= 0 && port_ != url.IntPort()) { + return false; + } + + if (wild_) { + return base::EndsWith(url.host_piece(), host_, + base::CompareCase::INSENSITIVE_ASCII); + } else { + // TODO: Not i18n-friendly. Figure out how to correctly deal with IDNs. + return host_ == base::ToLowerASCII(url.host_piece()); + } +} + +IntentFilter::PatternMatcher::PatternMatcher( + const mojom::PatternMatcherPtr& pattern) + : pattern_(pattern->pattern.get()), match_type_(pattern->type) {} + +// Transcribed from android's PatternMatcher#matchPattern. +bool IntentFilter::PatternMatcher::match(const std::string& str) const { + if (str.empty()) { + return false; + } + switch (match_type_) { + case mojom::PatternType::PATTERN_LITERAL: + return str == pattern_; + case mojom::PatternType::PATTERN_PREFIX: + return base::StartsWith(str, pattern_, + base::CompareCase::INSENSITIVE_ASCII); + case mojom::PatternType::PATTERN_SIMPLE_GLOB: + return matchGlob(str); + } + + return false; +} + +// Transcribed from android's PatternMatcher#matchPattern. +bool IntentFilter::PatternMatcher::matchGlob(const std::string& str) const { +#define GET_CHAR(s, i) (UNLIKELY(i >= s.length())) ? '\0' : s[i] + + const size_t NP = pattern_.length(); + const size_t NS = str.length(); + if (NP == 0) { + return NS == 0; + } + size_t ip = 0, is = 0; + char nextChar = GET_CHAR(pattern_, 0); + while (ip < NP && is < NS) { + char c = nextChar; + ++ip; + nextChar = GET_CHAR(pattern_, ip); + const bool escaped = (c == '\\'); + if (escaped) { + c = nextChar; + ++ip; + nextChar = GET_CHAR(pattern_, ip); + } + if (nextChar == '*') { + if (!escaped && c == '.') { + if (ip >= (NP - 1)) { + // At the end with a pattern match + return true; + } + ++ip; + nextChar = GET_CHAR(pattern_, ip); + // Consume everything until the next char in the pattern is found. + if (nextChar == '\\') { + ++ip; + nextChar = GET_CHAR(pattern_, ip); + } + do { + if (GET_CHAR(str, is) == nextChar) { + break; + } + ++is; + } while (is < NS); + if (is == NS) { + // Next char in the pattern didn't exist in the match. + return false; + } + ++ip; + nextChar = GET_CHAR(pattern_, ip); + ++is; + } else { + // Consume only characters matching the one before '*'. + do { + if (GET_CHAR(str, is) != c) { + break; + } + ++is; + } while (is < NS); + ++ip; + nextChar = GET_CHAR(pattern_, ip); + } + } else { + if (c != '.' && GET_CHAR(str, is) != c) + return false; + ++is; + } + } + + if (ip >= NP && is >= NS) { + // Reached the end of both strings + return true; + } + + // One last check: we may have finished the match string, but still have a + // '.*' at the end of the pattern, which is still a match. + if (ip == NP - 2 && GET_CHAR(pattern_, ip) == '.' && + GET_CHAR(pattern_, ip + 1) == '*') { + return true; + } + + return false; + +#undef GET_CHAR +} + +} // namespace arc
diff --git a/components/arc/intent_helper/intent_filter.h b/components/arc/intent_helper/intent_filter.h new file mode 100644 index 0000000..7136657 --- /dev/null +++ b/components/arc/intent_helper/intent_filter.h
@@ -0,0 +1,66 @@ +// 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 COMPONENTS_ARC_INTENT_HELPER_INTENT_FILTER_H_ +#define COMPONENTS_ARC_INTENT_HELPER_INTENT_FILTER_H_ + +#include <string> +#include <vector> + +#include "components/arc/common/intent_helper.mojom.h" + +class GURL; + +namespace arc { + +// A chrome-side implementation of Android's IntentFilter class. This is used +// to approximate the intent filtering and determine whether a given URL is +// likely to be handled by any android-side apps, prior to making expensive IPC +// calls. +class IntentFilter { + public: + explicit IntentFilter(const mojom::IntentFilterPtr& mojo_intent_filter); + IntentFilter(const IntentFilter& other); + ~IntentFilter(); + + bool match(const GURL& url) const; + + private: + // A helper class for handling matching of the host part of the URL. + class AuthorityEntry { + public: + explicit AuthorityEntry(const mojom::AuthorityEntryPtr& entry); + bool match(const GURL& url) const; + + private: + std::string host_; + bool wild_; + int port_; + }; + + // A helper class for handling matching of various patterns in the URL. + class PatternMatcher { + public: + explicit PatternMatcher(const mojom::PatternMatcherPtr& pattern); + bool match(const std::string& match) const; + + private: + bool matchGlob(const std::string& match) const; + + std::string pattern_; + mojom::PatternType match_type_; + }; + + bool matchDataAuthority(const GURL& url) const; + bool hasDataPath(const GURL& url) const; + bool hasDataSchemeSpecificPart(const GURL& url) const; + + std::vector<AuthorityEntry> authorities_; + std::vector<PatternMatcher> paths_; + std::vector<PatternMatcher> scheme_specific_parts_; +}; + +} // namespace arc + +#endif // COMPONENTS_ARC_INTENT_HELPER_INTENT_FILTER_H_
diff --git a/components/arc/intent_helper/link_handler_model_impl.cc b/components/arc/intent_helper/link_handler_model_impl.cc index 70806f6..9577901 100644 --- a/components/arc/intent_helper/link_handler_model_impl.cc +++ b/components/arc/intent_helper/link_handler_model_impl.cc
@@ -93,12 +93,12 @@ return nullptr; } mojom::IntentHelperInstance* intent_helper_instance = - bridge_service->intent_helper_instance(); + bridge_service->intent_helper()->instance(); if (!intent_helper_instance) { DLOG(WARNING) << "ARC intent helper instance is not ready."; return nullptr; } - if (bridge_service->intent_helper_version() < kMinInstanceVersion) { + if (bridge_service->intent_helper()->version() < kMinInstanceVersion) { DLOG(WARNING) << "ARC intent helper instance is too old."; return nullptr; }
diff --git a/components/arc/intent_helper/local_activity_resolver.cc b/components/arc/intent_helper/local_activity_resolver.cc index c47301b..b5905439 100644 --- a/components/arc/intent_helper/local_activity_resolver.cc +++ b/components/arc/intent_helper/local_activity_resolver.cc
@@ -6,15 +6,6 @@ #include "url/gurl.h" -namespace { - -constexpr char kIntentActionView[] = "android.intent.action.VIEW"; -constexpr char kIntentCategoryBrowsable[] = "android.intent.category.BROWSABLE"; -constexpr char kSchemeHttp[] = "http"; -constexpr char kSchemeHttps[] = "https"; - -} // namespace - namespace arc { LocalActivityResolver::LocalActivityResolver() = default; @@ -27,11 +18,8 @@ return true; } - for (const mojom::IntentFilterPtr& filter : intent_filters_) { - if (IsRelevantIntentFilter(filter)) { - // For now err on the side of caution and let Android - // handle cases where there are possible matching intent - // filters. + for (const IntentFilter& filter : intent_filters_) { + if (filter.match(url)) { return false; } } @@ -41,48 +29,11 @@ } void LocalActivityResolver::UpdateIntentFilters( - mojo::Array<mojom::IntentFilterPtr> intent_filters) { - intent_filters_ = std::move(intent_filters); -} - -bool LocalActivityResolver::IsRelevantIntentFilter( - const mojom::IntentFilterPtr& intent_filter) { - return FilterHasViewAction(intent_filter) && - FilterCategoryIsBrowsable(intent_filter) && - FilterHandlesWebSchemes(intent_filter); -} - -bool LocalActivityResolver::FilterHasViewAction( - const mojom::IntentFilterPtr& intent_filter) { - for (const mojo::String& action : intent_filter->actions) { - if (action == kIntentActionView) { - return true; - } + mojo::Array<mojom::IntentFilterPtr> mojo_intent_filters) { + intent_filters_.clear(); + for (mojom::IntentFilterPtr& mojo_filter : mojo_intent_filters) { + intent_filters_.emplace_back(mojo_filter); } - - return false; -} - -bool LocalActivityResolver::FilterCategoryIsBrowsable( - const mojom::IntentFilterPtr& intent_filter) { - for (const mojo::String& category : intent_filter->categories) { - if (category == kIntentCategoryBrowsable) { - return true; - } - } - - return false; -} - -bool LocalActivityResolver::FilterHandlesWebSchemes( - const mojom::IntentFilterPtr& intent_filter) { - for (const mojo::String& scheme : intent_filter->data_schemes) { - if (scheme == kSchemeHttp || scheme == kSchemeHttps) { - return true; - } - } - - return false; } } // namespace arc
diff --git a/components/arc/intent_helper/local_activity_resolver.h b/components/arc/intent_helper/local_activity_resolver.h index ec076253..2033b7744 100644 --- a/components/arc/intent_helper/local_activity_resolver.h +++ b/components/arc/intent_helper/local_activity_resolver.h
@@ -2,12 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_ARC_INTENT_HELPER_LOCAL_ACTIVITY_HELPER_H_ -#define COMPONENTS_ARC_INTENT_HELPER_LOCAL_ACTIVITY_HELPER_H_ +#ifndef COMPONENTS_ARC_INTENT_HELPER_LOCAL_ACTIVITY_RESOLVER_H_ +#define COMPONENTS_ARC_INTENT_HELPER_LOCAL_ACTIVITY_RESOLVER_H_ + +#include <vector> #include "base/macros.h" #include "base/memory/ref_counted.h" #include "components/arc/common/intent_helper.mojom.h" +#include "components/arc/intent_helper/intent_filter.h" #include "mojo/public/cpp/bindings/binding.h" class GURL; @@ -25,15 +28,9 @@ friend class base::RefCounted<LocalActivityResolver>; ~LocalActivityResolver(); - bool IsRelevantIntentFilter(const mojom::IntentFilterPtr& intent_filter); - bool FilterHasViewAction(const mojom::IntentFilterPtr& intent_filter); - bool FilterCategoryIsBrowsable(const mojom::IntentFilterPtr& intent_filter); - bool FilterHandlesWebSchemes(const mojom::IntentFilterPtr& intent_filter); - // List of intent filters from Android. Used to determine if Chrome should // handle a URL without handing off to Android. - mojo::Array<mojom::IntentFilterPtr> intent_filters_; - + std::vector<IntentFilter> intent_filters_; DISALLOW_COPY_AND_ASSIGN(LocalActivityResolver); };
diff --git a/components/arc/metrics/arc_metrics_service.cc b/components/arc/metrics/arc_metrics_service.cc index 5ce5aa1..9aca98bd 100644 --- a/components/arc/metrics/arc_metrics_service.cc +++ b/components/arc/metrics/arc_metrics_service.cc
@@ -4,6 +4,8 @@ #include "components/arc/metrics/arc_metrics_service.h" +#include <string> + #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" @@ -17,19 +19,24 @@ const char kGmsProcessNamePrefix[] = "com.google.android.gms"; const char kBootProgressEnableScreen[] = "boot_progress_enable_screen"; -} // namespace +} // namespace namespace arc { ArcMetricsService::ArcMetricsService(ArcBridgeService* bridge_service) - : ArcService(bridge_service), binding_(this), weak_ptr_factory_(this) { - arc_bridge_service()->AddObserver(this); + : ArcService(bridge_service), + binding_(this), + process_observer_(this), + weak_ptr_factory_(this) { + arc_bridge_service()->metrics()->AddObserver(this); + arc_bridge_service()->process()->AddObserver(&process_observer_); oom_kills_monitor_.Start(); } ArcMetricsService::~ArcMetricsService() { DCHECK(CalledOnValidThread()); - arc_bridge_service()->RemoveObserver(this); + arc_bridge_service()->process()->RemoveObserver(&process_observer_); + arc_bridge_service()->metrics()->RemoveObserver(this); } bool ArcMetricsService::CalledOnValidThread() { @@ -37,7 +44,7 @@ return thread_checker_.CalledOnValidThread(); } -void ArcMetricsService::OnMetricsInstanceReady() { +void ArcMetricsService::OnInstanceReady() { VLOG(2) << "Start metrics service."; // Retrieve ARC start time from session manager. chromeos::SessionManagerClient* session_manager_client = @@ -47,7 +54,7 @@ weak_ptr_factory_.GetWeakPtr())); } -void ArcMetricsService::OnMetricsInstanceClosed() { +void ArcMetricsService::OnInstanceClosed() { VLOG(2) << "Close metrics service."; DCHECK(CalledOnValidThread()); if (binding_.is_bound()) @@ -56,11 +63,9 @@ void ArcMetricsService::OnProcessInstanceReady() { VLOG(2) << "Start updating process list."; - timer_.Start( - FROM_HERE, - base::TimeDelta::FromMinutes(kRequestProcessListPeriodInMinutes), - this, - &ArcMetricsService::RequestProcessList); + timer_.Start(FROM_HERE, + base::TimeDelta::FromMinutes(kRequestProcessListPeriodInMinutes), + this, &ArcMetricsService::RequestProcessList); } void ArcMetricsService::OnProcessInstanceClosed() { @@ -70,16 +75,15 @@ void ArcMetricsService::RequestProcessList() { mojom::ProcessInstance* process_instance = - arc_bridge_service()->process_instance(); + arc_bridge_service()->process()->instance(); if (!process_instance) { LOG(ERROR) << "No process instance found before RequestProcessList"; return; } VLOG(2) << "RequestProcessList"; - process_instance->RequestProcessList( - base::Bind(&ArcMetricsService::ParseProcessList, - weak_ptr_factory_.GetWeakPtr())); + process_instance->RequestProcessList(base::Bind( + &ArcMetricsService::ParseProcessList, weak_ptr_factory_.GetWeakPtr())); } void ArcMetricsService::ParseProcessList( @@ -109,12 +113,17 @@ } void ArcMetricsService::OnArcStartTimeRetrieved( - bool success, base::TimeTicks arc_start_time) { + bool success, + base::TimeTicks arc_start_time) { DCHECK(CalledOnValidThread()); if (!success) { LOG(ERROR) << "Failed to retrieve ARC start timeticks."; return; } + if (!arc_bridge_service()->metrics()->instance()) { + LOG(ERROR) << "ARC metrics instance went away while retrieving start time."; + return; + } // The binding of host interface is deferred until the ARC start time is // retrieved here because it prevents race condition of the ARC start @@ -122,7 +131,7 @@ if (!binding_.is_bound()) { mojom::MetricsHostPtr host_ptr; binding_.Bind(mojo::GetProxy(&host_ptr)); - arc_bridge_service()->metrics_instance()->Init(std::move(host_ptr)); + arc_bridge_service()->metrics()->instance()->Init(std::move(host_ptr)); } arc_start_time_ = arc_start_time; VLOG(2) << "ARC start @" << arc_start_time_; @@ -134,27 +143,36 @@ int64_t arc_start_time_in_ms = (arc_start_time_ - base::TimeTicks()).InMilliseconds(); for (const auto& event : events) { - VLOG(2) << "Report boot progress event:" - << event->event << "@" << event->uptimeMillis; + VLOG(2) << "Report boot progress event:" << event->event << "@" + << event->uptimeMillis; std::string title = "Arc." + event->event.get(); base::TimeDelta elapsed_time = base::TimeDelta::FromMilliseconds( event->uptimeMillis - arc_start_time_in_ms); // Note: This leaks memory, which is expected behavior. - base::HistogramBase* histogram = - base::Histogram::FactoryTimeGet( - title, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromSeconds(30), - 50, - base::HistogramBase::kUmaTargetedHistogramFlag); + base::HistogramBase* histogram = base::Histogram::FactoryTimeGet( + title, base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromSeconds(30), 50, + base::HistogramBase::kUmaTargetedHistogramFlag); histogram->AddTime(elapsed_time); if (event->event.get().compare(kBootProgressEnableScreen) == 0) - UMA_HISTOGRAM_CUSTOM_TIMES("Arc.AndroidBootTime", - elapsed_time, + UMA_HISTOGRAM_CUSTOM_TIMES("Arc.AndroidBootTime", elapsed_time, base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromSeconds(30), - 50); + base::TimeDelta::FromSeconds(30), 50); } } +ArcMetricsService::ProcessObserver::ProcessObserver( + ArcMetricsService* arc_metrics_service) + : arc_metrics_service_(arc_metrics_service) {} + +ArcMetricsService::ProcessObserver::~ProcessObserver() = default; + +void ArcMetricsService::ProcessObserver::OnInstanceReady() { + arc_metrics_service_->OnProcessInstanceReady(); +} + +void ArcMetricsService::ProcessObserver::OnInstanceClosed() { + arc_metrics_service_->OnProcessInstanceClosed(); +} + } // namespace arc
diff --git a/components/arc/metrics/arc_metrics_service.h b/components/arc/metrics/arc_metrics_service.h index 4f611787..7b7958b 100644 --- a/components/arc/metrics/arc_metrics_service.h +++ b/components/arc/metrics/arc_metrics_service.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_ARC_METRICS_ARC_METRICS_SERVICE_H -#define COMPONENTS_ARC_METRICS_ARC_METRICS_SERVICE_H +#ifndef COMPONENTS_ARC_METRICS_ARC_METRICS_SERVICE_H_ +#define COMPONENTS_ARC_METRICS_ARC_METRICS_SERVICE_H_ #include "base/macros.h" #include "base/memory/weak_ptr.h" @@ -12,24 +12,28 @@ #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" #include "components/arc/common/arc_bridge.mojom.h" +#include "components/arc/instance_holder.h" #include "components/arc/metrics/oom_kills_monitor.h" #include "mojo/public/cpp/bindings/binding.h" namespace arc { // Collects information from other ArcServices and send UMA metrics. -class ArcMetricsService : public ArcService, - public ArcBridgeService::Observer, - public mojom::MetricsHost { +class ArcMetricsService + : public ArcService, + public InstanceHolder<mojom::MetricsInstance>::Observer, + public mojom::MetricsHost { public: explicit ArcMetricsService(ArcBridgeService* bridge_service); ~ArcMetricsService() override; - // ArcBridgeService::Observer overrides. - void OnMetricsInstanceReady() override; - void OnMetricsInstanceClosed() override; - void OnProcessInstanceReady() override; - void OnProcessInstanceClosed() override; + // InstanceHolder<mojom::MetricsInstance>::Observer overrides. + void OnInstanceReady() override; + void OnInstanceClosed() override; + + // Implementations for InstanceHolder<mojom::ProcessInstance>::Observer. + void OnProcessInstanceReady(); + void OnProcessInstanceClosed(); // MetricsHost overrides. void ReportBootProgress( @@ -45,8 +49,24 @@ void OnArcStartTimeRetrieved(bool success, base::TimeTicks arc_start_time); private: + // Adapter to be able to also observe ProcessInstance events. + class ProcessObserver + : public InstanceHolder<mojom::ProcessInstance>::Observer { + public: + explicit ProcessObserver(ArcMetricsService* arc_metrics_service); + ~ProcessObserver() override; + + private: + // InstanceHolder<mojom::ProcessInstance>::Observer overrides. + void OnInstanceReady() override; + void OnInstanceClosed() override; + + ArcMetricsService* arc_metrics_service_; + }; + mojo::Binding<mojom::MetricsHost> binding_; + ProcessObserver process_observer_; base::ThreadChecker thread_checker_; base::RepeatingTimer timer_; @@ -63,4 +83,4 @@ } // namespace arc -#endif // COMPONENTS_ARC_METRICS_ARC_METRICS_SERVICE_H +#endif // COMPONENTS_ARC_METRICS_ARC_METRICS_SERVICE_H_
diff --git a/components/arc/net/arc_net_host_impl.cc b/components/arc/net/arc_net_host_impl.cc index 63fe3295..2d03706 100644 --- a/components/arc/net/arc_net_host_impl.cc +++ b/components/arc/net/arc_net_host_impl.cc
@@ -305,24 +305,24 @@ ArcNetHostImpl::ArcNetHostImpl(ArcBridgeService* bridge_service) : ArcService(bridge_service), binding_(this), weak_factory_(this) { - arc_bridge_service()->AddObserver(this); + arc_bridge_service()->net()->AddObserver(this); GetStateHandler()->AddObserver(this, FROM_HERE); } ArcNetHostImpl::~ArcNetHostImpl() { DCHECK(thread_checker_.CalledOnValidThread()); - arc_bridge_service()->RemoveObserver(this); + arc_bridge_service()->net()->RemoveObserver(this); if (chromeos::NetworkHandler::IsInitialized()) { GetStateHandler()->RemoveObserver(this, FROM_HERE); } } -void ArcNetHostImpl::OnNetInstanceReady() { +void ArcNetHostImpl::OnInstanceReady() { DCHECK(thread_checker_.CalledOnValidThread()); mojom::NetHostPtr host; binding_.Bind(GetProxy(&host)); - arc_bridge_service()->net_instance()->Init(std::move(host)); + arc_bridge_service()->net()->instance()->Init(std::move(host)); } void ArcNetHostImpl::GetNetworksDeprecated( @@ -553,16 +553,16 @@ } void ArcNetHostImpl::ScanCompleted(const chromeos::DeviceState* /*unused*/) { - if (!arc_bridge_service()->net_instance()) { + if (!arc_bridge_service()->net()->instance()) { VLOG(2) << "NetInstance not ready yet"; return; } - if (arc_bridge_service()->net_version() < 1) { + if (arc_bridge_service()->net()->version() < 1) { VLOG(1) << "NetInstance does not support ScanCompleted."; return; } - arc_bridge_service()->net_instance()->ScanCompleted(); + arc_bridge_service()->net()->instance()->ScanCompleted(); } void ArcNetHostImpl::GetDefaultNetwork( @@ -586,22 +586,22 @@ void ArcNetHostImpl::DefaultNetworkSuccessCallback( const std::string& service_path, const base::DictionaryValue& dictionary) { - arc_bridge_service()->net_instance()->DefaultNetworkChanged( + arc_bridge_service()->net()->instance()->DefaultNetworkChanged( TranslateONCConfiguration(&dictionary), TranslateONCConfiguration(&dictionary)); } void ArcNetHostImpl::DefaultNetworkChanged( const chromeos::NetworkState* network) { - if (arc_bridge_service()->net_version() < 2) { + if (arc_bridge_service()->net()->version() < 2) { VLOG(1) << "ArcBridgeService does not support DefaultNetworkChanged."; return; } if (!network) { VLOG(1) << "No default network"; - arc_bridge_service()->net_instance()->DefaultNetworkChanged(nullptr, - nullptr); + arc_bridge_service()->net()->instance()->DefaultNetworkChanged(nullptr, + nullptr); return; } @@ -615,14 +615,14 @@ } void ArcNetHostImpl::DeviceListChanged() { - if (arc_bridge_service()->net_version() < 3) { + if (arc_bridge_service()->net()->version() < 3) { VLOG(1) << "ArcBridgeService does not support DeviceListChanged."; return; } bool is_enabled = GetStateHandler()->IsTechnologyEnabled( chromeos::NetworkTypePattern::WiFi()); - arc_bridge_service()->net_instance()->WifiEnabledStateChanged(is_enabled); + arc_bridge_service()->net()->instance()->WifiEnabledStateChanged(is_enabled); } void ArcNetHostImpl::OnShuttingDown() {
diff --git a/components/arc/net/arc_net_host_impl.h b/components/arc/net/arc_net_host_impl.h index 8aa52b7..a21a0b0 100644 --- a/components/arc/net/arc_net_host_impl.h +++ b/components/arc/net/arc_net_host_impl.h
@@ -17,6 +17,7 @@ #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" #include "components/arc/common/net.mojom.h" +#include "components/arc/instance_holder.h" #include "mojo/public/cpp/bindings/binding.h" namespace base { @@ -31,7 +32,7 @@ // Private implementation of ArcNetHost. class ArcNetHostImpl : public ArcService, - public ArcBridgeService::Observer, + public InstanceHolder<mojom::NetInstance>::Observer, public chromeos::NetworkStateHandlerObserver, public mojom::NetHost { public: @@ -77,8 +78,8 @@ void DeviceListChanged() override; void GetDefaultNetwork(const GetDefaultNetworkCallback& callback) override; - // Overridden from ArcBridgeService::Observer: - void OnNetInstanceReady() override; + // Overridden from ArcBridgeService::InterfaceObserver<mojom::NetInstance>: + void OnInstanceReady() override; private: void DefaultNetworkSuccessCallback(const std::string& service_path,
diff --git a/components/arc/obb_mounter/arc_obb_mounter_bridge.cc b/components/arc/obb_mounter/arc_obb_mounter_bridge.cc index b9f3356..04362b7c 100644 --- a/components/arc/obb_mounter/arc_obb_mounter_bridge.cc +++ b/components/arc/obb_mounter/arc_obb_mounter_bridge.cc
@@ -22,18 +22,17 @@ } // namespace ArcObbMounterBridge::ArcObbMounterBridge(ArcBridgeService* bridge_service) - : ArcService(bridge_service), - binding_(this) { - arc_bridge_service()->AddObserver(this); + : ArcService(bridge_service), binding_(this) { + arc_bridge_service()->obb_mounter()->AddObserver(this); } ArcObbMounterBridge::~ArcObbMounterBridge() { - arc_bridge_service()->RemoveObserver(this); + arc_bridge_service()->obb_mounter()->RemoveObserver(this); } -void ArcObbMounterBridge::OnObbMounterInstanceReady() { +void ArcObbMounterBridge::OnInstanceReady() { mojom::ObbMounterInstance* obb_mounter_instance = - arc_bridge_service()->obb_mounter_instance(); + arc_bridge_service()->obb_mounter()->instance(); obb_mounter_instance->Init(binding_.CreateInterfacePtrAndBind()); }
diff --git a/components/arc/obb_mounter/arc_obb_mounter_bridge.h b/components/arc/obb_mounter/arc_obb_mounter_bridge.h index d2371521..6b5e3fcc 100644 --- a/components/arc/obb_mounter/arc_obb_mounter_bridge.h +++ b/components/arc/obb_mounter/arc_obb_mounter_bridge.h
@@ -8,20 +8,22 @@ #include "base/macros.h" #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/instance_holder.h" #include "mojo/public/cpp/bindings/binding.h" namespace arc { // This class handles OBB mount/unmount requests from Android. -class ArcObbMounterBridge : public ArcService, - public ArcBridgeService::Observer, - public mojom::ObbMounterHost { +class ArcObbMounterBridge + : public ArcService, + public InstanceHolder<mojom::ObbMounterInstance>::Observer, + public mojom::ObbMounterHost { public: explicit ArcObbMounterBridge(ArcBridgeService* bridge_service); ~ArcObbMounterBridge() override; - // ArcBridgeService::Observer overrides: - void OnObbMounterInstanceReady() override; + // InstanceHolder<mojom::ObbMounterInstance>::Observer overrides: + void OnInstanceReady() override; // mojom::ObbMounterHost overrides: void MountObb(const mojo::String& obb_file,
diff --git a/components/arc/power/arc_power_bridge.cc b/components/arc/power/arc_power_bridge.cc index 7943943..fb8b1fdc 100644 --- a/components/arc/power/arc_power_bridge.cc +++ b/components/arc/power/arc_power_bridge.cc
@@ -16,16 +16,17 @@ ArcPowerBridge::ArcPowerBridge(ArcBridgeService* bridge_service) : ArcService(bridge_service), binding_(this) { - arc_bridge_service()->AddObserver(this); + arc_bridge_service()->power()->AddObserver(this); } ArcPowerBridge::~ArcPowerBridge() { - arc_bridge_service()->RemoveObserver(this); + arc_bridge_service()->power()->RemoveObserver(this); ReleaseAllDisplayWakeLocks(); } -void ArcPowerBridge::OnPowerInstanceReady() { - mojom::PowerInstance* power_instance = arc_bridge_service()->power_instance(); +void ArcPowerBridge::OnInstanceReady() { + mojom::PowerInstance* power_instance = + arc_bridge_service()->power()->instance(); if (!power_instance) { LOG(ERROR) << "OnPowerInstanceReady called, but no power instance found"; return; @@ -35,14 +36,15 @@ ash::Shell::GetInstance()->display_configurator()->AddObserver(this); } -void ArcPowerBridge::OnPowerInstanceClosed() { +void ArcPowerBridge::OnInstanceClosed() { ash::Shell::GetInstance()->display_configurator()->RemoveObserver(this); ReleaseAllDisplayWakeLocks(); } void ArcPowerBridge::OnPowerStateChanged( chromeos::DisplayPowerState power_state) { - mojom::PowerInstance* power_instance = arc_bridge_service()->power_instance(); + mojom::PowerInstance* power_instance = + arc_bridge_service()->power()->instance(); if (!power_instance) { LOG(ERROR) << "PowerInstance is not available"; return;
diff --git a/components/arc/power/arc_power_bridge.h b/components/arc/power/arc_power_bridge.h index d82aad6..c82c380 100644 --- a/components/arc/power/arc_power_bridge.h +++ b/components/arc/power/arc_power_bridge.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/instance_holder.h" #include "mojo/public/cpp/bindings/binding.h" #include "ui/display/chromeos/display_configurator.h" @@ -18,16 +19,16 @@ // ARC Power Client sets power management policy based on requests from // ARC instances. class ArcPowerBridge : public ArcService, - public ArcBridgeService::Observer, + public InstanceHolder<mojom::PowerInstance>::Observer, public ui::DisplayConfigurator::Observer, public mojom::PowerHost { public: explicit ArcPowerBridge(ArcBridgeService* bridge_service); ~ArcPowerBridge() override; - // ArcBridgeService::Observer overrides. - void OnPowerInstanceReady() override; - void OnPowerInstanceClosed() override; + // InstanceHolder<mojom::PowerInstance>::Observer overrides. + void OnInstanceReady() override; + void OnInstanceClosed() override; // DisplayConfigurator::Observer overrides. void OnPowerStateChanged(chromeos::DisplayPowerState power_state) override;
diff --git a/components/arc/storage_manager/arc_storage_manager.cc b/components/arc/storage_manager/arc_storage_manager.cc index 926ac50..6bc2cf5 100644 --- a/components/arc/storage_manager/arc_storage_manager.cc +++ b/components/arc/storage_manager/arc_storage_manager.cc
@@ -22,7 +22,7 @@ } // namespace -ArcStorageManager::ArcStorageManager(ArcBridgeService *bridge_service) +ArcStorageManager::ArcStorageManager(ArcBridgeService* bridge_service) : ArcService(bridge_service) { DCHECK(!g_arc_storage_manager); g_arc_storage_manager = this; @@ -39,10 +39,6 @@ return g_arc_storage_manager; } -void ArcStorageManager::OnStorageManagerInstanceReady() { - VLOG(1) << "ArcStorageManagerInstance is ready"; -} - bool ArcStorageManager::OpenPrivateVolumeSettings() { auto storage_manager_instance = GetStorageManagerInstance(); if (!storage_manager_instance) { @@ -74,12 +70,12 @@ mojom::StorageManagerInstance* ArcStorageManager::GetStorageManagerInstance() { auto bridge_service = arc_bridge_service(); - auto storage_manager_instance = bridge_service->storage_manager_instance(); + auto storage_manager_instance = bridge_service->storage_manager()->instance(); if (!storage_manager_instance) { DLOG(WARNING) << "ARC storage manager instance is not ready."; return nullptr; } - auto storage_manager_version = bridge_service->storage_manager_version(); + auto storage_manager_version = bridge_service->storage_manager()->version(); if (storage_manager_version < kMinInstanceVersion) { DLOG(ERROR) << "ARC storage manager instance (version " << storage_manager_version << ") is too old.";
diff --git a/components/arc/storage_manager/arc_storage_manager.h b/components/arc/storage_manager/arc_storage_manager.h index f4111bf..1ca766e7 100644 --- a/components/arc/storage_manager/arc_storage_manager.h +++ b/components/arc/storage_manager/arc_storage_manager.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_ARC_STORAGE_MANAGER_ARC_STORAGE_MANAGER_H -#define COMPONENTS_ARC_STORAGE_MANAGER_ARC_STORAGE_MANAGER_H +#ifndef COMPONENTS_ARC_STORAGE_MANAGER_ARC_STORAGE_MANAGER_H_ +#define COMPONENTS_ARC_STORAGE_MANAGER_ARC_STORAGE_MANAGER_H_ #include <memory> @@ -16,8 +16,7 @@ namespace arc { // This class represents as a simple proxy of StorageManager to Chrome OS. -class ArcStorageManager : public ArcService, - public ArcBridgeService::Observer { +class ArcStorageManager : public ArcService { public: explicit ArcStorageManager(ArcBridgeService* bridge_service); ~ArcStorageManager() override; @@ -27,16 +26,13 @@ // nullptr (or aborts on Debug build). static ArcStorageManager* Get(); - // ArcBridgeService::Observer - void OnStorageManagerInstanceReady() override; - // Opens detailed preference screen of private volume on ARC. // Returns false when an instance of ARC-side isn't ready yet. bool OpenPrivateVolumeSettings(); // Gets storage usage of all application's APK, data, and cache size. - using GetApplicationsSizeCallback = base::Callback< - void(bool succeeded, arc::mojom::ApplicationsSizePtr)>; + using GetApplicationsSizeCallback = + base::Callback<void(bool succeeded, arc::mojom::ApplicationsSizePtr)>; bool GetApplicationsSize(const GetApplicationsSizeCallback& callback); // Deletes all applications' cache files. @@ -50,4 +46,4 @@ } // namespace arc -#endif // COMPONENTS_ARC_STORAGE_MANAGER_ARC_STORAGE_MANAGER_H +#endif // COMPONENTS_ARC_STORAGE_MANAGER_ARC_STORAGE_MANAGER_H_
diff --git a/components/arc/test/fake_arc_bridge_bootstrap.cc b/components/arc/test/fake_arc_bridge_bootstrap.cc index cd05697..054ebad 100644 --- a/components/arc/test/fake_arc_bridge_bootstrap.cc +++ b/components/arc/test/fake_arc_bridge_bootstrap.cc
@@ -28,11 +28,13 @@ void FakeArcBridgeBootstrap::Stop() { DCHECK(delegate_); instance_->Unbind(); - delegate_->OnStopped(); + delegate_->OnStopped(ArcBridgeService::StopReason::SHUTDOWN); } -void FakeArcBridgeBootstrap::OnCrashed() { - Stop(); +void FakeArcBridgeBootstrap::OnStopped(ArcBridgeService::StopReason reason) { + DCHECK(delegate_); + instance_->Unbind(); + delegate_->OnStopped(reason); } } // namespace arc
diff --git a/components/arc/test/fake_arc_bridge_bootstrap.h b/components/arc/test/fake_arc_bridge_bootstrap.h index f9a9b2f..271a48a 100644 --- a/components/arc/test/fake_arc_bridge_bootstrap.h +++ b/components/arc/test/fake_arc_bridge_bootstrap.h
@@ -24,7 +24,7 @@ private: // FakeArcBridgeInstance::Delegate: - void OnCrashed() override; + void OnStopped(ArcBridgeService::StopReason reason) override; // Owned by the caller. FakeArcBridgeInstance* instance_;
diff --git a/components/arc/test/fake_arc_bridge_instance.cc b/components/arc/test/fake_arc_bridge_instance.cc index e51e54a..d657344 100644 --- a/components/arc/test/fake_arc_bridge_instance.cc +++ b/components/arc/test/fake_arc_bridge_instance.cc
@@ -31,10 +31,10 @@ binding_.WaitForIncomingMethodCall(); } -void FakeArcBridgeInstance::SimulateCrash() { +void FakeArcBridgeInstance::Stop(ArcBridgeService::StopReason reason) { if (!delegate_) return; - delegate_->OnCrashed(); + delegate_->OnStopped(reason); } } // namespace arc
diff --git a/components/arc/test/fake_arc_bridge_instance.h b/components/arc/test/fake_arc_bridge_instance.h index 5a3aa47..33d5751 100644 --- a/components/arc/test/fake_arc_bridge_instance.h +++ b/components/arc/test/fake_arc_bridge_instance.h
@@ -17,7 +17,7 @@ class Delegate { public: virtual ~Delegate() = default; - virtual void OnCrashed() = 0; + virtual void OnStopped(ArcBridgeService::StopReason reason) = 0; }; FakeArcBridgeInstance(); @@ -41,8 +41,8 @@ // The number of times Init() has been called. int init_calls() const { return init_calls_; } - // Simulates a crash by calling Stop() on the ArcBridgeBoostrap. - void SimulateCrash(); + // Stops the instance. + void Stop(ArcBridgeService::StopReason reason); private: Delegate* delegate_ = nullptr;
diff --git a/components/arc/test/fake_policy_instance.cc b/components/arc/test/fake_policy_instance.cc index 8111244c..42fd121c 100644 --- a/components/arc/test/fake_policy_instance.cc +++ b/components/arc/test/fake_policy_instance.cc
@@ -11,11 +11,11 @@ mojo::InterfaceRequest<mojom::PolicyInstance> request, ArcBridgeService* bridge_service) : binding_(this, std::move(request)), bridge_service_(bridge_service) { - bridge_service_->AddObserver(this); + bridge_service_->policy()->AddObserver(this); } FakePolicyInstance::~FakePolicyInstance() { - bridge_service_->RemoveObserver(this); + bridge_service_->policy()->RemoveObserver(this); } void FakePolicyInstance::OnPolicyUpdated() {} @@ -24,7 +24,7 @@ host_ptr_ = std::move(host_ptr); } -void FakePolicyInstance::OnPolicyInstanceReady() { +void FakePolicyInstance::OnInstanceReady() { ready_ = true; }
diff --git a/components/arc/test/fake_policy_instance.h b/components/arc/test/fake_policy_instance.h index 213f3d39..8bd5af9 100644 --- a/components/arc/test/fake_policy_instance.h +++ b/components/arc/test/fake_policy_instance.h
@@ -7,12 +7,14 @@ #include "components/arc/arc_bridge_service.h" #include "components/arc/common/policy.mojom.h" +#include "components/arc/instance_holder.h" #include "components/arc/test/fake_arc_bridge_instance.h" namespace arc { -class FakePolicyInstance : public mojom::PolicyInstance, - public arc::ArcBridgeService::Observer { +class FakePolicyInstance + : public mojom::PolicyInstance, + public arc::InstanceHolder<mojom::PolicyInstance>::Observer { public: // bridge_service should not be destroyed before the destructor is called. FakePolicyInstance(mojo::InterfaceRequest<mojom::PolicyInstance> request, @@ -23,8 +25,8 @@ void Init(mojom::PolicyHostPtr host_ptr) override; void OnPolicyUpdated() override; - // arc::ArcBridgeService::Observer - void OnPolicyInstanceReady() override; + // arc::InstanceHolder<mojom::PolicyInstance>::Observer + void OnInstanceReady() override; void WaitForOnPolicyInstanceReady(); void CallGetPolicies(const mojom::PolicyHost::GetPoliciesCallback& callback);
diff --git a/components/arc/user_data/arc_user_data_service.cc b/components/arc/user_data/arc_user_data_service.cc index e37f8782..1c464771 100644 --- a/components/arc/user_data/arc_user_data_service.cc +++ b/components/arc/user_data/arc_user_data_service.cc
@@ -31,7 +31,7 @@ arc_bridge_service()->RemoveObserver(this); } -void ArcUserDataService::OnBridgeStopped() { +void ArcUserDataService::OnBridgeStopped(ArcBridgeService::StopReason reason) { DCHECK(thread_checker_.CalledOnValidThread()); const AccountId& account_id = user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId();
diff --git a/components/arc/user_data/arc_user_data_service.h b/components/arc/user_data/arc_user_data_service.h index 29405f9..2bd3a03 100644 --- a/components/arc/user_data/arc_user_data_service.h +++ b/components/arc/user_data/arc_user_data_service.h
@@ -30,7 +30,7 @@ // ArcBridgeService::Observer: // Called whenever the arc bridge is stopped to potentially remove data if // the user has not opted in. - void OnBridgeStopped() override; + void OnBridgeStopped(ArcBridgeService::StopReason reason) override; private: base::ThreadChecker thread_checker_;
diff --git a/components/arc/window_manager/arc_window_manager_bridge.cc b/components/arc/window_manager/arc_window_manager_bridge.cc index 45b9686..ee2e28b5 100644 --- a/components/arc/window_manager/arc_window_manager_bridge.cc +++ b/components/arc/window_manager/arc_window_manager_bridge.cc
@@ -14,7 +14,7 @@ ArcWindowManagerBridge::ArcWindowManagerBridge(ArcBridgeService* bridge_service) : ArcService(bridge_service), current_mode_(mojom::WindowManagerMode::MODE_NORMAL) { - arc_bridge_service()->AddObserver(this); + arc_bridge_service()->window_manager()->AddObserver(this); if (!ash::WmShell::HasInstance()) { // The shell gets always loaded before ARC. If there is no shell it can only // mean that a unit test is running. @@ -24,7 +24,7 @@ ash::WmShell::Get()->AddShellObserver(this); } -void ArcWindowManagerBridge::OnWindowManagerInstanceReady() { +void ArcWindowManagerBridge::OnInstanceReady() { if (!ash::WmShell::HasInstance()) { // The shell gets always loaded before ARC. If there is no shell it can only // mean that a unit test is running. @@ -42,7 +42,7 @@ ArcWindowManagerBridge::~ArcWindowManagerBridge() { if (ash::WmShell::HasInstance()) ash::WmShell::Get()->RemoveShellObserver(this); - arc_bridge_service()->RemoveObserver(this); + arc_bridge_service()->window_manager()->RemoveObserver(this); } void ArcWindowManagerBridge::OnMaximizeModeStarted() { @@ -57,12 +57,12 @@ bool touch_view_enabled) { // We let the ArcBridgeService check that we are calling on the right thread. DCHECK(ArcBridgeService::Get() != nullptr); - mojom::WindowManagerMode wm_mode = touch_view_enabled ? - mojom::WindowManagerMode::MODE_TOUCH_VIEW : - mojom::WindowManagerMode::MODE_NORMAL; + mojom::WindowManagerMode wm_mode = + touch_view_enabled ? mojom::WindowManagerMode::MODE_TOUCH_VIEW + : mojom::WindowManagerMode::MODE_NORMAL; mojom::WindowManagerInstance* wm_instance = - arc_bridge_service()->window_manager_instance(); + arc_bridge_service()->window_manager()->instance(); if (!wm_instance || wm_mode == current_mode_) { return; }
diff --git a/components/arc/window_manager/arc_window_manager_bridge.h b/components/arc/window_manager/arc_window_manager_bridge.h index f206e5de..27a346d 100644 --- a/components/arc/window_manager/arc_window_manager_bridge.h +++ b/components/arc/window_manager/arc_window_manager_bridge.h
@@ -11,18 +11,20 @@ #include "base/macros.h" #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" +#include "components/arc/instance_holder.h" namespace arc { -class ArcWindowManagerBridge : public ArcService, - public ArcBridgeService::Observer, - public ash::ShellObserver { +class ArcWindowManagerBridge + : public ArcService, + public InstanceHolder<mojom::WindowManagerInstance>::Observer, + public ash::ShellObserver { public: explicit ArcWindowManagerBridge(ArcBridgeService* bridge_service); ~ArcWindowManagerBridge() override; - // ArcBridgeService::Observer - void OnWindowManagerInstanceReady() override; + // InstanceHolder<mojom::WindowManagerInstance>::Observer + void OnInstanceReady() override; // Ash::Shell::ShellObserver void OnMaximizeModeStarted() override;
diff --git a/components/autofill.gypi b/components/autofill.gypi index b0bc811..510807d2 100644 --- a/components/autofill.gypi +++ b/components/autofill.gypi
@@ -250,8 +250,6 @@ 'conditions': [ ['OS=="ios"', { 'sources': [ - 'autofill/core/browser/autofill_field_trial_ios.cc', - 'autofill/core/browser/autofill_field_trial_ios.h', 'autofill/core/browser/keyboard_accessory_metrics_logger.h', 'autofill/core/browser/keyboard_accessory_metrics_logger.mm', ],
diff --git a/components/autofill/content/common/OWNERS b/components/autofill/content/common/OWNERS index 9fbdf6f..25497bf 100644 --- a/components/autofill/content/common/OWNERS +++ b/components/autofill/content/common/OWNERS
@@ -2,3 +2,5 @@ # new sandbox escapes. per-file *_messages*.h=set noparent per-file *_messages*.h=file://ipc/SECURITY_OWNERS +per-file *_param_traits*.*=set noparent +per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/components/autofill/content/renderer/BUILD.gn b/components/autofill/content/renderer/BUILD.gn index 866fc7d..601e23d 100644 --- a/components/autofill/content/renderer/BUILD.gn +++ b/components/autofill/content/renderer/BUILD.gn
@@ -48,7 +48,7 @@ configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] } -source_set("test_support") { +static_library("test_support") { testonly = true sources = [ "test_password_autofill_agent.cc",
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index b51755e6..c6b33fe 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -147,8 +147,6 @@ if (is_ios) { sources += [ - "autofill_field_trial_ios.cc", - "autofill_field_trial_ios.h", "keyboard_accessory_metrics_logger.h", "keyboard_accessory_metrics_logger.mm", ] @@ -211,7 +209,7 @@ } } -source_set("test_support") { +static_library("test_support") { testonly = true sources = [ "autofill_test_utils.cc",
diff --git a/components/autofill/core/browser/autofill_external_delegate.cc b/components/autofill/core/browser/autofill_external_delegate.cc index a81613d0..cf22acfc 100644 --- a/components/autofill/core/browser/autofill_external_delegate.cc +++ b/components/autofill/core/browser/autofill_external_delegate.cc
@@ -12,6 +12,7 @@ #include "base/message_loop/message_loop.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/sparse_histogram.h" +#include "base/metrics/user_metrics.h" #include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -117,6 +118,8 @@ signin_promo_suggestion.frontend_id = POPUP_ITEM_ID_CREDIT_CARD_SIGNIN_PROMO; suggestions.push_back(signin_promo_suggestion); + base::RecordAction( + base::UserMetricsAction("Signin_Impression_FromAutofillDropdown")); } #if !defined(OS_ANDROID)
diff --git a/components/autofill/core/browser/autofill_external_delegate_unittest.cc b/components/autofill/core/browser/autofill_external_delegate_unittest.cc index fb67541..62e964d6 100644 --- a/components/autofill/core/browser/autofill_external_delegate_unittest.cc +++ b/components/autofill/core/browser/autofill_external_delegate_unittest.cc
@@ -12,6 +12,7 @@ #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "base/test/histogram_tester.h" +#include "base/test/user_action_tester.h" #include "build/build_config.h" #include "components/autofill/core/browser/autofill_manager.h" #include "components/autofill/core/browser/autofill_metrics.h" @@ -216,11 +217,15 @@ EXPECT_CALL(autofill_client_, ShowAutofillPopup(_, _, SuggestionVectorIdsAre(element_ids), _)); + base::UserActionTester user_action_tester; + // This should call ShowAutofillPopup. std::vector<Suggestion> autofill_item; autofill_item.push_back(Suggestion()); autofill_item[0].frontend_id = kAutofillProfileId; external_delegate_->OnSuggestionsReturned(kQueryId, autofill_item); + EXPECT_EQ(1, user_action_tester.GetActionCount( + "Signin_Impression_FromAutofillDropdown")); EXPECT_CALL( *autofill_manager_,
diff --git a/components/autofill/core/browser/autofill_field_trial_ios.cc b/components/autofill/core/browser/autofill_field_trial_ios.cc deleted file mode 100644 index 95290e0..0000000 --- a/components/autofill/core/browser/autofill_field_trial_ios.cc +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/autofill/core/browser/autofill_field_trial_ios.h" - -#include "base/command_line.h" -#include "base/metrics/field_trial.h" -#include "components/autofill/core/common/autofill_switches.h" - -namespace autofill { - -// The full-form Autofill field trial name. -const char kFullFormFieldTrialName[] = "FullFormAutofill"; - -// static -bool AutofillFieldTrialIOS::IsFullFormAutofillEnabled() { - // Query the field trial state first to ensure that UMA reports the correct - // group. - std::string field_trial_state = - base::FieldTrialList::FindFullName(kFullFormFieldTrialName); - - const base::CommandLine* command_line = - base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kDisableFullFormAutofillIOS)) - return false; - if (command_line->HasSwitch(switches::kEnableFullFormAutofillIOS)) - return true; - - return !field_trial_state.empty() && field_trial_state != "Disabled"; -} - -} // namespace autofill
diff --git a/components/autofill/core/browser/autofill_field_trial_ios.h b/components/autofill/core/browser/autofill_field_trial_ios.h deleted file mode 100644 index 9750b71..0000000 --- a/components/autofill/core/browser/autofill_field_trial_ios.h +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_FIELD_TRIAL_IOS_H_ -#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_FIELD_TRIAL_IOS_H_ - -#include "base/macros.h" - -namespace autofill { - -// This class manages the iOS Autofill field trials. -class AutofillFieldTrialIOS { - public: - // Returns whether the user is in a full-form Autofill field trial. Full-form - // Autofill fills all fields of the form at once, similar to the desktop and - // Clank Autofill implementations. Previous iOS implementation requires user - // to select an Autofill value for each field individually, automatically - // advancing focus to the next field after each selection. - static bool IsFullFormAutofillEnabled(); - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(AutofillFieldTrialIOS); -}; - -} // namespace autofill - -#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_FIELD_TRIAL_IOS_H_
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index e43e85b2..c42ca66 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc
@@ -66,7 +66,6 @@ #include "url/gurl.h" #if defined(OS_IOS) -#include "components/autofill/core/browser/autofill_field_trial_ios.h" #include "components/autofill/core/browser/keyboard_accessory_metrics_logger.h" #endif @@ -515,11 +514,15 @@ GetProfileSuggestions(*form_structure, field, *autofill_field); } if (!suggestions.empty()) { + bool is_context_secure = + client_->IsContextSecure(form_structure->source_url()); + if (is_filling_credit_card) + AutofillMetrics::LogIsQueriedCreditCardFormSecure(is_context_secure); + // Don't provide credit card suggestions for non-secure pages, but do // provide them for secure pages with passive mixed content (see impl. of // IsContextSecure). - if (is_filling_credit_card && - !client_->IsContextSecure(form_structure->source_url())) { + if (is_filling_credit_card && !is_context_secure) { Suggestion warning_suggestion(l10n_util::GetStringUTF16( IDS_AUTOFILL_WARNING_INSECURE_CONNECTION)); warning_suggestion.frontend_id = POPUP_ITEM_ID_WARNING_MESSAGE; @@ -591,13 +594,6 @@ if (autofill_field->Type().GetStorableType() == CREDIT_CARD_NUMBER) return true; -#if defined(OS_IOS) - // On iOS, we only fill out one field at a time (assuming the new full-form - // feature isn't enabled). So we only need to check the current field. - if (!AutofillFieldTrialIOS::IsFullFormAutofillEnabled()) - return false; -#endif - // If the relevant section is already autofilled, the new fill operation will // only fill |autofill_field|. if (SectionIsAutofilled(*form_structure, form, autofill_field->section()))
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc index 5ebd620..7e9fb10 100644 --- a/components/autofill/core/browser/autofill_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -923,20 +923,6 @@ autofill_manager_->FillOrPreviewCreditCardForm( AutofillDriver::FORM_DATA_ACTION_FILL, kDefaultPageID, *form, form->fields[0], *card); - -#if defined(OS_IOS) - // Filling out the entire form on iOS requires requesting autofill on each - // of the form fields. - autofill_manager_->FillOrPreviewCreditCardForm( - AutofillDriver::FORM_DATA_ACTION_FILL, kDefaultPageID, *form, - form->fields[1], *card); - autofill_manager_->FillOrPreviewCreditCardForm( - AutofillDriver::FORM_DATA_ACTION_FILL, kDefaultPageID, *form, - form->fields[2], *card); - autofill_manager_->FillOrPreviewCreditCardForm( - AutofillDriver::FORM_DATA_ACTION_FILL, kDefaultPageID, *form, - form->fields[3], *card); -#endif // defined(OS_IOS) } // Convenience method to cast the FullCardRequest into a CardUnmaskDelegate. @@ -1827,26 +1813,18 @@ month_field = &form.fields[i]; } - // Empty form - whole form is Autofilled (except on iOS). + // Empty form - whole form is Autofilled. EXPECT_TRUE(WillFillCreditCardNumber(form, *number_field)); -#if defined(OS_IOS) - EXPECT_FALSE(WillFillCreditCardNumber(form, *name_field)); -#else EXPECT_TRUE(WillFillCreditCardNumber(form, *name_field)); -#endif // defined(OS_IOS) // If the user has entered a value, it won't be overridden. number_field->value = ASCIIToUTF16("gibberish"); EXPECT_TRUE(WillFillCreditCardNumber(form, *number_field)); EXPECT_FALSE(WillFillCreditCardNumber(form, *name_field)); - // But if that value is removed, it will be Autofilled (except on iOS). + // But if that value is removed, it will be Autofilled. number_field->value.clear(); -#if defined(OS_IOS) - EXPECT_FALSE(WillFillCreditCardNumber(form, *name_field)); -#else EXPECT_TRUE(WillFillCreditCardNumber(form, *name_field)); -#endif // defined(OS_IOS) // When part of the section is Autofilled, only fill the initiating field. month_field->is_autofilled = true;
diff --git a/components/autofill/core/browser/autofill_metrics.cc b/components/autofill/core/browser/autofill_metrics.cc index ff13a65..aed621c 100644 --- a/components/autofill/core/browser/autofill_metrics.cc +++ b/components/autofill/core/browser/autofill_metrics.cc
@@ -641,6 +641,11 @@ std::min(int(num_removed), 50)); } +// static +void AutofillMetrics::LogIsQueriedCreditCardFormSecure(bool is_secure) { + UMA_HISTOGRAM_BOOLEAN("Autofill.QueriedCreditCardFormIsSecure", is_secure); +} + AutofillMetrics::FormEventLogger::FormEventLogger(bool is_for_credit_card) : is_for_credit_card_(is_for_credit_card), is_server_data_available_(false),
diff --git a/components/autofill/core/browser/autofill_metrics.h b/components/autofill/core/browser/autofill_metrics.h index de9b8ff54..d0fcb7c 100644 --- a/components/autofill/core/browser/autofill_metrics.h +++ b/components/autofill/core/browser/autofill_metrics.h
@@ -646,6 +646,10 @@ // Log how many profiles were removed as part of the deduplication process. static void LogNumberOfProfilesRemovedDuringDedupe(size_t num_removed); + // Log whether the Autofill query on a credit card form is made in a secure + // context. + static void LogIsQueriedCreditCardFormSecure(bool is_secure); + // Utility to autofill form events in the relevant histograms depending on // the presence of server and/or local data. class FormEventLogger {
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc index 1d5c5168..c19f5c2 100644 --- a/components/autofill/core/browser/autofill_metrics_unittest.cc +++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -155,7 +155,8 @@ local_credit_cards_.clear(); server_credit_cards_.clear(); if (include_local_credit_card) { - CreditCard* credit_card = new CreditCard; + CreditCard* credit_card = + new CreditCard(base::ASCIIToUTF16("4111111111111111"), 12, 24); credit_card->set_guid("10000000-0000-0000-0000-000000000001"); local_credit_cards_.push_back(credit_card); } @@ -1812,6 +1813,56 @@ "Autofill_PolledCreditCardSuggestions")); } +// Tests that the Autofill.QueriedCreditCardFormIsSecure histogram is logged +// properly. +TEST_F(AutofillMetricsTest, QueriedCreditCardFormIsSecure) { + personal_data_->RecreateCreditCards( + true /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); + + // Set up the form data. + FormData form; + form.name = ASCIIToUTF16("TestForm"); + form.origin = GURL("http://example.com/form.html"); + form.action = GURL("http://example.com/submit.html"); + + FormFieldData field; + std::vector<ServerFieldType> field_types; + test::CreateTestFormField("Month", "card_month", "", "text", &field); + form.fields.push_back(field); + field_types.push_back(CREDIT_CARD_EXP_MONTH); + test::CreateTestFormField("Year", "card_year", "", "text", &field); + form.fields.push_back(field); + field_types.push_back(CREDIT_CARD_EXP_2_DIGIT_YEAR); + test::CreateTestFormField("Credit card", "card", "", "text", &field); + form.fields.push_back(field); + field_types.push_back(CREDIT_CARD_NUMBER); + + // Simulate having seen this form on page load. + autofill_manager_->AddSeenForm(form, field_types, field_types); + + { + // Simulate an Autofill query on a credit card field. + autofill_client_.set_is_context_secure(true); + base::HistogramTester histogram_tester; + autofill_manager_->OnQueryFormFieldAutofill(0, form, form.fields[1], + gfx::RectF()); + histogram_tester.ExpectUniqueSample( + "Autofill.QueriedCreditCardFormIsSecure", true, 1); + } + + { + // Simulate an Autofill query on a credit card field. + autofill_client_.set_is_context_secure(false); + base::HistogramTester histogram_tester; + autofill_manager_->OnQueryFormFieldAutofill(0, form, form.fields[1], + gfx::RectF()); + histogram_tester.ExpectUniqueSample( + "Autofill.QueriedCreditCardFormIsSecure", false, 1); + } +} + // Tests that the Autofill_PolledProfileSuggestions user action is only logged // once if the field is queried repeatedly. TEST_F(AutofillMetricsTest, PolledProfileSuggestions_DebounceLogs) {
diff --git a/components/autofill/core/browser/autofill_profile_comparator.cc b/components/autofill/core/browser/autofill_profile_comparator.cc index d4c5003..38831cd 100644 --- a/components/autofill/core/browser/autofill_profile_comparator.cc +++ b/components/autofill/core/browser/autofill_profile_comparator.cc
@@ -309,7 +309,7 @@ // include the country code prefix. if (merged_number.country_code() == 1 && merged_number.national_number() <= 9999999 && - new_number.find("+1") == 0) { + base::StartsWith(new_number, "+1", base::CompareCase::SENSITIVE)) { size_t offset = 2; // The char just after "+1". while (offset < new_number.size() && base::IsAsciiWhitespace(new_number[offset])) {
diff --git a/components/autofill/core/common/autofill_switches.cc b/components/autofill/core/common/autofill_switches.cc index 42276f8..cf1b859 100644 --- a/components/autofill/core/common/autofill_switches.cc +++ b/components/autofill/core/common/autofill_switches.cc
@@ -12,9 +12,6 @@ // credit card form. const char kDisableCreditCardScan[] = "disable-credit-card-scan"; -// Disables the experimental Full Form Autofill on iOS feature. -const char kDisableFullFormAutofillIOS[] = "disable-full-form-autofill-ios"; - // Force hiding the local save checkbox in the autofill dialog box for getting // the full credit card number for a wallet card. The card will never be stored // locally. @@ -36,9 +33,6 @@ // credit card form. const char kEnableCreditCardScan[] = "enable-credit-card-scan"; -// Enables the experimental Full Form Autofill on iOS feature. -const char kEnableFullFormAutofillIOS[] = "enable-full-form-autofill-ios"; - // Force showing the local save checkbox in the autofill dialog box for getting // the full credit card number for a wallet card. const char kEnableOfferStoreUnmaskedWalletCards[] =
diff --git a/components/autofill/core/common/autofill_switches.h b/components/autofill/core/common/autofill_switches.h index 75c7a93..8d419ae 100644 --- a/components/autofill/core/common/autofill_switches.h +++ b/components/autofill/core/common/autofill_switches.h
@@ -13,13 +13,11 @@ // All switches in alphabetical order. The switches should be documented // alongside the definition of their values in the .cc file. extern const char kDisableCreditCardScan[]; -extern const char kDisableFullFormAutofillIOS[]; extern const char kDisableOfferStoreUnmaskedWalletCards[]; extern const char kDisableOfferUploadCreditCards[]; extern const char kDisablePasswordGeneration[]; extern const char kDisableSingleClickAutofill[]; extern const char kEnableCreditCardScan[]; -extern const char kEnableFullFormAutofillIOS[]; extern const char kEnableOfferStoreUnmaskedWalletCards[]; extern const char kEnableOfferUploadCreditCards[]; extern const char kEnablePasswordGeneration[];
diff --git a/components/autofill/ios/browser/js_autofill_manager.h b/components/autofill/ios/browser/js_autofill_manager.h index a1a797a9..6b957ca 100644 --- a/components/autofill/ios/browser/js_autofill_manager.h +++ b/components/autofill/ios/browser/js_autofill_manager.h
@@ -23,17 +23,8 @@ completionHandler: (void (^)(NSString*))completionHandler; -// Stores the current active element. This is used to make the element active -// again in case the web view loses focus when a dialog is presented over it. -- (void)storeActiveElement; - -// Clears the current active element. -- (void)clearActiveElement; - // Fills the data in JSON string |dataString| into the active form field, then -// executes the |completionHandler|. The active form field is either -// document.activeElement or the field stored by a call to storeActiveElement. -// non-null. +// executes the |completionHandler|. - (void)fillActiveFormField:(NSString*)dataString completionHandler:(ProceduralBlock)completionHandler;
diff --git a/components/autofill/ios/browser/js_autofill_manager.mm b/components/autofill/ios/browser/js_autofill_manager.mm index 84d5a72..68aa42d 100644 --- a/components/autofill/ios/browser/js_autofill_manager.mm +++ b/components/autofill/ios/browser/js_autofill_manager.mm
@@ -34,16 +34,6 @@ return @"__gCrWeb.autofill"; } -- (void)storeActiveElement { - NSString* js = @"__gCrWeb.autofill.storeActiveElement()"; - [self evaluate:js stringResultHandler:nil]; -} - -- (void)clearActiveElement { - NSString* js = @"__gCrWeb.autofill.clearActiveElement()"; - [self evaluate:js stringResultHandler:nil]; -} - - (void)fillActiveFormField:(NSString*)dataString completionHandler:(ProceduralBlock)completionHandler { web::JavaScriptCompletion resultHandler = ^void(NSString*, NSError*) {
diff --git a/components/autofill/ios/browser/resources/autofill_controller.js b/components/autofill/ios/browser/resources/autofill_controller.js index a760089..50ec736 100644 --- a/components/autofill/ios/browser/resources/autofill_controller.js +++ b/components/autofill/ios/browser/resources/autofill_controller.js
@@ -137,13 +137,6 @@ __gCrWeb.autofill.lastAutoFilledElement = null; /** - * The last element that was active (used to restore focus if necessary). - * - * @type {Element} - */ -__gCrWeb.autofill.lastActiveElement = null; - -/** * Whether CSS for autofilled elements has been injected into the page. * * @type {boolean} @@ -556,34 +549,12 @@ }; /** - * Stores the current active element. This is used to make the element active - * again in case the web view loses focus when a dialog is presented over it. - */ -__gCrWeb.autofill['storeActiveElement'] = function() { - __gCrWeb.autofill.lastActiveElement = document.activeElement; -} - -/** - * Clears the current active element by setting it to null. - */ -__gCrWeb.autofill['clearActiveElement'] = function() { - __gCrWeb.autofill.lastActiveElement = null; -} - -/** - * Fills data into the active form field. The active form field is either - * document.activeElement or the value of lastActiveElement if that value is - * non-null. + * Fills data into the active form field. * * @param {AutofillFormFieldData} data The data to fill in. */ __gCrWeb.autofill['fillActiveFormField'] = function(data) { var activeElement = document.activeElement; - if (__gCrWeb.autofill.lastActiveElement) { - activeElement = __gCrWeb.autofill.lastActiveElement; - activeElement.focus(); - __gCrWeb.autofill.lastActiveElement = null; - } if (data['name'] !== __gCrWeb['common'].nameForAutofill(activeElement)) { return; }
diff --git a/components/browser_sync/browser/BUILD.gn b/components/browser_sync/browser/BUILD.gn index b44150c..d74e2de 100644 --- a/components/browser_sync/browser/BUILD.gn +++ b/components/browser_sync/browser/BUILD.gn
@@ -97,7 +97,7 @@ ] } -source_set("test_support") { +static_library("test_support") { testonly = true sources = [ "abstract_profile_sync_service_test.cc",
diff --git a/components/browser_sync/browser/profile_sync_service.h b/components/browser_sync/browser/profile_sync_service.h index 201e3030..0e37bcf 100644 --- a/components/browser_sync/browser/profile_sync_service.h +++ b/components/browser_sync/browser/profile_sync_service.h
@@ -669,6 +669,7 @@ SYNC_INITIAL_STATE_LIMIT }; + friend class PermissionUmaUtilTest; friend class ProfileSyncServicePasswordTest; friend class SyncTest; friend class TestProfileSyncService;
diff --git a/components/browsing_data/pref_names.cc b/components/browsing_data/pref_names.cc index 5b789037..c4cb874 100644 --- a/components/browsing_data/pref_names.cc +++ b/components/browsing_data/pref_names.cc
@@ -8,9 +8,19 @@ namespace prefs { -// Clear browsing data delete time period +// Clear browsing data deletion time period. const char kDeleteTimePeriod[] = "browser.clear_data.time_period"; +// Clear Browsing Data dialog datatype preferences. +const char kDeleteBrowsingHistory[] = "browser.clear_data.browsing_history"; +const char kDeleteDownloadHistory[] = "browser.clear_data.download_history"; +const char kDeleteCache[] = "browser.clear_data.cache"; +const char kDeleteCookies[] = "browser.clear_data.cookies"; +const char kDeletePasswords[] = "browser.clear_data.passwords"; +const char kDeleteFormData[] = "browser.clear_data.form_data"; +const char kDeleteHostedAppsData[] = "browser.clear_data.hosted_apps_data"; +const char kDeleteMediaLicenses[] = "browser.clear_data.media_licenses"; + } // namespace prefs } // namespace browsing_data
diff --git a/components/browsing_data/pref_names.h b/components/browsing_data/pref_names.h index 16f20fe..8ee1e8c 100644 --- a/components/browsing_data/pref_names.h +++ b/components/browsing_data/pref_names.h
@@ -8,7 +8,18 @@ namespace browsing_data { namespace prefs { + extern const char kDeleteTimePeriod[]; + +extern const char kDeleteBrowsingHistory[]; +extern const char kDeleteDownloadHistory[]; +extern const char kDeleteCache[]; +extern const char kDeleteCookies[]; +extern const char kDeletePasswords[]; +extern const char kDeleteFormData[]; +extern const char kDeleteHostedAppsData[]; +extern const char kDeleteMediaLicenses[]; + } // namespace prefs } // namespace browsing_data
diff --git a/components/bubble/BUILD.gn b/components/bubble/BUILD.gn index 912dbad..b9e66327 100644 --- a/components/bubble/BUILD.gn +++ b/components/bubble/BUILD.gn
@@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("bubble") { +static_library("bubble") { sources = [ "bubble_close_reason.h", "bubble_controller.cc", @@ -20,7 +20,7 @@ ] } -source_set("test_support") { +static_library("test_support") { testonly = true sources = [
diff --git a/components/captive_portal/BUILD.gn b/components/captive_portal/BUILD.gn index 3d77291..c534db8 100644 --- a/components/captive_portal/BUILD.gn +++ b/components/captive_portal/BUILD.gn
@@ -20,7 +20,7 @@ ] } -source_set("test_support") { +static_library("test_support") { testonly = true sources = [ "captive_portal_testing_utils.cc",
diff --git a/components/cast_certificate/BUILD.gn b/components/cast_certificate/BUILD.gn index 7e53f20..9aec5bb 100644 --- a/components/cast_certificate/BUILD.gn +++ b/components/cast_certificate/BUILD.gn
@@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("cast_certificate") { +static_library("cast_certificate") { sources = [ "cast_cert_validator.cc", "cast_cert_validator.h", @@ -15,7 +15,7 @@ ] } -source_set("test_support") { +static_library("test_support") { testonly = true sources = [ "cast_cert_validator_test_helpers.cc",
diff --git a/components/component_updater/BUILD.gn b/components/component_updater/BUILD.gn index d01c1ade4..b2adc5a 100644 --- a/components/component_updater/BUILD.gn +++ b/components/component_updater/BUILD.gn
@@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("component_updater") { +static_library("component_updater") { sources = [ "component_updater_paths.cc", "component_updater_paths.h", @@ -32,7 +32,7 @@ ] } -source_set("test_support") { +static_library("test_support") { testonly = true sources = [ "mock_component_updater_service.cc",
diff --git a/components/components_tests.gyp b/components/components_tests.gyp index 6700418..de97a0920 100644 --- a/components/components_tests.gyp +++ b/components/components_tests.gyp
@@ -534,6 +534,7 @@ 'password_manager/core/browser/password_syncable_service_unittest.cc', 'password_manager/core/browser/password_ui_utils_unittest.cc', 'password_manager/core/browser/psl_matching_helper_unittest.cc', + 'password_manager/core/browser/sql_table_builder_unittest.cc', 'password_manager/core/browser/statistics_table_unittest.cc', 'password_manager/core/common/credential_manager_types_unittest.cc', 'password_manager/sync/browser/password_manager_setting_migrator_service_unittest.cc', @@ -807,6 +808,7 @@ 'subresource_filter/core/common/knuth_morris_pratt_unittest.cc', 'subresource_filter/core/common/ngram_extractor_unittest.cc', 'subresource_filter/core/common/string_splitter_unittest.cc', + 'subresource_filter/core/common/url_pattern_matching_unittest.cc', ], 'suggestions_unittest_sources': [ 'suggestions/blacklist_store_unittest.cc', @@ -874,6 +876,8 @@ 'tracing/core/proto_utils_unittest.cc', 'tracing/core/trace_ring_buffer_unittest.cc', 'tracing/core/scattered_stream_writer_unittest.cc', + 'tracing/test/fake_scattered_buffer.cc', + 'tracing/test/proto_zero_generation_unittest.cc', ], 'translate_unittest_sources': [ 'translate/core/browser/language_state_unittest.cc', @@ -1379,6 +1383,7 @@ 'components.gyp:zoom', 'scheduler/scheduler.gyp:scheduler', 'test_runner/test_runner.gyp:test_runner', + 'tracing.gyp:proto_zero_testing_messages', 'tracing.gyp:tracing', 'webcrypto/webcrypto.gyp:webcrypto', '../third_party/boringssl/boringssl.gyp:boringssl',
diff --git a/components/content_settings/core/common/content_settings_pattern.cc b/components/content_settings/core/common/content_settings_pattern.cc index d6dd272..aa89594 100644 --- a/components/content_settings/core/common/content_settings_pattern.cc +++ b/components/content_settings/core/common/content_settings_pattern.cc
@@ -29,7 +29,7 @@ return std::string(); } -// Returns true if |sub_domain| is a sub domain or equls |domain|. E.g. +// Returns true if |sub_domain| is a sub domain or equals |domain|. E.g. // "mail.google.com" is a sub domain of "google.com" but "evilhost.com" is not a // subdomain of "host.com". bool IsSubDomainOrEqual(const std::string& sub_domain,
diff --git a/components/crash/core/common/BUILD.gn b/components/crash/core/common/BUILD.gn index 3714a23..6cfc0fd 100644 --- a/components/crash/core/common/BUILD.gn +++ b/components/crash/core/common/BUILD.gn
@@ -2,7 +2,19 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -static_library("common") { +group("common") { + public_deps = [ + ":crash_keys", + ] + + if (is_mac || is_ios) { + public_deps += [ ":zombies" ] + } +} + +static_library("crash_keys") { + visibility = [ ":*" ] + sources = [ "crash_keys.cc", "crash_keys.h", @@ -11,12 +23,26 @@ deps = [ "//base", ] +} - if (is_mac || is_ios) { - sources += [ +if (is_mac || is_ios) { + component("zombies") { + visibility = [ ":common" ] + + sources = [ + "crash_keys.h", "objc_zombie.h", "objc_zombie.mm", ] + + defines = [ "CRASH_CORE_COMMON_IMPLEMENTATION" ] + + deps = [ + ":crash_keys", + "//base", + ] + + libs = [ "Foundation.framework" ] } }
diff --git a/components/crash/core/common/crash_export.h b/components/crash/core/common/crash_export.h new file mode 100644 index 0000000..f7c21b4 --- /dev/null +++ b/components/crash/core/common/crash_export.h
@@ -0,0 +1,29 @@ +// 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 COMPONENTS_CRASH_CORE_COMMON_CRASH_EXPORT_H_ +#define COMPONENTS_CRASH_CORE_COMMON_CRASH_EXPORT_H_ + +#if defined(COMPONENT_BUILD) +#if defined(WIN32) + +#if defined(CRASH_CORE_COMMON_IMPLEMENTATION) +#define CRASH_EXPORT __declspec(dllexport) +#else +#define CRASH_EXPORT __declspec(dllimport) +#endif // defined(CRASH_CORE_COMMON_IMPLEMENTATION) + +#else // defined(WIN32) +#if defined(CRASH_CORE_COMMON_IMPLEMENTATION) +#define CRASH_EXPORT __attribute__((visibility("default"))) +#else +#define CRASH_EXPORT +#endif // defined(CRASH_CORE_COMMON_IMPLEMENTATION) +#endif + +#else // defined(COMPONENT_BUILD) +#define CRASH_EXPORT +#endif + +#endif // COMPONENTS_CRASH_CORE_COMMON_CRASH_EXPORT_H_
diff --git a/components/crash/core/common/objc_zombie.h b/components/crash/core/common/objc_zombie.h index c023f1c..f1aa8e3f 100644 --- a/components/crash/core/common/objc_zombie.h +++ b/components/crash/core/common/objc_zombie.h
@@ -8,6 +8,7 @@ #include <stddef.h> #include "build/build_config.h" +#include "components/crash/core/common/crash_export.h" // You should think twice every single time you use anything from this // namespace. @@ -26,10 +27,10 @@ // |zombieCount| controls how many zombies to store before freeing the // oldest. Set to 0 to free objects immediately after making them // zombies. -bool ZombieEnable(bool zombieAllObjects, size_t zombieCount); +bool CRASH_EXPORT ZombieEnable(bool zombieAllObjects, size_t zombieCount); // Disable zombies. -void ZombieDisable(); +void CRASH_EXPORT ZombieDisable(); } // namespace ObjcEvilDoers
diff --git a/components/cronet/android/api/src/org/chromium/net/NetworkQualityRttListener.java b/components/cronet/android/api/src/org/chromium/net/NetworkQualityRttListener.java index 29dd1c10..c6705a9 100644 --- a/components/cronet/android/api/src/org/chromium/net/NetworkQualityRttListener.java +++ b/components/cronet/android/api/src/org/chromium/net/NetworkQualityRttListener.java
@@ -20,11 +20,6 @@ */ private final Executor mExecutor; - // TODO(tbansal): http://crbug.com/618034 Remove this constructor. - public NetworkQualityRttListener() { - mExecutor = null; - } - /** * @param executor The executor on which the observations are reported. */
diff --git a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java index 60ca98c..bbd522a 100644 --- a/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java +++ b/components/cronet/android/java/src/org/chromium/net/CronetUrlRequestContext.java
@@ -308,9 +308,6 @@ if (!mNetworkQualityEstimatorEnabled) { throw new IllegalStateException("Network quality estimator must be enabled"); } - if (mNetworkQualityExecutor == null && listener.getExecutor() == null) { - throw new IllegalStateException("Executor must not be null"); - } synchronized (mNetworkQualityLock) { if (mRttListenerList.isEmpty()) { synchronized (mLock) { @@ -496,14 +493,7 @@ listener.onRttObservation(rttMs, whenMs, source); } }; - // Use the executor provided by the listener. If not available, - // use the network quality executor. - // TODO(tbansal): Change this to always use the executor - // provided by the listener, once all embedders start providing - // a non-null executor. - Executor executor = listener.getExecutor() != null ? listener.getExecutor() - : mNetworkQualityExecutor; - postObservationTaskToExecutor(executor, task); + postObservationTaskToExecutor(listener.getExecutor(), task); } } }
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java index ee00041..0beee033 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUrlRequestContextTest.java
@@ -154,6 +154,7 @@ @SmallTest @Feature({"Cronet"}) + @SuppressWarnings("deprecation") public void testConfigUserAgent() throws Exception { String userAgentName = "User-Agent"; String userAgentValue = "User-Agent-Value"; @@ -180,8 +181,6 @@ @SmallTest @Feature({"Cronet"}) @OnlyRunNativeCronet - // TODO(xunjieli): Remove annotation after crbug.com/539519 is fixed. - @SuppressWarnings("deprecation") public void testDataReductionProxyEnabled() throws Exception { mTestFramework = startCronetTestFrameworkAndSkipLibraryInit(); @@ -244,8 +243,10 @@ } catch (IllegalStateException e) { } TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest urlRequest = - mTestFramework.mCronetEngine.createRequest(mUrl, callback, callback.getExecutor()); + UrlRequest.Builder builder = new UrlRequest.Builder( + mUrl, callback, callback.getExecutor(), mTestFramework.mCronetEngine); + UrlRequest urlRequest = builder.build(); + urlRequest.start(); callback.blockForDone(); assertEquals(0, rttListener.rttObservationCount()); @@ -255,25 +256,6 @@ @SmallTest @Feature({"Cronet"}) - public void testRealTimeNetworkQualityObservationsNotEnabled_LegacyAPI() throws Exception { - mTestFramework = startCronetTestFramework(); - TestNetworkQualityRttListener rttListener = new TestNetworkQualityRttListener(); - try { - mTestFramework.mCronetEngine.addRttListener(rttListener); - fail("Should throw an exception."); - } catch (IllegalStateException e) { - } - TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest urlRequest = - mTestFramework.mCronetEngine.createRequest(mUrl, callback, callback.getExecutor()); - urlRequest.start(); - callback.blockForDone(); - assertEquals(0, rttListener.rttObservationCount()); - mTestFramework.mCronetEngine.shutdown(); - } - - @SmallTest - @Feature({"Cronet"}) public void testRealTimeNetworkQualityObservationsListenerRemoved() throws Exception { CronetEngine.Builder mCronetEngineBuilder = new CronetEngine.Builder(getContext()); TestExecutor networkQualityExecutor = new TestExecutor(); @@ -287,8 +269,9 @@ mTestFramework.mCronetEngine.addRttListener(rttListener); mTestFramework.mCronetEngine.removeRttListener(rttListener); TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest urlRequest = - mTestFramework.mCronetEngine.createRequest(mUrl, callback, callback.getExecutor()); + UrlRequest.Builder builder = new UrlRequest.Builder( + mUrl, callback, callback.getExecutor(), mTestFramework.mCronetEngine); + UrlRequest urlRequest = builder.build(); urlRequest.start(); callback.blockForDone(); networkQualityExecutor.runAllTasks(); @@ -298,26 +281,6 @@ @SmallTest @Feature({"Cronet"}) - public void testRealTimeNetworkQualityObservationsListenerRemoved_LegacyAPI() throws Exception { - mTestFramework = startCronetTestFramework(); - TestExecutor testExecutor = new TestExecutor(); - TestNetworkQualityRttListener rttListener = new TestNetworkQualityRttListener(); - mTestFramework.mCronetEngine.enableNetworkQualityEstimator(testExecutor); - mTestFramework.mCronetEngine.configureNetworkQualityEstimatorForTesting(true, true); - mTestFramework.mCronetEngine.addRttListener(rttListener); - mTestFramework.mCronetEngine.removeRttListener(rttListener); - TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest urlRequest = - mTestFramework.mCronetEngine.createRequest(mUrl, callback, callback.getExecutor()); - urlRequest.start(); - callback.blockForDone(); - testExecutor.runAllTasks(); - assertEquals(0, rttListener.rttObservationCount()); - mTestFramework.mCronetEngine.shutdown(); - } - - @SmallTest - @Feature({"Cronet"}) public void testRealTimeNetworkQualityObservationsQuicDisabled() throws Exception { CronetEngine.Builder mCronetEngineBuilder = new CronetEngine.Builder(getContext()); Executor requestFinishedListenerExecutor = @@ -342,8 +305,9 @@ mTestFramework.mCronetEngine.addThroughputListener(throughputListener); TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest urlRequest = - mTestFramework.mCronetEngine.createRequest(mUrl, callback, callback.getExecutor()); + UrlRequest.Builder builder = new UrlRequest.Builder( + mUrl, callback, callback.getExecutor(), mTestFramework.mCronetEngine); + UrlRequest urlRequest = builder.build(); urlRequest.start(); callback.blockForDone(); @@ -373,38 +337,6 @@ mTestFramework.mCronetEngine.shutdown(); } - @SmallTest - @Feature({"Cronet"}) - public void testRealTimeNetworkQualityObservations_LegacyAPI() throws Exception { - mTestFramework = startCronetTestFramework(); - Executor executor = Executors.newSingleThreadExecutor(); - ConditionVariable waitForThroughput = new ConditionVariable(); - TestNetworkQualityRttListener rttListener = new TestNetworkQualityRttListener(); - TestNetworkQualityThroughputListener throughputListener = - new TestNetworkQualityThroughputListener(executor, waitForThroughput); - mTestFramework.mCronetEngine.enableNetworkQualityEstimator(executor); - mTestFramework.mCronetEngine.configureNetworkQualityEstimatorForTesting(true, true); - mTestFramework.mCronetEngine.addRttListener(rttListener); - mTestFramework.mCronetEngine.addThroughputListener(throughputListener); - TestUrlRequestCallback callback = new TestUrlRequestCallback(); - UrlRequest urlRequest = - mTestFramework.mCronetEngine.createRequest(mUrl, callback, callback.getExecutor()); - urlRequest.start(); - callback.blockForDone(); - - // Throughput observation is posted to the network quality estimator on the network thread - // after the UrlRequest is completed. The observations are then eventually posted to - // throughput listeners on the executor provided to network quality. - waitForThroughput.block(); - assertTrue(throughputListener.throughputObservationCount() > 0); - - // Check RTT observation count after throughput observation has been received. This ensures - // that executor has finished posting the RTT observation to the RTT listeners. - assertTrue(rttListener.rttObservationCount() > 0); - - mTestFramework.mCronetEngine.shutdown(); - } - // TODO(tbansal): http://crbug.com/618034 Remove this. private static class TestRequestFinishedListener implements CronetEngine.RequestFinishedListener {
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/TestNetworkQualityRttListener.java b/components/cronet/android/test/javatests/src/org/chromium/net/TestNetworkQualityRttListener.java index e43e4ad..afeec1f 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/TestNetworkQualityRttListener.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/TestNetworkQualityRttListener.java
@@ -20,13 +20,6 @@ private Thread mExecutorThread; - // TODO(tbansal): http://crbug.com/618034 Reomve this constructor once all - // embedders start providing a non-null executor, and the tests for legacy - // API are removed. - TestNetworkQualityRttListener() { - super(); - } - TestNetworkQualityRttListener(Executor executor) { super(executor); }
diff --git a/components/cronet/android/test/quic_test_server.cc b/components/cronet/android/test/quic_test_server.cc index 86a7a7c..60aa74b7 100644 --- a/components/cronet/android/test/quic_test_server.cc +++ b/components/cronet/android/test/quic_test_server.cc
@@ -44,13 +44,13 @@ // Set up server certs. base::FilePath directory = test_data_dir.Append("net/data/ssl/certificates"); - // TODO(xunjieli): Use scoped_ptr when crbug.com/545474 is fixed. - net::ProofSourceChromium* proof_source = new net::ProofSourceChromium(); + std::unique_ptr<net::ProofSourceChromium> proof_source( + new net::ProofSourceChromium()); CHECK(proof_source->Initialize( directory.Append("quic_test.example.com.crt"), directory.Append("quic_test.example.com.key.pkcs8"), directory.Append("quic_test.example.com.key.sct"))); - g_quic_server = new net::QuicSimpleServer(proof_source, config, + g_quic_server = new net::QuicSimpleServer(std::move(proof_source), config, net::QuicSupportedVersions()); // Start listening.
diff --git a/components/cronet/ios/test/quic_test_server.cc b/components/cronet/ios/test/quic_test_server.cc index 59a7c13..6353f4c2 100644 --- a/components/cronet/ios/test/quic_test_server.cc +++ b/components/cronet/ios/test/quic_test_server.cc
@@ -70,13 +70,13 @@ // Set up server certs. base::FilePath directory; directory = test_files_root; - // TODO(xunjieli): Use scoped_ptr when crbug.com/545474 is fixed. - net::ProofSourceChromium* proof_source = new net::ProofSourceChromium(); + std::unique_ptr<net::ProofSourceChromium> proof_source( + new net::ProofSourceChromium()); CHECK(proof_source->Initialize( directory.Append("quic_test.example.com.crt"), directory.Append("quic_test.example.com.key.pkcs8"), directory.Append("quic_test.example.com.key.sct"))); - g_quic_server = new net::QuicSimpleServer(proof_source, config, + g_quic_server = new net::QuicSimpleServer(std::move(proof_source), config, net::QuicSupportedVersions()); // Start listening.
diff --git a/components/data_reduction_proxy.gypi b/components/data_reduction_proxy.gypi index 47fd1af..6ffaa9b7 100644 --- a/components/data_reduction_proxy.gypi +++ b/components/data_reduction_proxy.gypi
@@ -73,6 +73,7 @@ 'data_reduction_proxy/core/common/data_reduction_proxy_event_store.h', 'data_reduction_proxy/core/common/data_reduction_proxy_headers.cc', 'data_reduction_proxy/core/common/data_reduction_proxy_headers.h', + 'data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.cc', 'data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.h', 'data_reduction_proxy/core/common/data_reduction_proxy_params.cc', 'data_reduction_proxy/core/common/data_reduction_proxy_params.h',
diff --git a/components/data_reduction_proxy/content/browser/content_lofi_decider.cc b/components/data_reduction_proxy/content/browser/content_lofi_decider.cc index 5fe9d03..0523f7ea 100644 --- a/components/data_reduction_proxy/content/browser/content_lofi_decider.cc +++ b/components/data_reduction_proxy/content/browser/content_lofi_decider.cc
@@ -88,4 +88,17 @@ return true; } +bool ContentLoFiDecider::ShouldRecordLoFiUMA( + const net::URLRequest& request) const { + const content::ResourceRequestInfo* request_info = + content::ResourceRequestInfo::ForRequest(&request); + + // User is not using Lo-Fi. + if (!request_info || !request_info->IsUsingLoFi()) + return false; + + return params::IsIncludedInLoFiEnabledFieldTrial() || + params::IsIncludedInLoFiControlFieldTrial(); +} + } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/content/browser/content_lofi_decider.h b/components/data_reduction_proxy/content/browser/content_lofi_decider.h index 01e0377..cc3face 100644 --- a/components/data_reduction_proxy/content/browser/content_lofi_decider.h +++ b/components/data_reduction_proxy/content/browser/content_lofi_decider.h
@@ -31,6 +31,7 @@ bool MaybeAddLoFiDirectiveToHeaders( const net::URLRequest& request, net::HttpRequestHeaders* headers) const override; + bool ShouldRecordLoFiUMA(const net::URLRequest& request) const override; private: DISALLOW_COPY_AND_ASSIGN(ContentLoFiDecider);
diff --git a/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc b/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc index cf1ffc4..a2c4341 100644 --- a/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc +++ b/components/data_reduction_proxy/content/browser/content_lofi_decider_unittest.cc
@@ -16,6 +16,7 @@ #include "base/strings/string_util.h" #include "build/build_config.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" @@ -220,6 +221,10 @@ tests[i].is_using_previews && tests[i].is_main_frame, headers); + DataReductionProxyData* data = DataReductionProxyData::GetData(*request); + // |lofi_requested| should be set to false when Lo-Fi is enabled using + // flags. + EXPECT_FALSE(data->lofi_requested()); // The Lo-Fi flag is "always-on" and Lo-Fi is being used. Lo-Fi header // should be added. @@ -242,6 +247,10 @@ headers); VerifyLoFiPreviewHeader(false, headers); VerifyLoFiIgnorePreviewBlacklistHeader(false, headers); + data = DataReductionProxyData::GetData(*request); + // |lofi_requested| should be set to false when Lo-Fi is enabled using + // flags. + EXPECT_FALSE(data->lofi_requested()); // The Lo-Fi flag is "slow-connections-only" and Lo-Fi is being used. Lo-Fi // header should be added. @@ -254,6 +263,10 @@ headers); VerifyLoFiPreviewHeader(false, headers); VerifyLoFiIgnorePreviewBlacklistHeader(false, headers); + data = DataReductionProxyData::GetData(*request); + // |lofi_requested| should be set to false when Lo-Fi is enabled using + // flags. + EXPECT_FALSE(data->lofi_requested()); } } @@ -278,6 +291,8 @@ headers); VerifyLoFiPreviewHeader(false, headers); VerifyLoFiIgnorePreviewBlacklistHeader(false, headers); + DataReductionProxyData* data = DataReductionProxyData::GetData(*request); + EXPECT_EQ(tests[i].is_using_lofi, data->lofi_requested()) << i; } } @@ -301,6 +316,8 @@ VerifyLoFiHeader(false, headers); VerifyLoFiPreviewHeader(false, headers); VerifyLoFiIgnorePreviewBlacklistHeader(false, headers); + DataReductionProxyData* data = DataReductionProxyData::GetData(*request); + EXPECT_EQ(tests[i].is_using_lofi, data->lofi_requested()) << i; } } @@ -327,6 +344,8 @@ VerifyLoFiPreviewHeader(tests[i].is_using_lofi && tests[i].is_main_frame, headers); VerifyLoFiIgnorePreviewBlacklistHeader(false, headers); + DataReductionProxyData* data = DataReductionProxyData::GetData(*request); + EXPECT_EQ(tests[i].is_using_lofi, data->lofi_requested()) << i; } }
diff --git a/components/data_reduction_proxy/core/browser/BUILD.gn b/components/data_reduction_proxy/core/browser/BUILD.gn index 2b51887..3bcd813 100644 --- a/components/data_reduction_proxy/core/browser/BUILD.gn +++ b/components/data_reduction_proxy/core/browser/BUILD.gn
@@ -96,7 +96,7 @@ } } -source_set("test_support") { +static_library("test_support") { testonly = true sources = [ "data_reduction_proxy_config_test_utils.cc",
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h index cb7c9107..4e44d72 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h
@@ -30,7 +30,9 @@ used_data_reduction_proxy_ = used_data_reduction_proxy; } - // Whether Lo-Fi was requested for this request or navigation. + // Whether Lo-Fi was requested for this request or navigation. True if the + // session is in Lo-Fi control or enabled group, and the network quality is + // slow. bool lofi_requested() const { return lofi_requested_; } void set_lofi_requested(bool lofi_requested) { lofi_requested_ = lofi_requested; @@ -65,7 +67,9 @@ // Whether the DataReductionProxy was used for this request or navigation. bool used_data_reduction_proxy_; - // Whether Lo-Fi was requested for this request or navigation. + // Whether Lo-Fi was requested for this request or navigation. True if the + // session is in Lo-Fi control or enabled group, and the network quality is + // slow. bool lofi_requested_; // The session key used for this request or navigation.
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc index 2b89856..4e11f1b 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
@@ -210,15 +210,16 @@ if (data_reduction_proxy_io_data_ && data_reduction_proxy_io_data_->lofi_decider()) { LoFiDecider* lofi_decider = data_reduction_proxy_io_data_->lofi_decider(); - bool is_using_lofi_mode = + const bool is_using_lofi_mode = lofi_decider->MaybeAddLoFiDirectiveToHeaders(*request, headers); if ((request->load_flags() & net::LOAD_MAIN_FRAME)) { data_reduction_proxy_io_data_->SetLoFiModeActiveOnMainFrame( is_using_lofi_mode); } + if (data) - data->set_lofi_requested(is_using_lofi_mode); + data->set_lofi_requested(lofi_decider->ShouldRecordLoFiUMA(*request)); } if (data_reduction_proxy_request_options_) {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc index 0c42547..8d7bd69 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
@@ -115,6 +115,10 @@ return false; } + bool ShouldRecordLoFiUMA(const net::URLRequest& request) const override { + return should_request_lofi_resource_; + } + private: bool should_request_lofi_resource_; }; @@ -189,6 +193,17 @@ EXPECT_EQ(is_preview, lofi_ui_service_->is_preview()); } + void VerifyDataReductionProxyData(const net::URLRequest& request, + bool data_reduction_proxy_used, + bool lofi_used) { + DataReductionProxyData* data = DataReductionProxyData::GetData(request); + if (!data_reduction_proxy_used) { + EXPECT_EQ(nullptr, data); + } else { + EXPECT_EQ(lofi_used, data->lofi_requested()); + } + } + // Each line in |response_headers| should end with "\r\n" and not '\0', and // the last line should have a second "\r\n". // An empty |response_headers| is allowed. It works by making this look like @@ -362,6 +377,9 @@ proxy_retry_info, &headers); VerifyHeaders(tests[i].is_data_reduction_proxy, true, headers); VerifyWasLoFiModeActiveOnMainFrame(tests[i].is_data_reduction_proxy); + VerifyDataReductionProxyData( + *fake_request, tests[i].is_data_reduction_proxy, + config()->ShouldEnableLoFiMode(*fake_request.get())); } { @@ -378,6 +396,8 @@ // Not a mainframe request, WasLoFiModeActiveOnMainFrame should still be // true if the proxy is a Data Reduction Proxy. VerifyWasLoFiModeActiveOnMainFrame(tests[i].is_data_reduction_proxy); + VerifyDataReductionProxyData(*fake_request, + tests[i].is_data_reduction_proxy, false); } { @@ -395,6 +415,8 @@ // Not a mainframe request, WasLoFiModeActiveOnMainFrame should still be // true if the proxy is a Data Reduction Proxy. VerifyWasLoFiModeActiveOnMainFrame(tests[i].is_data_reduction_proxy); + VerifyDataReductionProxyData(*fake_request, + tests[i].is_data_reduction_proxy, true); } { @@ -411,6 +433,8 @@ proxy_retry_info, &headers); VerifyHeaders(tests[i].is_data_reduction_proxy, false, headers); VerifyWasLoFiModeActiveOnMainFrame(false); + VerifyDataReductionProxyData(*fake_request, + tests[i].is_data_reduction_proxy, false); } { @@ -427,6 +451,8 @@ // Not a mainframe request, WasLoFiModeActiveOnMainFrame should still be // false. VerifyWasLoFiModeActiveOnMainFrame(false); + VerifyDataReductionProxyData(*fake_request, + tests[i].is_data_reduction_proxy, false); } { @@ -443,6 +469,9 @@ proxy_retry_info, &headers); VerifyHeaders(tests[i].is_data_reduction_proxy, true, headers); VerifyWasLoFiModeActiveOnMainFrame(tests[i].is_data_reduction_proxy); + VerifyDataReductionProxyData( + *fake_request, tests[i].is_data_reduction_proxy, + config()->ShouldEnableLoFiMode(*fake_request.get())); } } }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.cc index ece37b2..00cca9f 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.cc
@@ -5,6 +5,7 @@ #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client.h" #include "base/metrics/histogram.h" +#include "base/optional.h" #include "base/rand_util.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.h" @@ -41,25 +42,28 @@ .release()); if (request_data.original_request_url().is_valid()) request->set_first_request_url(request_data.original_request_url().spec()); - if (!timing.first_contentful_paint.is_zero()) { + if (timing.first_contentful_paint) { request->set_allocated_time_to_first_contentful_paint( protobuf_parser::CreateDurationFromTimeDelta( - timing.first_contentful_paint) + timing.first_contentful_paint.value()) .release()); } - if (!timing.first_image_paint.is_zero()) { + if (timing.first_image_paint) { request->set_allocated_time_to_first_image_paint( - protobuf_parser::CreateDurationFromTimeDelta(timing.first_image_paint) + protobuf_parser::CreateDurationFromTimeDelta( + timing.first_image_paint.value()) .release()); } - if (!timing.response_start.is_zero()) { + if (timing.response_start) { request->set_allocated_time_to_first_byte( - protobuf_parser::CreateDurationFromTimeDelta(timing.response_start) + protobuf_parser::CreateDurationFromTimeDelta( + timing.response_start.value()) .release()); } - if (!timing.load_event_start.is_zero()) { + if (timing.load_event_start) { request->set_allocated_page_load_time( - protobuf_parser::CreateDurationFromTimeDelta(timing.load_event_start) + protobuf_parser::CreateDurationFromTimeDelta( + timing.load_event_start.value()) .release()); } std::string serialized_request;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client_unittest.cc index 8131c02..50bb1308 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_pingback_client_unittest.cc
@@ -10,6 +10,7 @@ #include "base/command_line.h" #include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" +#include "base/optional.h" #include "base/test/histogram_tester.h" #include "base/time/time.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_data.h" @@ -68,10 +69,14 @@ public: DataReductionProxyPingbackClientTest() : timing_(base::Time::FromJsTime(1500), - base::TimeDelta::FromMilliseconds(1600), - base::TimeDelta::FromMilliseconds(1700), - base::TimeDelta::FromMilliseconds(1800), - base::TimeDelta::FromMilliseconds(1900)) {} + base::Optional<base::TimeDelta>( + base::TimeDelta::FromMilliseconds(1600)), + base::Optional<base::TimeDelta>( + base::TimeDelta::FromMilliseconds(1700)), + base::Optional<base::TimeDelta>( + base::TimeDelta::FromMilliseconds(1800)), + base::Optional<base::TimeDelta>( + base::TimeDelta::FromMilliseconds(1900))) {} TestDataReductionProxyPingbackClient* pingback_client() const { return pingback_client_.get(); @@ -123,15 +128,16 @@ EXPECT_EQ( timing().navigation_start, protobuf_parser::TimestampToTime(pageload_metrics.first_request_time())); - EXPECT_EQ(timing().response_start, + EXPECT_EQ(timing().response_start.value(), protobuf_parser::DurationToTimeDelta( pageload_metrics.time_to_first_byte())); - EXPECT_EQ(timing().load_event_start, protobuf_parser::DurationToTimeDelta( - pageload_metrics.page_load_time())); - EXPECT_EQ(timing().first_image_paint, + EXPECT_EQ( + timing().load_event_start.value(), + protobuf_parser::DurationToTimeDelta(pageload_metrics.page_load_time())); + EXPECT_EQ(timing().first_image_paint.value(), protobuf_parser::DurationToTimeDelta( pageload_metrics.time_to_first_image_paint())); - EXPECT_EQ(timing().first_contentful_paint, + EXPECT_EQ(timing().first_contentful_paint.value(), protobuf_parser::DurationToTimeDelta( pageload_metrics.time_to_first_contentful_paint()));
diff --git a/components/data_reduction_proxy/core/common/BUILD.gn b/components/data_reduction_proxy/core/common/BUILD.gn index f5da9da..ca83ae3f 100644 --- a/components/data_reduction_proxy/core/common/BUILD.gn +++ b/components/data_reduction_proxy/core/common/BUILD.gn
@@ -19,6 +19,7 @@ "data_reduction_proxy_event_store.h", "data_reduction_proxy_headers.cc", "data_reduction_proxy_headers.h", + "data_reduction_proxy_page_load_timing.cc", "data_reduction_proxy_page_load_timing.h", "data_reduction_proxy_params.cc", "data_reduction_proxy_params.h", @@ -57,7 +58,7 @@ ] } -source_set("test_support") { +static_library("test_support") { testonly = true sources = [ "data_reduction_proxy_event_storage_delegate_test_utils.cc",
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.cc new file mode 100644 index 0000000..fdccecb --- /dev/null +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.cc
@@ -0,0 +1,29 @@ +// 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 "components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.h" + +namespace data_reduction_proxy { + +DataReductionProxyPageLoadTiming::DataReductionProxyPageLoadTiming( + const base::Time& navigation_start, + const base::Optional<base::TimeDelta>& response_start, + const base::Optional<base::TimeDelta>& load_event_start, + const base::Optional<base::TimeDelta>& first_image_paint, + const base::Optional<base::TimeDelta>& first_contentful_paint) + : navigation_start(navigation_start), + response_start(response_start), + load_event_start(load_event_start), + first_image_paint(first_image_paint), + first_contentful_paint(first_contentful_paint) {} + +DataReductionProxyPageLoadTiming::DataReductionProxyPageLoadTiming( + const DataReductionProxyPageLoadTiming& other) + : navigation_start(other.navigation_start), + response_start(other.response_start), + load_event_start(other.load_event_start), + first_image_paint(other.first_image_paint), + first_contentful_paint(other.first_contentful_paint) {} + +} // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.h index d2d8416..0d6981b 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.h +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_page_load_timing.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_DATA_REDUCTION_PROXY_PAGE_LOAD_TIMING_H #define COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_DATA_REDUCTION_PROXY_PAGE_LOAD_TIMING_H +#include "base/optional.h" #include "base/time/time.h" namespace data_reduction_proxy { @@ -13,15 +14,13 @@ struct DataReductionProxyPageLoadTiming { DataReductionProxyPageLoadTiming( const base::Time& navigation_start, - const base::TimeDelta& response_start, - const base::TimeDelta& load_event_start, - const base::TimeDelta& first_image_paint, - const base::TimeDelta& first_contentful_paint) - : navigation_start(navigation_start), - response_start(response_start), - load_event_start(load_event_start), - first_image_paint(first_image_paint), - first_contentful_paint(first_contentful_paint) {} + const base::Optional<base::TimeDelta>& response_start, + const base::Optional<base::TimeDelta>& load_event_start, + const base::Optional<base::TimeDelta>& first_image_paint, + const base::Optional<base::TimeDelta>& first_contentful_paint); + + DataReductionProxyPageLoadTiming( + const DataReductionProxyPageLoadTiming& other); // Time that the navigation for the associated page was initiated. const base::Time navigation_start; @@ -29,15 +28,15 @@ // All TimeDeltas are relative to navigation_start // Time that the first byte of the response is received. - const base::TimeDelta response_start; + const base::Optional<base::TimeDelta> response_start; // Time immediately before the load event is fired. - const base::TimeDelta load_event_start; + const base::Optional<base::TimeDelta> load_event_start; // Time when the first image is painted. - const base::TimeDelta first_image_paint; + const base::Optional<base::TimeDelta> first_image_paint; // Time when the first contentful thing (image, text, etc.) is painted. - const base::TimeDelta first_contentful_paint; + const base::Optional<base::TimeDelta> first_contentful_paint; }; } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc index 6742221..eb7dc11d5 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
@@ -10,7 +10,6 @@ #include "base/command_line.h" #include "base/metrics/field_trial.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" @@ -56,24 +55,27 @@ const char kServerExperimentsFieldTrial[] = "DataReductionProxyServerExperiments"; +bool IsIncludedInFieldTrial(const std::string& name) { + return base::StartsWith(FieldTrialList::FindFullName(name), kEnabled, + base::CompareCase::SENSITIVE); +} + } // namespace namespace data_reduction_proxy { namespace params { bool IsIncludedInPromoFieldTrial() { - return FieldTrialList::FindFullName("DataCompressionProxyPromoVisibility") - .find(kEnabled) == 0; + return IsIncludedInFieldTrial("DataCompressionProxyPromoVisibility"); } bool IsIncludedInHoldbackFieldTrial() { - return FieldTrialList::FindFullName("DataCompressionProxyHoldback") - .find(kEnabled) == 0; + return IsIncludedInFieldTrial("DataCompressionProxyHoldback"); } -bool IsIncludedInAndroidOnePromoFieldTrial(const char* build_fingerprint) { - base::StringPiece fingerprint(build_fingerprint); - return (fingerprint.find(kAndroidOneIdentifier) != std::string::npos); +bool IsIncludedInAndroidOnePromoFieldTrial( + base::StringPiece build_fingerprint) { + return build_fingerprint.find(kAndroidOneIdentifier) != std::string::npos; } const char* GetTrustedSpdyProxyFieldTrialName() { @@ -81,8 +83,7 @@ } bool IsIncludedInTrustedSpdyProxyFieldTrial() { - return base::FieldTrialList::FindFullName(GetTrustedSpdyProxyFieldTrialName()) - .find(kEnabled) == 0; + return IsIncludedInFieldTrial(GetTrustedSpdyProxyFieldTrialName()); } const char* GetLoFiFieldTrialName() { @@ -95,20 +96,19 @@ bool IsIncludedInLoFiEnabledFieldTrial() { return !IsLoFiOnViaFlags() && !IsLoFiDisabledViaFlags() && - FieldTrialList::FindFullName(GetLoFiFieldTrialName()).find(kEnabled) == - 0; + IsIncludedInFieldTrial(GetLoFiFieldTrialName()); } bool IsIncludedInLoFiControlFieldTrial() { return !IsLoFiOnViaFlags() && !IsLoFiDisabledViaFlags() && - FieldTrialList::FindFullName(GetLoFiFieldTrialName()).find(kControl) == - 0; + base::StartsWith(FieldTrialList::FindFullName(GetLoFiFieldTrialName()), + kControl, base::CompareCase::SENSITIVE); } bool IsIncludedInLoFiPreviewFieldTrial() { return !IsLoFiOnViaFlags() && !IsLoFiDisabledViaFlags() && - FieldTrialList::FindFullName(GetLoFiFieldTrialName()).find(kPreview) == - 0; + base::StartsWith(FieldTrialList::FindFullName(GetLoFiFieldTrialName()), + kPreview, base::CompareCase::SENSITIVE); } bool IsIncludedInServerExperimentsFieldTrial() { @@ -120,8 +120,9 @@ } bool IsIncludedInTamperDetectionExperiment() { return IsIncludedInServerExperimentsFieldTrial() && - FieldTrialList::FindFullName(kServerExperimentsFieldTrial) - .find("TamperDetection_Enabled") == 0; + base::StartsWith( + FieldTrialList::FindFullName(kServerExperimentsFieldTrial), + "TamperDetection_Enabled", base::CompareCase::SENSITIVE); } bool IsLoFiOnViaFlags() { @@ -172,16 +173,12 @@ } bool WarnIfNoDataReductionProxy() { - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - data_reduction_proxy::switches:: - kEnableDataReductionProxyBypassWarning)) { - return true; - } - return false; + return base::CommandLine::ForCurrentProcess()->HasSwitch( + data_reduction_proxy::switches::kEnableDataReductionProxyBypassWarning); } bool IsIncludedInQuicFieldTrial() { - return FieldTrialList::FindFullName(kQuicFieldTrial).find(kEnabled) == 0; + return IsIncludedInFieldTrial(kQuicFieldTrial); } const char* GetQuicFieldTrialName() { @@ -332,14 +329,12 @@ DataReductionProxyTypeInfo::DataReductionProxyTypeInfo( const DataReductionProxyTypeInfo& other) = default; -DataReductionProxyTypeInfo::~DataReductionProxyTypeInfo(){ -} +DataReductionProxyTypeInfo::~DataReductionProxyTypeInfo() {} DataReductionProxyParams::DataReductionProxyParams(int flags) : DataReductionProxyParams(flags, true) {} -DataReductionProxyParams::~DataReductionProxyParams() { -} +DataReductionProxyParams::~DataReductionProxyParams() {} DataReductionProxyParams::DataReductionProxyParams(int flags, bool should_call_init)
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h index 57d4aff..a1df40a 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
@@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_PARAMS_H_ -#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_PARAMS_H_ +#ifndef COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_DATA_REDUCTION_PROXY_PARAMS_H_ +#define COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_DATA_REDUCTION_PROXY_PARAMS_H_ #include <string> #include <vector> #include "base/macros.h" +#include "base/strings/string_piece.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_config_values.h" #include "net/proxy/proxy_server.h" #include "url/gurl.h" @@ -49,7 +50,7 @@ // Returns true if this client is part of the field trial that should display // a promotion for the data reduction proxy on Android One devices. -bool IsIncludedInAndroidOnePromoFieldTrial(const char* build_fingerprint); +bool IsIncludedInAndroidOnePromoFieldTrial(base::StringPiece build_fingerprint); // Returns the name of the Lo-Fi field trial. const char* GetLoFiFieldTrialName(); @@ -252,4 +253,5 @@ }; } // namespace data_reduction_proxy -#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_PARAMS_H_ + +#endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_DATA_REDUCTION_PROXY_PARAMS_H_
diff --git a/components/data_reduction_proxy/core/common/lofi_decider.h b/components/data_reduction_proxy/core/common/lofi_decider.h index 3f0db843..1a66aad4 100644 --- a/components/data_reduction_proxy/core/common/lofi_decider.h +++ b/components/data_reduction_proxy/core/common/lofi_decider.h
@@ -32,6 +32,11 @@ virtual bool MaybeAddLoFiDirectiveToHeaders( const net::URLRequest& request, net::HttpRequestHeaders* headers) const = 0; + + // Returns true if the Lo-Fi specific UMA should be recorded. It is set to + // true if Lo-Fi is enabled for |request|, Chrome session is in Lo-Fi + // Enabled or Control field trial, and the network quality was slow. + virtual bool ShouldRecordLoFiUMA(const net::URLRequest& request) const = 0; }; } // namespace data_reduction_proxy
diff --git a/components/dom_distiller/core/BUILD.gn b/components/dom_distiller/core/BUILD.gn index 8406d9b..152b695b0 100644 --- a/components/dom_distiller/core/BUILD.gn +++ b/components/dom_distiller/core/BUILD.gn
@@ -88,7 +88,7 @@ } # GYP version: components/dom_distiller.gypi:dom_distiller_test_support -source_set("test_support") { +static_library("test_support") { testonly = true sources = [ "dom_distiller_test_util.cc",
diff --git a/components/drive/BUILD.gn b/components/drive/BUILD.gn index c5c95162..9ffcfac 100644 --- a/components/drive/BUILD.gn +++ b/components/drive/BUILD.gn
@@ -4,7 +4,7 @@ import("//third_party/protobuf/proto_library.gni") -source_set("drive") { +static_library("drive") { sources = [ "drive_api_util.cc", "drive_api_util.h", @@ -144,7 +144,7 @@ ] } -source_set("test_support") { +static_library("test_support") { testonly = true sources = [ "service/dummy_drive_service.cc", @@ -165,25 +165,27 @@ ] } -source_set("test_support_chromeos") { - testonly = true - sources = [ - "chromeos/drive_test_util.cc", - "chromeos/drive_test_util.h", - "chromeos/dummy_file_system.cc", - "chromeos/dummy_file_system.h", - "chromeos/fake_file_system.cc", - "chromeos/fake_file_system.h", - "chromeos/fake_free_disk_space_getter.cc", - "chromeos/fake_free_disk_space_getter.h", - ] - deps = [ - ":drive", - ":drive_chromeos", - ":proto", - "//base", - "//components/prefs:test_support", - "//content/test:test_support", - "//google_apis:test_support", - ] +if (is_chromeos) { + static_library("test_support_chromeos") { + testonly = true + sources = [ + "chromeos/drive_test_util.cc", + "chromeos/drive_test_util.h", + "chromeos/dummy_file_system.cc", + "chromeos/dummy_file_system.h", + "chromeos/fake_file_system.cc", + "chromeos/fake_file_system.h", + "chromeos/fake_free_disk_space_getter.cc", + "chromeos/fake_free_disk_space_getter.h", + ] + deps = [ + ":drive", + ":drive_chromeos", + ":proto", + "//base", + "//components/prefs:test_support", + "//content/test:test_support", + "//google_apis:test_support", + ] + } }
diff --git a/components/drive/job_scheduler_unittest.cc b/components/drive/job_scheduler_unittest.cc index b5624fc..005e0bec 100644 --- a/components/drive/job_scheduler_unittest.cc +++ b/components/drive/job_scheduler_unittest.cc
@@ -128,6 +128,9 @@ bool upload_new_file_cancelable_; }; +const char kHello[] = "Hello"; +const size_t kHelloLen = sizeof(kHello) - 1; + } // namespace class JobSchedulerTest : public testing::Test { @@ -928,13 +931,13 @@ // Upload job. path = temp_dir.path().AppendASCII("new_file.txt"); - ASSERT_TRUE(google_apis::test_util::WriteStringToFile(path, "Hello")); + ASSERT_TRUE(google_apis::test_util::WriteStringToFile(path, kHello)); google_apis::DriveApiErrorCode upload_error = google_apis::DRIVE_OTHER_ERROR; std::unique_ptr<google_apis::FileResource> entry; scheduler_->UploadNewFile( - fake_drive_service_->GetRootResourceId(), std::string("Hello").size(), + fake_drive_service_->GetRootResourceId(), kHelloLen, base::FilePath::FromUTF8Unsafe("drive/new_file.txt"), path, "dummy title", "plain/plain", UploadNewFileOptions(), ClientContext(BACKGROUND), google_apis::test_util::CreateCopyResultCallback(&upload_error, &entry)); @@ -952,7 +955,7 @@ base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt"); - ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello")); + ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, kHello)); // To create a pending job for testing, set the mode to cellular connection // and issue BACKGROUND jobs. @@ -963,7 +966,7 @@ google_apis::DriveApiErrorCode error1 = google_apis::DRIVE_OTHER_ERROR; std::unique_ptr<google_apis::FileResource> entry; scheduler_->UploadNewFile( - fake_drive_service_->GetRootResourceId(), std::string("Hello").size(), + fake_drive_service_->GetRootResourceId(), kHelloLen, base::FilePath::FromUTF8Unsafe("dummy/path"), upload_path, "dummy title 1", "text/plain", UploadNewFileOptions(), ClientContext(BACKGROUND), @@ -977,7 +980,7 @@ // Start the second job. google_apis::DriveApiErrorCode error2 = google_apis::DRIVE_OTHER_ERROR; scheduler_->UploadNewFile( - fake_drive_service_->GetRootResourceId(), std::string("Hello").size(), + fake_drive_service_->GetRootResourceId(), kHelloLen, base::FilePath::FromUTF8Unsafe("dummy/path"), upload_path, "dummy title 2", "text/plain", UploadNewFileOptions(), ClientContext(BACKGROUND), @@ -1000,14 +1003,14 @@ base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); base::FilePath upload_path = temp_dir.path().AppendASCII("new_file.txt"); - ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, "Hello")); + ASSERT_TRUE(google_apis::test_util::WriteStringToFile(upload_path, kHello)); // Run as a cancelable task. fake_drive_service_->set_upload_new_file_cancelable(true); google_apis::DriveApiErrorCode error1 = google_apis::DRIVE_OTHER_ERROR; std::unique_ptr<google_apis::FileResource> entry; scheduler_->UploadNewFile( - fake_drive_service_->GetRootResourceId(), std::string("Hello").size(), + fake_drive_service_->GetRootResourceId(), kHelloLen, base::FilePath::FromUTF8Unsafe("dummy/path"), upload_path, "dummy title 1", "text/plain", UploadNewFileOptions(), ClientContext(USER_INITIATED), @@ -1022,7 +1025,7 @@ fake_drive_service_->set_upload_new_file_cancelable(false); google_apis::DriveApiErrorCode error2 = google_apis::DRIVE_OTHER_ERROR; scheduler_->UploadNewFile( - fake_drive_service_->GetRootResourceId(), std::string("Hello").size(), + fake_drive_service_->GetRootResourceId(), kHelloLen, base::FilePath::FromUTF8Unsafe("dummy/path"), upload_path, "dummy title 2", "text/plain", UploadNewFileOptions(), ClientContext(USER_INITIATED),
diff --git a/components/exo.gypi b/components/exo.gypi index 680046f..9dca77f 100644 --- a/components/exo.gypi +++ b/components/exo.gypi
@@ -16,6 +16,7 @@ '../base/base.gyp:base', '../cc/cc.gyp:cc', '../cc/cc.gyp:cc_surfaces', + '../device/gamepad/gamepad.gyp:device_gamepad', '../gpu/gpu.gyp:gpu', '../skia/skia.gyp:skia', '../ui/aura/aura.gyp:aura', @@ -35,6 +36,8 @@ 'exo/buffer.h', 'exo/display.cc', 'exo/display.h', + 'exo/gamepad.cc', + 'exo/gamepad.h', 'exo/keyboard.cc', 'exo/keyboard.h', 'exo/keyboard_delegate.h', @@ -76,6 +79,7 @@ '../ipc/ipc.gyp:ipc', '../skia/skia.gyp:skia', '../third_party/wayland-protocols/wayland-protocols.gyp:alpha_compositing_protocol', + '../third_party/wayland-protocols/wayland-protocols.gyp:gaming_input_protocol', '../third_party/wayland-protocols/wayland-protocols.gyp:remote_shell_protocol', '../third_party/wayland-protocols/wayland-protocols.gyp:secure_output_protocol', '../third_party/wayland-protocols/wayland-protocols.gyp:viewporter_protocol',
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn index 1a6451c..fc04239 100644 --- a/components/exo/BUILD.gn +++ b/components/exo/BUILD.gn
@@ -11,6 +11,8 @@ "buffer.h", "display.cc", "display.h", + "gamepad.cc", + "gamepad.h", "keyboard.cc", "keyboard.h", "keyboard_delegate.h", @@ -41,6 +43,7 @@ "//base", "//cc", "//cc/surfaces:surfaces", + "//device/gamepad", "//gpu", "//gpu/command_buffer/client:gles2_interface", "//skia", @@ -83,6 +86,7 @@ sources = [ "buffer_unittest.cc", "display_unittest.cc", + "gamepad_unittest.cc", "keyboard_unittest.cc", "pointer_unittest.cc", "shared_memory_unittest.cc", @@ -97,9 +101,11 @@ ":test_support", "//ash", "//base", + "//base/test:test_support", "//cc", "//cc/surfaces:surfaces", "//components/user_manager", + "//device/gamepad:test_helpers", "//gpu/command_buffer/client:gles2_interface", "//skia", "//testing/gmock", @@ -129,6 +135,7 @@ "//ash:test_support", "//base", "//base/test:test_support", + "//device/gamepad:test_helpers", ] data_deps = [
diff --git a/components/exo/DEPS b/components/exo/DEPS index af9ba7fb..fb225746 100644 --- a/components/exo/DEPS +++ b/components/exo/DEPS
@@ -1,6 +1,7 @@ include_rules = [ "+ash", "+cc", + "+device/gamepad", "+gpu", "+third_party/khronos", "+third_party/skia",
diff --git a/components/exo/gamepad.cc b/components/exo/gamepad.cc new file mode 100644 index 0000000..dc49bce --- /dev/null +++ b/components/exo/gamepad.cc
@@ -0,0 +1,265 @@ +// 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 "components/exo/gamepad.h" + +#include <cmath> + +#include "ash/shell.h" +#include "base/bind.h" +#include "base/location.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread.h" +#include "base/threading/thread_task_runner_handle.h" +#include "components/exo/gamepad_delegate.h" +#include "components/exo/shell_surface.h" +#include "components/exo/surface.h" +#include "device/gamepad/gamepad_data_fetcher.h" +#include "device/gamepad/gamepad_platform_data_fetcher.h" +#include "ui/aura/client/focus_client.h" +#include "ui/aura/window.h" + +namespace exo { +namespace { + +constexpr double kGamepadButtonValueEpsilon = 0.001; +bool GamepadButtonValuesAreEqual(double a, double b) { + return fabs(a - b) < kGamepadButtonValueEpsilon; +} + +std::unique_ptr<device::GamepadDataFetcher> CreateGamepadPlatformDataFetcher() { + return std::unique_ptr<device::GamepadDataFetcher>( + new device::GamepadPlatformDataFetcher()); +} + +// Time between gamepad polls in milliseconds. +constexpr unsigned kPollingTimeIntervalMs = 16; + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// Gamepad::ThreadSafeGamepadChangeFetcher + +// Implements all methods and resources running on the polling thread. +// This class is reference counted to allow it to shut down safely on the +// polling thread even if the Gamepad has been destroyed on the origin thread. +class Gamepad::ThreadSafeGamepadChangeFetcher + : public base::RefCountedThreadSafe< + Gamepad::ThreadSafeGamepadChangeFetcher> { + public: + using ProcessGamepadChangesCallback = + base::Callback<void(const blink::WebGamepad)>; + + ThreadSafeGamepadChangeFetcher( + const ProcessGamepadChangesCallback& post_gamepad_changes, + const CreateGamepadDataFetcherCallback& create_fetcher_callback, + base::SingleThreadTaskRunner* task_runner) + : process_gamepad_changes_(post_gamepad_changes), + create_fetcher_callback_(create_fetcher_callback), + polling_task_runner_(task_runner), + origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) { + thread_checker_.DetachFromThread(); + } + + // Enable or disable gamepad polling. Can be called from any thread. + void EnablePolling(bool enabled) { + polling_task_runner_->PostTask( + FROM_HERE, + base::Bind( + &ThreadSafeGamepadChangeFetcher::EnablePollingOnPollingThread, + make_scoped_refptr(this), enabled)); + } + + private: + friend class base::RefCountedThreadSafe<ThreadSafeGamepadChangeFetcher>; + + virtual ~ThreadSafeGamepadChangeFetcher() {} + + // Enables or disables polling. + void EnablePollingOnPollingThread(bool enabled) { + DCHECK(thread_checker_.CalledOnValidThread()); + is_enabled_ = enabled; + + if (is_enabled_) { + if (!fetcher_) { + fetcher_ = create_fetcher_callback_.Run(); + DCHECK(fetcher_); + } + SchedulePollOnPollingThread(); + } else { + fetcher_.reset(); + } + } + + // Schedules the next poll on the polling thread. + void SchedulePollOnPollingThread() { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(fetcher_); + + if (!is_enabled_ || has_poll_scheduled_) + return; + + has_poll_scheduled_ = true; + polling_task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&ThreadSafeGamepadChangeFetcher::PollOnPollingThread, + make_scoped_refptr(this)), + base::TimeDelta::FromMilliseconds(kPollingTimeIntervalMs)); + } + + // Polls devices for new data and posts gamepad changes back to origin thread. + void PollOnPollingThread() { + DCHECK(thread_checker_.CalledOnValidThread()); + + has_poll_scheduled_ = false; + if (!is_enabled_) + return; + + DCHECK(fetcher_); + + blink::WebGamepads new_state = state_; + fetcher_->GetGamepadData(&new_state, false); + + if (std::max(new_state.length, state_.length) > 0) { + if (new_state.items[0].connected != state_.items[0].connected || + new_state.items[0].timestamp > state_.items[0].timestamp) { + origin_task_runner_->PostTask( + FROM_HERE, + base::Bind(process_gamepad_changes_, new_state.items[0])); + } + } + + state_ = new_state; + SchedulePollOnPollingThread(); + } + + // Callback to ProcessGamepadChanges using weak reference to Gamepad. + ProcessGamepadChangesCallback process_gamepad_changes_; + + // Callback method to create a gamepad data fetcher. + CreateGamepadDataFetcherCallback create_fetcher_callback_; + + // Reference to task runner on polling thread. + base::SingleThreadTaskRunner* polling_task_runner_; + + // Reference to task runner on origin thread. + scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_; + + // Gamepad data fetcher used for querying gamepad devices. + std::unique_ptr<device::GamepadDataFetcher> fetcher_; + + // The current state of all gamepads. + blink::WebGamepads state_; + + // True if a poll has been scheduled. + bool has_poll_scheduled_ = false; + + // True if the polling thread is paused. + bool is_enabled_ = false; + + // ThreadChecker for the polling thread. + base::ThreadChecker thread_checker_; + + DISALLOW_COPY_AND_ASSIGN(ThreadSafeGamepadChangeFetcher); +}; + +//////////////////////////////////////////////////////////////////////////////// +// Gamepad, public: + +Gamepad::Gamepad(GamepadDelegate* delegate, + base::SingleThreadTaskRunner* polling_task_runner) + : Gamepad(delegate, + polling_task_runner, + base::Bind(CreateGamepadPlatformDataFetcher)) {} + +Gamepad::Gamepad(GamepadDelegate* delegate, + base::SingleThreadTaskRunner* polling_task_runner, + CreateGamepadDataFetcherCallback create_fetcher_callback) + : delegate_(delegate), weak_factory_(this) { + gamepad_change_fetcher_ = new ThreadSafeGamepadChangeFetcher( + base::Bind(&Gamepad::ProcessGamepadChanges, weak_factory_.GetWeakPtr()), + create_fetcher_callback, polling_task_runner); + + aura::client::FocusClient* focus_client = + aura::client::GetFocusClient(ash::Shell::GetPrimaryRootWindow()); + focus_client->AddObserver(this); + OnWindowFocused(focus_client->GetFocusedWindow(), nullptr); +} + +Gamepad::~Gamepad() { + // Disable polling. Since ThreadSafeGamepadChangeFetcher are reference + // counted, we can safely have it shut down after Gamepad has been destroyed. + gamepad_change_fetcher_->EnablePolling(false); + + delegate_->OnGamepadDestroying(this); + aura::client::GetFocusClient(ash::Shell::GetPrimaryRootWindow()) + ->RemoveObserver(this); +} + +//////////////////////////////////////////////////////////////////////////////// +// aura::client::FocusChangeObserver overrides: + +void Gamepad::OnWindowFocused(aura::Window* gained_focus, + aura::Window* lost_focus) { + DCHECK(thread_checker_.CalledOnValidThread()); + Surface* target = nullptr; + if (gained_focus) { + target = Surface::AsSurface(gained_focus); + if (!target) { + aura::Window* top_level_window = gained_focus->GetToplevelWindow(); + if (top_level_window) + target = ShellSurface::GetMainSurface(top_level_window); + } + } + + bool focused = target && delegate_->CanAcceptGamepadEventsForSurface(target); + gamepad_change_fetcher_->EnablePolling(focused); +} + +//////////////////////////////////////////////////////////////////////////////// +// Gamepad, private: + +void Gamepad::ProcessGamepadChanges(const blink::WebGamepad new_pad) { + DCHECK(thread_checker_.CalledOnValidThread()); + bool send_frame = false; + + // Update connection state. + if (new_pad.connected != pad_state_.connected) { + delegate_->OnStateChange(new_pad.connected); + } + + if (!new_pad.connected || new_pad.timestamp <= pad_state_.timestamp) { + pad_state_ = new_pad; + return; + } + + // Notify delegate of updated axes. + for (size_t axis = 0; + axis < std::max(pad_state_.axesLength, new_pad.axesLength); ++axis) { + if (!GamepadButtonValuesAreEqual(new_pad.axes[axis], + pad_state_.axes[axis])) { + send_frame = true; + delegate_->OnAxis(axis, new_pad.axes[axis]); + } + } + + // Notify delegate of updated buttons. + for (size_t button_id = 0; + button_id < std::max(pad_state_.buttonsLength, new_pad.buttonsLength); + ++button_id) { + auto button = pad_state_.buttons[button_id]; + auto new_button = new_pad.buttons[button_id]; + if (button.pressed != new_button.pressed || + !GamepadButtonValuesAreEqual(button.value, new_button.value)) { + send_frame = true; + delegate_->OnButton(button_id, new_button.pressed, new_button.value); + } + } + if (send_frame) + delegate_->OnFrame(); + + pad_state_ = new_pad; +} + +} // namespace exo
diff --git a/components/exo/gamepad.h b/components/exo/gamepad.h new file mode 100644 index 0000000..578a8d12 --- /dev/null +++ b/components/exo/gamepad.h
@@ -0,0 +1,71 @@ +// 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 COMPONENTS_EXO_GAMEPAD_H_ +#define COMPONENTS_EXO_GAMEPAD_H_ + +#include <memory> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/sequenced_task_runner.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread.h" +#include "base/threading/thread_task_runner_handle.h" +#include "device/gamepad/gamepad_data_fetcher.h" +#include "ui/aura/client/focus_change_observer.h" + +namespace exo { +class GamepadDelegate; + +using CreateGamepadDataFetcherCallback = + base::Callback<std::unique_ptr<device::GamepadDataFetcher>()>; + +// This class represents one or more gamepads, it uses a background thread +// for polling gamepad devices and notifies the GamepadDelegate of any +// changes. +class Gamepad : public aura::client::FocusChangeObserver { + public: + // This class will post tasks to invoke the delegate on the thread runner + // which is associated with the thread that is creating this instance. + Gamepad(GamepadDelegate* delegate, + base::SingleThreadTaskRunner* polling_task_runner); + // Allows test cases to specify a CreateGamepadDataFetcherCallback that + // overrides the default GamepadPlatformDataFetcher. + Gamepad(GamepadDelegate* delegate, + base::SingleThreadTaskRunner* polling_task_runner, + CreateGamepadDataFetcherCallback create_fetcher_callback); + ~Gamepad() override; + + // Overridden aura::client::FocusChangeObserver: + void OnWindowFocused(aura::Window* gained_focus, + aura::Window* lost_focus) override; + + private: + class ThreadSafeGamepadChangeFetcher; + + // Processes updates of gamepad data and passes changes on to delegate. + void ProcessGamepadChanges(const blink::WebGamepad new_pad); + + // Private implementation of methods and resources that are used on the + // polling thread. + scoped_refptr<ThreadSafeGamepadChangeFetcher> gamepad_change_fetcher_; + + // The delegate instance that all events are dispatched to. + GamepadDelegate* const delegate_; + + // The current state of the gamepad represented by this instance. + blink::WebGamepad pad_state_; + + // ThreadChecker for the origin thread. + base::ThreadChecker thread_checker_; + + base::WeakPtrFactory<Gamepad> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(Gamepad); +}; + +} // namespace exo + +#endif // COMPONENTS_EXO_GAMEPAD_H_
diff --git a/components/exo/gamepad_delegate.h b/components/exo/gamepad_delegate.h new file mode 100644 index 0000000..5304413 --- /dev/null +++ b/components/exo/gamepad_delegate.h
@@ -0,0 +1,46 @@ +// 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 COMPONENTS_EXO_GAMEPAD_DELEGATE_H_ +#define COMPONENTS_EXO_GAMEPAD_DELEGATE_H_ + +#include "base/memory/weak_ptr.h" + +namespace exo { +class Gamepad; +class Surface; + +// Handles events on multiple gamepad +class GamepadDelegate { + public: + // Gives the delegate a chance to clean up when the Gamepad instance is + // destroyed. + virtual void OnGamepadDestroying(Gamepad* gamepad) = 0; + + // This should return true if |surface| is a valid target for this gamepad. + // E.g. the surface is owned by the same client as the gamepad. + virtual bool CanAcceptGamepadEventsForSurface(Surface* surface) const = 0; + + // Called when the state of the gamepad has changed. + virtual void OnStateChange(bool connected) = 0; + + // Called when the user moved an axis of the gamepad. Valid axes are defined + // by the W3C 'standard gamepad' specification. + virtual void OnAxis(int axis, double value) = 0; + + // Called when the user pressed or moved a button of the gamepad. + // Valid buttons are defined by the W3C 'standard gamepad' specification. + virtual void OnButton(int button, bool pressed, double value) = 0; + + // Called after all gamepad information of this frame has been set and the + // client should evaluate the updated state. + virtual void OnFrame() = 0; + + protected: + virtual ~GamepadDelegate() {} +}; + +} // namespace exo + +#endif // COMPONENTS_EXO_GAMEPAD_DELEGATE_H_
diff --git a/components/exo/gamepad_unittest.cc b/components/exo/gamepad_unittest.cc new file mode 100644 index 0000000..98d3e024 --- /dev/null +++ b/components/exo/gamepad_unittest.cc
@@ -0,0 +1,221 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/shell.h" +#include "base/command_line.h" +#include "base/test/test_simple_task_runner.h" +#include "components/exo/buffer.h" +#include "components/exo/gamepad.h" +#include "components/exo/gamepad_delegate.h" +#include "components/exo/shell_surface.h" +#include "components/exo/surface.h" +#include "components/exo/test/exo_test_base.h" +#include "components/exo/test/exo_test_helper.h" +#include "device/gamepad/gamepad_test_helpers.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/aura/client/focus_client.h" + +namespace exo { +namespace { + +class MockGamepadDelegate : public GamepadDelegate { + public: + MockGamepadDelegate() {} + + // Overridden from GamepadDelegate: + MOCK_METHOD1(OnGamepadDestroying, void(Gamepad*)); + MOCK_CONST_METHOD1(CanAcceptGamepadEventsForSurface, bool(Surface*)); + MOCK_METHOD1(OnStateChange, void(bool)); + MOCK_METHOD2(OnAxis, void(int, double)); + MOCK_METHOD3(OnButton, void(int, bool, double)); + MOCK_METHOD0(OnFrame, void()); +}; + +class GamepadTest : public test::ExoTestBase { + public: + GamepadTest() {} + + std::unique_ptr<device::GamepadDataFetcher> MockDataFetcherFactory() { + blink::WebGamepads initial_data; + std::unique_ptr<device::MockGamepadDataFetcher> fetcher( + new device::MockGamepadDataFetcher(initial_data)); + mock_data_fetcher_ = fetcher.get(); + return std::move(fetcher); + } + + void InitializeGamepad(MockGamepadDelegate* delegate) { + polling_task_runner_ = new base::TestSimpleTaskRunner(); + gamepad_.reset(new Gamepad(delegate, polling_task_runner_.get(), + base::Bind(&GamepadTest::MockDataFetcherFactory, + base::Unretained(this)))); + // Run the polling task runner to have it create the data fetcher. + polling_task_runner_->RunPendingTasks(); + } + + void DestroyGamepad(MockGamepadDelegate* delegate) { + EXPECT_CALL(*delegate, OnGamepadDestroying(testing::_)).Times(1); + mock_data_fetcher_ = nullptr; + gamepad_.reset(); + // Process tasks until polling is shut down. + polling_task_runner_->RunPendingTasks(); + polling_task_runner_ = nullptr; + } + + void SetDataAndPostToDelegate(const blink::WebGamepads& new_data) { + ASSERT_TRUE(mock_data_fetcher_ != nullptr); + mock_data_fetcher_->SetTestData(new_data); + // Run one polling cycle, which will post a task to the origin task runner. + polling_task_runner_->RunPendingTasks(); + // Run origin task runner to invoke delegate. + base::MessageLoop::current()->RunUntilIdle(); + } + + protected: + std::unique_ptr<Gamepad> gamepad_; + + // Task runner to simulate the polling thread. + scoped_refptr<base::TestSimpleTaskRunner> polling_task_runner_; + + // Weak reference to the mock data fetcher provided by MockDataFetcherFactory. + // This instance is valid until both gamepad_ and polling_task_runner_ are + // shut down. + device::MockGamepadDataFetcher* mock_data_fetcher_; + + DISALLOW_COPY_AND_ASSIGN(GamepadTest); +}; + +TEST_F(GamepadTest, OnStateChange) { + std::unique_ptr<Surface> surface(new Surface); + std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); + gfx::Size buffer_size(10, 10); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + surface->Attach(buffer.get()); + surface->Commit(); + + testing::StrictMock<MockGamepadDelegate> delegate; + EXPECT_CALL(delegate, CanAcceptGamepadEventsForSurface(testing::_)) + .WillOnce(testing::Return(true)); + + InitializeGamepad(&delegate); + + // Gamepad connected. + EXPECT_CALL(delegate, OnStateChange(true)).Times(1); + blink::WebGamepads gamepad_connected; + gamepad_connected.length = 1; + gamepad_connected.items[0].connected = true; + gamepad_connected.items[0].timestamp = 1; + SetDataAndPostToDelegate(gamepad_connected); + + // Gamepad disconnected. + blink::WebGamepads all_disconnected; + EXPECT_CALL(delegate, OnStateChange(false)).Times(1); + SetDataAndPostToDelegate(all_disconnected); + + DestroyGamepad(&delegate); +} + +TEST_F(GamepadTest, OnAxis) { + std::unique_ptr<Surface> surface(new Surface); + std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); + gfx::Size buffer_size(10, 10); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + surface->Attach(buffer.get()); + surface->Commit(); + + testing::StrictMock<MockGamepadDelegate> delegate; + EXPECT_CALL(delegate, CanAcceptGamepadEventsForSurface(testing::_)) + .WillOnce(testing::Return(true)); + + InitializeGamepad(&delegate); + + blink::WebGamepads axis_moved; + axis_moved.length = 1; + axis_moved.items[0].connected = true; + axis_moved.items[0].timestamp = 1; + axis_moved.items[0].axesLength = 1; + axis_moved.items[0].axes[0] = 1.0; + + EXPECT_CALL(delegate, OnStateChange(true)).Times(1); + EXPECT_CALL(delegate, OnAxis(0, 1.0)).Times(1); + EXPECT_CALL(delegate, OnFrame()).Times(1); + SetDataAndPostToDelegate(axis_moved); + + DestroyGamepad(&delegate); +} + +TEST_F(GamepadTest, OnButton) { + std::unique_ptr<Surface> surface(new Surface); + std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); + gfx::Size buffer_size(10, 10); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + surface->Attach(buffer.get()); + surface->Commit(); + + testing::StrictMock<MockGamepadDelegate> delegate; + EXPECT_CALL(delegate, CanAcceptGamepadEventsForSurface(testing::_)) + .WillOnce(testing::Return(true)); + + InitializeGamepad(&delegate); + + blink::WebGamepads axis_moved; + axis_moved.length = 1; + axis_moved.items[0].connected = true; + axis_moved.items[0].timestamp = 1; + axis_moved.items[0].buttonsLength = 1; + axis_moved.items[0].buttons[0].pressed = true; + axis_moved.items[0].buttons[0].value = 1.0; + + EXPECT_CALL(delegate, OnStateChange(true)).Times(1); + EXPECT_CALL(delegate, OnButton(0, true, 1.0)).Times(1); + EXPECT_CALL(delegate, OnFrame()).Times(1); + SetDataAndPostToDelegate(axis_moved); + + DestroyGamepad(&delegate); +} + +TEST_F(GamepadTest, OnWindowFocused) { + // Create surface and move focus to it. + std::unique_ptr<Surface> surface(new Surface); + std::unique_ptr<ShellSurface> shell_surface(new ShellSurface(surface.get())); + gfx::Size buffer_size(10, 10); + std::unique_ptr<Buffer> buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(buffer_size))); + surface->Attach(buffer.get()); + surface->Commit(); + + testing::StrictMock<MockGamepadDelegate> delegate; + EXPECT_CALL(delegate, CanAcceptGamepadEventsForSurface(testing::_)) + .WillOnce(testing::Return(true)); + + InitializeGamepad(&delegate); + + // In focus. Should be polling indefinitely, check a couple of time that the + // poll task is re-posted. + for (size_t i = 0; i < 5; ++i) { + polling_task_runner_->RunPendingTasks(); + ASSERT_TRUE(polling_task_runner_->HasPendingTask()); + } + + // Remove focus from window. + aura::client::FocusClient* focus_client = + aura::client::GetFocusClient(ash::Shell::GetPrimaryRootWindow()); + focus_client->FocusWindow(nullptr); + + // Run EnablePolling and OnPoll task, no more polls should be scheduled. + // In the first round of RunPendingTasks we will execute + // EnablePollingOnPollingThread, which will cause the polling to stop being + // scheduled in the next round. + polling_task_runner_->RunPendingTasks(); + polling_task_runner_->RunPendingTasks(); + ASSERT_FALSE(polling_task_runner_->HasPendingTask()); + + DestroyGamepad(&delegate); +} + +} // namespace +} // namespace exo
diff --git a/components/exo/surface.cc b/components/exo/surface.cc index 0822a3d..bd1167f3 100644 --- a/components/exo/surface.cc +++ b/components/exo/surface.cc
@@ -145,7 +145,7 @@ const cc::SurfaceSequence& sequence) { std::vector<uint32_t> sequences; sequences.push_back(sequence.sequence); - manager->DidSatisfySequences(sequence.id_namespace, &sequences); + manager->DidSatisfySequences(sequence.client_id, &sequences); } void RequireCallback(cc::SurfaceManager* manager, @@ -610,7 +610,7 @@ SetSurfaceLayerContents(new_layer); } -void Surface::WillDraw(cc::SurfaceId id) { +void Surface::WillDraw(const cc::SurfaceId& id) { while (!active_frame_callbacks_.empty()) { active_frame_callbacks_.front().Run(base::TimeTicks::Now()); active_frame_callbacks_.pop_front();
diff --git a/components/exo/surface.h b/components/exo/surface.h index 2db6298..9a36ab7 100644 --- a/components/exo/surface.h +++ b/components/exo/surface.h
@@ -102,7 +102,7 @@ aura::Window* window() { return window_.get(); } - cc::SurfaceId surface_id() const { return surface_id_; } + const cc::SurfaceId& surface_id() const { return surface_id_; } // Set a buffer as the content of this surface. A buffer can only be attached // to one surface at a time. @@ -215,7 +215,7 @@ // Overridden from ui::ContextFactoryObserver. void OnLostResources() override; - void WillDraw(cc::SurfaceId surface_id); + void WillDraw(const cc::SurfaceId& surface_id); // Check whether this Surface and its children need to create new cc::Surface // IDs for their contents next time they get new buffer contents.
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn index 36c21f3b..2f9e61513 100644 --- a/components/exo/wayland/BUILD.gn +++ b/components/exo/wayland/BUILD.gn
@@ -31,10 +31,12 @@ "//ash", "//base", "//components/exo", + "//device/gamepad", "//ipc:ipc", "//skia", "//third_party/wayland:wayland_server", "//third_party/wayland-protocols:alpha_compositing_protocol", + "//third_party/wayland-protocols:gaming_input_protocol", "//third_party/wayland-protocols:remote_shell_protocol", "//third_party/wayland-protocols:secure_output_protocol", "//third_party/wayland-protocols:viewporter_protocol",
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc index 0e7e730a..ee3a25a 100644 --- a/components/exo/wayland/server.cc +++ b/components/exo/wayland/server.cc
@@ -14,6 +14,7 @@ // Note: core wayland headers need to be included before protocol headers. #include <alpha-compositing-unstable-v1-server-protocol.h> // NOLINT +#include <gaming-input-unstable-v1-server-protocol.h> // NOLINT #include <remote-shell-unstable-v1-server-protocol.h> // NOLINT #include <secure-output-unstable-v1-server-protocol.h> // NOLINT #include <xdg-shell-unstable-v5-server-protocol.h> // NOLINT @@ -40,9 +41,12 @@ #include "base/memory/weak_ptr.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "base/threading/thread.h" #include "base/threading/thread_task_runner_handle.h" #include "components/exo/buffer.h" #include "components/exo/display.h" +#include "components/exo/gamepad.h" +#include "components/exo/gamepad_delegate.h" #include "components/exo/keyboard.h" #include "components/exo/keyboard_delegate.h" #include "components/exo/notification_surface.h" @@ -131,6 +135,10 @@ return (ticks - base::TimeTicks()).InMilliseconds(); } +uint32_t NowInMilliseconds() { + return TimeTicksToMilliseconds(base::TimeTicks::Now()); +} + // A property key containing the surface resource that is associated with // window. If unset, no surface resource is associated with window. DEFINE_SURFACE_PROPERTY_KEY(wl_resource*, kSurfaceResourceKey, nullptr); @@ -2794,6 +2802,96 @@ data, nullptr); } +//////////////////////////////////////////////////////////////////////////////// +// gaming_input_interface: + +// Gamepad delegate class that forwards gamepad events to the client resource. +class WaylandGamepadDelegate : public GamepadDelegate { + public: + explicit WaylandGamepadDelegate(wl_resource* gamepad_resource) + : gamepad_resource_(gamepad_resource) {} + + // Overridden from GamepadDelegate: + void OnGamepadDestroying(Gamepad* gamepad) override { delete this; } + bool CanAcceptGamepadEventsForSurface(Surface* surface) const override { + wl_resource* surface_resource = GetSurfaceResource(surface); + return surface_resource && + wl_resource_get_client(surface_resource) == client(); + } + void OnStateChange(bool connected) override { + uint32_t status = connected ? ZWP_GAMEPAD_V1_GAMEPAD_STATE_ON + : ZWP_GAMEPAD_V1_GAMEPAD_STATE_OFF; + zwp_gamepad_v1_send_state_change(gamepad_resource_, status); + wl_client_flush(client()); + } + void OnAxis(int axis, double value) override { + zwp_gamepad_v1_send_axis(gamepad_resource_, NowInMilliseconds(), axis, + wl_fixed_from_double(value)); + } + void OnButton(int button, bool pressed, double value) override { + uint32_t state = pressed ? ZWP_GAMEPAD_V1_BUTTON_STATE_PRESSED + : ZWP_GAMEPAD_V1_BUTTON_STATE_RELEASED; + zwp_gamepad_v1_send_button(gamepad_resource_, NowInMilliseconds(), button, + state, wl_fixed_from_double(value)); + } + void OnFrame() override { + zwp_gamepad_v1_send_frame(gamepad_resource_, NowInMilliseconds()); + wl_client_flush(client()); + } + + private: + // The client who own this gamepad instance. + wl_client* client() const { + return wl_resource_get_client(gamepad_resource_); + } + + // The gamepad resource associated with the gamepad. + wl_resource* const gamepad_resource_; + + DISALLOW_COPY_AND_ASSIGN(WaylandGamepadDelegate); +}; + +void gamepad_destroy(wl_client* client, wl_resource* resource) { + wl_resource_destroy(resource); +} + +const struct zwp_gamepad_v1_interface gamepad_implementation = { + gamepad_destroy}; + +void gaming_input_get_gamepad(wl_client* client, + wl_resource* resource, + uint32_t id, + wl_resource* seat) { + wl_resource* gamepad_resource = wl_resource_create( + client, &zwp_gamepad_v1_interface, wl_resource_get_version(resource), id); + + base::Thread* gaming_input_thread = GetUserDataAs<base::Thread>(resource); + + SetImplementation( + gamepad_resource, &gamepad_implementation, + base::WrapUnique(new Gamepad(new WaylandGamepadDelegate(gamepad_resource), + gaming_input_thread->task_runner().get()))); +} + +const struct zwp_gaming_input_v1_interface gaming_input_implementation = { + gaming_input_get_gamepad}; + +void bind_gaming_input(wl_client* client, + void* data, + uint32_t version, + uint32_t id) { + wl_resource* resource = + wl_resource_create(client, &zwp_gaming_input_v1_interface, version, id); + + std::unique_ptr<base::Thread> gaming_input_thread( + new base::Thread("Exo gaming input polling thread.")); + gaming_input_thread->StartWithOptions( + base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); + + SetImplementation(resource, &gaming_input_implementation, + std::move(gaming_input_thread)); +} + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -2832,6 +2930,8 @@ display_, bind_alpha_compositing); wl_global_create(wl_display_.get(), &zwp_remote_shell_v1_interface, remote_shell_version, display_, bind_remote_shell); + wl_global_create(wl_display_.get(), &zwp_gaming_input_v1_interface, 1, + display_, bind_gaming_input); } Server::~Server() {}
diff --git a/components/flags_ui/feature_entry.cc b/components/flags_ui/feature_entry.cc index 53a219c..80ea2a72 100644 --- a/components/flags_ui/feature_entry.cc +++ b/components/flags_ui/feature_entry.cc
@@ -41,11 +41,10 @@ if (index == 0) { description_id = IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT; } else if (index == 1) { - // Variation 1: the default enabled variation => "Enabled". description_id = IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED; } else if (index < num_options - 1) { - // Variations 2 .. n => "Enabled <description_text>". - int variation_index = index - 1; + // First two options do not have variations params. + int variation_index = index - 2; return l10n_util::GetStringUTF16(IDS_GENERIC_EXPERIMENT_CHOICE_ENABLED) + base::ASCIIToUTF16(" ") + base::ASCIIToUTF16( @@ -86,11 +85,12 @@ type == FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE); DCHECK_LT(index, num_options); - if (type == FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE && index > 0 && + if (type == FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE && index > 1 && index < num_options - 1) { // We have no variations for FEATURE_VALUE type. Option at |index| - // corresponds to variation at |index| - 1 as the first option is "Default". - return &feature_variations[index - 1]; + // corresponds to variation at |index| - 2 as the list starts with "Default" + // and "Enabled" (with default parameters). + return &feature_variations[index - 2]; } return nullptr; }
diff --git a/components/flags_ui/feature_entry.h b/components/flags_ui/feature_entry.h index a3930fd..5c44bc33 100644 --- a/components/flags_ui/feature_entry.h +++ b/components/flags_ui/feature_entry.h
@@ -50,10 +50,12 @@ // Corresponds to a base::Feature and additional options [O_1, ..., O_n] // that specify variation parameters. Each of the options can specify a set - // of variation parameters. The entry will have n+2 states: Default, - // Enabled: V_1, ..., Enabled: V_n, Disabled. When not specified or set to - // Default, the normal default values of the feature and of the parameters - // are used. + // of variation parameters. The entry will have n+3 states: Default, + // Enabled, Enabled V_1, ..., Enabled: V_n, Disabled. When set to Default, + // the normal default values of the feature and of the parameters are used + // (possibly passed from the server in a trial config). When set to Enabled, + // the feature is overriden to be enabled and empty set of parameters is + // used boiling down to the default behavior in the code. FEATURE_WITH_VARIATIONS_VALUE, };
diff --git a/components/flags_ui/feature_entry_macros.h b/components/flags_ui/feature_entry_macros.h index 9394b3730..f83ce31 100644 --- a/components/flags_ui/feature_entry_macros.h +++ b/components/flags_ui/feature_entry_macros.h
@@ -35,7 +35,7 @@ #define FEATURE_WITH_VARIATIONS_VALUE_TYPE(feature, feature_variations, \ feature_trial) \ flags_ui::FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE, nullptr, nullptr, \ - nullptr, nullptr, &feature, 2 + arraysize(feature_variations), nullptr, \ + nullptr, nullptr, &feature, 3 + arraysize(feature_variations), nullptr, \ feature_variations, feature_trial #endif // COMPONENTS_FLAGS_UI_FEATURE_ENTRY_MACROS_H_
diff --git a/components/flags_ui/flags_state.cc b/components/flags_ui/flags_state.cc index cadb8ee1..441949bc 100644 --- a/components/flags_ui/flags_state.cc +++ b/components/flags_ui/flags_state.cc
@@ -199,11 +199,14 @@ // |kTrialGroupAboutFlags|. void RegisterFeatureVariationParameters( const std::string& feature_trial_name, - const FeatureEntry::FeatureVariation& feature_variation) { + const FeatureEntry::FeatureVariation* feature_variation) { std::map<std::string, std::string> params; - for (int i = 0; i < feature_variation.num_params; ++i) { - params[feature_variation.params[i].param_name] = - feature_variation.params[i].param_value; + if (feature_variation) { + // Copy the parameters for non-null variations. + for (int i = 0; i < feature_variation->num_params; ++i) { + params[feature_variation->params[i].param_name] = + feature_variation->params[i].param_value; + } } bool success = variations::AssociateVariationParams( @@ -443,9 +446,10 @@ for (int j = 0; j < e.num_options; ++j) { const FeatureEntry::FeatureVariation* variation = e.VariationForOption(j); - if (variation != nullptr && enabled_entries.count(e.NameForOption(j))) { - // If the option is selected by the user & has variation, register it. - RegisterFeatureVariationParameters(e.feature_trial_name, *variation); + if (e.StateForOption(j) == FeatureEntry::FeatureState::ENABLED && + enabled_entries.count(e.NameForOption(j))) { + // If the option is enabled by the user, register it. + RegisterFeatureVariationParameters(e.feature_trial_name, variation); // TODO(jkrcal) The code does not associate the feature with the field // trial |e.feature_trial_name|. The reason is that features // overridden in chrome://flags are translated to command-line flags
diff --git a/components/flags_ui/flags_state_unittest.cc b/components/flags_ui/flags_state_unittest.cc index b95373a5..cc0a206 100644 --- a/components/flags_ui/flags_state_unittest.cc +++ b/components/flags_ui/flags_state_unittest.cc
@@ -62,22 +62,17 @@ const char kTestTrial[] = "TestTrial"; const char kTestParam[] = "param"; -const char kTestParamValue1[] = "value1"; -const char kTestParamValue2[] = "value2"; +const char kTestParamValue[] = "value"; const base::Feature kTestFeature1{"FeatureName1", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kTestFeature2{"FeatureName2", base::FEATURE_ENABLED_BY_DEFAULT}; -const FeatureEntry::FeatureParam kTestVariationDefault[] = { - {kTestParam, kTestParamValue1}}; - const FeatureEntry::FeatureParam kTestVariationOther[] = { - {kTestParam, kTestParamValue2}}; + {kTestParam, kTestParamValue}}; const FeatureEntry::FeatureVariation kTestVariations[] = { - {"", kTestVariationDefault, 1}, {"dummy description", kTestVariationOther, 1}}; // Those have to be valid ids for the translation system but the value are @@ -148,6 +143,10 @@ flags_state_.reset(new FlagsState(kEntries, arraysize(kEntries))); } + ~FlagsStateTest() override { + variations::testing::ClearAllVariationParams(); + } + TestingPrefServiceSimple prefs_; PrefServiceFlagsStorage flags_storage_; std::unique_ptr<FlagsState> flags_state_; @@ -268,7 +267,7 @@ TEST_F(FlagsStateTest, RegisterAllFeatureVariationParameters) { const FeatureEntry& entry = kEntries[7]; - // Select the "Disabled" variation. + // Select the "Default" variation. flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(0), true); flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_); @@ -278,13 +277,13 @@ base::FieldTrial* trial = base::FieldTrialList::Find(kTestTrial); EXPECT_EQ(nullptr, trial); - // Select the first "Enabled" variation. + // Select the default "Enabled" variation. flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(1), true); flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_); - // The value should be associated. - EXPECT_EQ(kTestParamValue1, + // No value should be associated as this is the default option. + EXPECT_EQ("", variations::GetVariationParamValue(kTestTrial, kTestParam)); // The trial should be created. @@ -293,12 +292,23 @@ // The about:flags group should be selected for the trial. EXPECT_EQ(internal::kTrialGroupAboutFlags, trial->group_name()); - // Select the second "Enabled" variation. + // Select the only one variation. flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2), true); flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_); // Associating for the second time should not change the value. - EXPECT_EQ(kTestParamValue1, + EXPECT_EQ("", + variations::GetVariationParamValue(kTestTrial, kTestParam)); +} + +TEST_F(FlagsStateTest, RegisterAllFeatureVariationParametersNonDefault) { + const FeatureEntry& entry = kEntries[7]; + // Select the only one variation. + flags_state_->SetFeatureEntryEnabled(&flags_storage_, entry.NameForOption(2), + true); + flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_); + // The param should have the value predefined in this variation. + EXPECT_EQ(kTestParamValue, variations::GetVariationParamValue(kTestTrial, kTestParam)); }
diff --git a/components/gcm_driver/BUILD.gn b/components/gcm_driver/BUILD.gn index 918029d..30a30ac 100644 --- a/components/gcm_driver/BUILD.gn +++ b/components/gcm_driver/BUILD.gn
@@ -107,7 +107,7 @@ } # GYP version: components/gcm_driver.gypi:gcm_driver_test_support -source_set("test_support") { +static_library("test_support") { testonly = true sources = [ "fake_gcm_app_handler.cc",
diff --git a/components/gcm_driver/crypto/BUILD.gn b/components/gcm_driver/crypto/BUILD.gn index 3752eb9..ccf11e2 100644 --- a/components/gcm_driver/crypto/BUILD.gn +++ b/components/gcm_driver/crypto/BUILD.gn
@@ -32,7 +32,7 @@ } # GYP version: components/gcm_driver.gypi:gcm_driver_crypto_test_support -source_set("test_support") { +static_library("test_support") { testonly = true sources = [ "gcm_crypto_test_helpers.cc",
diff --git a/components/gcm_driver/instance_id/BUILD.gn b/components/gcm_driver/instance_id/BUILD.gn index 7e893ffe..bf12b0d 100644 --- a/components/gcm_driver/instance_id/BUILD.gn +++ b/components/gcm_driver/instance_id/BUILD.gn
@@ -3,7 +3,7 @@ # found in the LICENSE file. # GYP version: components/gcm_driver.gypi:instance_id_driver -source_set("instance_id") { +static_library("instance_id") { sources = [ "android/component_jni_registrar.cc", "android/component_jni_registrar.h", @@ -36,7 +36,7 @@ } # GYP version: components/gcm_driver.gypi:instance_id_test_support -source_set("test_support") { +static_library("test_support") { testonly = true sources = [ "fake_gcm_driver_for_instance_id.cc",
diff --git a/components/guest_view/browser/BUILD.gn b/components/guest_view/browser/BUILD.gn index e6d27b7b..59f9aa4 100644 --- a/components/guest_view/browser/BUILD.gn +++ b/components/guest_view/browser/BUILD.gn
@@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("browser") { +static_library("browser") { output_name = "guest_view_browser" sources = [ "//components/guest_view/browser/guest_view.h", @@ -30,7 +30,7 @@ ] } -source_set("test_support") { +static_library("test_support") { testonly = true sources = [ "//components/guest_view/browser/test_guest_view_manager.cc",
diff --git a/components/leveldb_proto/BUILD.gn b/components/leveldb_proto/BUILD.gn index 120f2417..88541d5 100644 --- a/components/leveldb_proto/BUILD.gn +++ b/components/leveldb_proto/BUILD.gn
@@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("leveldb_proto") { +static_library("leveldb_proto") { sources = [ "leveldb_database.cc", "leveldb_database.h",
diff --git a/components/memory_coordinator.gypi b/components/memory_coordinator.gypi index bb848e14..d7002f3 100644 --- a/components/memory_coordinator.gypi +++ b/components/memory_coordinator.gypi
@@ -10,18 +10,22 @@ 'type': 'static_library', 'sources': [ 'memory_coordinator/public/interfaces/child_memory_coordinator.mojom', + 'memory_coordinator/public/interfaces/memory_coordinator.mojom', ], 'includes': [ '../mojo/mojom_bindings_generator.gypi' ], }, { # GN version: //components/memory_coordinator/common 'target_name': 'memory_coordinator_common', - 'type': 'none', + 'type': 'static_library', 'dependencies': [ + '<(DEPTH)/base/base.gyp:base', 'memory_coordinator_mojo_bindings', ], 'sources': [ 'memory_coordinator/common/memory_coordinator_client.h', + 'memory_coordinator/common/memory_coordinator_features.cc', + 'memory_coordinator/common/memory_coordinator_features.h', ], }, { @@ -38,5 +42,19 @@ 'memory_coordinator/child/child_memory_coordinator_impl.h', ], }, + { + # GN version: //components/memory_coordinator/browser + 'target_name': 'memory_coordinator_browser', + 'type': 'static_library', + 'dependencies': [ + '<(DEPTH)/base/base.gyp:base', + 'memory_coordinator_common', + 'memory_coordinator_mojo_bindings', + ], + 'sources': [ + 'memory_coordinator/browser/memory_coordinator.cc', + 'memory_coordinator/browser/memory_coordinator.h', + ], + }, ], }
diff --git a/components/memory_coordinator/DEPS b/components/memory_coordinator/DEPS index ef8ad28..1cd1e07 100644 --- a/components/memory_coordinator/DEPS +++ b/components/memory_coordinator/DEPS
@@ -1,3 +1,4 @@ include_rules = [ "+mojo/public", + "+services/shell", ]
diff --git a/components/memory_coordinator/browser/BUILD.gn b/components/memory_coordinator/browser/BUILD.gn new file mode 100644 index 0000000..ac0869a --- /dev/null +++ b/components/memory_coordinator/browser/BUILD.gn
@@ -0,0 +1,19 @@ +# 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. + +source_set("browser") { + sources = [ + "memory_coordinator.cc", + "memory_coordinator.h", + ] + + deps = [ + "//base", + "//components/memory_coordinator/public/interfaces", + ] + + public_deps = [ + "//components/memory_coordinator/common", + ] +}
diff --git a/components/memory_coordinator/browser/memory_coordinator.cc b/components/memory_coordinator/browser/memory_coordinator.cc new file mode 100644 index 0000000..101426f --- /dev/null +++ b/components/memory_coordinator/browser/memory_coordinator.cc
@@ -0,0 +1,56 @@ +// 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 "components/memory_coordinator/browser/memory_coordinator.h" + +namespace memory_coordinator { + +// The implementation of MemoryCoordinatorHandle. See memory_coordinator.mojom +// for the role of this class. +class MemoryCoordinatorHandleImpl : public mojom::MemoryCoordinatorHandle { + public: + MemoryCoordinatorHandleImpl(mojom::MemoryCoordinatorHandleRequest request) + : binding_(this, std::move(request)) { + } + + // mojom::MemoryCoordinatorHandle implementations: + + void AddChild(mojom::ChildMemoryCoordinatorPtr child) override { + DCHECK(!child_.is_bound()); + child_ = std::move(child); + } + + mojom::ChildMemoryCoordinatorPtr& child() { return child_; } + mojo::Binding<mojom::MemoryCoordinatorHandle>& binding() { return binding_; } + + private: + mojom::ChildMemoryCoordinatorPtr child_; + mojo::Binding<mojom::MemoryCoordinatorHandle> binding_; + + DISALLOW_COPY_AND_ASSIGN(MemoryCoordinatorHandleImpl); +}; + +MemoryCoordinator::MemoryCoordinator() {} + +MemoryCoordinator::~MemoryCoordinator() {} + +void MemoryCoordinator::CreateHandle( + int render_process_id, + mojom::MemoryCoordinatorHandleRequest request) { + auto handle = new MemoryCoordinatorHandleImpl(std::move(request)); + handle->binding().set_connection_error_handler( + base::Bind(&MemoryCoordinator::OnConnectionError, base::Unretained(this), + render_process_id)); + children_[render_process_id].reset(handle); +} + +size_t MemoryCoordinator::NumChildrenForTesting() { + return children_.size(); +} + +void MemoryCoordinator::OnConnectionError(int render_process_id) { + children_.erase(render_process_id); +} + +} // namespace memory_coordinator
diff --git a/components/memory_coordinator/browser/memory_coordinator.h b/components/memory_coordinator/browser/memory_coordinator.h new file mode 100644 index 0000000..8ae02eb --- /dev/null +++ b/components/memory_coordinator/browser/memory_coordinator.h
@@ -0,0 +1,42 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_MEMORY_COORDINATOR_BROWSER_MEMORY_COORDINATOR_H_ +#define COMPONENTS_MEMORY_COORDINATOR_BROWSER_MEMORY_COORDINATOR_H_ + +#include "components/memory_coordinator/public/interfaces/memory_coordinator.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" + +namespace memory_coordinator { + +class MemoryCoordinatorHandleImpl; + +// MemoryCoordinator is responsible for the whole memory management accross the +// browser and child proceeses. It will dispatch memory events to its clients +// and child processes based on its best knowledge of the memory usage. +class MemoryCoordinator { + public: + MemoryCoordinator(); + ~MemoryCoordinator(); + + void CreateHandle(int render_process_id, + mojom::MemoryCoordinatorHandleRequest request); + + // Returns number of children. Only used for testing. + size_t NumChildrenForTesting(); + + private: + void OnConnectionError(int render_process_id); + + // Mappings of RenderProcessHost::GetID() -> MemoryCoordinatorHandleImpl. + // A mapping is added when a renderer connects to MemoryCoordinator and + // removed automatically when a underlying binding is disconnected. + std::map<int, std::unique_ptr<MemoryCoordinatorHandleImpl>> children_; + + DISALLOW_COPY_AND_ASSIGN(MemoryCoordinator); +}; + +} // memory_coordinator + +#endif // COMPONENTS_MEMORY_COORDINATOR_BROWSER_MEMORY_COORDINATOR_H_
diff --git a/components/memory_coordinator/child/BUILD.gn b/components/memory_coordinator/child/BUILD.gn index db58c2d..47eecb1 100644 --- a/components/memory_coordinator/child/BUILD.gn +++ b/components/memory_coordinator/child/BUILD.gn
@@ -10,8 +10,12 @@ deps = [ "//base", - "//components/memory_coordinator/common", "//components/memory_coordinator/public/interfaces", + "//services/shell/public/cpp", + ] + + public_deps = [ + "//components/memory_coordinator/common", ] }
diff --git a/components/memory_coordinator/child/child_memory_coordinator_impl.cc b/components/memory_coordinator/child/child_memory_coordinator_impl.cc index 75889ed..d1f9f6c 100644 --- a/components/memory_coordinator/child/child_memory_coordinator_impl.cc +++ b/components/memory_coordinator/child/child_memory_coordinator_impl.cc
@@ -7,12 +7,26 @@ namespace memory_coordinator { ChildMemoryCoordinatorImpl::ChildMemoryCoordinatorImpl( - mojo::InterfaceRequest<mojom::ChildMemoryCoordinator> request, - scoped_refptr<ClientList> clients) - : binding_(this, std::move(request)), - clients_(clients) {} + shell::InterfaceProvider* remote_interfaces) + : binding_(this), clients_(new ClientList) { + if (remote_interfaces) { + remote_interfaces->GetInterface(mojo::GetProxy(&parent_)); + parent_->AddChild(binding_.CreateInterfacePtrAndBind()); + } +} -ChildMemoryCoordinatorImpl::~ChildMemoryCoordinatorImpl() {} +ChildMemoryCoordinatorImpl::~ChildMemoryCoordinatorImpl() { +} + +void ChildMemoryCoordinatorImpl::RegisterClient( + MemoryCoordinatorClient* client) { + clients_->AddObserver(client); +} + +void ChildMemoryCoordinatorImpl::UnregisterClient( + MemoryCoordinatorClient* client) { + clients_->RemoveObserver(client); +} void ChildMemoryCoordinatorImpl::OnStateChange(mojom::MemoryState state) { clients_->Notify(FROM_HERE, &MemoryCoordinatorClient::OnMemoryStateChange,
diff --git a/components/memory_coordinator/child/child_memory_coordinator_impl.h b/components/memory_coordinator/child/child_memory_coordinator_impl.h index bdb6376a..7471c53 100644 --- a/components/memory_coordinator/child/child_memory_coordinator_impl.h +++ b/components/memory_coordinator/child/child_memory_coordinator_impl.h
@@ -8,8 +8,11 @@ #include "base/compiler_specific.h" #include "base/observer_list_threadsafe.h" #include "components/memory_coordinator/common/memory_coordinator_client.h" +#include "components/memory_coordinator/common/memory_coordinator_features.h" #include "components/memory_coordinator/public/interfaces/child_memory_coordinator.mojom.h" -#include "mojo/public/cpp/bindings/strong_binding.h" +#include "components/memory_coordinator/public/interfaces/memory_coordinator.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "services/shell/public/cpp/interface_provider.h" namespace memory_coordinator { @@ -19,18 +22,23 @@ class ChildMemoryCoordinatorImpl : NON_EXPORTED_BASE(public mojom::ChildMemoryCoordinator) { public: - using ClientList = base::ObserverListThreadSafe<MemoryCoordinatorClient>; - ChildMemoryCoordinatorImpl( - mojo::InterfaceRequest<mojom::ChildMemoryCoordinator> request, - scoped_refptr<ClientList> clients); + ChildMemoryCoordinatorImpl(shell::InterfaceProvider* remote_interfaces); ~ChildMemoryCoordinatorImpl() override; + // Registers/unregisters a client. Does not take ownership of client. + void RegisterClient(MemoryCoordinatorClient* client); + void UnregisterClient(MemoryCoordinatorClient* client); + // mojom::ChildMemoryCoordinator implementations: void OnStateChange(mojom::MemoryState state) override; private: - mojo::StrongBinding<mojom::ChildMemoryCoordinator> binding_; + friend class ChildMemoryCoordinatorImplTest; + + mojo::Binding<mojom::ChildMemoryCoordinator> binding_; + using ClientList = base::ObserverListThreadSafe<MemoryCoordinatorClient>; scoped_refptr<ClientList> clients_; + mojom::MemoryCoordinatorHandlePtr parent_; DISALLOW_COPY_AND_ASSIGN(ChildMemoryCoordinatorImpl); };
diff --git a/components/memory_coordinator/child/child_memory_coordinator_impl_unittest.cc b/components/memory_coordinator/child/child_memory_coordinator_impl_unittest.cc index 3b7db40..7486d86 100644 --- a/components/memory_coordinator/child/child_memory_coordinator_impl_unittest.cc +++ b/components/memory_coordinator/child/child_memory_coordinator_impl_unittest.cc
@@ -13,21 +13,20 @@ namespace memory_coordinator { -namespace { - class ChildMemoryCoordinatorImplTest : public testing::Test { public: ChildMemoryCoordinatorImplTest() - : clients_(new ChildMemoryCoordinatorImpl::ClientList), - message_loop_(new base::MessageLoop), - coordinator_impl_(mojo::GetProxy(&coordinator_), clients_) {} + : message_loop_(new base::MessageLoop), + coordinator_impl_(nullptr) { + coordinator_ = coordinator_impl_.binding_.CreateInterfacePtrAndBind(); + } void RegisterClient(MemoryCoordinatorClient* client) { - clients_->AddObserver(client); + coordinator_impl_.RegisterClient(client); } void UnregisterClient(MemoryCoordinatorClient* client) { - clients_->RemoveObserver(client); + coordinator_impl_.UnregisterClient(client); } mojom::ChildMemoryCoordinatorPtr& coordinator() { return coordinator_; } @@ -39,17 +38,16 @@ loop.RunUntilIdle(); } - protected: - scoped_refptr<ChildMemoryCoordinatorImpl::ClientList> clients_; - private: std::unique_ptr<base::MessageLoop> message_loop_; - mojom::ChildMemoryCoordinatorPtr coordinator_ = nullptr; ChildMemoryCoordinatorImpl coordinator_impl_; + mojom::ChildMemoryCoordinatorPtr coordinator_ = nullptr; DISALLOW_COPY_AND_ASSIGN(ChildMemoryCoordinatorImplTest); }; +namespace { + class MockMemoryCoordinatorClient final : public MemoryCoordinatorClient { public: void OnMemoryStateChange(mojom::MemoryState state) override { @@ -67,12 +65,12 @@ public: MemoryCoordinatorTestThread( const std::string& name, - scoped_refptr<ChildMemoryCoordinatorImpl::ClientList> clients) - : Thread(name), clients_(clients) {} + ChildMemoryCoordinatorImpl& coordinator) + : Thread(name), coordinator_(coordinator) {} ~MemoryCoordinatorTestThread() override { Stop(); } void Init() override { - clients_->AddObserver(this); + coordinator_.RegisterClient(this); } void OnMemoryStateChange(mojom::MemoryState state) override { @@ -94,7 +92,7 @@ EXPECT_EQ(state, last_state_); } - scoped_refptr<ChildMemoryCoordinatorImpl::ClientList> clients_; + ChildMemoryCoordinatorImpl& coordinator_; mojom::MemoryState last_state_ = mojom::MemoryState::UNKNOWN; }; @@ -114,8 +112,8 @@ } TEST_F(ChildMemoryCoordinatorImplTest, MultipleClients) { - MemoryCoordinatorTestThread t1("thread 1", clients_); - MemoryCoordinatorTestThread t2("thread 2", clients_); + MemoryCoordinatorTestThread t1("thread 1", coordinator_impl()); + MemoryCoordinatorTestThread t2("thread 2", coordinator_impl()); t1.StartAndWaitForTesting(); t2.StartAndWaitForTesting();
diff --git a/components/memory_coordinator/common/BUILD.gn b/components/memory_coordinator/common/BUILD.gn index 950b137..a2c0f5e5 100644 --- a/components/memory_coordinator/common/BUILD.gn +++ b/components/memory_coordinator/common/BUILD.gn
@@ -5,6 +5,12 @@ source_set("common") { sources = [ "memory_coordinator_client.h", + "memory_coordinator_features.cc", + "memory_coordinator_features.h", + ] + + deps = [ + "//base", ] public_deps = [
diff --git a/components/memory_coordinator/common/memory_coordinator_features.cc b/components/memory_coordinator/common/memory_coordinator_features.cc new file mode 100644 index 0000000..a5e892f --- /dev/null +++ b/components/memory_coordinator/common/memory_coordinator_features.cc
@@ -0,0 +1,24 @@ +// 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 "base/feature_list.h" + +namespace memory_coordinator { + +const base::Feature kMemoryCoordinator { + "MemoryCoordinator", base::FEATURE_DISABLED_BY_DEFAULT +}; + +bool IsEnabled() { + return base::FeatureList::IsEnabled(kMemoryCoordinator); +} + +void EnableForTesting() { + base::FeatureList::ClearInstanceForTesting(); + std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); + feature_list->InitializeFromCommandLine(kMemoryCoordinator.name, ""); + base::FeatureList::SetInstance(std::move(feature_list)); +} + +} // namespace memory_coordinator
diff --git a/components/memory_coordinator/common/memory_coordinator_features.h b/components/memory_coordinator/common/memory_coordinator_features.h new file mode 100644 index 0000000..8b0518a --- /dev/null +++ b/components/memory_coordinator/common/memory_coordinator_features.h
@@ -0,0 +1,24 @@ +// 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 COMPONENTS_MEMORY_COORDINATOR_COMMON_MEMORY_COORDINATOR_FEATURES_H_ +#define COMPONENTS_MEMORY_COORDINATOR_COMMON_MEMORY_COORDINATOR_FEATURES_H_ + +#include "base/feature_list.h" + +// WARNING: +// The memory coordinator is not ready for use and enabling this may cause +// unexpected memory regression at this point. Please do not enable this. + +namespace memory_coordinator { + +// Returns true when the memory coordinator is enabled. +bool IsEnabled(); + +// Enables the memory coordinator for testing. +void EnableForTesting(); + +} // memory_coordinator + +#endif // COMPONENTS_MEMORY_COORDINATOR_COMMON_MEMORY_COORDINATOR_FEATURES_H_
diff --git a/components/memory_coordinator/public/interfaces/BUILD.gn b/components/memory_coordinator/public/interfaces/BUILD.gn index 770bc29..95c1c6f 100644 --- a/components/memory_coordinator/public/interfaces/BUILD.gn +++ b/components/memory_coordinator/public/interfaces/BUILD.gn
@@ -7,5 +7,6 @@ mojom("interfaces") { sources = [ "child_memory_coordinator.mojom", + "memory_coordinator.mojom", ] }
diff --git a/components/memory_coordinator/public/interfaces/memory_coordinator.mojom b/components/memory_coordinator/public/interfaces/memory_coordinator.mojom new file mode 100644 index 0000000..f56250a --- /dev/null +++ b/components/memory_coordinator/public/interfaces/memory_coordinator.mojom
@@ -0,0 +1,14 @@ +// 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. + +module memory_coordinator.mojom; + +import "components/memory_coordinator/public/interfaces/child_memory_coordinator.mojom"; + +// An interface to access the central memory coordinator from a child process. +// The browser process creates a handle for each child process. +interface MemoryCoordinatorHandle { + // A child process calls this method when ChildMemoryCoordinator is created. + AddChild(ChildMemoryCoordinator child); +};
diff --git a/components/memory_pressure/direct_memory_pressure_calculator_linux.cc b/components/memory_pressure/direct_memory_pressure_calculator_linux.cc index f1dbc01f..cb548ad 100644 --- a/components/memory_pressure/direct_memory_pressure_calculator_linux.cc +++ b/components/memory_pressure/direct_memory_pressure_calculator_linux.cc
@@ -13,6 +13,14 @@ static const int kKiBperMiB = 1024; +int GetAvailableSystemMemoryMiB(const base::SystemMemoryInfoKB* mem_info) { + // How much system memory is actively available for use right now, in MBs. + return (mem_info->available + ? mem_info->available + : (mem_info->free + mem_info->buffers + mem_info->cached)) / + kKiBperMiB; +} + } // namespace // Thresholds at which we consider the system being under moderate/critical @@ -39,9 +47,7 @@ base::SystemMemoryInfoKB mem_info = {}; if (!GetSystemMemoryInfo(&mem_info)) return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; - - // How much system memory is actively available for use right now, in MBs. - int phys_free = mem_info.free / kKiBperMiB; + int phys_free = GetAvailableSystemMemoryMiB(&mem_info); // Determine if the physical memory is under critical memory pressure. if (phys_free <= critical_threshold_mb_)
diff --git a/components/metrics/BUILD.gn b/components/metrics/BUILD.gn index 7fc0934..9d7a2afc 100644 --- a/components/metrics/BUILD.gn +++ b/components/metrics/BUILD.gn
@@ -14,7 +14,7 @@ } # GYP version: components/metrics.gypi:metrics -source_set("metrics") { +static_library("metrics") { sources = [ "call_stack_profile_metrics_provider.cc", "call_stack_profile_metrics_provider.h", @@ -130,7 +130,7 @@ if (is_chromeos) { # GYP version: components/metrics.gypi:metrics_leak_detector - source_set("leak_detector") { + static_library("leak_detector") { sources = [ "leak_detector/call_stack_manager.cc", "leak_detector/call_stack_manager.h", @@ -196,7 +196,7 @@ } # GYP version: components/metrics.gypi:metrics_profiler -source_set("profiler") { +static_library("profiler") { sources = [ "profiler/profiler_metrics_provider.cc", "profiler/profiler_metrics_provider.h", @@ -236,7 +236,7 @@ if (!is_ios) { # GYP version: components/metrics.gypi:metrics_profiler_content - source_set("profiler_content") { + static_library("profiler_content") { sources = [ "profiler/content/content_tracking_synchronizer_delegate.cc", "profiler/content/content_tracking_synchronizer_delegate.h", @@ -254,7 +254,7 @@ } } else { # GYP version: components/metrics.gypi:metrics_profiler_ios - source_set("profiler_ios") { + static_library("profiler_ios") { sources = [ "profiler/ios/ios_tracking_synchronizer_delegate.cc", "profiler/ios/ios_tracking_synchronizer_delegate.h", @@ -270,7 +270,7 @@ } # GYP version: components/metrics.gypi:metrics_test_support -source_set("test_support") { +static_library("test_support") { testonly = true sources = [ "test_enabled_state_provider.cc", @@ -291,7 +291,7 @@ if (is_linux) { # GYP version: components/metrics.gypi:metrics_serialization - source_set("serialization") { + static_library("serialization") { sources = [ "serialization/metric_sample.cc", "serialization/metric_sample.h",
diff --git a/components/metrics/file_metrics_provider.cc b/components/metrics/file_metrics_provider.cc index 2d331d6..14d853a 100644 --- a/components/metrics/file_metrics_provider.cc +++ b/components/metrics/file_metrics_provider.cc
@@ -372,7 +372,7 @@ std::unique_ptr<base::HistogramBase> histogram = histogram_iter.GetNext(); if (!histogram) break; - snapshot_manager->PrepareFinalDeltaTakingOwnership(std::move(histogram)); + snapshot_manager->PrepareFinalDelta(histogram.get()); ++histogram_count; }
diff --git a/components/metrics/file_metrics_provider_unittest.cc b/components/metrics/file_metrics_provider_unittest.cc index d1d340b..19e33a4 100644 --- a/components/metrics/file_metrics_provider_unittest.cc +++ b/components/metrics/file_metrics_provider_unittest.cc
@@ -411,9 +411,7 @@ { HistogramFlattenerDeltaRecorder flattener; base::HistogramSnapshotManager snapshot_manager(&flattener); - snapshot_manager.StartDeltas(); RecordInitialHistogramSnapshots(&snapshot_manager); - snapshot_manager.FinishDeltas(); EXPECT_EQ(2U, flattener.GetRecordedDeltaHistogramNames().size()); } EXPECT_TRUE(base::PathExists(metrics_file()));
diff --git a/components/metrics/metrics_service.cc b/components/metrics/metrics_service.cc index a14b047..cad1598 100644 --- a/components/metrics/metrics_service.cc +++ b/components/metrics/metrics_service.cc
@@ -1125,28 +1125,24 @@ for (MetricsProvider* provider : metrics_providers_) provider->MergeHistogramDeltas(); - histogram_snapshot_manager_.StartDeltas(); // "true" to the begin() call indicates that StatisticsRecorder should include // histograms held in persistent storage. - histogram_snapshot_manager_.PrepareDeltasWithoutStartFinish( + histogram_snapshot_manager_.PrepareDeltas( base::StatisticsRecorder::begin(true), base::StatisticsRecorder::end(), base::Histogram::kNoFlags, base::Histogram::kUmaTargetedHistogramFlag); for (MetricsProvider* provider : metrics_providers_) provider->RecordHistogramSnapshots(&histogram_snapshot_manager_); - histogram_snapshot_manager_.FinishDeltas(); } void MetricsService::RecordCurrentStabilityHistograms() { DCHECK(log_manager_.current_log()); - histogram_snapshot_manager_.StartDeltas(); // "true" indicates that StatisticsRecorder should include histograms in // persistent storage. - histogram_snapshot_manager_.PrepareDeltasWithoutStartFinish( + histogram_snapshot_manager_.PrepareDeltas( base::StatisticsRecorder::begin(true), base::StatisticsRecorder::end(), base::Histogram::kNoFlags, base::Histogram::kUmaStabilityHistogramFlag); for (MetricsProvider* provider : metrics_providers_) provider->RecordInitialHistogramSnapshots(&histogram_snapshot_manager_); - histogram_snapshot_manager_.FinishDeltas(); } void MetricsService::LogCleanShutdown() {
diff --git a/components/nacl/loader/nonsfi/nonsfi_listener.cc b/components/nacl/loader/nonsfi/nonsfi_listener.cc index 2ea4d59..3ee8aa0 100644 --- a/components/nacl/loader/nonsfi/nonsfi_listener.cc +++ b/components/nacl/loader/nonsfi/nonsfi_listener.cc
@@ -92,10 +92,10 @@ CHECK_NE(params.trusted_service_channel_handle.socket.fd, -1); CHECK_NE(params.manifest_service_channel_handle.socket.fd, -1); - ppapi::SetIPCFileDescriptors( - params.ppapi_browser_channel_handle.socket.fd, - params.ppapi_renderer_channel_handle.socket.fd, - params.manifest_service_channel_handle.socket.fd); + ppapi::SetIPCChannelHandles( + params.ppapi_browser_channel_handle, + params.ppapi_renderer_channel_handle, + params.manifest_service_channel_handle); ppapi::StartUpPlugin(); // TODO(teravest): Do we plan on using this renderer handle for nexe loading
diff --git a/components/nacl/renderer/ppb_nacl_private_impl.cc b/components/nacl/renderer/ppb_nacl_private_impl.cc index 4daa4c7..0d6eacf 100644 --- a/components/nacl/renderer/ppb_nacl_private_impl.cc +++ b/components/nacl/renderer/ppb_nacl_private_impl.cc
@@ -348,7 +348,6 @@ blink::WebURLRequest CreateWebURLRequest(const blink::WebDocument& document, const GURL& gurl) { blink::WebURLRequest request; - request.initialize(); request.setURL(gurl); request.setFirstPartyForCookies(document.firstPartyForCookies()); return request; @@ -1469,7 +1468,8 @@ // Handle special PNaCl support files which are installed on the user's // machine. - if (url.find(kPNaClTranslatorBaseUrl, 0) == 0) { + if (base::StartsWith(url, kPNaClTranslatorBaseUrl, + base::CompareCase::SENSITIVE)) { PP_NaClFileInfo file_info = kInvalidNaClFileInfo; PP_FileHandle handle = GetReadonlyPnaclFd(url.c_str(), false /* is_executable */,
diff --git a/components/network_session_configurator/network_session_configurator.cc b/components/network_session_configurator/network_session_configurator.cc index 710daa64..5df2b8e 100644 --- a/components/network_session_configurator/network_session_configurator.cc +++ b/components/network_session_configurator/network_session_configurator.cc
@@ -284,6 +284,14 @@ GetVariationParam(quic_trial_params, "migrate_sessions_early"), "true"); } +bool ShouldQuicAllowServerMigration( + const VariationParameters& quic_trial_params) { + return base::LowerCaseEqualsASCII( + GetVariationParam(quic_trial_params, + "allow_server_migration"), + "true"); +} + size_t GetQuicMaxPacketLength(const base::CommandLine& command_line, const VariationParameters& quic_trial_params) { if (command_line.HasSwitch(switches::kQuicMaxPacketLength)) { @@ -394,6 +402,8 @@ ShouldQuicMigrateSessionsOnNetworkChange(quic_trial_params); params->quic_migrate_sessions_early = ShouldQuicMigrateSessionsEarly(quic_trial_params); + params->quic_allow_server_migration = + ShouldQuicAllowServerMigration(quic_trial_params); } size_t max_packet_length =
diff --git a/components/network_session_configurator/network_session_configurator_unittest.cc b/components/network_session_configurator/network_session_configurator_unittest.cc index 0e8bde8..7cf71e7 100644 --- a/components/network_session_configurator/network_session_configurator_unittest.cc +++ b/components/network_session_configurator/network_session_configurator_unittest.cc
@@ -119,6 +119,7 @@ EXPECT_FALSE(params_.quic_disable_preconnect_if_0rtt); EXPECT_FALSE(params_.quic_migrate_sessions_on_network_change); EXPECT_FALSE(params_.quic_migrate_sessions_early); + EXPECT_FALSE(params_.quic_allow_server_migration); EXPECT_TRUE(params_.quic_host_whitelist.empty()); EXPECT_FALSE(params_.quic_force_hol_blocking); @@ -258,6 +259,18 @@ EXPECT_TRUE(params_.quic_migrate_sessions_early); } +TEST_F(NetworkSessionConfiguratorTest, + QuicAllowServerMigrationFromFieldTrialParams) { + std::map<std::string, std::string> field_trial_params; + field_trial_params["allow_server_migration"] = "true"; + variations::AssociateVariationParams("QUIC", "Enabled", field_trial_params); + base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled"); + + ParseFieldTrials(); + + EXPECT_TRUE(params_.quic_allow_server_migration); +} + TEST_F(NetworkSessionConfiguratorTest, PacketLengthFromFieldTrialParams) { std::map<std::string, std::string> field_trial_params; field_trial_params["max_packet_length"] = "1450";
diff --git a/components/ntp_snippets/content_suggestions_category_status.h b/components/ntp_snippets/content_suggestions_category_status.h index d3b5ba4..16b65af0 100644 --- a/components/ntp_snippets/content_suggestions_category_status.h +++ b/components/ntp_snippets/content_suggestions_category_status.h
@@ -11,6 +11,10 @@ // On Android builds, a Java counterpart will be generated for this enum. // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.ntp.snippets enum class ContentSuggestionsCategoryStatus { + // The provider is still initializing and it is not yet determined whether + // content suggestions will be available or not. + INITIALIZING, + // Content suggestions are available (though the list of available suggestions // may be empty simply because there are no reasonable suggestions to be made // at the moment). @@ -36,9 +40,10 @@ PASSPHRASE_ENCRYPTION_ENABLED, // Content suggestions are not available because history sync is disabled. HISTORY_SYNC_DISABLED, - // Content suggestions are not available because the history sync service is - // not yet completely initialized and its status is unknown. - HISTORY_SYNC_STATE_UNKNOWN + + // Content suggestions are not available because an error occured when loading + // or updating them. + LOADING_ERROR }; // Determines whether the given status is one of the AVAILABLE statuses.
diff --git a/components/ntp_snippets/content_suggestions_provider.cc b/components/ntp_snippets/content_suggestions_provider.cc index 696a3813..e4565e5 100644 --- a/components/ntp_snippets/content_suggestions_provider.cc +++ b/components/ntp_snippets/content_suggestions_provider.cc
@@ -23,7 +23,8 @@ std::string ContentSuggestionsProvider::MakeUniqueID( ContentSuggestionsCategory category, const std::string& within_category_id) { - return base::StringPrintf(kCombinedIDFormat, int(category), + return base::StringPrintf(kCombinedIDFormat, + static_cast<int>(category), within_category_id.c_str()); }
diff --git a/components/ntp_snippets/content_suggestions_provider.h b/components/ntp_snippets/content_suggestions_provider.h index 93872f58..8d0b5dd 100644 --- a/components/ntp_snippets/content_suggestions_provider.h +++ b/components/ntp_snippets/content_suggestions_provider.h
@@ -62,7 +62,8 @@ }; // Sets an observer which is notified about changes to the available - // suggestions, or removes it by passing a nullptr. + // suggestions, or removes it by passing a nullptr. The provider does not take + // ownership of the observer and the observer must outlive this provider. virtual void SetObserver(Observer* observer) = 0; // Determines the status of the given |category|, see @@ -78,6 +79,8 @@ // Fetches the image for the suggestion with the given ID and returns it // through the callback. This fetch may occur locally or from the internet. + // If that suggestion doesn't exist, doesn't have an image or if the fetch + // fails, the callback gets a null image. virtual void FetchSuggestionImage(const std::string& suggestion_id, const ImageFetchedCallback& callback) = 0;
diff --git a/components/ntp_snippets/content_suggestions_service.cc b/components/ntp_snippets/content_suggestions_service.cc index 5b86d95..3ce179f4 100644 --- a/components/ntp_snippets/content_suggestions_service.cc +++ b/components/ntp_snippets/content_suggestions_service.cc
@@ -61,7 +61,7 @@ ContentSuggestionsCategory category = id_category_map_[suggestion_id]; if (!providers_.count(category)) { LOG(WARNING) << "Requested image for suggestion " << suggestion_id - << " for unavailable category " << int(category); + << " for unavailable category " << static_cast<int>(category); callback.Run(suggestion_id, gfx::Image()); return; } @@ -92,7 +92,7 @@ ContentSuggestionsCategory category = id_category_map_[suggestion_id]; if (!providers_.count(category)) { LOG(WARNING) << "Discarded suggestion " << suggestion_id - << " for unavailable category " << int(category); + << " for unavailable category " << static_cast<int>(category); return; } providers_[category]->DiscardSuggestion(suggestion_id);
diff --git a/components/ntp_snippets/ntp_snippets_service.cc b/components/ntp_snippets/ntp_snippets_service.cc index 51efc2a..e13b8c32 100644 --- a/components/ntp_snippets/ntp_snippets_service.cc +++ b/components/ntp_snippets/ntp_snippets_service.cc
@@ -193,10 +193,13 @@ std::unique_ptr<ImageDecoder> image_decoder, std::unique_ptr<NTPSnippetsDatabase> database, std::unique_ptr<NTPSnippetsStatusService> status_service) - : state_(State::NOT_INITED), + : ContentSuggestionsProvider({ContentSuggestionsCategory::ARTICLES}), + state_(State::NOT_INITED), + category_status_(ContentSuggestionsCategoryStatus::INITIALIZING), pref_service_(pref_service), suggestions_service_(suggestions_service), application_language_code_(application_language_code), + observer_(nullptr), scheduler_(scheduler), snippets_fetcher_(std::move(snippets_fetcher)), image_fetcher_(std::move(image_fetcher)), @@ -204,9 +207,15 @@ database_(std::move(database)), snippets_status_service_(std::move(status_service)), fetch_after_load_(false) { - if (!enabled || database_->IsErrorState()) { - // Don't even bother loading the database. - EnterState(State::SHUT_DOWN); + // In some cases, don't even bother loading the database. + if (!enabled) { + EnterState(State::SHUT_DOWN, + ContentSuggestionsCategoryStatus::CATEGORY_EXPLICITLY_DISABLED); + return; + } + if (database_->IsErrorState()) { + EnterState(State::SHUT_DOWN, + ContentSuggestionsCategoryStatus::LOADING_ERROR); return; } @@ -230,7 +239,7 @@ // Inherited from KeyedService. void NTPSnippetsService::Shutdown() { - EnterState(State::SHUT_DOWN); + EnterState(State::SHUT_DOWN, ContentSuggestionsCategoryStatus::NOT_PROVIDED); } void NTPSnippetsService::FetchSnippets() { @@ -263,16 +272,16 @@ } } -void NTPSnippetsService::FetchSnippetImage( - const std::string& snippet_id, +void NTPSnippetsService::FetchSuggestionImage( + const std::string& suggestion_id, const ImageFetchedCallback& callback) { database_->LoadImage( - snippet_id, + suggestion_id, base::Bind(&NTPSnippetsService::OnSnippetImageFetchedFromDatabase, - base::Unretained(this), snippet_id, callback)); + base::Unretained(this), suggestion_id, callback)); } -void NTPSnippetsService::ClearSnippets() { +void NTPSnippetsService::ClearCachedSuggestionsForDebugging() { if (!initialized()) return; @@ -282,8 +291,7 @@ database_->DeleteSnippets(snippets_); snippets_.clear(); - FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, - NTPSnippetsServiceLoaded()); + NotifyNewSuggestions(); } std::set<std::string> NTPSnippetsService::GetSuggestionsHosts() const { @@ -296,17 +304,17 @@ suggestions_service_->GetSuggestionsDataFromCache()); } -bool NTPSnippetsService::DiscardSnippet(const std::string& snippet_id) { +void NTPSnippetsService::DiscardSuggestion(const std::string& suggestion_id) { if (!ready()) - return false; + return; - auto it = - std::find_if(snippets_.begin(), snippets_.end(), - [&snippet_id](const std::unique_ptr<NTPSnippet>& snippet) { - return snippet->id() == snippet_id; - }); + auto it = std::find_if( + snippets_.begin(), snippets_.end(), + [&suggestion_id](const std::unique_ptr<NTPSnippet>& snippet) { + return snippet->id() == suggestion_id; + }); if (it == snippets_.end()) - return false; + return; (*it)->set_discarded(true); @@ -316,12 +324,10 @@ discarded_snippets_.push_back(std::move(*it)); snippets_.erase(it); - FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, - NTPSnippetsServiceLoaded()); - return true; + NotifyNewSuggestions(); } -void NTPSnippetsService::ClearDiscardedSnippets() { +void NTPSnippetsService::ClearDiscardedSuggestionsForDebugging() { if (!initialized()) return; @@ -332,6 +338,16 @@ discarded_snippets_.clear(); } +void NTPSnippetsService::SetObserver(Observer* observer) { + observer_ = observer; +} + +ContentSuggestionsCategoryStatus NTPSnippetsService::GetCategoryStatus( + ContentSuggestionsCategory category) { + DCHECK_EQ(ContentSuggestionsCategory::ARTICLES, category); + return category_status_; +} + void NTPSnippetsService::AddObserver(NTPSnippetsServiceObserver* observer) { observers_.AddObserver(observer); } @@ -390,7 +406,7 @@ } void NTPSnippetsService::OnDatabaseError() { - EnterState(State::SHUT_DOWN); + EnterState(State::SHUT_DOWN, ContentSuggestionsCategoryStatus::LOADING_ERROR); } void NTPSnippetsService::OnSuggestionsChanged( @@ -416,8 +432,7 @@ StoreSnippetHostsToPrefs(hosts); - FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, - NTPSnippetsServiceLoaded()); + NotifyNewSuggestions(); FetchSnippetsFromHosts(hosts); } @@ -454,8 +469,7 @@ discarded_snippets_.size()); } - FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, - NTPSnippetsServiceLoaded()); + NotifyNewSuggestions(); } void NTPSnippetsService::MergeSnippets(NTPSnippet::PtrVector new_snippets) { @@ -647,8 +661,8 @@ } void NTPSnippetsService::EnterStateDisabled() { - ClearSnippets(); - ClearDiscardedSnippets(); + ClearCachedSuggestionsForDebugging(); + ClearDiscardedSuggestionsForDebugging(); expiry_timer_.Stop(); suggestions_service_subscription_.reset(); @@ -679,18 +693,16 @@ snippets_status_service_->Init(base::Bind( &NTPSnippetsService::UpdateStateForStatus, base::Unretained(this))); - FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, - NTPSnippetsServiceLoaded()); + NotifyNewSuggestions(); } void NTPSnippetsService::UpdateStateForStatus(DisabledReason disabled_reason) { FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, NTPSnippetsServiceDisabledReasonChanged(disabled_reason)); - State new_state; switch (disabled_reason) { case DisabledReason::NONE: - new_state = State::READY; + EnterState(State::READY, ContentSuggestionsCategoryStatus::AVAILABLE); break; case DisabledReason::HISTORY_SYNC_STATE_UNKNOWN: @@ -699,28 +711,44 @@ // |OnStateChanged| will call this function again to update the state. DVLOG(1) << "Sync configuration incomplete, continuing based on the " "current state."; - new_state = state_; + EnterState(state_, ContentSuggestionsCategoryStatus::INITIALIZING); break; case DisabledReason::EXPLICITLY_DISABLED: - case DisabledReason::SIGNED_OUT: - case DisabledReason::SYNC_DISABLED: - case DisabledReason::PASSPHRASE_ENCRYPTION_ENABLED: - case DisabledReason::HISTORY_SYNC_DISABLED: - new_state = State::DISABLED; + EnterState( + State::DISABLED, + ContentSuggestionsCategoryStatus::CATEGORY_EXPLICITLY_DISABLED); break; - default: - // All cases should be handled by the above switch - NOTREACHED(); - new_state = State::DISABLED; + case DisabledReason::SIGNED_OUT: + EnterState(State::DISABLED, ContentSuggestionsCategoryStatus::SIGNED_OUT); + break; + + case DisabledReason::SYNC_DISABLED: + EnterState(State::DISABLED, + ContentSuggestionsCategoryStatus::SYNC_DISABLED); + break; + + case DisabledReason::PASSPHRASE_ENCRYPTION_ENABLED: + EnterState( + State::DISABLED, + ContentSuggestionsCategoryStatus::PASSPHRASE_ENCRYPTION_ENABLED); + break; + + case DisabledReason::HISTORY_SYNC_DISABLED: + EnterState(State::DISABLED, + ContentSuggestionsCategoryStatus::HISTORY_SYNC_DISABLED); break; } - - EnterState(new_state); } -void NTPSnippetsService::EnterState(State state) { +void NTPSnippetsService::EnterState(State state, + ContentSuggestionsCategoryStatus status) { + if (status != category_status_) { + category_status_ = status; + NotifyCategoryStatusChanged(); + } + if (state == state_) return; @@ -757,4 +785,38 @@ } } +void NTPSnippetsService::NotifyNewSuggestions() { + // TODO(pke): Remove this as soon as this becomes a pure provider. + FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, + NTPSnippetsServiceLoaded()); + + if (!observer_) + return; + + std::vector<ContentSuggestion> result; + for (const std::unique_ptr<NTPSnippet>& snippet : snippets_) { + if (!snippet->is_complete()) + continue; + ContentSuggestion suggestion( + MakeUniqueID(ContentSuggestionsCategory::ARTICLES, snippet->id()), + snippet->best_source().url); + suggestion.set_amp_url(snippet->best_source().amp_url); + suggestion.set_title(snippet->title()); + suggestion.set_snippet_text(snippet->snippet()); + suggestion.set_publish_date(snippet->publish_date()); + suggestion.set_publisher_name(snippet->best_source().publisher_name); + suggestion.set_score(snippet->score()); + result.emplace_back(std::move(suggestion)); + } + observer_->OnNewSuggestions(ContentSuggestionsCategory::ARTICLES, + std::move(result)); +} + +void NTPSnippetsService::NotifyCategoryStatusChanged() { + if (observer_) { + observer_->OnCategoryStatusChanged(ContentSuggestionsCategory::ARTICLES, + category_status_); + } +} + } // namespace ntp_snippets
diff --git a/components/ntp_snippets/ntp_snippets_service.h b/components/ntp_snippets/ntp_snippets_service.h index 1482fb9..6e13c3c 100644 --- a/components/ntp_snippets/ntp_snippets_service.h +++ b/components/ntp_snippets/ntp_snippets_service.h
@@ -19,6 +19,10 @@ #include "base/timer/timer.h" #include "components/image_fetcher/image_fetcher_delegate.h" #include "components/keyed_service/core/keyed_service.h" +#include "components/ntp_snippets/content_suggestion.h" +#include "components/ntp_snippets/content_suggestions_category.h" +#include "components/ntp_snippets/content_suggestions_category_status.h" +#include "components/ntp_snippets/content_suggestions_provider.h" #include "components/ntp_snippets/ntp_snippet.h" #include "components/ntp_snippets/ntp_snippets_fetcher.h" #include "components/ntp_snippets/ntp_snippets_scheduler.h" @@ -58,11 +62,14 @@ class NTPSnippetsServiceObserver; // Stores and vends fresh content data for the NTP. +// TODO(pke): Rename this service to ArticleSuggestionsService and move to +// a subdirectory. class NTPSnippetsService : public KeyedService, - public image_fetcher::ImageFetcherDelegate { + public image_fetcher::ImageFetcherDelegate, + public ContentSuggestionsProvider { public: using ImageFetchedCallback = - base::Callback<void(const std::string& snippet_id, const gfx::Image&)>; + base::Callback<void(const std::string& suggestion_id, const gfx::Image&)>; // |application_language_code| should be a ISO 639-1 compliant string, e.g. // 'en' or 'en-US'. Note that this code should only specify the language, not @@ -126,21 +133,17 @@ // the schedule depends on the time of day. void RescheduleFetching(); - // Fetches the image for the snippet with the given |snippet_id| and runs the - // |callback|. If that snippet doesn't exist or the fetch fails, the callback - // gets a null image. - void FetchSnippetImage(const std::string& snippet_id, - const ImageFetchedCallback& callback); - - // Deletes all currently stored snippets. - void ClearSnippets(); - - // Discards the snippet with the given |snippet_id|, if it exists. Returns - // true iff a snippet was discarded. - bool DiscardSnippet(const std::string& snippet_id); - - // Clears the lists of snippets previously discarded by the user. - void ClearDiscardedSnippets(); + // ContentSuggestionsProvider implementation + // TODO(pke): At some point reorder the implementations in the .cc file + // accordingly. + void SetObserver(Observer* observer) override; + ContentSuggestionsCategoryStatus GetCategoryStatus( + ContentSuggestionsCategory category) override; + void DiscardSuggestion(const std::string& suggestion_id) override; + void FetchSuggestionImage(const std::string& suggestion_id, + const ImageFetchedCallback& callback) override; + void ClearCachedSuggestionsForDebugging() override; + void ClearDiscardedSuggestionsForDebugging() override; // Returns the lists of suggestion hosts the snippets are restricted to. std::set<std::string> GetSuggestionsHosts() const; @@ -155,6 +158,9 @@ private: FRIEND_TEST_ALL_PREFIXES(NTPSnippetsServiceTest, HistorySyncStateChanges); + // TODO(pke): As soon as the DisabledReason is replaced with the new status, + // also remove the old State enum and replace it with + // ContentSuggestionsCategoryStatus and a similar status diagram. // Possible state transitions: // +------- NOT_INITED ------+ // | / \ | @@ -238,8 +244,9 @@ void UpdateStateForStatus(DisabledReason disabled_reason); // Verifies state transitions (see |State|'s documentation) and applies them. - // Does nothing if called with the current state. - void EnterState(State state); + // Also updates the provider status. Does nothing except updating the provider + // status if called with the current state. + void EnterState(State state, ContentSuggestionsCategoryStatus status); // Enables the service and triggers a fetch if required. Do not call directly, // use |EnterState| instead. @@ -252,8 +259,18 @@ // directly, use |EnterState| instead. void EnterStateShutdown(); + // Converts the cached snippets to article content suggestions and notifies + // the observers. + void NotifyNewSuggestions(); + + // Notifies the content suggestions observer about a change in the + // |category_status_|. + void NotifyCategoryStatusChanged(); + State state_; + ContentSuggestionsCategoryStatus category_status_; + PrefService* pref_service_; suggestions::SuggestionsService* suggestions_service_; @@ -269,8 +286,12 @@ const std::string application_language_code_; // The observers. + // TODO(pke): This is an old kind of observers that will be removed. base::ObserverList<NTPSnippetsServiceObserver> observers_; + // The observer to deliver data to. + Observer* observer_; + // Scheduler for fetching snippets. Not owned. NTPSnippetsScheduler* scheduler_; @@ -303,6 +324,8 @@ DISALLOW_COPY_AND_ASSIGN(NTPSnippetsService); }; +// TODO(pke): Remove this when snippets internals don't access this service +// directly anymore. class NTPSnippetsServiceObserver { public: // Sent every time the service loads a new set of data.
diff --git a/components/ntp_snippets/ntp_snippets_service_unittest.cc b/components/ntp_snippets/ntp_snippets_service_unittest.cc index 9ba767d..9a7dad0 100644 --- a/components/ntp_snippets/ntp_snippets_service_unittest.cc +++ b/components/ntp_snippets/ntp_snippets_service_unittest.cc
@@ -414,7 +414,7 @@ LoadFromJSONString(json_str); EXPECT_THAT(service()->snippets(), SizeIs(1)); - service()->ClearSnippets(); + service()->ClearCachedSuggestionsForDebugging(); EXPECT_THAT(service()->snippets(), IsEmpty()); } @@ -499,11 +499,11 @@ ASSERT_THAT(service()->snippets(), SizeIs(1)); // Discarding a non-existent snippet shouldn't do anything. - EXPECT_FALSE(service()->DiscardSnippet("http://othersite.com")); + service()->DiscardSuggestion("http://othersite.com"); EXPECT_THAT(service()->snippets(), SizeIs(1)); // Discard the snippet. - EXPECT_TRUE(service()->DiscardSnippet(kSnippetUrl)); + service()->DiscardSuggestion(kSnippetUrl); EXPECT_THAT(service()->snippets(), IsEmpty()); // Make sure that fetching the same snippet again does not re-add it. @@ -517,7 +517,7 @@ EXPECT_THAT(service()->snippets(), IsEmpty()); // The snippet can be added again after clearing discarded snippets. - service()->ClearDiscardedSnippets(); + service()->ClearDiscardedSuggestionsForDebugging(); EXPECT_THAT(service()->snippets(), IsEmpty()); LoadFromJSONString(json_str); EXPECT_THAT(service()->snippets(), SizeIs(1)); @@ -526,8 +526,7 @@ TEST_F(NTPSnippetsServiceTest, GetDiscarded) { LoadFromJSONString(GetTestJson({GetSnippet()})); - // For the test, we need the snippet to get discarded. - ASSERT_TRUE(service()->DiscardSnippet(kSnippetUrl)); + service()->DiscardSuggestion(kSnippetUrl); const NTPSnippet::PtrVector& snippets = service()->discarded_snippets(); EXPECT_EQ(1u, snippets.size()); for (auto& snippet : snippets) { @@ -535,7 +534,7 @@ } // There should be no discarded snippet after clearing the list. - service()->ClearDiscardedSnippets(); + service()->ClearDiscardedSuggestionsForDebugging(); EXPECT_EQ(0u, service()->discarded_snippets().size()); } @@ -648,7 +647,7 @@ EXPECT_EQ(snippet.best_source().amp_url, GURL()); } - service()->ClearSnippets(); + service()->ClearCachedSuggestionsForDebugging(); // Set Source 1 to have no AMP url, and Source 2 to have no publisher name // Source 1 should win in this case since we prefer publisher name to AMP url source_urls.clear(); @@ -674,7 +673,7 @@ EXPECT_EQ(snippet.best_source().amp_url, GURL()); } - service()->ClearSnippets(); + service()->ClearCachedSuggestionsForDebugging(); // Set source 1 to have no AMP url and no source, and source 2 to only have // amp url. There should be no snippets since we only add sources we consider // complete @@ -721,7 +720,7 @@ } // Test 2 complete sources, we should choose the first complete source - service()->ClearSnippets(); + service()->ClearCachedSuggestionsForDebugging(); source_urls.clear(); source_urls.push_back(std::string("http://source1.com")); source_urls.push_back(std::string("http://source2.com")); @@ -749,7 +748,7 @@ } // Test 3 complete sources, we should choose the first complete source - service()->ClearSnippets(); + service()->ClearCachedSuggestionsForDebugging(); source_urls.clear(); source_urls.push_back(std::string("http://source1.com")); source_urls.push_back(std::string("http://source2.com")); @@ -813,7 +812,7 @@ IsEmpty()); // Discarding a snippet should decrease the list size. This will only be // logged after the next fetch. - EXPECT_TRUE(service()->DiscardSnippet(kSnippetUrl)); + service()->DiscardSuggestion(kSnippetUrl); LoadFromJSONString(GetTestJson({GetSnippet()})); EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticles"), ElementsAre(base::Bucket(/*min=*/0, /*count=*/3), @@ -852,7 +851,7 @@ source_urls[0], creation, expiry, source_urls, publishers, amp_urls)})); ASSERT_THAT(service()->snippets(), SizeIs(1)); // Discard the snippet via the mashable source corpus ID. - EXPECT_TRUE(service()->DiscardSnippet(source_urls[0])); + service()->DiscardSuggestion(source_urls[0]); EXPECT_THAT(service()->snippets(), IsEmpty()); // The same article from the AOL domain should now be detected as discarded.
diff --git a/components/ntp_tiles.gypi b/components/ntp_tiles.gypi index 1e6de87..232a4ad 100644 --- a/components/ntp_tiles.gypi +++ b/components/ntp_tiles.gypi
@@ -49,7 +49,7 @@ 'target_name': 'ntp_tiles_enums_java', 'type': 'none', 'variables': { - 'source_file': 'ntp_tiles/most_visited_sites.cc', + 'source_file': 'ntp_tiles/most_visited_sites.h', }, 'includes': [ '../build/android/java_cpp_enum.gypi'
diff --git a/components/ntp_tiles/BUILD.gn b/components/ntp_tiles/BUILD.gn index 7422d6d..a948cd1 100644 --- a/components/ntp_tiles/BUILD.gn +++ b/components/ntp_tiles/BUILD.gn
@@ -54,7 +54,7 @@ if (is_android) { java_cpp_enum("ntp_tiles_enums_java") { sources = [ - "most_visited_sites.cc", + "most_visited_sites.h", ] } }
diff --git a/components/ntp_tiles/most_visited_sites.cc b/components/ntp_tiles/most_visited_sites.cc index 3da5f03a..47cb499 100644 --- a/components/ntp_tiles/most_visited_sites.cc +++ b/components/ntp_tiles/most_visited_sites.cc
@@ -25,7 +25,6 @@ #include "components/ntp_tiles/switches.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" -#include "ui/gfx/codec/jpeg_codec.h" #include "url/gurl.h" using history::TopSites; @@ -40,32 +39,12 @@ // Identifiers for the various tile sources. const char kHistogramClientName[] = "client"; const char kHistogramServerName[] = "server"; -const char kHistogramServerFormat[] = "server%d"; const char kHistogramPopularName[] = "popular"; const char kHistogramWhitelistName[] = "whitelist"; const base::Feature kDisplaySuggestionsServiceTiles{ "DisplaySuggestionsServiceTiles", base::FEATURE_ENABLED_BY_DEFAULT}; -// The visual type of a most visited tile. -// -// These values must stay in sync with the MostVisitedTileType enum -// in histograms.xml. -// -// A Java counterpart will be generated for this enum. -// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.ntp -enum MostVisitedTileType { - // The icon or thumbnail hasn't loaded yet. - NONE, - // The item displays a site's actual favicon or touch icon. - ICON_REAL, - // The item displays a color derived from the site's favicon or touch icon. - ICON_COLOR, - // The item displays a default gray box in place of an icon. - ICON_DEFAULT, - NUM_TILE_TYPES, -}; - // Log an event for a given |histogram| at a given element |position|. This // routine exists because regular histogram macros are cached thus can't be used // if the name of the histogram will change at a given call site. @@ -98,16 +77,20 @@ // Determine whether we need any popular suggestions to fill up a grid of // |num_tiles| tiles. -bool NeedPopularSites(const PrefService* prefs, size_t num_tiles) { +bool NeedPopularSites(const PrefService* prefs, int num_tiles) { + if (num_tiles <= prefs->GetInteger(prefs::kNumPersonalSuggestions)) + return false; + + // TODO(treib): Remove after M55. const base::ListValue* source_list = - prefs->GetList(ntp_tiles::prefs::kNTPSuggestionsIsPersonal); + prefs->GetList(ntp_tiles::prefs::kDeprecatedNTPSuggestionsIsPersonal); // If there aren't enough previous suggestions to fill the grid, we need // popular suggestions. - if (source_list->GetSize() < num_tiles) + if (static_cast<int>(source_list->GetSize()) < num_tiles) return true; // Otherwise, if any of the previous suggestions is not personal, then also // get popular suggestions. - for (size_t i = 0; i < num_tiles; ++i) { + for (int i = 0; i < num_tiles; ++i) { bool is_personal = false; if (source_list->GetBoolean(i, &is_personal) && !is_personal) return true; @@ -121,9 +104,8 @@ return url1.host() == url2.host() && url1.path() == url2.path(); } -std::string GetSourceHistogramName( - const MostVisitedSites::Suggestion& suggestion) { - switch (suggestion.source) { +std::string GetSourceHistogramName(int source) { + switch (source) { case MostVisitedSites::TOP_SITES: return kHistogramClientName; case MostVisitedSites::POPULAR: @@ -131,10 +113,7 @@ case MostVisitedSites::WHITELIST: return kHistogramWhitelistName; case MostVisitedSites::SUGGESTIONS_SERVICE: - return suggestion.provider_index >= 0 - ? base::StringPrintf(kHistogramServerFormat, - suggestion.provider_index) - : kHistogramServerName; + return kHistogramServerName; } NOTREACHED(); return std::string(); @@ -149,7 +128,7 @@ } // namespace -MostVisitedSites::Suggestion::Suggestion() : provider_index(-1) {} +MostVisitedSites::Suggestion::Suggestion() {} MostVisitedSites::Suggestion::~Suggestion() {} @@ -252,15 +231,18 @@ } void MostVisitedSites::RecordTileTypeMetrics( - const std::vector<int>& tile_types) { - DCHECK_EQ(current_suggestions_.size(), tile_types.size()); + const std::vector<int>& tile_types, + const std::vector<int>& sources) { int counts_per_type[NUM_TILE_TYPES] = {0}; for (size_t i = 0; i < tile_types.size(); ++i) { int tile_type = tile_types[i]; ++counts_per_type[tile_type]; + + UMA_HISTOGRAM_ENUMERATION("NewTabPage.TileType", tile_type, NUM_TILE_TYPES); + std::string histogram = base::StringPrintf( "NewTabPage.TileType.%s", - GetSourceHistogramName(current_suggestions_[i]).c_str()); + GetSourceHistogramName(sources[i]).c_str()); LogHistogramEvent(histogram, tile_type, NUM_TILE_TYPES); } @@ -272,17 +254,20 @@ counts_per_type[ICON_DEFAULT]); } -void MostVisitedSites::RecordOpenedMostVisitedItem(int index, int tile_type) { - DCHECK_GE(index, 0); - DCHECK_LT(index, static_cast<int>(current_suggestions_.size())); +void MostVisitedSites::RecordOpenedMostVisitedItem(int index, + int tile_type, + int source) { + UMA_HISTOGRAM_ENUMERATION("NewTabPage.MostVisited", index, num_sites_); + std::string histogram = base::StringPrintf( - "NewTabPage.MostVisited.%s", - GetSourceHistogramName(current_suggestions_[index]).c_str()); + "NewTabPage.MostVisited.%s", GetSourceHistogramName(source).c_str()); LogHistogramEvent(histogram, index, num_sites_); - histogram = base::StringPrintf( - "NewTabPage.TileTypeClicked.%s", - GetSourceHistogramName(current_suggestions_[index]).c_str()); + UMA_HISTOGRAM_ENUMERATION( + "NewTabPage.TileTypeClicked", tile_type, NUM_TILE_TYPES); + + histogram = base::StringPrintf("NewTabPage.TileTypeClicked.%s", + GetSourceHistogramName(source).c_str()); LogHistogramEvent(histogram, tile_type, NUM_TILE_TYPES); } @@ -293,13 +278,10 @@ // static void MostVisitedSites::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - // TODO(treib): Remove this, it's unused. Do we need migration code to clean - // up existing entries? - registry->RegisterListPref(ntp_tiles::prefs::kNTPSuggestionsURL); - // TODO(treib): Remove this. It's only used to determine if we need - // PopularSites at all. Find a way to do that without prefs, or failing that, - // replace this list pref by a simple bool. - registry->RegisterListPref(ntp_tiles::prefs::kNTPSuggestionsIsPersonal); + registry->RegisterIntegerPref(prefs::kNumPersonalSuggestions, 0); + // TODO(treib): Remove after M55. + registry->RegisterListPref(prefs::kDeprecatedNTPSuggestionsURL); + registry->RegisterListPref(prefs::kDeprecatedNTPSuggestionsIsPersonal); } void MostVisitedSites::BuildCurrentSuggestions() { @@ -379,8 +361,6 @@ generated_suggestion.source = SUGGESTIONS_SERVICE; generated_suggestion.whitelist_icon_path = GetWhitelistLargeIconPath(GURL(suggestion.url())); - if (suggestion.providers_size() > 0) - generated_suggestion.provider_index = suggestion.providers(0); suggestions.push_back(std::move(generated_suggestion)); } @@ -495,8 +475,15 @@ std::move(popular_sites_suggestions)); DCHECK_EQ(num_actual_tiles, current_suggestions_.size()); - if (received_popular_sites_) - SaveCurrentSuggestionsToPrefs(); + int num_personal_suggestions = 0; + for (const auto& suggestion : current_suggestions_) { + if (suggestion.source != POPULAR) + num_personal_suggestions++; + } + prefs_->SetInteger(prefs::kNumPersonalSuggestions, num_personal_suggestions); + // TODO(treib): Remove after M55. + prefs_->ClearPref(prefs::kDeprecatedNTPSuggestionsIsPersonal); + prefs_->ClearPref(prefs::kDeprecatedNTPSuggestionsURL); } // static @@ -511,23 +498,10 @@ return merged_suggestions; } -void MostVisitedSites::SaveCurrentSuggestionsToPrefs() { - base::ListValue url_list; - base::ListValue source_list; - for (const auto& suggestion : current_suggestions_) { - url_list.AppendString(suggestion.url.spec()); - source_list.AppendBoolean(suggestion.source != POPULAR); - } - prefs_->Set(ntp_tiles::prefs::kNTPSuggestionsIsPersonal, source_list); - prefs_->Set(ntp_tiles::prefs::kNTPSuggestionsURL, url_list); -} - void MostVisitedSites::NotifyMostVisitedURLsObserver() { if (received_most_visited_sites_ && received_popular_sites_ && !recorded_uma_) { RecordImpressionUMAMetrics(); - UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.NumberOfTiles", - current_suggestions_.size()); recorded_uma_ = true; } @@ -554,10 +528,16 @@ } void MostVisitedSites::RecordImpressionUMAMetrics() { + UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.NumberOfTiles", + current_suggestions_.size()); + for (size_t i = 0; i < current_suggestions_.size(); i++) { + UMA_HISTOGRAM_ENUMERATION( + "NewTabPage.SuggestionsImpression", static_cast<int>(i), num_sites_); + std::string histogram = base::StringPrintf( "NewTabPage.SuggestionsImpression.%s", - GetSourceHistogramName(current_suggestions_[i]).c_str()); + GetSourceHistogramName(current_suggestions_[i].source).c_str()); LogHistogramEvent(histogram, static_cast<int>(i), num_sites_); } }
diff --git a/components/ntp_tiles/most_visited_sites.h b/components/ntp_tiles/most_visited_sites.h index 2765d97f..236f19e 100644 --- a/components/ntp_tiles/most_visited_sites.h +++ b/components/ntp_tiles/most_visited_sites.h
@@ -91,8 +91,38 @@ using SuggestionsVector = std::vector<Suggestion>; using PopularSitesVector = std::vector<PopularSites::Site>; + // The visual type of a most visited tile. + // + // These values must stay in sync with the MostVisitedTileType enum + // in histograms.xml. + // + // A Java counterpart will be generated for this enum. + // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.ntp + enum MostVisitedTileType { + // The icon or thumbnail hasn't loaded yet. + NONE, + // The item displays a site's actual favicon or touch icon. + ICON_REAL, + // The item displays a color derived from the site's favicon or touch icon. + ICON_COLOR, + // The item displays a default gray box in place of an icon. + ICON_DEFAULT, + NUM_TILE_TYPES, + }; + // The source of the Most Visited sites. - enum MostVisitedSource { TOP_SITES, SUGGESTIONS_SERVICE, POPULAR, WHITELIST }; + // A Java counterpart will be generated for this enum. + // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.ntp + enum MostVisitedSource { + // Item comes from the personal top sites list. + TOP_SITES, + // Item comes from the suggestions service. + SUGGESTIONS_SERVICE, + // Item is regionally popular. + POPULAR, + // Item is on an custodian-managed whitelist. + WHITELIST + }; // The observer to be notified when the list of most visited sites changes. class Observer { @@ -113,9 +143,6 @@ // Only valid for source == WHITELIST (empty otherwise). base::FilePath whitelist_icon_path; - // Only valid for source == SUGGESTIONS_SERVICE (-1 otherwise). - int provider_index; - Suggestion(); ~Suggestion(); @@ -143,8 +170,9 @@ void SetMostVisitedURLsObserver(Observer* observer, int num_sites); void AddOrRemoveBlacklistedUrl(const GURL& url, bool add_url); - void RecordTileTypeMetrics(const std::vector<int>& tile_types); - void RecordOpenedMostVisitedItem(int index, int tile_type); + void RecordTileTypeMetrics(const std::vector<int>& tile_types, + const std::vector<int>& sources); + void RecordOpenedMostVisitedItem(int index, int tile_type, int source); // MostVisitedSitesSupervisor::Observer implementation. void OnBlockedSitesChanged() override; @@ -193,17 +221,12 @@ SuggestionsVector whitelist_suggestions, SuggestionsVector popular_suggestions); - void SaveCurrentSuggestionsToPrefs(); - // Notifies the observer about the availability of suggestions. // Also records impressions UMA if not done already. void NotifyMostVisitedURLsObserver(); void OnPopularSitesAvailable(bool success); - // Records thumbnail-related UMA histogram metrics. - void RecordThumbnailUMAMetrics(); - // Records UMA histogram metrics related to the number of impressions. void RecordImpressionUMAMetrics();
diff --git a/components/ntp_tiles/pref_names.cc b/components/ntp_tiles/pref_names.cc index dd72edbf..77c47d05 100644 --- a/components/ntp_tiles/pref_names.cc +++ b/components/ntp_tiles/pref_names.cc
@@ -7,12 +7,13 @@ namespace ntp_tiles { namespace prefs { -// Ordered list of website suggestions shown on the new tab page that will allow -// retaining the order even if the suggestions change over time. -const char kNTPSuggestionsURL[] = "ntp.suggestions_url"; +const char kDeprecatedNTPSuggestionsURL[] = "ntp.suggestions_url"; +const char kDeprecatedNTPSuggestionsIsPersonal[] = + "ntp.suggestions_is_personal"; -// Whether the suggestion was derived from personal data. -const char kNTPSuggestionsIsPersonal[] = "ntp.suggestions_is_personal"; +// The number of personal suggestions we had previously. Used to figure out +// whether we need popular sites. +const char kNumPersonalSuggestions[] = "ntp.num_personal_suggestions"; // If set, overrides the URL for popular sites, including the individual // overrides for country and version below.
diff --git a/components/ntp_tiles/pref_names.h b/components/ntp_tiles/pref_names.h index d1ca404..81f62f1 100644 --- a/components/ntp_tiles/pref_names.h +++ b/components/ntp_tiles/pref_names.h
@@ -8,8 +8,11 @@ namespace ntp_tiles { namespace prefs { -extern const char kNTPSuggestionsURL[]; -extern const char kNTPSuggestionsIsPersonal[]; +// TODO(treib): Remove after M55. +extern const char kDeprecatedNTPSuggestionsURL[]; +extern const char kDeprecatedNTPSuggestionsIsPersonal[]; + +extern const char kNumPersonalSuggestions[]; extern const char kPopularSitesOverrideURL[]; extern const char kPopularSitesOverrideCountry[];
diff --git a/components/offline_pages/background/offliner.h b/components/offline_pages/background/offliner.h index 745fc61..0873186e 100644 --- a/components/offline_pages/background/offliner.h +++ b/components/offline_pages/background/offliner.h
@@ -16,14 +16,20 @@ class Offliner { public: // Status of processing an offline page request. - enum class RequestStatus { - UNKNOWN, // No status determined/reported yet. - LOADED, // Page loaded but not (yet) saved. - SAVED, // Offline page snapshot saved. - CANCELED, // Request was canceled. - FAILED, // Failed to load page. - FAILED_SAVE, // Failed to save loaded page. - // TODO(dougarnett): Define a retry-able failure status. + // WARNING: You must update histograms.xml to match any changes made to + // this enum (ie, OfflinePagesBackgroundOfflinerRequestStatus histogram enum). + enum RequestStatus { + UNKNOWN = 0, // No status determined/reported yet. Interim status, not sent + // in callback. + LOADED = 1, // Page loaded but not (yet) saved. Interim status, not sent in + // callback. + SAVED = 2, // Offline page snapshot saved. + REQUEST_COORDINATOR_CANCELED = 3, // RequestCoordinator canceled request. + PRERENDERING_CANCELED = 4, // Prerendering was canceled. + PRERENDERING_FAILED = 5, // Prerendering failed to load page. + SAVE_FAILED = 6, // Failed to save loaded page. + // NOTE: insert new values above this line and update histogram enum too. + STATUS_COUNT }; // Reports the completion status of a request. @@ -41,7 +47,8 @@ const SavePageRequest& request, const CompletionCallback& callback) = 0; - // Clears the currently processing request, if any. + // Clears the currently processing request, if any, and skips running its + // CompletionCallback. virtual void Cancel() = 0; // TODO(dougarnett): add policy support methods.
diff --git a/components/offline_pages/background/request_coordinator.cc b/components/offline_pages/background/request_coordinator.cc index 6292aa8..e6ac73f 100644 --- a/components/offline_pages/background/request_coordinator.cc +++ b/components/offline_pages/background/request_coordinator.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/callback.h" #include "base/logging.h" +#include "base/metrics/histogram_macros.h" #include "base/time/time.h" #include "components/offline_pages/background/offliner_factory.h" #include "components/offline_pages/background/offliner_policy.h" @@ -19,6 +20,15 @@ namespace offline_pages { namespace { + +// Records the final request status UMA for an offlining request. This should +// only be called once per Offliner::LoadAndSave request. +void RecordOfflinerResultUMA(Offliner::RequestStatus request_status) { + UMA_HISTOGRAM_ENUMERATION("OfflinePages.Background.OfflinerRequestStatus", + request_status, + Offliner::RequestStatus::STATUS_COUNT); +} + // TODO(dougarnett/petewil): Move to Policy object. Also consider lower minimum // battery percentage once there is some processing time limits in place. const Scheduler::TriggerConditions kUserRequestTriggerConditions( @@ -92,6 +102,11 @@ if (offliner_ && is_busy_) offliner_->Cancel(); + // Stopping offliner means it will not call callback. + last_offlining_status_ = + Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED; + RecordOfflinerResultUMA(last_offlining_status_); + // Let the scheduler know we are done processing. scheduler_callback_.Run(true); } @@ -167,11 +182,14 @@ DVLOG(2) << "offliner finished, saved: " << (status == Offliner::RequestStatus::SAVED) << ", status: " << (int) status << ", " << __FUNCTION__; + DCHECK_NE(status, Offliner::RequestStatus::UNKNOWN); + DCHECK_NE(status, Offliner::RequestStatus::LOADED); event_logger_.RecordSavePageRequestUpdated( request.client_id().name_space, "Saved", request.request_id()); last_offlining_status_ = status; + RecordOfflinerResultUMA(last_offlining_status_); watchdog_timer_.Stop(); is_busy_ = false;
diff --git a/components/offline_pages/background/request_coordinator_unittest.cc b/components/offline_pages/background/request_coordinator_unittest.cc index 0204b1b..34f29f99 100644 --- a/components/offline_pages/background/request_coordinator_unittest.cc +++ b/components/offline_pages/background/request_coordinator_unittest.cc
@@ -68,8 +68,10 @@ class OfflinerStub : public Offliner { public: - OfflinerStub() : request_(kRequestId, kUrl, kClientId, base::Time::Now()), - enable_callback_(false) {} + OfflinerStub() + : request_(kRequestId, kUrl, kClientId, base::Time::Now()), + enable_callback_(false), + cancel_called_(false) {} bool LoadAndSave(const SavePageRequest& request, const CompletionCallback& callback) override { @@ -84,28 +86,23 @@ return true; } - // Clears the currently processing request, if any. Must have called - // LoadAndSave first to set the callback and request. - // Clears the currently processing request, if any. - void Cancel() override { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(callback_, request_, Offliner::RequestStatus::CANCELED)); - } + void Cancel() override { cancel_called_ = true; } void enable_callback(bool enable) { enable_callback_ = enable; } + bool cancel_called() { return cancel_called_; } + private: CompletionCallback callback_; SavePageRequest request_; bool enable_callback_; + bool cancel_called_; }; class OfflinerFactoryStub : public OfflinerFactory { public: - OfflinerFactoryStub() : offliner_(nullptr) {} Offliner* GetOffliner(const OfflinerPolicy* policy) override { @@ -185,6 +182,8 @@ return coordinator_->last_offlining_status_; } + bool OfflinerWasCanceled() const { return offliner_->cancel_called(); } + private: RequestQueue::GetRequestsResult last_get_requests_result_; std::vector<SavePageRequest> last_requests_; @@ -356,7 +355,8 @@ // Call the OfflinerDoneCallback to simulate the request failed, wait // for callbacks. EnableOfflinerCallback(true); - SendOfflinerDoneCallback(request, Offliner::RequestStatus::FAILED); + SendOfflinerDoneCallback(request, + Offliner::RequestStatus::PRERENDERING_FAILED); PumpLoop(); // Verify the request is not removed from the queue, and wait for callbacks. @@ -397,8 +397,12 @@ PumpLoop(); // OfflinerDoneCallback will not end up getting called with status SAVED, - // Since we cancelled the event before it called offliner_->LoadAndSave(). - EXPECT_NE(Offliner::RequestStatus::SAVED, last_offlining_status()); + // since we cancelled the event before it called offliner_->LoadAndSave(). + EXPECT_EQ(Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED, + last_offlining_status()); + + // Since offliner was not started, it will not have seen cancel call. + EXPECT_FALSE(OfflinerWasCanceled()); } // This tests a StopProcessing call after the prerenderer has been started. @@ -433,8 +437,12 @@ PumpLoop(); // OfflinerDoneCallback will not end up getting called with status SAVED, - // Since we cancelled the event before it called offliner_->LoadAndSave(). - EXPECT_EQ(Offliner::RequestStatus::CANCELED, last_offlining_status()); + // since we cancelled the event before the LoadAndSave completed. + EXPECT_EQ(Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED, + last_offlining_status()); + + // Since offliner was started, it will have seen cancel call. + EXPECT_TRUE(OfflinerWasCanceled()); } TEST_F(RequestCoordinatorTest, PrerendererTimeout) { @@ -477,8 +485,9 @@ WaitForCallback(); PumpLoop(); - // Now trying to start processing on another request should return false. - EXPECT_EQ(Offliner::RequestStatus::CANCELED, last_offlining_status()); + EXPECT_TRUE(OfflinerWasCanceled()); + EXPECT_EQ(Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED, + last_offlining_status()); } } // namespace offline_pages
diff --git a/components/offline_pages/client_namespace_constants.cc b/components/offline_pages/client_namespace_constants.cc index 508db279..c6c67882 100644 --- a/components/offline_pages/client_namespace_constants.cc +++ b/components/offline_pages/client_namespace_constants.cc
@@ -8,6 +8,7 @@ const char kBookmarkNamespace[] = "bookmark"; const char kLastNNamespace[] = "last_n"; +const char kAsyncNamespace[] = "async_loading"; const char kDefaultNamespace[] = "default";
diff --git a/components/offline_pages/client_namespace_constants.h b/components/offline_pages/client_namespace_constants.h index 108e0315..3372186 100644 --- a/components/offline_pages/client_namespace_constants.h +++ b/components/offline_pages/client_namespace_constants.h
@@ -13,6 +13,7 @@ // OfflinePagesNamespace (histograms.xml) for consistency. extern const char kBookmarkNamespace[]; extern const char kLastNNamespace[]; +extern const char kAsyncNamespace[]; // Currently used for fallbacks like tests. extern const char kDefaultNamespace[];
diff --git a/components/offline_pages/client_policy_controller.cc b/components/offline_pages/client_policy_controller.cc index 6f379dbe..7adf46c 100644 --- a/components/offline_pages/client_policy_controller.cc +++ b/components/offline_pages/client_policy_controller.cc
@@ -24,6 +24,10 @@ kLastNNamespace, MakePolicy(kLastNNamespace, LifetimeType::TEMPORARY, base::TimeDelta::FromDays(2), kUnlimitedPages, kUnlimitedPages))); + policies_.insert(std::make_pair( + kAsyncNamespace, MakePolicy(kAsyncNamespace, LifetimeType::PERSISTENT, + base::TimeDelta::FromDays(2), kUnlimitedPages, + kUnlimitedPages))); // Fallback policy. policies_.insert(std::make_pair( kDefaultNamespace, MakePolicy(kDefaultNamespace, LifetimeType::TEMPORARY,
diff --git a/components/offline_pages/client_policy_controller_unittest.cc b/components/offline_pages/client_policy_controller_unittest.cc index 918de56d5..0654c343 100644 --- a/components/offline_pages/client_policy_controller_unittest.cc +++ b/components/offline_pages/client_policy_controller_unittest.cc
@@ -17,12 +17,8 @@ const char kUndefinedNamespace[] = "undefined"; bool isTemporary(const OfflinePageClientPolicy& policy) { - // Check if policy has a expire period > 0 or a limited number - // of pages allowed. - return (policy.lifetime_policy.page_limit > kUnlimitedPages || - !policy.lifetime_policy.expiration_period.is_zero()); + return policy.lifetime_policy.lifetime_type == LifetimeType::TEMPORARY; } - } // namespace class ClientPolicyControllerTest : public testing::Test { @@ -63,4 +59,10 @@ EXPECT_TRUE(isTemporary(policy)); } +TEST_F(ClientPolicyControllerTest, CheckAsyncDefined) { + OfflinePageClientPolicy policy = controller()->GetPolicy(kAsyncNamespace); + EXPECT_EQ(policy.name_space, kAsyncNamespace); + EXPECT_FALSE(isTemporary(policy)); +} + } // namespace offline_pages
diff --git a/components/offline_pages/offline_page_model.h b/components/offline_pages/offline_page_model.h index c7ea6b0..9c6efb7 100644 --- a/components/offline_pages/offline_page_model.h +++ b/components/offline_pages/offline_page_model.h
@@ -119,6 +119,10 @@ // Gets all offline pages. virtual void GetAllPages(const MultipleOfflinePageItemCallback& callback) = 0; + // Gets all offline pages including expired ones. + virtual void GetAllPagesWithExpired( + const MultipleOfflinePageItemCallback& callback) = 0; + // Gets all offline ids where the offline page has the matching client id. virtual void GetOfflineIdsForClientId( const ClientId& client_id,
diff --git a/components/offline_pages/offline_page_model_impl.cc b/components/offline_pages/offline_page_model_impl.cc index 8642ab13..f08f1fee 100644 --- a/components/offline_pages/offline_page_model_impl.cc +++ b/components/offline_pages/offline_page_model_impl.cc
@@ -450,16 +450,26 @@ void OfflinePageModelImpl::GetAllPages( const MultipleOfflinePageItemCallback& callback) { RunWhenLoaded(base::Bind(&OfflinePageModelImpl::GetAllPagesAfterLoadDone, - weak_ptr_factory_.GetWeakPtr(), callback)); + weak_ptr_factory_.GetWeakPtr(), GetAllPageMode::ALL, + callback)); +} + +void OfflinePageModelImpl::GetAllPagesWithExpired( + const MultipleOfflinePageItemCallback& callback) { + RunWhenLoaded(base::Bind(&OfflinePageModelImpl::GetAllPagesAfterLoadDone, + weak_ptr_factory_.GetWeakPtr(), + GetAllPageMode::ALL_WITH_EXPIRED, callback)); } void OfflinePageModelImpl::GetAllPagesAfterLoadDone( + GetAllPageMode mode, const MultipleOfflinePageItemCallback& callback) const { DCHECK(is_loaded_); MultipleOfflinePageItemResult offline_pages; for (const auto& id_page_pair : offline_pages_) { - if (!id_page_pair.second.IsExpired()) + if (mode == GetAllPageMode::ALL_WITH_EXPIRED || + !id_page_pair.second.IsExpired()) offline_pages.push_back(id_page_pair.second); } @@ -654,17 +664,18 @@ if (iter != offline_pages_.end()) { iter->second.expiration_time = expiration_time; ClientId client_id = iter->second.client_id; - UMA_HISTOGRAM_CUSTOM_COUNTS( - AddHistogramSuffix(client_id, "OfflinePages.ExpirePage.PageLifetime") - .c_str(), - (expiration_time - iter->second.creation_time).InMinutes(), 1, - base::TimeDelta::FromDays(30).InMinutes(), 50); - UMA_HISTOGRAM_CUSTOM_COUNTS( + base::HistogramBase* histogram = base::Histogram::FactoryGet( + AddHistogramSuffix(client_id, "OfflinePages.ExpirePage.PageLifetime"), + 1, base::TimeDelta::FromDays(30).InMinutes(), 50, + base::HistogramBase::kUmaTargetedHistogramFlag); + histogram->Add((expiration_time - iter->second.creation_time).InMinutes()); + histogram = base::Histogram::FactoryGet( AddHistogramSuffix(client_id, - "OfflinePages.ExpirePage.TimeSinceLastAccess") - .c_str(), - (expiration_time - iter->second.last_access_time).InMinutes(), 1, - base::TimeDelta::FromDays(30).InMinutes(), 50); + "OfflinePages.ExpirePage.TimeSinceLastAccess"), + 1, base::TimeDelta::FromDays(30).InMinutes(), 50, + base::HistogramBase::kUmaTargetedHistogramFlag); + histogram->Add( + (expiration_time - iter->second.last_access_time).InMinutes()); } }
diff --git a/components/offline_pages/offline_page_model_impl.h b/components/offline_pages/offline_page_model_impl.h index 1efb687..b93a227 100644 --- a/components/offline_pages/offline_page_model_impl.h +++ b/components/offline_pages/offline_page_model_impl.h
@@ -81,6 +81,8 @@ const std::set<GURL>& urls, const CheckPagesExistOfflineCallback& callback) override; void GetAllPages(const MultipleOfflinePageItemCallback& callback) override; + void GetAllPagesWithExpired( + const MultipleOfflinePageItemCallback& callback) override; void GetOfflineIdsForClientId( const ClientId& client_id, const MultipleOfflineIdCallback& callback) override; @@ -127,12 +129,18 @@ private: FRIEND_TEST_ALL_PREFIXES(OfflinePageModelImplTest, MarkPageForDeletion); + enum class GetAllPageMode { + ALL, // Get all active page entries. + ALL_WITH_EXPIRED, // Get all pages entries including expired ones. + }; + typedef ScopedVector<OfflinePageArchiver> PendingArchivers; // Callback for ensuring archive directory is created. void OnEnsureArchivesDirCreatedDone(const base::TimeTicks& start_time); void GetAllPagesAfterLoadDone( + GetAllPageMode mode, const MultipleOfflinePageItemCallback& callback) const; void CheckPagesExistOfflineAfterLoadDone( const std::set<GURL>& urls,
diff --git a/components/offline_pages/offline_page_storage_manager.cc b/components/offline_pages/offline_page_storage_manager.cc index 4a23269e..cc3fd4c 100644 --- a/components/offline_pages/offline_page_storage_manager.cc +++ b/components/offline_pages/offline_page_storage_manager.cc
@@ -14,6 +14,8 @@ #include "components/offline_pages/offline_page_item.h" #include "components/offline_pages/offline_page_model.h" +using LifetimeType = offline_pages::LifetimePolicy::LifetimeType; + namespace offline_pages { OfflinePageStorageManager::OfflinePageStorageManager( @@ -108,6 +110,7 @@ const ArchiveManager::StorageStats& stats, std::vector<int64_t>* page_ids_to_expire, std::vector<int64_t>* page_ids_to_remove) { + // TODO(romax): See how persistent should be considered here. // Creating a map from namespace to a vector of page items. // Sort each vector based on last accessed time and all pages after index // min{size(), page_limit} should be expired. And then start iterating @@ -200,7 +203,8 @@ const OfflinePageItem& page) const { const LifetimePolicy& policy = policy_controller_->GetPolicy(page.client_id.name_space).lifetime_policy; - return clear_time_ - page.last_access_time >= policy.expiration_period; + return policy.lifetime_type == LifetimeType::TEMPORARY && + clear_time_ - page.last_access_time >= policy.expiration_period; } bool OfflinePageStorageManager::IsInProgress() const {
diff --git a/components/offline_pages/offline_page_storage_manager_unittest.cc b/components/offline_pages/offline_page_storage_manager_unittest.cc index 75bda82..69c1325 100644 --- a/components/offline_pages/offline_page_storage_manager_unittest.cc +++ b/components/offline_pages/offline_page_storage_manager_unittest.cc
@@ -300,6 +300,16 @@ EXPECT_EQ(0, static_cast<int>(model()->GetRemovedPages().size())); } +TEST_F(OfflinePageStorageManagerTest, TestDeleteAsyncPages) { + Initialize(std::vector<PageSettings>({{kAsyncNamespace, 20, 0}})); + clock()->Advance(base::TimeDelta::FromDays(367)); + TryClearPages(); + EXPECT_EQ(0, last_cleared_page_count()); + EXPECT_EQ(1, total_cleared_times()); + EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result()); + EXPECT_EQ(0, static_cast<int>(model()->GetRemovedPages().size())); +} + TEST_F(OfflinePageStorageManagerTest, TestDeletionFailed) { Initialize(std::vector<PageSettings>( {{kBookmarkNamespace, 10, 10}, {kLastNNamespace, 10, 10}}), @@ -376,8 +386,9 @@ } TEST_F(OfflinePageStorageManagerTest, TestClearMultipleTimes) { - Initialize(std::vector<PageSettings>( - {{kBookmarkNamespace, 30, 0}, {kLastNNamespace, 100, 1}}), + Initialize(std::vector<PageSettings>({{kBookmarkNamespace, 30, 0}, + {kLastNNamespace, 100, 1}, + {kAsyncNamespace, 40, 0}}), {1000 * (1 << 20), 0}); clock()->Advance(base::TimeDelta::FromMinutes(30)); LifetimePolicy policy =
diff --git a/components/offline_pages/stub_offline_page_model.cc b/components/offline_pages/stub_offline_page_model.cc index 3c17ad31..9d00e46a 100644 --- a/components/offline_pages/stub_offline_page_model.cc +++ b/components/offline_pages/stub_offline_page_model.cc
@@ -31,6 +31,8 @@ const CheckPagesExistOfflineCallback& callback) {} void StubOfflinePageModel::GetAllPages( const MultipleOfflinePageItemCallback& callback) {} +void StubOfflinePageModel::GetAllPagesWithExpired( + const MultipleOfflinePageItemCallback& callback) {} void StubOfflinePageModel::GetOfflineIdsForClientId( const ClientId& client_id, const MultipleOfflineIdCallback& callback) {}
diff --git a/components/offline_pages/stub_offline_page_model.h b/components/offline_pages/stub_offline_page_model.h index c851588..36515df 100644 --- a/components/offline_pages/stub_offline_page_model.h +++ b/components/offline_pages/stub_offline_page_model.h
@@ -39,6 +39,8 @@ const std::set<GURL>& urls, const CheckPagesExistOfflineCallback& callback) override; void GetAllPages(const MultipleOfflinePageItemCallback& callback) override; + void GetAllPagesWithExpired( + const MultipleOfflinePageItemCallback& callback) override; void GetOfflineIdsForClientId( const ClientId& client_id, const MultipleOfflineIdCallback& callback) override;
diff --git a/components/omnibox/browser/clipboard_url_provider.cc b/components/omnibox/browser/clipboard_url_provider.cc index e4459e75..93d4976 100644 --- a/components/omnibox/browser/clipboard_url_provider.cc +++ b/components/omnibox/browser/clipboard_url_provider.cc
@@ -30,24 +30,29 @@ void ClipboardURLProvider::Start(const AutocompleteInput& input, bool minimal_changes) { matches_.clear(); + + // If the user started typing, do not offer clipboard based match. if (!input.from_omnibox_focus()) return; GURL url; + // If the clipboard does not contain any URL, or the URL on the page is the + // same as the URL in the clipboard, early return. if (!clipboard_content_->GetRecentURLFromClipboard(&url) || url == input.current_url()) return; DCHECK(url.is_valid()); - // Adds a default match. This match will be opened when the user presses "Go". - AutocompleteMatch verbatim_match = VerbatimMatchForURL( - client_, input, input.current_url(), history_url_provider_, -1); - if (verbatim_match.destination_url.is_valid()) + // If the omnibox is not empty, add a default match. + // This match will be opened when the user presses "Enter". + if (!input.text().empty()) { + AutocompleteMatch verbatim_match = VerbatimMatchForURL( + client_, input, input.current_url(), history_url_provider_, -1); matches_.push_back(verbatim_match); + } - // Add a clipboard match just below the verbatim match. - AutocompleteMatch match(this, verbatim_match.relevance - 1, false, - AutocompleteMatchType::CLIPBOARD); + // Add the clipboard match. The relevance is 800 to beat ZeroSuggest results. + AutocompleteMatch match(this, 800, false, AutocompleteMatchType::CLIPBOARD); match.destination_url = url; match.contents.assign(url_formatter::FormatUrl( url, url_formatter::kFormatUrlOmitAll, net::UnescapeRule::SPACES,
diff --git a/components/omnibox/browser/verbatim_match.cc b/components/omnibox/browser/verbatim_match.cc index c74cf1e..e4efcf7 100644 --- a/components/omnibox/browser/verbatim_match.cc +++ b/components/omnibox/browser/verbatim_match.cc
@@ -4,6 +4,7 @@ #include "components/omnibox/browser/verbatim_match.h" +#include "base/logging.h" #include "components/omnibox/browser/autocomplete_classifier.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_provider_client.h" @@ -17,6 +18,7 @@ const GURL& destination_url, HistoryURLProvider* history_url_provider, int verbatim_relevance) { + DCHECK(!input.text().empty()); AutocompleteMatch match; // If query-in-the-omnibox is not enabled (and thus the verbatim match for // a URL is guaranteed to be a URL) and the caller already knows where the
diff --git a/components/omnibox/browser/verbatim_match.h b/components/omnibox/browser/verbatim_match.h index 05573b1..9b4f0b6c 100644 --- a/components/omnibox/browser/verbatim_match.h +++ b/components/omnibox/browser/verbatim_match.h
@@ -15,9 +15,10 @@ // Returns a verbatim match for input.text() with a relevance of // |verbatim_relevance|. If |verbatim_relevance| is negative then a default -// value is used. If the desired |destination_url| is already known and a +// value is used. If the desired |destination_url| is already known and a // |history_url_provider| is also provided, this may be more efficient (see // implementation for details) than the default code path. +// input.text() must not be empty. AutocompleteMatch VerbatimMatchForURL( AutocompleteProviderClient* client, const AutocompleteInput& input,
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer.cc b/components/page_load_metrics/browser/metrics_web_contents_observer.cc index 5009703..c9896b7 100644 --- a/components/page_load_metrics/browser/metrics_web_contents_observer.cc +++ b/components/page_load_metrics/browser/metrics_web_contents_observer.cc
@@ -786,12 +786,8 @@ if (event.type == blink::WebInputEvent::Type::Undefined) return; - if (!committed_load_) { - RecordInternalError(ERR_USER_INPUT_WITH_NO_RELEVANT_LOAD); - return; - } - - committed_load_->OnInputEvent(event); + if (committed_load_) + committed_load_->OnInputEvent(event); } void MetricsWebContentsObserver::DidRedirectNavigation(
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer.h b/components/page_load_metrics/browser/metrics_web_contents_observer.h index d9e06e8..0d01729 100644 --- a/components/page_load_metrics/browser/metrics_web_contents_observer.h +++ b/components/page_load_metrics/browser/metrics_web_contents_observer.h
@@ -89,8 +89,11 @@ // latest aborted load is used to track the chain size. ERR_NAVIGATION_SIGNALS_MULIPLE_ABORTED_LOADS, - // Receives user input before navigation start - ERR_USER_INPUT_WITH_NO_RELEVANT_LOAD, + // Received user input without a relevant load. This error type is deprecated, + // as it is valid to receive user input without a relevant load. We leave the + // enum value here since it's also used in histogram recording, so it's + // important that we not re-use this enum entry for a different value. + DEPRECATED_ERR_USER_INPUT_WITH_NO_RELEVANT_LOAD, // A TimeTicks value in the browser process has value less than // navigation_start_. This could happen if navigation_start_ was computed in
diff --git a/components/password_manager.gypi b/components/password_manager.gypi index 38d6a78..72c0f4d 100644 --- a/components/password_manager.gypi +++ b/components/password_manager.gypi
@@ -128,6 +128,8 @@ 'password_manager/core/browser/password_ui_utils.h', 'password_manager/core/browser/psl_matching_helper.cc', 'password_manager/core/browser/psl_matching_helper.h', + 'password_manager/core/browser/sql_table_builder.cc', + 'password_manager/core/browser/sql_table_builder.h', 'password_manager/core/browser/statistics_table.cc', 'password_manager/core/browser/statistics_table.h', 'password_manager/core/browser/test_affiliation_fetcher_factory.h',
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn index 145ad67..e4c2541 100644 --- a/components/password_manager/core/browser/BUILD.gn +++ b/components/password_manager/core/browser/BUILD.gn
@@ -108,6 +108,8 @@ "password_ui_utils.h", "psl_matching_helper.cc", "psl_matching_helper.h", + "sql_table_builder.cc", + "sql_table_builder.h", "statistics_table.cc", "statistics_table.h", "test_affiliation_fetcher_factory.h", @@ -269,6 +271,7 @@ "password_syncable_service_unittest.cc", "password_ui_utils_unittest.cc", "psl_matching_helper_unittest.cc", + "sql_table_builder_unittest.cc", "statistics_table_unittest.cc", ] if (is_mac) {
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc index d4e913c..a3532452 100644 --- a/components/password_manager/core/browser/login_database.cc +++ b/components/password_manager/core/browser/login_database.cc
@@ -8,6 +8,7 @@ #include <stdint.h> #include <algorithm> #include <limits> +#include <map> #include <utility> #include "base/bind.h" @@ -16,6 +17,7 @@ #include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/sparse_histogram.h" +#include "base/numerics/safe_conversions.h" #include "base/pickle.h" #include "base/stl_util.h" #include "base/strings/string_util.h" @@ -26,6 +28,7 @@ #include "components/password_manager/core/browser/affiliation_utils.h" #include "components/password_manager/core/browser/password_manager_client.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" +#include "components/password_manager/core/browser/sql_table_builder.h" #include "google_apis/gaia/gaia_auth_util.h" #include "google_apis/gaia/gaia_urls.h" #include "sql/connection.h" @@ -90,6 +93,7 @@ COLUMN_FEDERATION_URL, COLUMN_SKIP_ZERO_CLICK, COLUMN_GENERATION_UPLOAD_STATUS, + COLUMN_NUM // Keep this last. }; enum class HistogramSize { SMALL, LARGE }; @@ -334,45 +338,166 @@ } } -// Creates a table named |table_name| using our current schema. -bool CreateNewTable(sql::Connection* db, - const char* table_name, - const char* extra_columns) { - std::string query = base::StringPrintf( - "CREATE TABLE %s (" - "origin_url VARCHAR NOT NULL, " - "action_url VARCHAR, " - "username_element VARCHAR, " - "username_value VARCHAR, " - "password_element VARCHAR, " - "password_value BLOB, " - "submit_element VARCHAR, " - "signon_realm VARCHAR NOT NULL," - "ssl_valid INTEGER NOT NULL," - "preferred INTEGER NOT NULL," - "date_created INTEGER NOT NULL," - "blacklisted_by_user INTEGER NOT NULL," - "scheme INTEGER NOT NULL," - "password_type INTEGER," - "possible_usernames BLOB," - "times_used INTEGER," - "form_data BLOB," - "date_synced INTEGER," - "display_name VARCHAR," - "icon_url VARCHAR," - "federation_url VARCHAR," - "skip_zero_click INTEGER," - "%s" - "UNIQUE (origin_url, username_element, username_value, " - "password_element, signon_realm))", - table_name, extra_columns); - return db->Execute(query.c_str()); +// Teaches |builder| about the different DB schemes in different versions. +void InitializeBuilder(SQLTableBuilder* builder) { + // Versions 0 and 1, which are the same. + builder->AddColumnToUniqueKey("origin_url", "VARCHAR NOT NULL"); + builder->AddColumn("action_url", "VARCHAR"); + builder->AddColumnToUniqueKey("username_element", "VARCHAR"); + builder->AddColumnToUniqueKey("username_value", "VARCHAR"); + builder->AddColumnToUniqueKey("password_element", "VARCHAR"); + builder->AddColumn("password_value", "BLOB"); + builder->AddColumn("submit_element", "VARCHAR"); + builder->AddColumnToUniqueKey("signon_realm", "VARCHAR NOT NULL"); + builder->AddColumn("ssl_valid", "INTEGER NOT NULL"); + builder->AddColumn("preferred", "INTEGER NOT NULL"); + builder->AddColumn("date_created", "INTEGER NOT NULL"); + builder->AddColumn("blacklisted_by_user", "INTEGER NOT NULL"); + builder->AddColumn("scheme", "INTEGER NOT NULL"); + builder->SealVersion(); + unsigned version = builder->SealVersion(); + DCHECK_EQ(1u, version); + + // Version 2. + builder->AddColumn("password_type", "INTEGER"); + builder->AddColumn("possible_usernames", "BLOB"); + version = builder->SealVersion(); + DCHECK_EQ(2u, version); + + // Version 3. + builder->AddColumn("times_used", "INTEGER"); + version = builder->SealVersion(); + DCHECK_EQ(3u, version); + + // Version 4. + builder->AddColumn("form_data", "BLOB"); + version = builder->SealVersion(); + DCHECK_EQ(4u, version); + + // Version 5. + builder->AddColumn("use_additional_auth", "INTEGER"); + version = builder->SealVersion(); + DCHECK_EQ(5u, version); + + // Version 6. + builder->AddColumn("date_synced", "INTEGER"); + version = builder->SealVersion(); + DCHECK_EQ(6u, version); + + // Version 7. + builder->AddColumn("display_name", "VARCHAR"); + builder->AddColumn("avatar_url", "VARCHAR"); + builder->AddColumn("federation_url", "VARCHAR"); + builder->AddColumn("is_zero_click", "INTEGER"); + version = builder->SealVersion(); + DCHECK_EQ(7u, version); + + // Version 8. + builder->SealVersion(); + // Version 9. + version = builder->SealVersion(); + // Version 10. + builder->DropColumn("use_additional_auth"); + version = builder->SealVersion(); + DCHECK_EQ(10u, version); + + // Version 11. + builder->RenameColumn("is_zero_click", "skip_zero_click"); + version = builder->SealVersion(); + DCHECK_EQ(11u, version); + + // Version 12. + builder->AddColumn("generation_upload_status", "INTEGER"); + version = builder->SealVersion(); + DCHECK_EQ(12u, version); + + // Version 13. + builder->SealVersion(); + // Version 14. + builder->RenameColumn("avatar_url", "icon_url"); + version = builder->SealVersion(); + DCHECK_EQ(14u, version); + + // Version 15. + builder->SealVersion(); + // Version 16. + builder->SealVersion(); + // Version 17. + version = builder->SealVersion(); + DCHECK_EQ(17u, version); + + DCHECK_EQ(static_cast<size_t>(COLUMN_NUM), builder->NumberOfColumns()) + << "Adjust LoginTableColumns if you change column definitions here."; } -bool CreateIndexOnSignonRealm(sql::Connection* db, const char* table_name) { - std::string query = base::StringPrintf( - "CREATE INDEX logins_signon ON %s (signon_realm)", table_name); - return db->Execute(query.c_str()); +// Call this after having called InitializeBuilder, to migrate the database from +// the current version to kCurrentVersionNumber. +bool MigrateLogins(unsigned current_version, + SQLTableBuilder* builder, + sql::Connection* db) { + if (!builder->MigrateFrom(current_version, db)) + return false; + + // Data changes, not covered by the schema migration above. + if (current_version <= 8) { + sql::Statement fix_time_format; + fix_time_format.Assign(db->GetCachedStatement( + SQL_FROM_HERE, + "UPDATE logins SET date_created = (date_created * ?) + ?")); + fix_time_format.BindInt64(0, base::Time::kMicrosecondsPerSecond); + fix_time_format.BindInt64(1, base::Time::kTimeTToMicrosecondsOffset); + if (!fix_time_format.Run()) + return false; + } + + if (current_version <= 16) { + sql::Statement reset_zero_click; + reset_zero_click.Assign(db->GetCachedStatement( + SQL_FROM_HERE, "UPDATE logins SET skip_zero_click = 1")); + if (!reset_zero_click.Run()) + return false; + } + + return true; +} + +// Because of https://crbug.com/295851, some early version numbers might be +// wrong. This function detects that and fixes the version. +bool FixVersionIfNeeded(sql::Connection* db, int* current_version) { + if (*current_version == 1) { + int extra_columns = 0; + if (db->DoesColumnExist("logins", "password_type")) + ++extra_columns; + if (db->DoesColumnExist("logins", "possible_usernames")) + ++extra_columns; + if (extra_columns == 2) { + *current_version = 2; + } else if (extra_columns == 1) { + // If this is https://crbug.com/295851 then either both columns exist + // or none. + return false; + } + } + if (*current_version == 2) { + if (db->DoesColumnExist("logins", "times_used")) + *current_version = 3; + } + if (*current_version == 3) { + if (db->DoesColumnExist("logins", "form_data")) + *current_version = 4; + } + return true; +} + +// Generates the string "(?,?,...,?)" with |count| repetitions of "?". +std::string GeneratePlaceholders(size_t count) { + std::string result(2 * count + 1, ','); + result.front() = '('; + result.back() = ')'; + for (size_t i = 1; i < 2 * count + 1; i += 2) { + result[i] = '?'; + } + return result; } } // namespace @@ -423,18 +548,36 @@ return false; } - // Initialize the tables. - if (!InitLoginsTable()) { - LogDatabaseInitError(INIT_LOGINS_ERROR); - LOG(ERROR) << "Unable to initialize the logins table."; - db_.Close(); - return false; + SQLTableBuilder builder; + InitializeBuilder(&builder); + InitializeStatementStrings(builder); + + if (!db_.DoesTableExist("logins")) { + if (!builder.CreateTable(&db_)) { + VLOG(0) << "Failed to create the 'logins' table"; + db_.Close(); + return false; + } } + stats_table_.Init(&db_); + int current_version = meta_table_.GetVersionNumber(); + bool migration_success = FixVersionIfNeeded(&db_, ¤t_version); + DCHECK_LE(current_version, kCurrentVersionNumber); + // If the file on disk is an older database version, bring it up to date. - if (meta_table_.GetVersionNumber() < kCurrentVersionNumber && - !MigrateOldVersionsAsNeeded()) { + if (migration_success && current_version < kCurrentVersionNumber) { + migration_success = MigrateLogins( + base::checked_cast<unsigned>(current_version), &builder, &db_); + } + if (migration_success && current_version <= 15) { + migration_success = stats_table_.MigrateToVersion(16); + } + if (migration_success) { + meta_table_.SetCompatibleVersionNumber(kCompatibleVersionNumber); + meta_table_.SetVersionNumber(kCurrentVersionNumber); + } else { LogDatabaseInitError(MIGRATION_ERROR); UMA_HISTOGRAM_SPARSE_SLOWLY("PasswordManager.LoginDatabaseFailedVersion", meta_table_.GetVersionNumber()); @@ -463,204 +606,6 @@ return true; } -bool LoginDatabase::MigrateOldVersionsAsNeeded() { - const int original_version = meta_table_.GetVersionNumber(); - switch (original_version) { - case 1: - // Column could exist because of https://crbug.com/295851 - if (!db_.DoesColumnExist("logins", "password_type") && - !db_.Execute("ALTER TABLE logins " - "ADD COLUMN password_type INTEGER")) { - return false; - } - if (!db_.DoesColumnExist("logins", "possible_usernames") && - !db_.Execute("ALTER TABLE logins " - "ADD COLUMN possible_usernames BLOB")) { - return false; - } - // Fall through. - case 2: - // Column could exist because of https://crbug.com/295851 - if (!db_.DoesColumnExist("logins", "times_used") && - !db_.Execute("ALTER TABLE logins ADD COLUMN times_used INTEGER")) { - return false; - } - // Fall through. - case 3: - // Column could exist because of https://crbug.com/295851 - if (!db_.DoesColumnExist("logins", "form_data") && - !db_.Execute("ALTER TABLE logins ADD COLUMN form_data BLOB")) { - return false; - } - // Fall through. - case 4: - if (!db_.Execute( - "ALTER TABLE logins ADD COLUMN use_additional_auth INTEGER")) { - return false; - } - // Fall through. - case 5: - if (!db_.Execute("ALTER TABLE logins ADD COLUMN date_synced INTEGER")) { - return false; - } - // Fall through. - case 6: - if (!db_.Execute("ALTER TABLE logins ADD COLUMN display_name VARCHAR") || - !db_.Execute("ALTER TABLE logins ADD COLUMN avatar_url VARCHAR") || - !db_.Execute("ALTER TABLE logins " - "ADD COLUMN federation_url VARCHAR") || - !db_.Execute("ALTER TABLE logins ADD COLUMN is_zero_click INTEGER")) { - return false; - } - // Fall through. - case 7: { - // Keep version 8 around even though no changes are made. See - // crbug.com/423716 for context. - // Fall through. - } - case 8: { - sql::Statement s; - s.Assign(db_.GetCachedStatement(SQL_FROM_HERE, - "UPDATE logins SET " - "date_created = " - "(date_created * ?) + ?")); - s.BindInt64(0, base::Time::kMicrosecondsPerSecond); - s.BindInt64(1, base::Time::kTimeTToMicrosecondsOffset); - if (!s.Run()) - return false; - // Fall through. - } - case 9: { - // Remove use_additional_auth column from database schema - // crbug.com/423716 for context. - std::string fields_to_copy = - "origin_url, action_url, username_element, username_value, " - "password_element, password_value, submit_element, " - "signon_realm, ssl_valid, preferred, date_created, " - "blacklisted_by_user, scheme, password_type, possible_usernames, " - "times_used, form_data, date_synced, display_name, avatar_url, " - "federation_url, is_zero_click"; - auto copy_data_query = - [&fields_to_copy](const std::string& from, const std::string& to) { - return "INSERT INTO " + to + " SELECT " + fields_to_copy + " FROM " + - from; - }; - - if (!db_.Execute(("CREATE TEMPORARY TABLE logins_data(" + fields_to_copy + - ")").c_str()) || - !db_.Execute(copy_data_query("logins", "logins_data").c_str()) || - !db_.Execute("DROP TABLE logins") || - !db_.Execute( - ("CREATE TABLE logins(" + fields_to_copy + ")").c_str()) || - !db_.Execute(copy_data_query("logins_data", "logins").c_str()) || - !db_.Execute("DROP TABLE logins_data") || - !CreateIndexOnSignonRealm(&db_, "logins")) { - return false; - } - // Fall through. - } - case 10: { - // Rename is_zero_click -> skip_zero_click. Note that previous versions - // may have incorrectly used a 6-column key (origin_url, username_element, - // username_value, password_element, signon_realm, submit_element). - // In that case, this step also restores the correct 5-column key; - // that is, the above without "submit_element". - const char copy_query[] = "INSERT OR REPLACE INTO logins_new SELECT " - "origin_url, action_url, username_element, username_value, " - "password_element, password_value, submit_element, signon_realm, " - "ssl_valid, preferred, date_created, blacklisted_by_user, scheme, " - "password_type, possible_usernames, times_used, form_data, " - "date_synced, display_name, avatar_url, federation_url, is_zero_click" - " FROM logins"; - if (!CreateNewTable(&db_, "logins_new", "") || - !db_.Execute(copy_query) || - !db_.Execute("DROP TABLE logins") || - !db_.Execute("ALTER TABLE logins_new RENAME TO logins") || - !CreateIndexOnSignonRealm(&db_, "logins")) { - return false; - } - // Fall through. - } - case 11: - if (!db_.Execute( - "ALTER TABLE logins ADD COLUMN " - "generation_upload_status INTEGER")) - return false; - // Fall through. - case 12: - // The stats table was added. Nothing to do really. - // Fall through. - case 13: { - // Rename avatar_url -> icon_url. Note that if the original version was - // at most 10, this renaming would have already happened in step 10, - // as |CreateNewTable| would create a table with the new column name. - if (original_version > 10) { - const char copy_query[] = "INSERT OR REPLACE INTO logins_new SELECT " - "origin_url, action_url, username_element, username_value, " - "password_element, password_value, submit_element, signon_realm, " - "ssl_valid, preferred, date_created, blacklisted_by_user, scheme, " - "password_type, possible_usernames, times_used, form_data, " - "date_synced, display_name, avatar_url, federation_url, " - "skip_zero_click, generation_upload_status FROM logins"; - if (!CreateNewTable( - &db_, "logins_new", "generation_upload_status INTEGER,") || - !db_.Execute(copy_query) || - !db_.Execute("DROP TABLE logins") || - !db_.Execute("ALTER TABLE logins_new RENAME TO logins") || - !CreateIndexOnSignonRealm(&db_, "logins")) { - return false; - } - } - // Fall through. - } - case 14: - // No change of schema. Version 15 was introduced to force all databases - // through an otherwise no-op migration process that will, however, now - // correctly set the 'compatible version number'. Previously, it was - // always being set to (and forever left at) version 1. - meta_table_.SetCompatibleVersionNumber(kCompatibleVersionNumber); - case 15: - // Recreate the statistics. - if (!stats_table_.MigrateToVersion(16)) - return false; - case 16: { - // No change in scheme: just disable auto sign-in by default in - // preparation to launch the credential management API. - if (!db_.Execute("UPDATE logins SET skip_zero_click = 1")) - return false; - // Fall through. - } - - // ------------------------------------------------------------------------- - // DO NOT FORGET to update |kCompatibleVersionNumber| if you add a migration - // step that is a breaking change. This is needed so that an older version - // of the browser can fail with a meaningful error when opening a newer - // database, as opposed to failing on the first database operation. - // ------------------------------------------------------------------------- - case kCurrentVersionNumber: - // Already up to date. - meta_table_.SetVersionNumber(kCurrentVersionNumber); - return true; - default: - NOTREACHED(); - return false; - } -} - -bool LoginDatabase::InitLoginsTable() { - if (!db_.DoesTableExist("logins")) { - if (!CreateNewTable(&db_, "logins", "generation_upload_status INTEGER,")) { - NOTREACHED(); - return false; - } - if (!CreateIndexOnSignonRealm(&db_, "logins")) { - NOTREACHED(); - return false; - } - } - return true; -} - void LoginDatabase::ReportMetrics(const std::string& sync_username, bool custom_passphrase_sync_enabled) { sql::Statement s(db_.GetCachedStatement( @@ -855,17 +800,9 @@ &encrypted_password) != ENCRYPTION_RESULT_SUCCESS) return list; - // You *must* change LoginTableColumns if this query changes. - sql::Statement s(db_.GetCachedStatement( - SQL_FROM_HERE, - "INSERT INTO logins " - "(origin_url, action_url, username_element, username_value, " - " password_element, password_value, submit_element, " - " signon_realm, ssl_valid, preferred, date_created, blacklisted_by_user, " - " scheme, password_type, possible_usernames, times_used, form_data, " - " date_synced, display_name, icon_url," - " federation_url, skip_zero_click, generation_upload_status) VALUES " - "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")); + DCHECK(!add_statement_.empty()); + sql::Statement s( + db_.GetCachedStatement(SQL_FROM_HERE, add_statement_.c_str())); BindAddStatement(form, encrypted_password, &s); db_.set_error_callback(base::Bind(&AddCallback)); const bool success = s.Run(); @@ -875,16 +812,9 @@ return list; } // Repeat the same statement but with REPLACE semantic. - s.Assign(db_.GetCachedStatement( - SQL_FROM_HERE, - "INSERT OR REPLACE INTO logins " - "(origin_url, action_url, username_element, username_value, " - " password_element, password_value, submit_element, " - " signon_realm, ssl_valid, preferred, date_created, blacklisted_by_user, " - " scheme, password_type, possible_usernames, times_used, form_data, " - " date_synced, display_name, icon_url," - " federation_url, skip_zero_click, generation_upload_status) VALUES " - "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")); + DCHECK(!add_replace_statement_.empty()); + s.Assign( + db_.GetCachedStatement(SQL_FROM_HERE, add_replace_statement_.c_str())); BindAddStatement(form, encrypted_password, &s); if (s.Run()) { list.push_back(PasswordStoreChange(PasswordStoreChange::REMOVE, form)); @@ -905,59 +835,41 @@ #endif // Replacement is necessary to deal with updating imported credentials. See // crbug.com/349138 for details. - sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE, - "UPDATE OR REPLACE logins SET " - "action_url = ?, " - "password_value = ?, " - "ssl_valid = ?, " - "preferred = ?, " - "possible_usernames = ?, " - "times_used = ?, " - "submit_element = ?, " - "date_synced = ?, " - "date_created = ?, " - "blacklisted_by_user = ?, " - "scheme = ?, " - "password_type = ?, " - "display_name = ?, " - "icon_url = ?, " - "federation_url = ?, " - "skip_zero_click = ?, " - "generation_upload_status = ? " - "WHERE origin_url = ? AND " - "username_element = ? AND " - "username_value = ? AND " - "password_element = ? AND " - "signon_realm = ?")); + DCHECK(!update_statement_.empty()); + sql::Statement s( + db_.GetCachedStatement(SQL_FROM_HERE, update_statement_.c_str())); s.BindString(0, form.action.spec()); s.BindBlob(1, encrypted_password.data(), static_cast<int>(encrypted_password.length())); - s.BindInt(2, form.ssl_valid); - s.BindInt(3, form.preferred); + s.BindString16(2, form.submit_element); + s.BindInt(3, form.ssl_valid); + s.BindInt(4, form.preferred); + s.BindInt64(5, form.date_created.ToInternalValue()); + s.BindInt(6, form.blacklisted_by_user); + s.BindInt(7, form.scheme); + s.BindInt(8, form.type); base::Pickle pickle = SerializeVector(form.other_possible_usernames); - s.BindBlob(4, pickle.data(), pickle.size()); - s.BindInt(5, form.times_used); - s.BindString16(6, form.submit_element); - s.BindInt64(7, form.date_synced.ToInternalValue()); - s.BindInt64(8, form.date_created.ToInternalValue()); - s.BindInt(9, form.blacklisted_by_user); - s.BindInt(10, form.scheme); - s.BindInt(11, form.type); - s.BindString16(12, form.display_name); - s.BindString(13, form.icon_url.spec()); + s.BindBlob(9, pickle.data(), pickle.size()); + s.BindInt(10, form.times_used); + base::Pickle form_data_pickle; + autofill::SerializeFormData(form.form_data, &form_data_pickle); + s.BindBlob(11, form_data_pickle.data(), form_data_pickle.size()); + s.BindInt64(12, form.date_synced.ToInternalValue()); + s.BindString16(13, form.display_name); + s.BindString(14, form.icon_url.spec()); // An empty Origin serializes as "null" which would be strange to store here. - s.BindString(14, form.federation_origin.unique() + s.BindString(15, form.federation_origin.unique() ? std::string() : form.federation_origin.Serialize()); - s.BindInt(15, form.skip_zero_click); - s.BindInt(16, form.generation_upload_status); + s.BindInt(16, form.skip_zero_click); + s.BindInt(17, form.generation_upload_status); // WHERE starts here. - s.BindString(17, form.origin.spec()); - s.BindString16(18, form.username_element); - s.BindString16(19, form.username_value); - s.BindString16(20, form.password_element); - s.BindString(21, form.signon_realm); + s.BindString(18, form.origin.spec()); + s.BindString16(19, form.username_element); + s.BindString16(20, form.username_value); + s.BindString16(21, form.password_element); + s.BindString(22, form.signon_realm); if (!s.Run()) return PasswordStoreChangeList(); @@ -979,20 +891,14 @@ DeleteEncryptedPassword(form); #endif // Remove a login by UNIQUE-constrained fields. - sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE, - "DELETE FROM logins WHERE " - "origin_url = ? AND " - "username_element = ? AND " - "username_value = ? AND " - "password_element = ? AND " - "submit_element = ? AND " - "signon_realm = ? ")); + DCHECK(!delete_statement_.empty()); + sql::Statement s( + db_.GetCachedStatement(SQL_FROM_HERE, delete_statement_.c_str())); s.BindString(0, form.origin.spec()); s.BindString16(1, form.username_element); s.BindString16(2, form.username_value); s.BindString16(3, form.password_element); - s.BindString16(4, form.submit_element); - s.BindString(5, form.signon_realm); + s.BindString(4, form.signon_realm); return s.Run() && db_.GetLastChangeCount() > 0; } @@ -1034,22 +940,18 @@ bool LoginDatabase::GetAutoSignInLogins( ScopedVector<autofill::PasswordForm>* forms) const { DCHECK(forms); - sql::Statement s(db_.GetCachedStatement( - SQL_FROM_HERE, - "SELECT origin_url, action_url, username_element, username_value, " - "password_element, password_value, submit_element, signon_realm, " - "ssl_valid, preferred, date_created, blacklisted_by_user, " - "scheme, password_type, possible_usernames, times_used, form_data, " - "date_synced, display_name, icon_url, " - "federation_url, skip_zero_click, generation_upload_status FROM logins " - "WHERE skip_zero_click = 0 ORDER BY origin_url")); + DCHECK(!autosignin_statement_.empty()); + sql::Statement s( + db_.GetCachedStatement(SQL_FROM_HERE, autosignin_statement_.c_str())); return StatementToForms(&s, nullptr, forms); } -bool LoginDatabase::DisableAutoSignInForAllLogins() { +bool LoginDatabase::DisableAutoSignInForOrigin(const GURL& origin) { sql::Statement s(db_.GetCachedStatement( - SQL_FROM_HERE, "UPDATE logins SET skip_zero_click = 1;")); + SQL_FROM_HERE, + "UPDATE logins SET skip_zero_click = 1 WHERE origin_url = ?;")); + s.BindString(0, origin.spec()); return s.Run(); } @@ -1057,7 +959,7 @@ // static LoginDatabase::EncryptionResult LoginDatabase::InitPasswordFormFromStatement( PasswordForm* form, - sql::Statement& s) { + const sql::Statement& s) { std::string encrypted_password; s.ColumnBlobAsString(COLUMN_PASSWORD_VALUE, &encrypted_password); base::string16 decrypted_password; @@ -1132,30 +1034,27 @@ const PasswordForm& form, ScopedVector<autofill::PasswordForm>* forms) const { DCHECK(forms); - // You *must* change LoginTableColumns if this query changes. - std::string sql_query = - "SELECT origin_url, action_url, " - "username_element, username_value, " - "password_element, password_value, submit_element, " - "signon_realm, ssl_valid, preferred, date_created, blacklisted_by_user, " - "scheme, password_type, possible_usernames, times_used, form_data, " - "date_synced, display_name, icon_url, " - "federation_url, skip_zero_click, generation_upload_status " - "FROM logins WHERE signon_realm == ? "; const GURL signon_realm(form.signon_realm); std::string registered_domain = GetRegistryControlledDomain(signon_realm); const bool should_PSL_matching_apply = form.scheme == PasswordForm::SCHEME_HTML && ShouldPSLDomainMatchingApply(registered_domain); const bool should_federated_apply = form.scheme == PasswordForm::SCHEME_HTML; - if (should_PSL_matching_apply) - sql_query += "OR signon_realm REGEXP ? "; - if (should_federated_apply) - sql_query += "OR (signon_realm LIKE ? AND password_type == 2) "; + DCHECK(!get_statement_.empty()); + DCHECK(!get_statement_psl_.empty()); + DCHECK(!get_statement_federated_.empty()); + DCHECK(!get_statement_psl_federated_.empty()); + const std::string* sql_query = &get_statement_; + if (should_PSL_matching_apply && should_federated_apply) + sql_query = &get_statement_psl_federated_; + else if (should_PSL_matching_apply) + sql_query = &get_statement_psl_; + else if (should_federated_apply) + sql_query = &get_statement_federated_; // TODO(nyquist) Consider usage of GetCachedStatement when // http://crbug.com/248608 is fixed. - sql::Statement s(db_.GetUniqueStatement(sql_query.c_str())); + sql::Statement s(db_.GetUniqueStatement(sql_query->c_str())); s.BindString(0, form.signon_realm); int placeholder = 1; @@ -1207,17 +1106,9 @@ const base::Time end, ScopedVector<autofill::PasswordForm>* forms) const { DCHECK(forms); - sql::Statement s(db_.GetCachedStatement( - SQL_FROM_HERE, - "SELECT origin_url, action_url, " - "username_element, username_value, " - "password_element, password_value, submit_element, " - "signon_realm, ssl_valid, preferred, date_created, blacklisted_by_user, " - "scheme, password_type, possible_usernames, times_used, form_data, " - "date_synced, display_name, icon_url, " - "federation_url, skip_zero_click, generation_upload_status FROM logins " - "WHERE date_created >= ? AND date_created < ?" - "ORDER BY origin_url")); + DCHECK(!created_statement_.empty()); + sql::Statement s( + db_.GetCachedStatement(SQL_FROM_HERE, created_statement_.c_str())); s.BindInt64(0, begin.ToInternalValue()); s.BindInt64(1, end.is_null() ? std::numeric_limits<int64_t>::max() : end.ToInternalValue()); @@ -1230,16 +1121,9 @@ const base::Time end, ScopedVector<autofill::PasswordForm>* forms) const { DCHECK(forms); - sql::Statement s(db_.GetCachedStatement( - SQL_FROM_HERE, - "SELECT origin_url, action_url, username_element, username_value, " - "password_element, password_value, submit_element, signon_realm, " - "ssl_valid, preferred, date_created, blacklisted_by_user, " - "scheme, password_type, possible_usernames, times_used, form_data, " - "date_synced, display_name, icon_url, " - "federation_url, skip_zero_click, generation_upload_status FROM logins " - "WHERE date_synced >= ? AND date_synced < ?" - "ORDER BY origin_url")); + DCHECK(!synced_statement_.empty()); + sql::Statement s( + db_.GetCachedStatement(SQL_FROM_HERE, synced_statement_.c_str())); s.BindInt64(0, begin.ToInternalValue()); s.BindInt64(1, end.is_null() ? base::Time::Max().ToInternalValue() @@ -1262,17 +1146,9 @@ bool blacklisted, ScopedVector<autofill::PasswordForm>* forms) const { DCHECK(forms); - // You *must* change LoginTableColumns if this query changes. - sql::Statement s(db_.GetCachedStatement( - SQL_FROM_HERE, - "SELECT origin_url, action_url, " - "username_element, username_value, " - "password_element, password_value, submit_element, " - "signon_realm, ssl_valid, preferred, date_created, blacklisted_by_user, " - "scheme, password_type, possible_usernames, times_used, form_data, " - "date_synced, display_name, icon_url, " - "federation_url, skip_zero_click, generation_upload_status FROM logins " - "WHERE blacklisted_by_user == ? ORDER BY origin_url")); + DCHECK(!blacklisted_statement_.empty()); + sql::Statement s( + db_.GetCachedStatement(SQL_FROM_HERE, blacklisted_statement_.c_str())); s.BindInt(0, blacklisted ? 1 : 0); return StatementToForms(&s, nullptr, forms); @@ -1288,22 +1164,15 @@ std::string LoginDatabase::GetEncryptedPassword( const autofill::PasswordForm& form) const { + DCHECK(!encrypted_statement_.empty()); sql::Statement s( - db_.GetCachedStatement(SQL_FROM_HERE, - "SELECT password_value FROM logins WHERE " - "origin_url = ? AND " - "username_element = ? AND " - "username_value = ? AND " - "password_element = ? AND " - "submit_element = ? AND " - "signon_realm = ? ")); + db_.GetCachedStatement(SQL_FROM_HERE, encrypted_statement_.c_str())); s.BindString(0, form.origin.spec()); s.BindString16(1, form.username_element); s.BindString16(2, form.username_value); s.BindString16(3, form.password_element); - s.BindString16(4, form.submit_element); - s.BindString(5, form.signon_realm); + s.BindString(4, form.signon_realm); std::string encrypted_password; if (s.Step()) { @@ -1357,4 +1226,68 @@ return true; } +void LoginDatabase::InitializeStatementStrings(const SQLTableBuilder& builder) { + // This method may be called multiple times, if Chrome switches backends and + // LoginDatabase::DeleteAndRecreateDatabaseFile ends up being called. In those + // case do not recompute the SQL statements, because they would end up the + // same. + if (!add_statement_.empty()) + return; + + // Initialize the cached strings. + std::string all_column_names = builder.ListAllColumnNames(); + std::string right_amount_of_placeholders = + GeneratePlaceholders(builder.NumberOfColumns()); + std::string all_unique_key_column_names = builder.ListAllUniqueKeyNames(); + std::string all_nonunique_key_column_names = + builder.ListAllNonuniqueKeyNames(); + + add_statement_ = "INSERT INTO logins (" + all_column_names + ") VALUES " + + right_amount_of_placeholders; + DCHECK(add_replace_statement_.empty()); + add_replace_statement_ = "INSERT OR REPLACE INTO logins (" + + all_column_names + ") VALUES " + + right_amount_of_placeholders; + DCHECK(update_statement_.empty()); + update_statement_ = "UPDATE OR REPLACE logins SET " + + all_nonunique_key_column_names + " WHERE " + + all_unique_key_column_names; + DCHECK(delete_statement_.empty()); + delete_statement_ = "DELETE FROM logins WHERE " + all_unique_key_column_names; + DCHECK(autosignin_statement_.empty()); + autosignin_statement_ = "SELECT " + all_column_names + + " FROM logins " + "WHERE skip_zero_click = 0 ORDER BY origin_url"; + DCHECK(get_statement_.empty()); + get_statement_ = "SELECT " + all_column_names + + " FROM logins " + "WHERE signon_realm == ?"; + std::string psl_statement = "OR signon_realm REGEXP ? "; + std::string federated_statement = + "OR (signon_realm LIKE ? AND password_type == 2) "; + DCHECK(get_statement_psl_.empty()); + get_statement_psl_ = get_statement_ + psl_statement; + DCHECK(get_statement_federated_.empty()); + get_statement_federated_ = get_statement_ + federated_statement; + DCHECK(get_statement_psl_federated_.empty()); + get_statement_psl_federated_ = + get_statement_ + psl_statement + federated_statement; + DCHECK(created_statement_.empty()); + created_statement_ = + "SELECT " + all_column_names + + " FROM logins WHERE date_created >= ? AND date_created < " + "? ORDER BY origin_url"; + DCHECK(synced_statement_.empty()); + synced_statement_ = "SELECT " + all_column_names + + " FROM logins WHERE date_synced >= ? AND date_synced < " + "? ORDER BY origin_url"; + DCHECK(blacklisted_statement_.empty()); + blacklisted_statement_ = + "SELECT " + all_column_names + + " FROM logins WHERE blacklisted_by_user == ? ORDER BY origin_url"; + DCHECK(encrypted_statement_.empty()); + encrypted_statement_ = + "SELECT password_value FROM logins WHERE " + all_unique_key_column_names; +} + } // namespace password_manager
diff --git a/components/password_manager/core/browser/login_database.h b/components/password_manager/core/browser/login_database.h index c992f3e..c6bc208 100644 --- a/components/password_manager/core/browser/login_database.h +++ b/components/password_manager/core/browser/login_database.h
@@ -28,6 +28,8 @@ namespace password_manager { +class SQLTableBuilder; + extern const int kCurrentVersionNumber; extern const int kCompatibleVersionNumber; @@ -36,7 +38,7 @@ // the login information. class LoginDatabase { public: - LoginDatabase(const base::FilePath& db_path); + explicit LoginDatabase(const base::FilePath& db_path); virtual ~LoginDatabase(); // Actually creates/opens the database. If false is returned, no other method @@ -77,8 +79,8 @@ bool RemoveLoginsSyncedBetween(base::Time delete_begin, base::Time delete_end); - // Sets the 'skip_zero_click' flag to 'true' for all logins. - bool DisableAutoSignInForAllLogins(); + // Sets the 'skip_zero_click' flag on all forms on |origin| to 'true'. + bool DisableAutoSignInForOrigin(const GURL& origin); // All Get* methods below overwrite |forms| with the returned credentials. On // success, those methods return true. @@ -170,16 +172,13 @@ static EncryptionResult DecryptedString(const std::string& cipher_text, base::string16* plain_text); - bool InitLoginsTable(); - bool MigrateOldVersionsAsNeeded(); - // Fills |form| from the values in the given statement (which is assumed to // be of the form used by the Get*Logins methods). // Returns the EncryptionResult from decrypting the password in |s|; if not // ENCRYPTION_RESULT_SUCCESS, |form| is not filled. static EncryptionResult InitPasswordFormFromStatement( autofill::PasswordForm* form, - sql::Statement& s); + const sql::Statement& s); // Gets all blacklisted or all non-blacklisted (depending on |blacklisted|) // credentials. On success returns true and overwrites |forms| with the @@ -195,6 +194,10 @@ const autofill::PasswordForm* matched_form, ScopedVector<autofill::PasswordForm>* forms); + // Initializes all the *_statement_ data members with appropriate SQL + // fragments based on |builder|. + void InitializeStatementStrings(const SQLTableBuilder& builder); + base::FilePath db_path_; mutable sql::Connection db_; sql::MetaTable meta_table_; @@ -207,6 +210,21 @@ // crbug.com/466638 bool clear_password_values_; + // These cached strings are used to build SQL statements. + std::string add_statement_; + std::string add_replace_statement_; + std::string update_statement_; + std::string delete_statement_; + std::string autosignin_statement_; + std::string get_statement_; + std::string get_statement_psl_; + std::string get_statement_federated_; + std::string get_statement_psl_federated_; + std::string created_statement_; + std::string synced_statement_; + std::string blacklisted_statement_; + std::string encrypted_statement_; + DISALLOW_COPY_AND_ASSIGN(LoginDatabase); };
diff --git a/components/password_manager/core/browser/login_database_unittest.cc b/components/password_manager/core/browser/login_database_unittest.cc index abf7ab0..73226b516 100644 --- a/components/password_manager/core/browser/login_database_unittest.cc +++ b/components/password_manager/core/browser/login_database_unittest.cc
@@ -88,18 +88,19 @@ } bool AddZeroClickableLogin(LoginDatabase* db, - const std::string& unique_string) { + const std::string& unique_string, + const GURL& origin) { // Example password form. PasswordForm form; - form.origin = GURL("https://example.com/"); + form.origin = origin; form.username_element = ASCIIToUTF16(unique_string); form.username_value = ASCIIToUTF16(unique_string); form.password_element = ASCIIToUTF16(unique_string); form.submit_element = ASCIIToUTF16("signIn"); form.signon_realm = form.origin.spec(); form.display_name = ASCIIToUTF16(unique_string); - form.icon_url = GURL("https://example.com/"); - form.federation_origin = url::Origin(GURL("https://example.com/")); + form.icon_url = origin; + form.federation_origin = url::Origin(origin); form.date_created = base::Time::Now(); form.skip_zero_click = false; @@ -854,37 +855,47 @@ TEST_F(LoginDatabaseTest, GetAutoSignInLogins) { ScopedVector<autofill::PasswordForm> result; - EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo1")); - EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo2")); - EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo3")); - EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo4")); + GURL origin("https://example.com"); + EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo1", origin)); + EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo2", origin)); + EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo3", origin)); + EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo4", origin)); EXPECT_TRUE(db().GetAutoSignInLogins(&result)); EXPECT_EQ(4U, result.size()); for (const auto& form : result) EXPECT_FALSE(form->skip_zero_click); - EXPECT_TRUE(db().DisableAutoSignInForAllLogins()); + EXPECT_TRUE(db().DisableAutoSignInForOrigin(origin)); EXPECT_TRUE(db().GetAutoSignInLogins(&result)); EXPECT_EQ(0U, result.size()); } -TEST_F(LoginDatabaseTest, DisableAutoSignInForAllLogins) { +TEST_F(LoginDatabaseTest, DisableAutoSignInForOrigin) { ScopedVector<autofill::PasswordForm> result; - EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo1")); - EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo2")); - EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo3")); - EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo4")); + GURL origin1("https://google.com"); + GURL origin2("https://chrome.com"); + GURL origin3("http://example.com"); + GURL origin4("http://localhost"); + EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo1", origin1)); + EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo2", origin2)); + EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo3", origin3)); + EXPECT_TRUE(AddZeroClickableLogin(&db(), "foo4", origin4)); EXPECT_TRUE(db().GetAutofillableLogins(&result)); for (const auto& form : result) EXPECT_FALSE(form->skip_zero_click); - EXPECT_TRUE(db().DisableAutoSignInForAllLogins()); + EXPECT_TRUE(db().DisableAutoSignInForOrigin(origin1)); + EXPECT_TRUE(db().DisableAutoSignInForOrigin(origin3)); EXPECT_TRUE(db().GetAutofillableLogins(&result)); - for (const auto& form : result) - EXPECT_TRUE(form->skip_zero_click); + for (const auto* form : result) { + if (form->origin == origin1 || form->origin == origin3) + EXPECT_TRUE(form->skip_zero_click); + else + EXPECT_FALSE(form->skip_zero_click); + } } TEST_F(LoginDatabaseTest, BlacklistedLogins) {
diff --git a/components/password_manager/core/browser/mock_password_store.h b/components/password_manager/core/browser/mock_password_store.h index 0c127f7..1806d66 100644 --- a/components/password_manager/core/browser/mock_password_store.h +++ b/components/password_manager/core/browser/mock_password_store.h
@@ -45,7 +45,9 @@ PasswordStoreChangeList(base::Time, base::Time)); MOCK_METHOD2(RemoveStatisticsCreatedBetweenImpl, bool(base::Time, base::Time)); - MOCK_METHOD0(DisableAutoSignInForAllLoginsImpl, PasswordStoreChangeList()); + MOCK_METHOD1( + DisableAutoSignInForOriginsImpl, + PasswordStoreChangeList(const base::Callback<bool(const GURL&)>&)); ScopedVector<autofill::PasswordForm> FillMatchingLogins( const autofill::PasswordForm& form) override { return ScopedVector<autofill::PasswordForm>();
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index 28085c07..37835477 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc
@@ -635,19 +635,15 @@ provisional_save_manager_->pending_credentials().action, all_visible_forms_[i].action)) { provisional_save_manager_->LogSubmitFailed(); - // Generated passwords should always be saved, but we do want to - // record that the submission normally would have failed for UMA. - if (!provisional_save_manager_->has_generated_password()) { - if (logger) { - logger->LogPasswordForm(Logger::STRING_PASSWORD_FORM_REAPPEARED, - all_visible_forms_[i]); - logger->LogMessage(Logger::STRING_DECISION_DROP); - } - provisional_save_manager_.reset(); - // Clear all_visible_forms_ once we found the match. - all_visible_forms_.clear(); - return; + if (logger) { + logger->LogPasswordForm(Logger::STRING_PASSWORD_FORM_REAPPEARED, + all_visible_forms_[i]); + logger->LogMessage(Logger::STRING_DECISION_DROP); } + provisional_save_manager_.reset(); + // Clear all_visible_forms_ once we found the match. + all_visible_forms_.clear(); + return; } } } else {
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc index 3fe98f205..ae4886df 100644 --- a/components/password_manager/core/browser/password_manager_unittest.cc +++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -1108,11 +1108,7 @@ form_manager_to_save->Save(); } -TEST_F(PasswordManagerTest, PasswordGenerationForceSaving) { - // Test the safety net against password loss during generation - // (http://crbug.com/506307) -- out of the two rules (1) "always save - // generated passwords" and (2) "do not save passwords when the password form - // reappears", rule (1) takes precedence. +TEST_F(PasswordManagerTest, PasswordGeneration_FailedSubmission) { std::vector<PasswordForm> observed; PasswordForm form(MakeFormWithOnlyNewPasswordField()); observed.push_back(form); @@ -1125,29 +1121,21 @@ .WillRepeatedly(Return(true)); manager()->SetHasGeneratedPasswordForForm(&driver_, form, true); - // The user should not need to confirm saving as they have already given - // consent by using the generated password. The form should be saved once - // navigation occurs. The client will be informed that automatic saving has - // occured. + // Do not save generated password when the password form reappears. EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_, _)).Times(0); - PasswordForm form_to_save; - EXPECT_CALL(*store_, AddLogin(_)).WillOnce(SaveArg<0>(&form_to_save)); - EXPECT_CALL(client_, AutomaticPasswordSaveIndicator()); + EXPECT_CALL(*store_, AddLogin(_)).Times(0); + EXPECT_CALL(client_, AutomaticPasswordSaveIndicator()).Times(0); // Simulate submission failing, with the same form being visible after // navigation. OnPasswordFormSubmitted(form); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); - EXPECT_EQ(form.username_value, form_to_save.username_value); - // What was "new password" field in the submitted form, becomes the current - // password field in the form to save. - EXPECT_EQ(form.new_password_value, form_to_save.password_value); } // If the user edits the generated password, but does not remove it completely, // it should stay treated as a generated password. -TEST_F(PasswordManagerTest, PasswordGenerationPasswordEdited) { +TEST_F(PasswordManagerTest, PasswordGenerationPasswordEdited_FailedSubmission) { std::vector<PasswordForm> observed; PasswordForm form(MakeFormWithOnlyNewPasswordField()); observed.push_back(form); @@ -1165,23 +1153,15 @@ form.new_password_value = ASCIIToUTF16("different_password"); OnPasswordFormSubmitted(form); - // The user should not be presented with an infobar as they have already given - // consent by using the generated password. The form should be saved once - // navigation occurs. The client will be informed that automatic saving has - // occurred. + // Do not save generated password when the password form reappears. EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_, _)).Times(0); - PasswordForm form_to_save; - EXPECT_CALL(*store_, AddLogin(_)).WillOnce(SaveArg<0>(&form_to_save)); - EXPECT_CALL(client_, AutomaticPasswordSaveIndicator()); + EXPECT_CALL(*store_, AddLogin(_)).Times(0); + EXPECT_CALL(client_, AutomaticPasswordSaveIndicator()).Times(0); // Simulate submission failing, with the same form being visible after // navigation. manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); - EXPECT_EQ(form.username_value, form_to_save.username_value); - // What was "new password" field in the submitted form, becomes the current - // password field in the form to save. - EXPECT_EQ(form.new_password_value, form_to_save.password_value); } // Generated password are saved even if it looks like the submit failed (the
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc index 1ffb69d..111c861 100644 --- a/components/password_manager/core/browser/password_store.cc +++ b/components/password_manager/core/browser/password_store.cc
@@ -149,10 +149,12 @@ delete_begin, delete_end, completion)); } -void PasswordStore::DisableAutoSignInForAllLogins( +void PasswordStore::DisableAutoSignInForOrigins( + const base::Callback<bool(const GURL&)>& origin_filter, const base::Closure& completion) { - ScheduleTask(base::Bind(&PasswordStore::DisableAutoSignInForAllLoginsInternal, - this, completion)); + ScheduleTask( + base::Bind(&PasswordStore::DisableAutoSignInForOriginsInternal, this, + base::Callback<bool(const GURL&)>(origin_filter), completion)); } void PasswordStore::TrimAffiliationCache() { @@ -417,9 +419,10 @@ main_thread_runner_->PostTask(FROM_HERE, completion); } -void PasswordStore::DisableAutoSignInForAllLoginsInternal( +void PasswordStore::DisableAutoSignInForOriginsInternal( + const base::Callback<bool(const GURL&)>& origin_filter, const base::Closure& completion) { - DisableAutoSignInForAllLoginsImpl(); + DisableAutoSignInForOriginsImpl(origin_filter); if (!completion.is_null()) main_thread_runner_->PostTask(FROM_HERE, completion); }
diff --git a/components/password_manager/core/browser/password_store.h b/components/password_manager/core/browser/password_store.h index 7a36fdf..5f03a99 100644 --- a/components/password_manager/core/browser/password_store.h +++ b/components/password_manager/core/browser/password_store.h
@@ -136,10 +136,13 @@ base::Time delete_end, const base::Closure& completion); - // Sets the 'skip_zero_click' flag for all logins in the database to 'true'. - // |completion| will be posted to the |main_thread_runner_| after these - // modifications are completed and notifications are sent out. - void DisableAutoSignInForAllLogins(const base::Closure& completion); + // Sets the 'skip_zero_click' flag for all logins in the database that match + // |origin_filter| to 'true'. |completion| will be posted to + // the |main_thread_runner_| after these modifications are completed + // and notifications are sent out. + void DisableAutoSignInForOrigins( + const base::Callback<bool(const GURL&)>& origin_filter, + const base::Closure& completion); // Removes cached affiliation data that is no longer needed; provided that // affiliation-based matching is enabled. @@ -269,7 +272,8 @@ base::Time delete_end) = 0; // Synchronous implementation to disable auto sign-in. - virtual PasswordStoreChangeList DisableAutoSignInForAllLoginsImpl() = 0; + virtual PasswordStoreChangeList DisableAutoSignInForOriginsImpl( + const base::Callback<bool(const GURL&)>& origin_filter) = 0; // Finds all PasswordForms with a signon_realm that is equal to, or is a // PSL-match to that of |form|, and takes care of notifying the consumer with @@ -371,7 +375,9 @@ void RemoveStatisticsCreatedBetweenInternal(base::Time delete_begin, base::Time delete_end, const base::Closure& completion); - void DisableAutoSignInForAllLoginsInternal(const base::Closure& completion); + void DisableAutoSignInForOriginsInternal( + const base::Callback<bool(const GURL&)>& origin_filter, + const base::Closure& completion); // Finds all non-blacklist PasswordForms, and notifies the consumer. void GetAutofillableLoginsImpl(std::unique_ptr<GetLoginsRequest> request);
diff --git a/components/password_manager/core/browser/password_store_default.cc b/components/password_manager/core/browser/password_store_default.cc index 79cae2a..1a7b647 100644 --- a/components/password_manager/core/browser/password_store_default.cc +++ b/components/password_manager/core/browser/password_store_default.cc
@@ -135,18 +135,32 @@ return changes; } -PasswordStoreChangeList -PasswordStoreDefault::DisableAutoSignInForAllLoginsImpl() { +PasswordStoreChangeList PasswordStoreDefault::DisableAutoSignInForOriginsImpl( + const base::Callback<bool(const GURL&)>& origin_filter) { ScopedVector<autofill::PasswordForm> forms; PasswordStoreChangeList changes; - if (login_db_ && login_db_->GetAutoSignInLogins(&forms)) { - if (login_db_->DisableAutoSignInForAllLogins()) { - for (const auto* form : forms) { - changes.push_back( - PasswordStoreChange(PasswordStoreChange::UPDATE, *form)); - } + if (!login_db_ || !login_db_->GetAutoSignInLogins(&forms)) + return changes; + + std::set<GURL> origins_to_update; + for (const auto* form : forms) { + if (origin_filter.Run(form->origin)) + origins_to_update.insert(form->origin); + } + + std::set<GURL> origins_updated; + for (const GURL& origin : origins_to_update) { + if (login_db_->DisableAutoSignInForOrigin(origin)) + origins_updated.insert(origin); + } + + for (const auto* form : forms) { + if (origins_updated.count(form->origin)) { + changes.push_back( + PasswordStoreChange(PasswordStoreChange::UPDATE, *form)); } } + return changes; }
diff --git a/components/password_manager/core/browser/password_store_default.h b/components/password_manager/core/browser/password_store_default.h index 9ebcea09..55428a9 100644 --- a/components/password_manager/core/browser/password_store_default.h +++ b/components/password_manager/core/browser/password_store_default.h
@@ -58,7 +58,8 @@ PasswordStoreChangeList RemoveLoginsSyncedBetweenImpl( base::Time delete_begin, base::Time delete_end) override; - PasswordStoreChangeList DisableAutoSignInForAllLoginsImpl() override; + PasswordStoreChangeList DisableAutoSignInForOriginsImpl( + const base::Callback<bool(const GURL&)>& origin_filter) override; bool RemoveStatisticsCreatedBetweenImpl(base::Time delete_begin, base::Time delete_end) override; ScopedVector<autofill::PasswordForm> FillMatchingLogins(
diff --git a/components/password_manager/core/browser/sql_table_builder.cc b/components/password_manager/core/browser/sql_table_builder.cc new file mode 100644 index 0000000..3c11742 --- /dev/null +++ b/components/password_manager/core/browser/sql_table_builder.cc
@@ -0,0 +1,319 @@ +// 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 "components/password_manager/core/browser/sql_table_builder.h" + +#include <algorithm> +#include <utility> +#include <vector> + +#include "base/numerics/safe_conversions.h" +#include "sql/connection.h" +#include "sql/transaction.h" + +namespace password_manager { + +namespace { + +// Appends |name| to |list_of_names|, separating items with ", ". +void Append(const std::string& name, std::string* list_of_names) { + if (list_of_names->empty()) + *list_of_names = name; + else + *list_of_names += ", " + name; +} + +} // namespace + +struct SQLTableBuilder::Column { + std::string name; + std::string type; + bool part_of_unique_key; + // The first version this column is part of. + unsigned min_version; + // The last version this column is part of. The value of kInvalidVersion + // means that it is part of all versions since |min_version|. + unsigned max_version; + // Renaming of a column is stored as a sequence of one removed and one added + // column in |columns_|. To distinguish it from an unrelated removal and + // addition, the following bit is set to true for the added columns which + // are part of renaming. Those columns will get the data of their + // predecessors. If the bit is false, the column will be filled with the + // default value on creation. + bool gets_previous_data; +}; + +SQLTableBuilder::SQLTableBuilder() = default; + +SQLTableBuilder::~SQLTableBuilder() = default; + +void SQLTableBuilder::AddColumn(const std::string& name, + const std::string& type) { + DCHECK(FindLastByName(name) == columns_.rend()); + Column column = {name, type, false, sealed_version_ + 1, kInvalidVersion, + false}; + columns_.push_back(std::move(column)); +} + +void SQLTableBuilder::AddColumnToUniqueKey(const std::string& name, + const std::string& type) { + AddColumn(name, type); + columns_.back().part_of_unique_key = true; +} + +void SQLTableBuilder::RenameColumn(const std::string& old_name, + const std::string& new_name) { + auto old_column = FindLastByName(old_name); + DCHECK(old_column != columns_.rend()); + + if (old_name == new_name) // The easy case. + return; + + DCHECK_NE("signon_realm", old_name); + if (sealed_version_ != kInvalidVersion && + old_column->min_version <= sealed_version_) { + // This column exists in the last sealed version. Therefore it cannot be + // just replaced, it needs to be kept for generating the migration code. + Column new_column = {new_name, + old_column->type, + old_column->part_of_unique_key, + sealed_version_ + 1, + kInvalidVersion, + true}; + old_column->max_version = sealed_version_; + auto past_old = + old_column.base(); // Points one element after |old_column|. + columns_.insert(past_old, std::move(new_column)); + } else { + // This column was just introduced in the currently unsealed version. To + // rename it, it is enough just to modify the entry in columns_. + old_column->name = new_name; + } +} + +// Removes column |name|. |name| must have been added in the past. +void SQLTableBuilder::DropColumn(const std::string& name) { + auto column = FindLastByName(name); + DCHECK(column != columns_.rend()); + DCHECK_NE("signon_realm", name); + if (sealed_version_ != kInvalidVersion && + column->min_version <= sealed_version_) { + // This column exists in the last sealed version. Therefore it cannot be + // just deleted, it needs to be kept for generating the migration code. + column->max_version = sealed_version_; + } else { + // This column was just introduced in the currently unsealed version. It + // can be just erased from |columns_|. + columns_.erase( + --(column.base())); // base() points one element after |column|. + } +} + +unsigned SQLTableBuilder::SealVersion() { + DCHECK(FindLastByName("signon_realm") != columns_.rend()); + if (sealed_version_ == kInvalidVersion) { + DCHECK_EQ(std::string(), unique_constraint_); + // First sealed version, time to compute the UNIQUE string. + std::string unique_key; + for (const Column& column : columns_) { + if (column.part_of_unique_key) + Append(column.name, &unique_key); + } + DCHECK(!unique_key.empty()); + unique_constraint_ = "UNIQUE (" + unique_key + ")"; + } + DCHECK(!unique_constraint_.empty()); + return ++sealed_version_; +} + +bool SQLTableBuilder::MigrateFrom(unsigned old_version, sql::Connection* db) { + for (; old_version < sealed_version_; ++old_version) { + if (!MigrateToNextFrom(old_version, db)) + return false; + } + + return true; +} + +bool SQLTableBuilder::CreateTable(sql::Connection* db) { + DCHECK(IsVersionLastAndSealed(sealed_version_)); + DCHECK(!unique_constraint_.empty()); + + if (db->DoesTableExist("logins")) + return true; + + std::string names; // Names and types of the current columns. + for (const Column& column : columns_) { + if (IsInLastVersion(column)) + Append(column.name + " " + column.type, &names); + } + + sql::Transaction transaction(db); + return transaction.Begin() && + db->Execute( + ("CREATE TABLE logins (" + names + ", " + unique_constraint_ + ")") + .c_str()) && + db->Execute("CREATE INDEX logins_signon ON logins (signon_realm)") && + transaction.Commit(); +} + +std::string SQLTableBuilder::ListAllColumnNames() const { + DCHECK(IsVersionLastAndSealed(sealed_version_)); + std::string result; + for (const Column& column : columns_) { + if (IsInLastVersion(column)) + Append(column.name, &result); + } + return result; +} + +std::string SQLTableBuilder::ListAllNonuniqueKeyNames() const { + DCHECK(IsVersionLastAndSealed(sealed_version_)); + std::string result; + for (const Column& column : columns_) { + if (IsInLastVersion(column) && !column.part_of_unique_key) + Append(column.name + "=?", &result); + } + return result; +} + +std::string SQLTableBuilder::ListAllUniqueKeyNames() const { + DCHECK(IsVersionLastAndSealed(sealed_version_)); + std::string result; + for (const Column& column : columns_) { + if (IsInLastVersion(column) && column.part_of_unique_key) { + if (!result.empty()) + result += " AND "; + result += column.name + "=?"; + } + } + return result; +} + +size_t SQLTableBuilder::NumberOfColumns() const { + DCHECK(IsVersionLastAndSealed(sealed_version_)); + return base::checked_cast<size_t>(std::count_if( + columns_.begin(), columns_.end(), + [this](const Column& column) { return (IsInLastVersion(column)); })); +} + +bool SQLTableBuilder::MigrateToNextFrom(unsigned old_version, + sql::Connection* db) { + DCHECK_LT(old_version, sealed_version_); + DCHECK_GE(old_version, 0u); + DCHECK(IsVersionLastAndSealed(sealed_version_)); + DCHECK(!unique_constraint_.empty()); + + // Names of columns from old version, values of which are copied. + std::string old_names; + // Names of columns in new version, except for added ones. + std::string new_names; + std::vector<std::string> added_names; // Names of added columns. + + // A temporary table will be needed if some columns are dropped or renamed, + // because that is not supported by a single SQLite command. + bool needs_temp_table = false; + + for (auto column = columns_.begin(); column != columns_.end(); ++column) { + if (column->max_version == old_version) { + DCHECK(!column->part_of_unique_key); + // This column was deleted after |old_version|. It can have two reasons: + needs_temp_table = true; + auto next_column = column; + ++next_column; + if (next_column != columns_.end() && next_column->gets_previous_data) { + // (1) The column is being renamed. + DCHECK_EQ(column->type, next_column->type); + DCHECK_NE(column->name, next_column->name); + Append(column->name, &old_names); + Append(next_column->name + " " + next_column->type, &new_names); + ++column; // Avoid processing next_column in the next loop. + } else { + // (2) The column is being dropped. + } + } else if (column->min_version == old_version + 1) { + // This column was added after old_version. + DCHECK(!column->part_of_unique_key); + added_names.push_back(column->name + " " + column->type); + } else if (column->min_version <= old_version && + (column->max_version == kInvalidVersion || + column->max_version > old_version)) { + // This column stays. + Append(column->name, &old_names); + Append(column->name + " " + column->type, &new_names); + } + } + + if (needs_temp_table) { + // Following the instructions from + // https://www.sqlite.org/lang_altertable.html#otheralter, this code works + // around the fact that SQLite does not allow dropping or renaming + // columns. Instead, a new table is constructed, with the new column + // names, and data from all but dropped columns from the current table are + // copied into it. After that, the new table is renamed to the current + // one. + + // Foreign key constraints are not enabled for the login database, so no + // PRAGMA foreign_keys=off needed. + sql::Transaction transaction(db); + if (!transaction.Begin() || + !db->Execute(("CREATE TABLE temp_logins (" + new_names + ", " + + unique_constraint_ + ")") + .c_str()) || + !db->Execute(("INSERT OR REPLACE INTO temp_logins SELECT " + old_names + + " FROM logins") + .c_str()) || + !db->Execute("DROP TABLE logins") || + !db->Execute("ALTER TABLE temp_logins RENAME TO logins") || + !db->Execute("CREATE INDEX logins_signon ON logins (signon_realm)") || + !transaction.Commit()) { + return false; + } + } + + if (!added_names.empty()) { + sql::Transaction transaction(db); + if (!transaction.Begin()) + return false; + for (const std::string& name : added_names) { + if (!db->Execute(("ALTER TABLE logins ADD COLUMN " + name).c_str())) + return false; + } + if (!transaction.Commit()) + return false; + } + + return true; +} + +std::list<SQLTableBuilder::Column>::reverse_iterator +SQLTableBuilder::FindLastByName(const std::string& name) { + return std::find_if( + columns_.rbegin(), columns_.rend(), + [&name](const Column& column) { return name == column.name; }); +} + +bool SQLTableBuilder::IsVersionLastAndSealed(unsigned version) const { + // Is |version| the last sealed one? + if (sealed_version_ != version) + return false; + // Is the current version the last sealed one? In other words, is there + // either a column added past the sealed version (min_version > sealed) or + // deleted one version after the sealed (max_version == sealed)? + return columns_.end() == + std::find_if(columns_.begin(), columns_.end(), + [this](const Column& column) { + return column.min_version > sealed_version_ || + column.max_version == sealed_version_; + }); +} + +bool SQLTableBuilder::IsInLastVersion(const Column& column) const { + DCHECK(IsVersionLastAndSealed(sealed_version_)); + return (column.min_version <= sealed_version_ && + (column.max_version == kInvalidVersion || + column.max_version >= sealed_version_)); +} + +} // namespace password_manager
diff --git a/components/password_manager/core/browser/sql_table_builder.h b/components/password_manager/core/browser/sql_table_builder.h new file mode 100644 index 0000000..bac1394f --- /dev/null +++ b/components/password_manager/core/browser/sql_table_builder.h
@@ -0,0 +1,149 @@ +// 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 COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_SQL_TABLE_BUILDER_H_ +#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_SQL_TABLE_BUILDER_H_ + +#include <limits> +#include <list> +#include <string> + +#include "base/macros.h" + +namespace sql { +class Connection; +} + +namespace password_manager { + +// Use this class to represent the versioned evolution of a SQLite table +// structure and generate creating and migrating statements for it. +// +// Two values are currently hard-coded, because they are the same in the +// current use-cases: +// * The table name is hard-coded as "logins". +// * The index is built for column "signon_realm" which is expected to exist. +// +// Usage example: +// +// SQLTableBuilder builder; +// +// // First describe a couple of versions: +// builder.AddColumn("name", "VARCHAR"); +// builder.AddColumn("icon", "VARCHAR"); +// builder.AddColumn("password", "VARCHAR NOT NULL"); +// unsigned version = builder.SealVersion(); // Version 0 is sealed. +// DCHECK_EQ(0u, version); +// builder.RenameColumn("icon", "avatar"); +// version = builder.SealVersion(); // Version 1 is sealed. +// DCHECK_EQ(1u, version); +// +// // Now, assuming that |db| has a table "logins" in a state corresponding +// // version 0, this will migrate it to version 1: +// sql::Connection* db = ...; +// builder.MigrateToNextFrom(0, db); +// +// // And assuming |db| has no table called "logins", this will create one +// // in a state corresponding the latest sealed version: +// builder.CreateTable(db); +class SQLTableBuilder { + public: + // Create the builder for "logins". + SQLTableBuilder(); + + ~SQLTableBuilder(); + + // Adds a column in the table description, with |name| and |type|. |name| + // must not have been added to the table in this version before. + void AddColumn(const std::string& name, const std::string& type); + + // As AddColumn but also adds column |name| to the unique key of the table. + // SealVersion must not have been called yet (the builder does not currently + // support migration code for changing the unique key between versions). + void AddColumnToUniqueKey(const std::string& name, const std::string& type); + + // Renames column |old_name| to |new_name|. |old_name| must have been added in + // the past. The column "signon_realm" must not be renamed. + void RenameColumn(const std::string& old_name, const std::string& new_name); + + // Removes column |name|. |name| must have been added in the past. The column + // "signon_realm" must not be renamed. + void DropColumn(const std::string& name); + + // Increments the internal version counter and marks the current state of the + // table as that version. Returns the sealed version. Calling any of the + // *Column* methods above will result in starting a new version which is not + // considered sealed. The first version is 0. The column "signon_realm" must + // be present in |columns_| every time this is called, and at least one call + // to AddColumnToUniqueKey must have been done before this is called the first + // time. + unsigned SealVersion(); + + // Assuming that the database connected through |db| contains a table called + // "logins" in a state described by version |old_version|, migrates it to + // the current version, which must be sealed. Returns true on success. + bool MigrateFrom(unsigned old_version, sql::Connection* db); + + // If |db| connects to a database where table "logins" already exists, + // this is a no-op and returns true. Otherwise, "logins" is created in a + // state described by the current version known to the builder. The current + // version must be sealed. Returns true on success. + bool CreateTable(sql::Connection* db); + + // Returns the comma-separated list of all column names present in the last + // version. The last version must be sealed. + std::string ListAllColumnNames() const; + + // Same as ListAllColumnNames, but for non-unique key names only, and with + // names followed by " = ?". + std::string ListAllNonuniqueKeyNames() const; + + // Same as ListAllNonuniqueKeyNames, but for unique key names and separated by + // " AND ". + std::string ListAllUniqueKeyNames() const; + + // Returns the number of all columns present in the last version. The last + // version must be sealed. + size_t NumberOfColumns() const; + + private: + // Stores the information about one column (name, type, etc.). + struct Column; + + static unsigned constexpr kInvalidVersion = + std::numeric_limits<unsigned>::max(); + + // Assuming that the database connected through |db| contains a table called + // "logins" in a state described by version |old_version|, migrates it to + // version |old_version + 1|. The current version known to the builder must be + // at least |old_version + 1| and sealed. Returns true on success. + bool MigrateToNextFrom(unsigned old_version, sql::Connection* db); + + // Looks up column named |name| in |columns_|. If present, returns the last + // one. + std::list<Column>::reverse_iterator FindLastByName(const std::string& name); + + // Returns whether the last version is |version| and whether it was sealed + // (by calling SealVersion with no table modifications afterwards). + bool IsVersionLastAndSealed(unsigned version) const; + + // Whether |column| is present in the last version. The last version must be + // sealed. + bool IsInLastVersion(const Column& column) const; + + // Last sealed version, kInvalidVersion means "none". + unsigned sealed_version_ = kInvalidVersion; + + std::list<Column> columns_; // Columns of the table, across all versions. + + // The "UNIQUE" part of an SQL CREATE TABLE constraint. This value is + // computed dring sealing the first version (0). + std::string unique_constraint_; + + DISALLOW_COPY_AND_ASSIGN(SQLTableBuilder); +}; + +} // namespace password_manager + +#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_SQL_TABLE_BUILDER_H_
diff --git a/components/password_manager/core/browser/sql_table_builder_unittest.cc b/components/password_manager/core/browser/sql_table_builder_unittest.cc new file mode 100644 index 0000000..a15cf93 --- /dev/null +++ b/components/password_manager/core/browser/sql_table_builder_unittest.cc
@@ -0,0 +1,253 @@ +// 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 "components/password_manager/core/browser/sql_table_builder.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/macros.h" +#include "sql/connection.h" +#include "sql/statement.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace password_manager { + +class SQLTableBuilderTest : public testing::Test { + public: + SQLTableBuilderTest() { Init(); } + + ~SQLTableBuilderTest() override = default; + + protected: + // Checks whether a column with a given |name| is listed with the given + // |type| in the database. + bool IsColumnOfType(const std::string& name, const std::string& type); + + sql::Connection* db() { return &db_; } + + SQLTableBuilder* builder() { return &builder_; } + + private: + // Part of constructor, needs to be a void-returning function to use ASSERTs. + void Init(); + + // Error handler for the SQL connection, prints the error code and the + // statement details. + void PrintDBError(int code, sql::Statement* statement); + + sql::Connection db_; + SQLTableBuilder builder_; + + DISALLOW_COPY_AND_ASSIGN(SQLTableBuilderTest); +}; + +bool SQLTableBuilderTest::IsColumnOfType(const std::string& name, + const std::string& type) { + return db()->GetSchema().find(name + " " + type) != std::string::npos; +} + +void SQLTableBuilderTest::Init() { + db_.set_error_callback( + base::Bind(&SQLTableBuilderTest::PrintDBError, base::Unretained(this))); + ASSERT_TRUE(db_.OpenInMemory()); + // The following column must always be present, so let's add it here. + builder_.AddColumnToUniqueKey("signon_realm", "VARCHAR NOT NULL"); +} + +void SQLTableBuilderTest::PrintDBError(int code, sql::Statement* statement) { + VLOG(0) << "DB error encountered, code = " << code; + if (statement) { + VLOG(0) << "statement string = " << statement->GetSQLStatement(); + VLOG(0) << "statement is " << (statement->is_valid() ? "valid" : "invalid"); + } +} + +TEST_F(SQLTableBuilderTest, SealVersion_0) { + EXPECT_EQ(0u, builder()->SealVersion()); + EXPECT_TRUE(builder()->MigrateFrom(0, db())); + EXPECT_TRUE(builder()->CreateTable(db())); + EXPECT_TRUE(db()->DoesTableExist("logins")); + EXPECT_TRUE(db()->DoesIndexExist("logins_signon")); + EXPECT_TRUE(db()->DoesColumnExist("logins", "signon_realm")); + EXPECT_TRUE(IsColumnOfType("signon_realm", "VARCHAR NOT NULL")); +} + +TEST_F(SQLTableBuilderTest, AddColumn) { + builder()->AddColumn("password_value", "BLOB"); + EXPECT_EQ(0u, builder()->SealVersion()); + EXPECT_TRUE(builder()->MigrateFrom(0, db())); + EXPECT_TRUE(builder()->CreateTable(db())); + EXPECT_TRUE(db()->DoesTableExist("logins")); + EXPECT_TRUE(db()->DoesIndexExist("logins_signon")); + EXPECT_TRUE(db()->DoesColumnExist("logins", "signon_realm")); + EXPECT_TRUE(db()->DoesColumnExist("logins", "password_value")); + EXPECT_TRUE(IsColumnOfType("password_value", "BLOB")); +} + +TEST_F(SQLTableBuilderTest, RenameColumn_InSameVersion) { + builder()->AddColumn("old_name", "BLOB"); + builder()->RenameColumn("old_name", "password_value"); + EXPECT_EQ(0u, builder()->SealVersion()); + EXPECT_TRUE(builder()->CreateTable(db())); + EXPECT_TRUE(db()->DoesTableExist("logins")); + EXPECT_FALSE(db()->DoesColumnExist("logins", "old_name")); + EXPECT_TRUE(db()->DoesColumnExist("logins", "password_value")); + EXPECT_TRUE(IsColumnOfType("password_value", "BLOB")); +} + +TEST_F(SQLTableBuilderTest, RenameColumn_InNextVersion) { + builder()->AddColumn("old_name", "BLOB"); + EXPECT_EQ(0u, builder()->SealVersion()); + builder()->RenameColumn("old_name", "password_value"); + EXPECT_EQ(1u, builder()->SealVersion()); + EXPECT_TRUE(builder()->CreateTable(db())); + EXPECT_TRUE(db()->DoesTableExist("logins")); + EXPECT_FALSE(db()->DoesColumnExist("logins", "old_name")); + EXPECT_TRUE(db()->DoesColumnExist("logins", "password_value")); + EXPECT_TRUE(IsColumnOfType("password_value", "BLOB")); +} + +TEST_F(SQLTableBuilderTest, RenameColumn_SameNameInSameVersion) { + builder()->AddColumn("name", "BLOB"); + builder()->RenameColumn("name", "name"); + EXPECT_EQ(0u, builder()->SealVersion()); + EXPECT_TRUE(builder()->CreateTable(db())); + EXPECT_TRUE(db()->DoesTableExist("logins")); + EXPECT_TRUE(db()->DoesColumnExist("logins", "name")); + EXPECT_TRUE(IsColumnOfType("name", "BLOB")); +} + +TEST_F(SQLTableBuilderTest, RenameColumn_SameNameInNextVersion) { + builder()->AddColumn("name", "BLOB"); + EXPECT_EQ(0u, builder()->SealVersion()); + builder()->RenameColumn("name", "name"); + EXPECT_EQ(1u, builder()->SealVersion()); + EXPECT_TRUE(builder()->CreateTable(db())); + EXPECT_TRUE(db()->DoesTableExist("logins")); + EXPECT_TRUE(db()->DoesColumnExist("logins", "name")); + EXPECT_TRUE(IsColumnOfType("name", "BLOB")); +} + +TEST_F(SQLTableBuilderTest, DropColumn_InSameVersion) { + builder()->AddColumn("password_value", "BLOB"); + builder()->DropColumn("password_value"); + EXPECT_EQ(0u, builder()->SealVersion()); + EXPECT_TRUE(builder()->CreateTable(db())); + EXPECT_TRUE(db()->DoesTableExist("logins")); + EXPECT_FALSE(db()->DoesColumnExist("logins", "password_value")); +} + +TEST_F(SQLTableBuilderTest, DropColumn_InNextVersion) { + builder()->AddColumn("password_value", "BLOB"); + EXPECT_EQ(0u, builder()->SealVersion()); + builder()->DropColumn("password_value"); + EXPECT_EQ(1u, builder()->SealVersion()); + EXPECT_TRUE(builder()->CreateTable(db())); + EXPECT_TRUE(db()->DoesTableExist("logins")); + EXPECT_FALSE(db()->DoesColumnExist("logins", "password_value")); +} + +TEST_F(SQLTableBuilderTest, MigrateFrom) { + // First, create a table at version 0, with some columns. + builder()->AddColumn("for_renaming", "INTEGER DEFAULT 100"); + builder()->AddColumn("for_deletion", "INTEGER"); + EXPECT_EQ(0u, builder()->SealVersion()); + EXPECT_TRUE(builder()->CreateTable(db())); + EXPECT_TRUE(db()->DoesTableExist("logins")); + EXPECT_TRUE(db()->DoesColumnExist("logins", "for_renaming")); + EXPECT_TRUE(db()->DoesColumnExist("logins", "for_deletion")); + EXPECT_TRUE( + db()->Execute("INSERT INTO logins (signon_realm, for_renaming, " + "for_deletion) VALUES ('abc', 123, 456)")); + const char retrieval[] = "SELECT * FROM logins"; + sql::Statement first_check( + db()->GetCachedStatement(SQL_FROM_HERE, retrieval)); + EXPECT_TRUE(first_check.Step()); + EXPECT_EQ(3, first_check.ColumnCount()); + EXPECT_EQ("abc", first_check.ColumnString(0)); + EXPECT_EQ(123, first_check.ColumnInt(1)); + EXPECT_EQ(456, first_check.ColumnInt(2)); + EXPECT_FALSE(first_check.Step()); + EXPECT_TRUE(first_check.Succeeded()); + + // Now, specify some modifications for version 1. + builder()->RenameColumn("for_renaming", "renamed"); + builder()->DropColumn("for_deletion"); + builder()->AddColumn("new_column", "INTEGER DEFAULT 789"); + EXPECT_EQ(1u, builder()->SealVersion()); + + // The migration should have the following effect: + // * The renamed column should keep its non-default value. + // * The succession of column removal and addition should not result in the + // values from the deleted column to be copied to the added one. + EXPECT_TRUE(builder()->MigrateFrom(0, db())); + EXPECT_FALSE(db()->DoesColumnExist("logins", "for_renaming")); + EXPECT_FALSE(db()->DoesColumnExist("logins", "for_deletion")); + EXPECT_TRUE(db()->DoesColumnExist("logins", "renamed")); + EXPECT_TRUE(IsColumnOfType("renamed", "INTEGER")); + EXPECT_TRUE(db()->DoesColumnExist("logins", "new_column")); + sql::Statement second_check( + db()->GetCachedStatement(SQL_FROM_HERE, retrieval)); + EXPECT_TRUE(second_check.Step()); + EXPECT_EQ(3, second_check.ColumnCount()); + EXPECT_EQ("abc", second_check.ColumnString(0)); + EXPECT_EQ(123, second_check.ColumnInt(1)); + EXPECT_EQ(789, second_check.ColumnInt(2)); + EXPECT_FALSE(second_check.Step()); + EXPECT_TRUE(second_check.Succeeded()); +} + +TEST_F(SQLTableBuilderTest, MigrateFrom_RenameAndAdd) { + builder()->AddColumn("old_name", "INTEGER"); + EXPECT_EQ(0u, builder()->SealVersion()); + + EXPECT_TRUE(builder()->CreateTable(db())); + + builder()->RenameColumn("old_name", "new_name"); + EXPECT_EQ(1u, builder()->SealVersion()); + + builder()->AddColumn("added", "VARCHAR"); + EXPECT_EQ(2u, builder()->SealVersion()); + + EXPECT_TRUE(builder()->MigrateFrom(0, db())); + EXPECT_FALSE(db()->DoesColumnExist("logins", "old_name")); + EXPECT_TRUE(db()->DoesColumnExist("logins", "added")); + EXPECT_TRUE(db()->DoesColumnExist("logins", "new_name")); + EXPECT_TRUE(IsColumnOfType("added", "VARCHAR")); + EXPECT_TRUE(IsColumnOfType("new_name", "INTEGER")); + EXPECT_EQ(3u, builder()->NumberOfColumns()); + EXPECT_EQ("signon_realm, new_name, added", builder()->ListAllColumnNames()); + EXPECT_EQ("new_name=?, added=?", builder()->ListAllNonuniqueKeyNames()); + EXPECT_EQ("signon_realm=?", builder()->ListAllUniqueKeyNames()); +} + +TEST_F(SQLTableBuilderTest, MigrateFrom_RenameAndAddAndDrop) { + builder()->AddColumnToUniqueKey("uni", "VARCHAR NOT NULL"); + builder()->AddColumn("old_name", "INTEGER"); + EXPECT_EQ(0u, builder()->SealVersion()); + + EXPECT_TRUE(builder()->CreateTable(db())); + + builder()->RenameColumn("old_name", "new_name"); + EXPECT_EQ(1u, builder()->SealVersion()); + + builder()->AddColumn("added", "VARCHAR"); + EXPECT_EQ(2u, builder()->SealVersion()); + + builder()->DropColumn("added"); + EXPECT_EQ(3u, builder()->SealVersion()); + + EXPECT_TRUE(builder()->MigrateFrom(0, db())); + EXPECT_FALSE(db()->DoesColumnExist("logins", "old_name")); + EXPECT_FALSE(db()->DoesColumnExist("logins", "added")); + EXPECT_TRUE(db()->DoesColumnExist("logins", "uni")); + EXPECT_TRUE(db()->DoesColumnExist("logins", "new_name")); + EXPECT_TRUE(IsColumnOfType("new_name", "INTEGER")); + EXPECT_EQ(3u, builder()->NumberOfColumns()); + EXPECT_EQ("signon_realm, uni, new_name", builder()->ListAllColumnNames()); + EXPECT_EQ("new_name=?", builder()->ListAllNonuniqueKeyNames()); + EXPECT_EQ("signon_realm=? AND uni=?", builder()->ListAllUniqueKeyNames()); +} + +} // namespace password_manager
diff --git a/components/password_manager/core/browser/test_password_store.cc b/components/password_manager/core/browser/test_password_store.cc index f4a0f6f5..6e79357 100644 --- a/components/password_manager/core/browser/test_password_store.cc +++ b/components/password_manager/core/browser/test_password_store.cc
@@ -118,7 +118,8 @@ return PasswordStoreChangeList(); } -PasswordStoreChangeList TestPasswordStore::DisableAutoSignInForAllLoginsImpl() { +PasswordStoreChangeList TestPasswordStore::DisableAutoSignInForOriginsImpl( + const base::Callback<bool(const GURL&)>& origin_filter) { return PasswordStoreChangeList(); }
diff --git a/components/password_manager/core/browser/test_password_store.h b/components/password_manager/core/browser/test_password_store.h index 1e76e305..f8a2f5b8 100644 --- a/components/password_manager/core/browser/test_password_store.h +++ b/components/password_manager/core/browser/test_password_store.h
@@ -60,7 +60,8 @@ PasswordStoreChangeList RemoveLoginsSyncedBetweenImpl( base::Time delete_begin, base::Time delete_end) override; - PasswordStoreChangeList DisableAutoSignInForAllLoginsImpl() override; + PasswordStoreChangeList DisableAutoSignInForOriginsImpl( + const base::Callback<bool(const GURL&)>& origin_filter) override; bool RemoveStatisticsCreatedBetweenImpl(base::Time delete_begin, base::Time delete_end) override; bool FillAutofillableLogins(
diff --git a/components/pdf/renderer/pepper_pdf_host.cc b/components/pdf/renderer/pepper_pdf_host.cc index ab9418b..5de42de 100644 --- a/components/pdf/renderer/pepper_pdf_host.cc +++ b/components/pdf/renderer/pepper_pdf_host.cc
@@ -142,6 +142,11 @@ if (!instance) return PP_ERROR_FAILED; + // TODO(thestig): Turn CHECKs into the proper if statement after figuring out + // what's wrong for https://crbug.com/627814 + CHECK(instance->GetContainer()); + CHECK(instance->GetContainer()->document().frame()); + CHECK(instance->GetContainer()->document().frame()->view()); blink::WebView* view = instance->GetContainer()->document().frame()->view(); content::RenderView* render_view = content::RenderView::FromWebView(view);
diff --git a/components/plugins/renderer/loadable_plugin_placeholder.cc b/components/plugins/renderer/loadable_plugin_placeholder.cc index 2da903e..aa9a97fe 100644 --- a/components/plugins/renderer/loadable_plugin_placeholder.cc +++ b/components/plugins/renderer/loadable_plugin_placeholder.cc
@@ -60,7 +60,7 @@ const blink::WebPluginParams& params, const std::string& html_data) : PluginPlaceholderBase(render_frame, frame, params, html_data), - is_delayed_placeholder_(false), + is_blocked_for_tinyness_(false), is_blocked_for_background_tab_(false), is_blocked_for_prerendering_(false), is_blocked_for_power_saver_poster_(false), @@ -74,11 +74,6 @@ LoadablePluginPlaceholder::~LoadablePluginPlaceholder() { } -void LoadablePluginPlaceholder::SetDelegate( - std::unique_ptr<Delegate> delegate) { - delegate_ = std::move(delegate); -} - void LoadablePluginPlaceholder::MarkPluginEssential( PluginInstanceThrottler::PowerSaverUnthrottleMethod method) { if (!power_saver_enabled_) @@ -91,11 +86,10 @@ else if (method != PluginInstanceThrottler::UNTHROTTLE_METHOD_DO_NOT_RECORD) PluginInstanceThrottler::RecordUnthrottleMethodMetric(method); - if (is_blocked_for_power_saver_poster_) { - is_blocked_for_power_saver_poster_ = false; - if (!LoadingBlocked()) - LoadPlugin(); - } + is_blocked_for_power_saver_poster_ = false; + is_blocked_for_tinyness_ = false; + if (!LoadingBlocked()) + LoadPlugin(); } void LoadablePluginPlaceholder::ReplacePlugin(blink::WebPlugin* new_plugin) { @@ -192,10 +186,12 @@ const gfx::Rect& unobscured_rect) { DCHECK(content::RenderThread::Get()); - // TODO(groby): Handle the case of power saver not being enabled. if (!plugin() || !finished_loading_) return; + if (!is_blocked_for_tinyness_ && !is_blocked_for_power_saver_poster_) + return; + if (unobscured_rect_ == unobscured_rect) return; @@ -213,12 +209,40 @@ render_frame()->GetPeripheralContentStatus( render_frame()->GetWebFrame()->top()->getSecurityOrigin(), content_origin, gfx::Size(width, height)); - // If this is a "delay" placeholder, delegate decisions. - if (is_delayed_placeholder_) { - OnLoadedRectUpdate(gfx::Rect(x, y, width, height), status); - is_delayed_placeholder_ = false; + + bool plugin_is_tiny_and_blocked = + is_blocked_for_tinyness_ && + status == + content::RenderFrame::CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_TINY; + + // Early exit for plugins that we've discovered to be essential. + if (!plugin_is_tiny_and_blocked && + status != content::RenderFrame::CONTENT_STATUS_PERIPHERAL) { + MarkPluginEssential( + heuristic_run_before_ + ? PluginInstanceThrottler::UNTHROTTLE_METHOD_BY_SIZE_CHANGE + : PluginInstanceThrottler::UNTHROTTLE_METHOD_DO_NOT_RECORD); + + if (!heuristic_run_before_ && + status == + content::RenderFrame::CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_BIG) { + render_frame()->WhitelistContentOrigin(content_origin); + } + return; } + heuristic_run_before_ = true; + + if (is_blocked_for_tinyness_) { + if (plugin_is_tiny_and_blocked) { + OnBlockedTinyContent(); + } else { + is_blocked_for_tinyness_ = false; + if (!LoadingBlocked()) { + LoadPlugin(); + } + } + } if (is_blocked_for_power_saver_poster_) { // Adjust poster container padding and dimensions to center play button for @@ -228,21 +252,6 @@ height); plugin()->web_view()->mainFrame()->executeScript( blink::WebScriptSource(base::UTF8ToUTF16(script))); - - if (status != content::RenderFrame::CONTENT_STATUS_PERIPHERAL) { - MarkPluginEssential( - heuristic_run_before_ - ? PluginInstanceThrottler::UNTHROTTLE_METHOD_BY_SIZE_CHANGE - : PluginInstanceThrottler::UNTHROTTLE_METHOD_DO_NOT_RECORD); - - if (!heuristic_run_before_ && - status == - content::RenderFrame::CONTENT_STATUS_ESSENTIAL_CROSS_ORIGIN_BIG) { - render_frame()->WhitelistContentOrigin(content_origin); - } - } - - heuristic_run_before_ = true; } } @@ -358,8 +367,8 @@ bool LoadablePluginPlaceholder::LoadingBlocked() const { DCHECK(allow_loading_); - return is_blocked_for_background_tab_ || is_blocked_for_power_saver_poster_ || - is_blocked_for_prerendering_; + return is_blocked_for_tinyness_ || is_blocked_for_background_tab_ || + is_blocked_for_power_saver_poster_ || is_blocked_for_prerendering_; } } // namespace plugins
diff --git a/components/plugins/renderer/loadable_plugin_placeholder.h b/components/plugins/renderer/loadable_plugin_placeholder.h index c46b711..0d7d8d9 100644 --- a/components/plugins/renderer/loadable_plugin_placeholder.h +++ b/components/plugins/renderer/loadable_plugin_placeholder.h
@@ -21,7 +21,9 @@ // (blocked or disabled). class LoadablePluginPlaceholder : public PluginPlaceholderBase { public: - void set_delayed(bool delayed) { is_delayed_placeholder_ = delayed; } + void set_blocked_for_tinyness(bool blocked_for_tinyness) { + is_blocked_for_tinyness_ = blocked_for_tinyness; + } void set_blocked_for_background_tab(bool blocked_for_background_tab) { is_blocked_for_background_tab_ = blocked_for_background_tab; @@ -53,8 +55,6 @@ ~LoadablePluginPlaceholder() override; - void SetDelegate(std::unique_ptr<Delegate> delegate); - void MarkPluginEssential( content::PluginInstanceThrottler::PowerSaverUnthrottleMethod method); @@ -99,18 +99,16 @@ // Plugin creation is embedder-specific. virtual blink::WebPlugin* CreatePlugin() = 0; - // Handling of delayed behavior is embedder-specific. - virtual void OnLoadedRectUpdate( - const gfx::Rect& unobscured_rect, - content::RenderFrame::PeripheralContentStatus status) = 0; + // Embedder-specific behavior. + virtual void OnBlockedTinyContent() = 0; content::WebPluginInfo plugin_info_; base::string16 message_; - // True if this is a "delayed" placeholder - one that will make a decision - // on placeholder vs. plugin behavior once initial size has been determined. - bool is_delayed_placeholder_; + // True if the plugin load was deferred because this might be a tiny plugin. + // Plugin may be automatically loaded if it receives non-tiny geometry. + bool is_blocked_for_tinyness_; // True if the plugin load was deferred due to page being a background tab. // Plugin may be automatically loaded when the page is foregrounded. @@ -140,8 +138,6 @@ // True if the power saver heuristic has already been run on this content. bool heuristic_run_before_; - std::unique_ptr<Delegate> delegate_; - base::WeakPtrFactory<LoadablePluginPlaceholder> weak_factory_; DISALLOW_COPY_AND_ASSIGN(LoadablePluginPlaceholder);
diff --git a/components/plugins/renderer/mobile_youtube_plugin.cc b/components/plugins/renderer/mobile_youtube_plugin.cc index 4b77abd5..455640b 100644 --- a/components/plugins/renderer/mobile_youtube_plugin.cc +++ b/components/plugins/renderer/mobile_youtube_plugin.cc
@@ -106,7 +106,6 @@ std::string youtube("vnd.youtube:"); GURL url(youtube.append(GetYoutubeVideoId(GetPluginParams()))); WebURLRequest request; - request.initialize(); request.setURL(url); render_frame()->LoadURLExternally(request, blink::WebNavigationPolicyNewForegroundTab);
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto index bbdc25e..f0d3ba0 100644 --- a/components/policy/proto/device_management_backend.proto +++ b/components/policy/proto/device_management_backend.proto
@@ -377,16 +377,16 @@ // The unique directory api ID of the device which was generated on the // server-side. optional string directory_api_id = 22; - + // List of device affiliation IDs. If exists overlap between user // affiliation IDs and device affiliation IDs, we consider that the user is // affiliated on the device. Otherwise the user is not affiliated on the - // device. Should be fetched with device policy. Ignored if fetched with + // device. Should be fetched with device policy. Ignored if fetched with // other polices. repeated string device_affiliation_ids = 23; - + // List of user affiliation IDs. The list is used to define if current user - // is affiliated on the device. See device_affiliation_ids for details. + // is affiliated on the device. See device_affiliation_ids for details. // Should be fetched with user policy. Ignored if fetched with other polices. repeated string user_affiliation_ids = 24; } @@ -745,6 +745,36 @@ // CPU temp information. repeated CPUTempInfo cpu_temp_info = 16; + + // This field is set only when an OS update is needed because of the required + // platform version of an updated kiosk app is different from the current + // OS version. + optional OsUpdateStatus os_update_status = 17; + + // Set only when there is an auto launched with zero delay kiosk app + // and it is currently running. Otherwise, this field is empty. + optional AppStatus running_kiosk_app = 18; +} + +message OsUpdateStatus { + enum UpdateStatus { + OS_UP_TO_DATE = 0; + OS_IMAGE_DOWNLOAD_NOT_STARTED = 1; + OS_IMAGE_DOWNLOAD_IN_PROGRESS = 2; + OS_UPDATE_NEED_REBOOT = 3; + } + + optional UpdateStatus update_status = 1; + + // New platform version of the os image being downloaded and applied. It + // is only set when update status is OS_IMAGE_DOWNLOAD_IN_PROGRESS or + // OS_UPDATE_NEED_REBOOT. Note this could be a dummy "0.0.0.0" for + // OS_UPDATE_NEED_REBOOT status for some edge cases, e.g. update engine is + // restarted without a reboot. + optional string new_platform_version = 2; + + // New required platform version from the pending updated kiosk app. + optional string new_required_platform_version = 3; } // Provides status information for an installed app/extension. @@ -760,6 +790,9 @@ // If true, the application is currently in a self-reported error state. optional bool error = 4; + + // App required Chrome version, specified in app’s manifest file. + optional string required_platform_version = 5; } // Report session (a user on one device) level status.
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 177040f1..00cccee 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -4859,13 +4859,13 @@ }, 'example_value': False, 'id': 293, - 'caption': '''Send monitoring heartbeats to the management server''', + 'caption': '''Send network packets to the management server to monitor online status''', 'tags': ['admin-sharing'], - 'desc': '''Send monitoring heartbeats to the management server, to allow + 'desc': '''Send network packets to the management server to monitor online status, to allow the server to detect if the device is offline. - If this policy is set to true, monitoring heartbeats will be sent. If set - to false or unset, then no heartbeats will be sent.''', + If this policy is set to true, monitoring network packets (so-called <ph name="HEARTBEATS_TERM">heartbeats</ph>) will be sent. + If set to false or unset, no packets will be sent.''', }, { 'name': 'HeartbeatFrequency', @@ -4878,9 +4878,9 @@ }, 'example_value': 180000, 'id': 294, - 'caption': '''Frequency of monitoring heartbeats''', + 'caption': '''Frequency of monitoring network packets''', 'tags': [], - 'desc': '''How frequently monitoring heartbeats are sent, in milliseconds. + 'desc': '''How frequently monitoring network packets are sent, in milliseconds. If this policy is unset, the default frequency is 3 minutes. The minimum frequency is 30 seconds and the maximum frequency is 24 hours - values
diff --git a/components/printing/test/print_web_view_helper_browsertest.cc b/components/printing/test/print_web_view_helper_browsertest.cc index c6e58cb..5fbfacc 100644 --- a/components/printing/test/print_web_view_helper_browsertest.cc +++ b/components/printing/test/print_web_view_helper_browsertest.cc
@@ -41,11 +41,10 @@ namespace { -#if !defined(OS_CHROMEOS) - // A simple web page. const char kHelloWorldHTML[] = "<body><p>Hello World!</p></body>"; +#if !defined(OS_CHROMEOS) // A simple webpage with a button to print itself with. const char kPrintOnUserAction[] = "<body>"
diff --git a/components/proximity_auth/fake_secure_context.cc b/components/proximity_auth/fake_secure_context.cc index 92e54b0..f8f8802 100644 --- a/components/proximity_auth/fake_secure_context.cc +++ b/components/proximity_auth/fake_secure_context.cc
@@ -2,15 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "components/proximity_auth/fake_secure_context.h" + #include <stddef.h> -#include "components/proximity_auth/fake_secure_context.h" +#include "base/strings/string_util.h" namespace proximity_auth { namespace { + const char kFakeEncodingSuffix[] = ", but encoded"; +const size_t kFakeEncodingSuffixLen = sizeof(kFakeEncodingSuffix) - 1; const char kChannelBindingData[] = "channel binding data"; + } // namespace FakeSecureContext::FakeSecureContext() @@ -33,15 +38,13 @@ void FakeSecureContext::Decode(const std::string& encoded_message, const MessageCallback& callback) { - size_t suffix_size = std::string(kFakeEncodingSuffix).size(); - if (encoded_message.size() < suffix_size && - encoded_message.substr(encoded_message.size() - suffix_size) != - kFakeEncodingSuffix) { + if (!EndsWith(encoded_message, kFakeEncodingSuffix, + base::CompareCase::SENSITIVE)) { callback.Run(std::string()); } std::string decoded_message = encoded_message; - decoded_message.erase(decoded_message.rfind(kFakeEncodingSuffix)); + decoded_message.erase(decoded_message.size() - kFakeEncodingSuffixLen); callback.Run(decoded_message); }
diff --git a/components/renderer_context_menu/render_view_context_menu_base.h b/components/renderer_context_menu/render_view_context_menu_base.h index 82792dd..d57b9dc1 100644 --- a/components/renderer_context_menu/render_view_context_menu_base.h +++ b/components/renderer_context_menu/render_view_context_menu_base.h
@@ -149,8 +149,8 @@ #endif // Returns the accelerator for given |command_id|. - bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override = 0; + bool GetAcceleratorForCommandId(int command_id, ui::Accelerator* accelerator) + const override = 0; // Subclasses should send notification. virtual void NotifyMenuShown() = 0;
diff --git a/components/safe_browsing_db/v4_database.cc b/components/safe_browsing_db/v4_database.cc index c54cdbc..3c1cf1c 100644 --- a/components/safe_browsing_db/v4_database.cc +++ b/components/safe_browsing_db/v4_database.cc
@@ -137,7 +137,9 @@ std::unique_ptr<V4Store> new_store) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(pending_store_updates_); - (*store_map_)[identifier] = std::move(new_store); + if (new_store) { + (*store_map_)[identifier] = std::move(new_store); + } pending_store_updates_--; if (!pending_store_updates_) {
diff --git a/components/safe_browsing_db/v4_database.h b/components/safe_browsing_db/v4_database.h index ceacfc1..df458a2 100644 --- a/components/safe_browsing_db/v4_database.h +++ b/components/safe_browsing_db/v4_database.h
@@ -89,6 +89,7 @@ FRIEND_TEST_ALL_PREFIXES(V4DatabaseTest, TestApplyUpdateWithNewStates); FRIEND_TEST_ALL_PREFIXES(V4DatabaseTest, TestApplyUpdateWithNoNewState); FRIEND_TEST_ALL_PREFIXES(V4DatabaseTest, TestApplyUpdateWithEmptyUpdate); + FRIEND_TEST_ALL_PREFIXES(V4DatabaseTest, TestApplyUpdateWithInvalidUpdate); // Makes the passed |factory| the factory used to instantiate a V4Store. Only // for tests.
diff --git a/components/safe_browsing_db/v4_database_unittest.cc b/components/safe_browsing_db/v4_database_unittest.cc index 2dee2a66..c841cbfb2 100644 --- a/components/safe_browsing_db/v4_database_unittest.cc +++ b/components/safe_browsing_db/v4_database_unittest.cc
@@ -127,17 +127,23 @@ } std::unique_ptr<ParsedServerResponse> CreateFakeServerResponse( - StoreStateMap store_state_map) { + StoreStateMap store_state_map, + bool use_valid_response_type) { std::unique_ptr<ParsedServerResponse> parsed_server_response( new ParsedServerResponse); for (const auto& store_state_iter : store_state_map) { UpdateListIdentifier identifier = store_state_iter.first; - ListUpdateResponse* list_update_response = new ListUpdateResponse; - list_update_response->set_platform_type(identifier.platform_type); - list_update_response->set_threat_entry_type(identifier.threat_entry_type); - list_update_response->set_threat_type(identifier.threat_type); - list_update_response->set_new_client_state(store_state_iter.second); - parsed_server_response->push_back(base::WrapUnique(list_update_response)); + ListUpdateResponse* lur = new ListUpdateResponse; + lur->set_platform_type(identifier.platform_type); + lur->set_threat_entry_type(identifier.threat_entry_type); + lur->set_threat_type(identifier.threat_type); + lur->set_new_client_state(store_state_iter.second); + if (use_valid_response_type) { + lur->set_response_type(ListUpdateResponse::FULL_UPDATE); + } else { + lur->set_response_type(ListUpdateResponse::RESPONSE_TYPE_UNSPECIFIED); + } + parsed_server_response->push_back(base::WrapUnique(lur)); } return parsed_server_response; } @@ -237,8 +243,9 @@ old_stores_map_[store_iter.first] = store; } - v4_database_->ApplyUpdate(CreateFakeServerResponse(expected_store_state_map_), - callback_db_updated_); + v4_database_->ApplyUpdate( + CreateFakeServerResponse(expected_store_state_map_, true), + callback_db_updated_); task_runner_->RunPendingTasks(); base::RunLoop().RunUntilIdle(); @@ -267,8 +274,9 @@ old_stores_map_[store_iter.first] = store; } - v4_database_->ApplyUpdate(CreateFakeServerResponse(expected_store_state_map_), - callback_db_updated_); + v4_database_->ApplyUpdate( + CreateFakeServerResponse(expected_store_state_map_, true), + callback_db_updated_); task_runner_->RunPendingTasks(); base::RunLoop().RunUntilIdle(); @@ -308,4 +316,34 @@ VerifyExpectedStoresState(false); } +// Test to ensure invalid update leads to no store changes. +TEST_F(V4DatabaseTest, TestApplyUpdateWithInvalidUpdate) { + expected_resets_successfully_ = true; + RegisterFactory(!expected_resets_successfully_); + + V4Database::Create(task_runner_, database_dirname_, store_file_name_map_, + callback_db_ready_); + created_but_not_called_back_ = true; + task_runner_->RunPendingTasks(); + base::RunLoop().RunUntilIdle(); + + // The database has now been created. Time to try to update it. + EXPECT_TRUE(v4_database_); + const StoreMap* db_stores = v4_database_->store_map_.get(); + EXPECT_EQ(expected_store_paths_.size(), db_stores->size()); + for (const auto& store_iter : *db_stores) { + V4Store* store = store_iter.second.get(); + expected_store_state_map_[store_iter.first] = store->state(); + old_stores_map_[store_iter.first] = store; + } + + v4_database_->ApplyUpdate( + CreateFakeServerResponse(expected_store_state_map_, false), + callback_db_updated_); + task_runner_->RunPendingTasks(); + base::RunLoop().RunUntilIdle(); + + VerifyExpectedStoresState(false); +} + } // namespace safe_browsing
diff --git a/components/safe_browsing_db/v4_store.cc b/components/safe_browsing_db/v4_store.cc index 2ef5c03..7f375d6 100644 --- a/components/safe_browsing_db/v4_store.cc +++ b/components/safe_browsing_db/v4_store.cc
@@ -18,6 +18,13 @@ const uint32_t kFileVersion = 9; +// The minimum expected size (in bytes) of a hash-prefix. +const uint32_t kMinHashPrefixLength = 4; + +// The maximum expected size (in bytes) of a hash-prefix. This represents the +// length of a SHA256 hash. +const uint32_t kMaxHashPrefixLength = 32; + void RecordStoreReadResult(StoreReadResult result) { UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4StoreReadResult", result, STORE_READ_RESULT_MAX); @@ -28,6 +35,11 @@ STORE_WRITE_RESULT_MAX); } +void RecordApplyUpdateResult(ApplyUpdateResult result) { + UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4ApplyUpdateResult", result, + APPLY_UPDATE_RESULT_MAX); +} + // Returns the name of the temporary file used to buffer data for // |filename|. Exported for unit tests. const base::FilePath TemporaryFileForFilename(const base::FilePath& filename) { @@ -83,22 +95,232 @@ UpdatedStoreReadyCallback callback) { std::unique_ptr<V4Store> new_store( new V4Store(this->task_runner_, this->store_path_)); - new_store->state_ = response->new_client_state(); // TODO(vakh): // 1. Merge the old store and the new update in new_store. // 2. Create a ListUpdateResponse containing RICE encoded hash-prefixes and // response_type as FULL_UPDATE, and write that to disk. // 3. Remove this if condition after completing 1. and 2. - if (response->has_response_type() && - response->response_type() == ListUpdateResponse::FULL_UPDATE) { - StoreWriteResult result = new_store->WriteToDisk(std::move(response)); - RecordStoreWriteResult(result); + HashPrefixMap hash_prefix_map; + ApplyUpdateResult apply_update_result; + if (response->response_type() == ListUpdateResponse::PARTIAL_UPDATE) { + for (const auto& removal : response->removals()) { + // TODO(vakh): Allow other compression types. + // See: https://bugs.chromium.org/p/chromium/issues/detail?id=624567 + DCHECK_EQ(RAW, removal.compression_type()); + } + + apply_update_result = UpdateHashPrefixMapFromAdditions( + response->additions(), &hash_prefix_map); + if (apply_update_result == APPLY_UPDATE_SUCCESS) { + apply_update_result = + new_store->MergeUpdate(hash_prefix_map_, hash_prefix_map); + } + // TODO(vakh): Generate the updated ListUpdateResponse to write to disk. + } else if (response->response_type() == ListUpdateResponse::FULL_UPDATE) { + apply_update_result = UpdateHashPrefixMapFromAdditions( + response->additions(), &hash_prefix_map); + if (apply_update_result == APPLY_UPDATE_SUCCESS) { + new_store->hash_prefix_map_ = hash_prefix_map; + RecordStoreWriteResult(new_store->WriteToDisk(std::move(response))); + } + } else { + apply_update_result = UNEXPECTED_RESPONSE_TYPE_FAILURE; + NOTREACHED() << "Unexpected response type: " << response->response_type(); } - // new_store is done updating, pass it to the callback. - callback_task_runner->PostTask( - FROM_HERE, base::Bind(callback, base::Passed(&new_store))); + if (apply_update_result == APPLY_UPDATE_SUCCESS) { + // new_store is done updating, pass it to the callback. + callback_task_runner->PostTask( + FROM_HERE, base::Bind(callback, base::Passed(&new_store))); + } else { + // new_store failed updating. Pass a nullptr to the callback. + callback_task_runner->PostTask(FROM_HERE, base::Bind(callback, nullptr)); + } + + RecordApplyUpdateResult(apply_update_result); +} + +// static +ApplyUpdateResult V4Store::UpdateHashPrefixMapFromAdditions( + const ::google::protobuf::RepeatedPtrField<ThreatEntrySet>& additions, + HashPrefixMap* additions_map) { + for (const auto& addition : additions) { + // TODO(vakh): Allow other compression types. + // See: https://bugs.chromium.org/p/chromium/issues/detail?id=624567 + DCHECK_EQ(RAW, addition.compression_type()); + + DCHECK(addition.has_raw_hashes()); + DCHECK(addition.raw_hashes().has_raw_hashes()); + + PrefixSize prefix_size = addition.raw_hashes().prefix_size(); + ApplyUpdateResult result = AddUnlumpedHashes( + prefix_size, addition.raw_hashes().raw_hashes(), additions_map); + if (result != APPLY_UPDATE_SUCCESS) { + // If there was an error in updating the map, discard the update entirely. + return result; + } + } + return APPLY_UPDATE_SUCCESS; +} + +// static +ApplyUpdateResult V4Store::AddUnlumpedHashes(PrefixSize prefix_size, + const std::string& lumped_hashes, + HashPrefixMap* additions_map) { + if (prefix_size < kMinHashPrefixLength) { + NOTREACHED(); + return PREFIX_SIZE_TOO_SMALL_FAILURE; + } + if (prefix_size > kMaxHashPrefixLength) { + NOTREACHED(); + return PREFIX_SIZE_TOO_LARGE_FAILURE; + } + if (lumped_hashes.size() % prefix_size != 0) { + return ADDITIONS_SIZE_UNEXPECTED_FAILURE; + } + // TODO(vakh): Figure out a way to avoid the following copy operation. + (*additions_map)[prefix_size] = lumped_hashes; + return APPLY_UPDATE_SUCCESS; +} + +// static +bool V4Store::GetNextSmallestPrefixSize(const HashPrefixMap& hash_prefix_map, + const CounterMap& counter_map, + PrefixSize* smallest_prefix_size) { + HashPrefix smallest_prefix, current_prefix; + for (const auto& counter_pair : counter_map) { + PrefixSize prefix_size = counter_pair.first; + size_t index = counter_pair.second; + size_t sized_index = prefix_size * index; + + const HashPrefixes& hash_prefixes = hash_prefix_map.at(prefix_size); + if (sized_index < hash_prefixes.size()) { + current_prefix = hash_prefixes.substr(sized_index, prefix_size); + if (smallest_prefix.empty() || smallest_prefix > current_prefix) { + smallest_prefix = current_prefix; + *smallest_prefix_size = prefix_size; + } + } + } + return !smallest_prefix.empty(); +} + +// static +void V4Store::InitializeCounterMap(const HashPrefixMap& hash_prefix_map, + CounterMap* counter_map) { + for (const auto& map_pair : hash_prefix_map) { + (*counter_map)[map_pair.first] = 0; + } +} + +// static +HashPrefix V4Store::GetNextUnmergedPrefixForSize( + PrefixSize prefix_size, + const HashPrefixMap& hash_prefix_map, + const CounterMap& counter_map) { + const HashPrefixes& hash_prefixes = hash_prefix_map.at(prefix_size); + size_t index_within_list = counter_map.at(prefix_size); + size_t sized_index = prefix_size * index_within_list; + return hash_prefixes.substr(sized_index, prefix_size); +} + +// static +void V4Store::ReserveSpaceInPrefixMap(const HashPrefixMap& other_prefixes_map, + HashPrefixMap* prefix_map_to_update) { + for (const auto& pair : other_prefixes_map) { + PrefixSize prefix_size = pair.first; + size_t prefix_length_to_add = pair.second.length(); + + const HashPrefixes& existing_prefixes = + (*prefix_map_to_update)[prefix_size]; + size_t existing_capacity = existing_prefixes.capacity(); + + (*prefix_map_to_update)[prefix_size].reserve(existing_capacity + + prefix_length_to_add); + } +} + +ApplyUpdateResult V4Store::MergeUpdate(const HashPrefixMap& old_prefixes_map, + const HashPrefixMap& additions_map) { + DCHECK(hash_prefix_map_.empty()); + hash_prefix_map_.clear(); + ReserveSpaceInPrefixMap(old_prefixes_map, &hash_prefix_map_); + ReserveSpaceInPrefixMap(additions_map, &hash_prefix_map_); + + PrefixSize next_size_for_old; + CounterMap old_counter_map; + InitializeCounterMap(old_prefixes_map, &old_counter_map); + bool old_has_unmerged = GetNextSmallestPrefixSize( + old_prefixes_map, old_counter_map, &next_size_for_old); + + PrefixSize next_size_for_additions; + CounterMap additions_counter_map; + InitializeCounterMap(additions_map, &additions_counter_map); + bool additions_has_unmerged = GetNextSmallestPrefixSize( + additions_map, additions_counter_map, &next_size_for_additions); + + // Classical merge sort. + // The two constructs to merge are maps: old_prefixes_map, additions_map. + + HashPrefix next_smallest_prefix_old, next_smallest_prefix_additions; + // At least one of the maps still has elements that need to be merged into the + // new store. + while (old_has_unmerged || additions_has_unmerged) { + // Old map still has elements that need to be merged. + if (old_has_unmerged) { + // Get the lexographically smallest hash prefix from the old store. + next_smallest_prefix_old = GetNextUnmergedPrefixForSize( + next_size_for_old, old_prefixes_map, old_counter_map); + } + + // Additions map still has elements that need to be merged. + if (additions_has_unmerged) { + // Get the lexographically smallest hash prefix from the additions in the + // latest update from the server. + next_smallest_prefix_additions = GetNextUnmergedPrefixForSize( + next_size_for_additions, additions_map, additions_counter_map); + } + + // If the same hash prefix appears in the existing store and the additions + // list, something is clearly wrong. Discard the update. + if (old_has_unmerged && additions_has_unmerged && + next_smallest_prefix_old == next_smallest_prefix_additions) { + return ADDITIONS_HAS_EXISTING_PREFIX_FAILURE; + } + + // Select which map to pick the next hash prefix from to keep the result in + // lexographically sorted order. + bool pick_from_old = + old_has_unmerged && + (!additions_has_unmerged || + (next_smallest_prefix_old < next_smallest_prefix_additions)); + + if (pick_from_old) { + hash_prefix_map_[next_size_for_old] += next_smallest_prefix_old; + + // Update the counter map, which means that we have merged one hash + // prefix of size |next_size_for_old| from the old store. + old_counter_map[next_size_for_old]++; + + // Find the next smallest unmerged element in the old store's map. + old_has_unmerged = GetNextSmallestPrefixSize( + old_prefixes_map, old_counter_map, &next_size_for_old); + } else { + hash_prefix_map_[next_size_for_additions] += + next_smallest_prefix_additions; + + // Update the counter map, which means that we have merged one hash + // prefix of size |next_size_for_additions| from the update. + additions_counter_map[next_size_for_additions]++; + + // Find the next smallest unmerged element in the additions map. + additions_has_unmerged = GetNextSmallestPrefixSize( + additions_map, additions_counter_map, &next_size_for_additions); + } + } + + return APPLY_UPDATE_SUCCESS; } StoreReadResult V4Store::ReadFromDisk() {
diff --git a/components/safe_browsing_db/v4_store.h b/components/safe_browsing_db/v4_store.h index bbafbe7..31b3836 100644 --- a/components/safe_browsing_db/v4_store.h +++ b/components/safe_browsing_db/v4_store.h
@@ -18,6 +18,25 @@ typedef base::Callback<void(std::unique_ptr<V4Store>)> UpdatedStoreReadyCallback; +// The size of the hash prefix, in bytes. It should be between 4 to 32 (full +// hash). +typedef size_t PrefixSize; + +// A hash prefix sent by the SafeBrowsing PVer4 service. +typedef std::string HashPrefix; + +// The sorted list of hash prefixes. +typedef std::string HashPrefixes; + +// Stores the list of sorted hash prefixes, by size. +// For instance: {4: ["abcd", "bcde", "cdef", "gggg"], 5: ["fffff"]} +typedef base::hash_map<PrefixSize, HashPrefixes> HashPrefixMap; + +// Stores the index of the last element merged from the HashPrefixMap for a +// given prefix size. For instance: {4:3, 5:1} means that we have already merged +// 3 hash prefixes of length 4, and 1 hash prefix of length 5. +typedef base::hash_map<PrefixSize, size_t> CounterMap; + // Enumerate different failure events while parsing the file read from disk for // histogramming purposes. DO NOT CHANGE THE ORDERING OF THESE VALUES. enum StoreReadResult { @@ -79,6 +98,37 @@ STORE_WRITE_RESULT_MAX }; +// Enumerate different events while applying the update fetched fom the server +// for histogramming purposes. +// DO NOT CHANGE THE ORDERING OF THESE VALUES. +enum ApplyUpdateResult { + // No errors. + APPLY_UPDATE_SUCCESS = 0, + + // Reserved for errors in parsing this enum. + UNEXPECTED_APPLY_UPDATE_FAILURE = 1, + + // Prefix size smaller than 4 (which is the lowest expected). + PREFIX_SIZE_TOO_SMALL_FAILURE = 2, + + // Prefix size larger than 32 (length of a full SHA256 hash). + PREFIX_SIZE_TOO_LARGE_FAILURE = 3, + + // The number of bytes in additions isn't a multiple of prefix size. + ADDITIONS_SIZE_UNEXPECTED_FAILURE = 4, + + // The update received from the server contains a prefix that's already + // present in the map. + ADDITIONS_HAS_EXISTING_PREFIX_FAILURE = 5, + + // The server sent a response_type that the client did not expect. + UNEXPECTED_RESPONSE_TYPE_FAILURE = 6, + + // Memory space for histograms is determined by the max. ALWAYS + // ADD NEW VALUES BEFORE THIS ONE. + APPLY_UPDATE_RESULT_MAX +}; + // Factory for creating V4Store. Tests implement this factory to create fake // stores for testing. class V4StoreFactory { @@ -127,6 +177,69 @@ FRIEND_TEST_ALL_PREFIXES(V4StoreTest, TestWritePartialResponseType); FRIEND_TEST_ALL_PREFIXES(V4StoreTest, TestWriteFullResponseType); FRIEND_TEST_ALL_PREFIXES(V4StoreTest, TestReadFromFileWithUnknownProto); + FRIEND_TEST_ALL_PREFIXES(V4StoreTest, + TestAddUnlumpedHashesWithInvalidAddition); + FRIEND_TEST_ALL_PREFIXES(V4StoreTest, TestAddUnlumpedHashes); + FRIEND_TEST_ALL_PREFIXES(V4StoreTest, TestAddUnlumpedHashesWithEmptyString); + FRIEND_TEST_ALL_PREFIXES(V4StoreTest, + TestGetNextSmallestPrefixSizeWithEmptyPrefixMap); + FRIEND_TEST_ALL_PREFIXES(V4StoreTest, TestGetNextSmallestPrefixSize); + FRIEND_TEST_ALL_PREFIXES(V4StoreTest, TestGetNextUnmergedPrefix); + FRIEND_TEST_ALL_PREFIXES(V4StoreTest, TestMergeUpdatesWithSameSizesInEachMap); + FRIEND_TEST_ALL_PREFIXES(V4StoreTest, + TestMergeUpdatesWithDifferentSizesInEachMap); + FRIEND_TEST_ALL_PREFIXES(V4StoreTest, TestMergeUpdatesOldMapRunsOutFirst); + FRIEND_TEST_ALL_PREFIXES(V4StoreTest, + TestMergeUpdatesAdditionsMapRunsOutFirst); + FRIEND_TEST_ALL_PREFIXES(V4StoreTest, + TestMergeUpdatesFailsForRepeatedhashPrefix); + + // If |prefix_size| is within expected range, and |raw_hashes| is not invalid, + // then it sets |raw_hashes| as the value at key |prefix_size| in + // |additions_map| + static ApplyUpdateResult AddUnlumpedHashes(PrefixSize prefix_size, + const std::string& raw_hashes, + HashPrefixMap* additions_map); + + // Get the size of the next unmerged hash prefix in dictionary order from + // |hash_prefix_map|. |counter_map| is used to determine which hash prefixes + // have been merged already. Returns true if there are any unmerged hash + // prefixes in the list. + static bool GetNextSmallestPrefixSize(const HashPrefixMap& hash_prefix_map, + const CounterMap& counter_map, + PrefixSize* smallest_prefix_size); + + // Returns the next hash prefix of length |prefix_size| from |hash_prefix_map| + // that hasn't been merged already. |counter_map| is used to determine the + // index of the next prefix of size |prefix_size| to merge. + static HashPrefix GetNextUnmergedPrefixForSize( + PrefixSize prefix_size, + const HashPrefixMap& hash_prefix_map, + const CounterMap& counter_map); + + // Sets a value of 0 in |counter_map| for all keys in |hash_prefix_map|. + static void InitializeCounterMap(const HashPrefixMap& hash_prefix_map, + CounterMap* counter_map); + + // Reserve the appropriate string size so that the string size of the merged + // list is exact. This ignores the space that would otherwise be released by + // deletions specified in the update because it is non-trivial to calculate + // those deletions upfront. This isn't so bad since deletions are supposed to + // be small and infrequent. + static void ReserveSpaceInPrefixMap(const HashPrefixMap& other_prefixes_map, + HashPrefixMap* prefix_map_to_update); + + // Updates the |additions_map| with the additions received in the partial + // update from the server. + static ApplyUpdateResult UpdateHashPrefixMapFromAdditions( + const ::google::protobuf::RepeatedPtrField<ThreatEntrySet>& additions, + HashPrefixMap* additions_map); + + // Merges the prefix map from the old store (|old_hash_prefix_map|) and the + // update (additions_map) to populate the prefix map for the current store. + // TODO(vakh): Process removals also. + ApplyUpdateResult MergeUpdate(const HashPrefixMap& old_hash_prefix_map, + const HashPrefixMap& additions_map); // Reads the state of the store from the file on disk and returns the reason // for the failure or reports success. @@ -140,6 +253,7 @@ // update response. std::string state_; const base::FilePath store_path_; + HashPrefixMap hash_prefix_map_; const scoped_refptr<base::SequencedTaskRunner> task_runner_; };
diff --git a/components/safe_browsing_db/v4_store_unittest.cc b/components/safe_browsing_db/v4_store_unittest.cc index ec41208..877b077d 100644 --- a/components/safe_browsing_db/v4_store_unittest.cc +++ b/components/safe_browsing_db/v4_store_unittest.cc
@@ -141,4 +141,200 @@ EXPECT_EQ("test_client_state", read_store->state_); } +TEST_F(V4StoreTest, TestAddUnlumpedHashesWithInvalidAddition) { + HashPrefixMap prefix_map; + EXPECT_EQ(ADDITIONS_SIZE_UNEXPECTED_FAILURE, + V4Store::AddUnlumpedHashes(5, "a", &prefix_map)); + EXPECT_TRUE(prefix_map.empty()); +} + +TEST_F(V4StoreTest, TestAddUnlumpedHashesWithEmptyString) { + HashPrefixMap prefix_map; + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(5, "", &prefix_map)); + EXPECT_TRUE(prefix_map[5].empty()); +} + +TEST_F(V4StoreTest, TestAddUnlumpedHashes) { + HashPrefixMap prefix_map; + PrefixSize prefix_size = 5; + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(prefix_size, "abcde5432100000-----", + &prefix_map)); + EXPECT_EQ(1u, prefix_map.size()); + HashPrefixes hash_prefixes = prefix_map.at(prefix_size); + EXPECT_EQ(4 * prefix_size, hash_prefixes.size()); + EXPECT_EQ("abcde5432100000-----", hash_prefixes); + + prefix_size = 4; + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(prefix_size, "abcde5432100000-----", + &prefix_map)); + EXPECT_EQ(2u, prefix_map.size()); + hash_prefixes = prefix_map.at(prefix_size); + EXPECT_EQ(5 * prefix_size, hash_prefixes.size()); + EXPECT_EQ("abcde5432100000-----", hash_prefixes); +} + +TEST_F(V4StoreTest, TestGetNextSmallestPrefixSizeWithEmptyPrefixMap) { + HashPrefixMap prefix_map; + CounterMap counter_map; + V4Store::InitializeCounterMap(prefix_map, &counter_map); + + PrefixSize prefix_size; + EXPECT_FALSE(V4Store::GetNextSmallestPrefixSize(prefix_map, counter_map, + &prefix_size)); +} + +TEST_F(V4StoreTest, TestGetNextSmallestPrefixSize) { + HashPrefixMap prefix_map; + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(5, "-----0000054321abcde", &prefix_map)); + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(4, "-----0000054321abcde", &prefix_map)); + CounterMap counter_map; + V4Store::InitializeCounterMap(prefix_map, &counter_map); + + PrefixSize prefix_size; + EXPECT_TRUE(V4Store::GetNextSmallestPrefixSize(prefix_map, counter_map, + &prefix_size)); + EXPECT_EQ(4u, prefix_size); +} + +TEST_F(V4StoreTest, TestGetNextUnmergedPrefix) { + HashPrefixMap prefix_map; + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(5, "-----0000054321abcde", &prefix_map)); + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(4, "-----0000054321abcde", &prefix_map)); + CounterMap counter_map; + V4Store::InitializeCounterMap(prefix_map, &counter_map); + + PrefixSize prefix_size; + EXPECT_TRUE(V4Store::GetNextSmallestPrefixSize(prefix_map, counter_map, + &prefix_size)); + const HashPrefix& prefix = V4Store::GetNextUnmergedPrefixForSize( + prefix_size, prefix_map, counter_map); + EXPECT_EQ("----", prefix); +} + +TEST_F(V4StoreTest, TestMergeUpdatesWithSameSizesInEachMap) { + HashPrefixMap prefix_map_old; + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(4, "abcdefgh", &prefix_map_old)); + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(5, "54321abcde", &prefix_map_old)); + HashPrefixMap prefix_map_additions; + EXPECT_EQ( + APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(4, "----1111bbbb", &prefix_map_additions)); + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(5, "22222bcdef", &prefix_map_additions)); + + std::unique_ptr<V4Store> store(new V4Store(task_runner_, store_path_)); + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + store->MergeUpdate(prefix_map_old, prefix_map_additions)); + const HashPrefixMap& prefix_map = store->hash_prefix_map_; + EXPECT_EQ(2u, prefix_map.size()); + + PrefixSize prefix_size = 4; + HashPrefixes hash_prefixes = prefix_map.at(prefix_size); + EXPECT_EQ(5 * prefix_size, hash_prefixes.size()); + EXPECT_EQ("----", hash_prefixes.substr(0 * prefix_size, prefix_size)); + EXPECT_EQ("1111", hash_prefixes.substr(1 * prefix_size, prefix_size)); + EXPECT_EQ("abcd", hash_prefixes.substr(2 * prefix_size, prefix_size)); + EXPECT_EQ("bbbb", hash_prefixes.substr(3 * prefix_size, prefix_size)); + EXPECT_EQ("efgh", hash_prefixes.substr(4 * prefix_size, prefix_size)); + + prefix_size = 5; + hash_prefixes = prefix_map.at(prefix_size); + EXPECT_EQ(4 * prefix_size, hash_prefixes.size()); + EXPECT_EQ("22222", hash_prefixes.substr(0 * prefix_size, prefix_size)); + EXPECT_EQ("54321", hash_prefixes.substr(1 * prefix_size, prefix_size)); + EXPECT_EQ("abcde", hash_prefixes.substr(2 * prefix_size, prefix_size)); + EXPECT_EQ("bcdef", hash_prefixes.substr(3 * prefix_size, prefix_size)); +} + +TEST_F(V4StoreTest, TestMergeUpdatesWithDifferentSizesInEachMap) { + HashPrefixMap prefix_map_old; + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(4, "1111abcdefgh", &prefix_map_old)); + HashPrefixMap prefix_map_additions; + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(5, "22222bcdef", &prefix_map_additions)); + + std::unique_ptr<V4Store> store(new V4Store(task_runner_, store_path_)); + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + store->MergeUpdate(prefix_map_old, prefix_map_additions)); + const HashPrefixMap& prefix_map = store->hash_prefix_map_; + EXPECT_EQ(2u, prefix_map.size()); + + PrefixSize prefix_size = 4; + HashPrefixes hash_prefixes = prefix_map.at(prefix_size); + EXPECT_EQ(3 * prefix_size, hash_prefixes.size()); + EXPECT_EQ("1111abcdefgh", hash_prefixes); + + prefix_size = 5; + hash_prefixes = prefix_map.at(prefix_size); + EXPECT_EQ(2 * prefix_size, hash_prefixes.size()); + EXPECT_EQ("22222bcdef", hash_prefixes); +} + +TEST_F(V4StoreTest, TestMergeUpdatesOldMapRunsOutFirst) { + HashPrefixMap prefix_map_old; + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(4, "00001111", &prefix_map_old)); + HashPrefixMap prefix_map_additions; + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(4, "2222", &prefix_map_additions)); + + std::unique_ptr<V4Store> store(new V4Store(task_runner_, store_path_)); + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + store->MergeUpdate(prefix_map_old, prefix_map_additions)); + const HashPrefixMap& prefix_map = store->hash_prefix_map_; + EXPECT_EQ(1u, prefix_map.size()); + + PrefixSize prefix_size = 4; + HashPrefixes hash_prefixes = prefix_map.at(prefix_size); + EXPECT_EQ(3 * prefix_size, hash_prefixes.size()); + EXPECT_EQ("0000", hash_prefixes.substr(0 * prefix_size, prefix_size)); + EXPECT_EQ("1111", hash_prefixes.substr(1 * prefix_size, prefix_size)); + EXPECT_EQ("2222", hash_prefixes.substr(2 * prefix_size, prefix_size)); +} + +TEST_F(V4StoreTest, TestMergeUpdatesAdditionsMapRunsOutFirst) { + HashPrefixMap prefix_map_old; + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(4, "2222", &prefix_map_old)); + HashPrefixMap prefix_map_additions; + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(4, "00001111", &prefix_map_additions)); + + std::unique_ptr<V4Store> store(new V4Store(task_runner_, store_path_)); + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + store->MergeUpdate(prefix_map_old, prefix_map_additions)); + const HashPrefixMap& prefix_map = store->hash_prefix_map_; + EXPECT_EQ(1u, prefix_map.size()); + + PrefixSize prefix_size = 4; + HashPrefixes hash_prefixes = prefix_map.at(prefix_size); + EXPECT_EQ(3 * prefix_size, hash_prefixes.size()); + EXPECT_EQ("0000", hash_prefixes.substr(0 * prefix_size, prefix_size)); + EXPECT_EQ("1111", hash_prefixes.substr(1 * prefix_size, prefix_size)); + EXPECT_EQ("2222", hash_prefixes.substr(2 * prefix_size, prefix_size)); +} + +TEST_F(V4StoreTest, TestMergeUpdatesFailsForRepeatedhashPrefix) { + HashPrefixMap prefix_map_old; + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(4, "2222", &prefix_map_old)); + HashPrefixMap prefix_map_additions; + EXPECT_EQ(APPLY_UPDATE_SUCCESS, + V4Store::AddUnlumpedHashes(4, "2222", &prefix_map_additions)); + + std::unique_ptr<V4Store> store(new V4Store(task_runner_, store_path_)); + EXPECT_EQ(ADDITIONS_HAS_EXISTING_PREFIX_FAILURE, + store->MergeUpdate(prefix_map_old, prefix_map_additions)); +} + } // namespace safe_browsing
diff --git a/components/subresource_filter.gypi b/components/subresource_filter.gypi index b864159..2e347cd 100644 --- a/components/subresource_filter.gypi +++ b/components/subresource_filter.gypi
@@ -72,6 +72,10 @@ 'subresource_filter/core/common/ngram_extractor.h', 'subresource_filter/core/common/string_splitter.h', 'subresource_filter/core/common/uint64_hasher.h', + 'subresource_filter/core/common/url_pattern.cc', + 'subresource_filter/core/common/url_pattern.h', + 'subresource_filter/core/common/url_pattern_matching.cc', + 'subresource_filter/core/common/url_pattern_matching.h', ], 'export_dependent_settings': [ 'subresource_filter_core_common_ruleset_flatbuffer',
diff --git a/components/subresource_filter/core/common/BUILD.gn b/components/subresource_filter/core/common/BUILD.gn index d8c3659..f8e2e787 100644 --- a/components/subresource_filter/core/common/BUILD.gn +++ b/components/subresource_filter/core/common/BUILD.gn
@@ -15,6 +15,10 @@ "ngram_extractor.h", "string_splitter.h", "uint64_hasher.h", + "url_pattern.cc", + "url_pattern.h", + "url_pattern_matching.cc", + "url_pattern_matching.h", ] public_deps = [ @@ -24,6 +28,7 @@ deps = [ "//base", + "//url:url", ] } @@ -35,10 +40,12 @@ "knuth_morris_pratt_unittest.cc", "ngram_extractor_unittest.cc", "string_splitter_unittest.cc", + "url_pattern_matching_unittest.cc", ] deps = [ ":common", "//base", "//testing/gtest", + "//url:url", ] }
diff --git a/components/subresource_filter/core/common/url_pattern.cc b/components/subresource_filter/core/common/url_pattern.cc new file mode 100644 index 0000000..1cfa663 --- /dev/null +++ b/components/subresource_filter/core/common/url_pattern.cc
@@ -0,0 +1,76 @@ +// 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 "components/subresource_filter/core/common/url_pattern.h" + +#include "components/subresource_filter/core/common/flat/rules_generated.h" + +namespace subresource_filter { + +namespace { + +proto::UrlPatternType ConvertUrlPatternType(flat::UrlPatternType type) { + switch (type) { + case flat::UrlPatternType_SUBSTRING: + return proto::URL_PATTERN_TYPE_SUBSTRING; + case flat::UrlPatternType_WILDCARDED: + return proto::URL_PATTERN_TYPE_WILDCARDED; + case flat::UrlPatternType_REGEXP: + return proto::URL_PATTERN_TYPE_REGEXP; + default: + return proto::URL_PATTERN_TYPE_UNSPECIFIED; + } +} + +proto::AnchorType ConvertAnchorType(flat::AnchorType type) { + switch (type) { + case flat::AnchorType_NONE: + return proto::ANCHOR_TYPE_NONE; + case flat::AnchorType_BOUNDARY: + return proto::ANCHOR_TYPE_BOUNDARY; + case flat::AnchorType_SUBDOMAIN: + return proto::ANCHOR_TYPE_SUBDOMAIN; + default: + return proto::ANCHOR_TYPE_UNSPECIFIED; + } +} + +base::StringPiece ConvertString(const flatbuffers::String* string) { + return string ? base::StringPiece(string->data(), string->size()) + : base::StringPiece(); +} + +} // namespace + +UrlPattern::UrlPattern() = default; + +UrlPattern::UrlPattern(base::StringPiece url_pattern, + proto::UrlPatternType type) + : type(type), url_pattern(url_pattern) {} + +UrlPattern::UrlPattern(base::StringPiece url_pattern, + proto::AnchorType anchor_left, + proto::AnchorType anchor_right) + : type(proto::URL_PATTERN_TYPE_WILDCARDED), + url_pattern(url_pattern), + anchor_left(anchor_left), + anchor_right(anchor_right) {} + +UrlPattern::UrlPattern(const flat::UrlRule& rule) + : type(ConvertUrlPatternType(rule.url_pattern_type())), + url_pattern(ConvertString(rule.url_pattern())), + anchor_left(ConvertAnchorType(rule.anchor_left())), + anchor_right(ConvertAnchorType(rule.anchor_right())), + match_case(!!(rule.options() & flat::OptionFlag_IS_MATCH_CASE)) {} + +UrlPattern::UrlPattern(const proto::UrlRule& rule) + : type(rule.url_pattern_type()), + url_pattern(rule.url_pattern()), + anchor_left(rule.anchor_left()), + anchor_right(rule.anchor_right()), + match_case(rule.match_case()) {} + +UrlPattern::~UrlPattern() = default; + +} // namespace subresource_filter
diff --git a/components/subresource_filter/core/common/url_pattern.h b/components/subresource_filter/core/common/url_pattern.h new file mode 100644 index 0000000..f49b5ea --- /dev/null +++ b/components/subresource_filter/core/common/url_pattern.h
@@ -0,0 +1,53 @@ +// 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 COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_URL_PATTERN_H_ +#define COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_URL_PATTERN_H_ + +#include "base/macros.h" +#include "base/strings/string_piece.h" +#include "components/subresource_filter/core/common/proto/rules.pb.h" + +namespace subresource_filter { + +namespace flat { +struct UrlRule; // The FlatBuffers version of UrlRule. +} + +// The structure used to mirror a URL pattern regardless of the representation +// of the UrlRule that owns it. +struct UrlPattern { + UrlPattern(); + + // Creates a |url_pattern| of a certain |type|. + UrlPattern(base::StringPiece url_pattern, + proto::UrlPatternType type = proto::URL_PATTERN_TYPE_WILDCARDED); + + // Creates a WILDCARDED |url_pattern| with the specified anchors. + UrlPattern(base::StringPiece url_pattern, + proto::AnchorType anchor_left, + proto::AnchorType anchor_right); + + // The following constructors create UrlPattern from one of the UrlRule + // representations. The passed in |rule| must outlive the created instance. + explicit UrlPattern(const flat::UrlRule& rule); + explicit UrlPattern(const proto::UrlRule& rule); + + ~UrlPattern(); + + proto::UrlPatternType type = proto::URL_PATTERN_TYPE_UNSPECIFIED; + base::StringPiece url_pattern; + + proto::AnchorType anchor_left = proto::ANCHOR_TYPE_NONE; + proto::AnchorType anchor_right = proto::ANCHOR_TYPE_NONE; + + bool match_case = false; + + private: + DISALLOW_COPY_AND_ASSIGN(UrlPattern); +}; + +} // namespace subresource_filter + +#endif // COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_URL_PATTERN_H_
diff --git a/components/subresource_filter/core/common/url_pattern_matching.cc b/components/subresource_filter/core/common/url_pattern_matching.cc new file mode 100644 index 0000000..91541c0 --- /dev/null +++ b/components/subresource_filter/core/common/url_pattern_matching.cc
@@ -0,0 +1,125 @@ +// 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 "components/subresource_filter/core/common/url_pattern_matching.h" + +#include "base/logging.h" +#include "components/subresource_filter/core/common/fuzzy_pattern_matching.h" +#include "components/subresource_filter/core/common/knuth_morris_pratt.h" +#include "components/subresource_filter/core/common/string_splitter.h" +#include "components/subresource_filter/core/common/url_pattern.h" + +namespace subresource_filter { + +namespace { + +bool IsWildcard(char c) { + return c == '*'; +} + +size_t FindFirstOccurrenceFuzzy(base::StringPiece text, + base::StringPiece subpattern, + const size_t* failure) { + return *AllOccurrencesFuzzy(text, subpattern, failure).begin(); +} + +} // namespace + +void BuildFailureFunction(const UrlPattern& pattern, + std::vector<size_t>* failure) { + auto subpatterns = CreateStringSplitter(pattern.url_pattern, IsWildcard); + auto subpattern_it = subpatterns.begin(); + auto subpattern_end = subpatterns.end(); + + if (subpattern_it == subpattern_end) + return; + if (pattern.anchor_left == proto::ANCHOR_TYPE_BOUNDARY) + ++subpattern_it; + + while (subpattern_it != subpattern_end) { + const base::StringPiece part = *subpattern_it++; + DCHECK(!part.empty()); + if (pattern.anchor_right == proto::ANCHOR_TYPE_BOUNDARY && + subpattern_it == subpattern_end) { + break; + } + + if (part.find(kSeparatorPlaceholder) == base::StringPiece::npos) { + BuildFailureFunction(part, failure); + } else { + // Prepend the value '1' to the failure function to let matchers + // distinguish between the subpatterns with separator placeholders and + // those without. + failure->push_back(1); + BuildFailureFunctionFuzzy(part, failure); + } + } +} + +// TODO(pkalinnikov): Support SUBDOMAIN anchors. +bool IsMatch(const GURL& url, + const UrlPattern& pattern, + const std::vector<size_t>& failure) { + auto subpatterns = CreateStringSplitter(pattern.url_pattern, IsWildcard); + auto subpattern_it = subpatterns.begin(); + auto subpattern_end = subpatterns.end(); + + if (subpattern_it == subpattern_end) { + return pattern.anchor_left != proto::ANCHOR_TYPE_BOUNDARY || + pattern.anchor_right != proto::ANCHOR_TYPE_BOUNDARY || + url.is_empty(); + } + + base::StringPiece spec = url.spec(); + + if (pattern.anchor_left == proto::ANCHOR_TYPE_BOUNDARY) { + const base::StringPiece subpattern = *subpattern_it++; + if (!StartsWithFuzzy(spec, subpattern)) + return false; + if (subpattern_it == subpattern_end) { + return pattern.anchor_right != proto::ANCHOR_TYPE_BOUNDARY || + spec.size() == subpattern.size(); + } + spec.remove_prefix(subpattern.size()); + } + + base::StringPiece subpattern; + auto failure_it = failure.begin(); + while (subpattern_it != subpattern_end) { + subpattern = *subpattern_it++; + DCHECK(!subpattern.empty()); + + if (subpattern_it == subpattern_end && + pattern.anchor_right == proto::ANCHOR_TYPE_BOUNDARY) { + break; + } + + // The subpatterns with separator placeholders were indexed differently and + // should be matched accordingly. Their failure functions were prepended by + // a non-zero value, and we need to skip it. If the value turned to be zero, + // it is the initial value of a failure function of a regular substring. + CHECK(failure_it < failure.end()); + const bool has_separator_placeholders = (*failure_it != 0); + if (has_separator_placeholders) + ++failure_it; + CHECK(failure_it + subpattern.size() <= failure.end()); + + // If the subpattern has separator placeholders, it should be matched with + // FindFirstOccurrenceOfSubpattern, otherwise it can be found as a regular + // substring. + const size_t match_end = + (has_separator_placeholders + ? FindFirstOccurrenceFuzzy(spec, subpattern, &*failure_it) + : FindFirstOccurrence(spec, subpattern, &*failure_it)); + if (match_end == base::StringPiece::npos) + return false; + spec.remove_prefix(match_end); + failure_it += subpattern.size(); + } + + return pattern.anchor_right != proto::ANCHOR_TYPE_BOUNDARY || + EndsWithFuzzy(spec, subpattern); +} + +} // namespace subresource_filter
diff --git a/components/subresource_filter/core/common/url_pattern_matching.h b/components/subresource_filter/core/common/url_pattern_matching.h new file mode 100644 index 0000000..74c6a3a --- /dev/null +++ b/components/subresource_filter/core/common/url_pattern_matching.h
@@ -0,0 +1,61 @@ +// 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. + +// The matching logic distinguishes between the terms URL pattern and +// subpattern. A URL pattern usually stands for the full thing, e.g. +// "example.com^*path*par=val^", whereas subpattern denotes a maximal substring +// of a pattern not containing the wildcard '*' character. For the example above +// the subpatterns are: "example.com^", "path" and "par=val^". +// +// The separator placeholder '^' symbol is used in subpatterns to match any +// separator character, which is any ASCII symbol except letters, digits, and +// the following: '_', '-', '.', '%'. Note that the separator placeholder +// character '^' is itself a separator, as well as '\0'. + +#ifndef COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_URL_PATTERN_MATCHING_H_ +#define COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_URL_PATTERN_MATCHING_H_ + +#include <stddef.h> + +#include <vector> + +#include "base/strings/string_piece.h" +#include "url/gurl.h" + +namespace subresource_filter { + +struct UrlPattern; + +// Builds a compound Knuth-Morris-Pratt failure function used to match URLs +// against the |pattern|. +// +// The |pattern| is split on the '*' wildcard symbol and then a failure function +// is built for each subpattern by BuildFailureFunctionFuzzy or +// BuildFailureFunction (depending on whether the subpattern contains separator +// placeholders), and appended to the returned vector. Some of the subpatterns +// can be exempted from being indexed. E.g., if the |pattern| has a BOUNDARY +// left anchor, the first subpattern can be matched by checking if it's a prefix +// of a URL. +// +// Each subpattern indexed with BuildFailureFunctionFuzzy is prepended with a +// value 1 (to distinguish them from the subpatterns indexed with +// BuildFailureFunction, their failure functions always start with 0). +// +// The URL |pattern| must be normalized. Namely, it must not have the following +// substrings: **, *<END>, <BEGIN>*. If the the |pattern| has a BOUNDARY anchor, +// the corresponding side of its string must not end with a '*' wildcard. +void BuildFailureFunction(const UrlPattern& pattern, + std::vector<size_t>* failure); + +// Returns whether the |url| matches the URL |pattern|. The |failure| function +// must be the output of BuildFailureFunction() called with the same |pattern|. +// +// TODO(pkalinnikov): Outline algorithms implemented in this function. +bool IsMatch(const GURL& url, + const UrlPattern& pattern, + const std::vector<size_t>& failure); + +} // namespace subresource_filter + +#endif // COMPONENTS_SUBRESOURCE_FILTER_CORE_COMMON_URL_PATTERN_MATCHING_H_
diff --git a/components/subresource_filter/core/common/url_pattern_matching_unittest.cc b/components/subresource_filter/core/common/url_pattern_matching_unittest.cc new file mode 100644 index 0000000..e87aa08 --- /dev/null +++ b/components/subresource_filter/core/common/url_pattern_matching_unittest.cc
@@ -0,0 +1,133 @@ +// 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 "components/subresource_filter/core/common/url_pattern_matching.h" + +#include <vector> + +#include "components/subresource_filter/core/common/url_pattern.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace subresource_filter { + +namespace { + +constexpr proto::AnchorType kAnchorNone = proto::ANCHOR_TYPE_NONE; +constexpr proto::AnchorType kBoundary = proto::ANCHOR_TYPE_BOUNDARY; +constexpr proto::AnchorType kSubdomain = proto::ANCHOR_TYPE_SUBDOMAIN; + +} // namespace + +TEST(UrlPatternMatchingTest, BuildFailureFunctionForUrlPattern) { + const struct { + UrlPattern url_pattern; + std::vector<size_t> expected_failure_function; + } kTestCases[] = { + {{"abcd", proto::URL_PATTERN_TYPE_SUBSTRING}, {0, 0, 0, 0}}, + {{"&a?a/"}, {0, 0, 0, 0, 0}}, + {{"^a?a/"}, {1, 0, 0, 1, 2, 3}}, + + {{"abc*abc", kBoundary, kAnchorNone}, {0, 0, 0}}, + {{"abc*aaa", kBoundary, kAnchorNone}, {0, 1, 2}}, + {{"aaa*abc", kBoundary, kAnchorNone}, {0, 0, 0}}, + + {{"abc*abc", kAnchorNone, kBoundary}, {0, 0, 0}}, + {{"abc*aaa", kAnchorNone, kBoundary}, {0, 0, 0}}, + {{"aaa*abc", kAnchorNone, kBoundary}, {0, 1, 2}}, + + {{"abc*cca", kSubdomain, kAnchorNone}, {0, 0, 0, 0, 1, 0}}, + {{"abc*cca", kBoundary, kAnchorNone}, {0, 1, 0}}, + {{"abc*cca"}, {0, 0, 0, 0, 1, 0}}, + + {{"abc*abacaba*cab"}, {0, 0, 0, 0, 0, 1, 0, 1, 2, 3, 0, 0, 0}}, + {{"aaa*a^d*^^b"}, {0, 1, 2, 1, 0, 0, 0, 1, 0, 1, 0}}, + {{"aaa*a^d*^^b", kAnchorNone, kBoundary}, {0, 1, 2, 1, 0, 0, 0}}, + {{"^^a*a^d*^^b", kBoundary, kAnchorNone}, {1, 0, 0, 0, 1, 0, 1, 0}}, + }; + + for (const auto& test_case : kTestCases) { + SCOPED_TRACE(testing::Message() + << "Pattern: " << test_case.url_pattern.url_pattern + << "; Anchors: " + << static_cast<int>(test_case.url_pattern.anchor_left) << ", " + << static_cast<int>(test_case.url_pattern.anchor_right)); + + std::vector<size_t> failure; + BuildFailureFunction(test_case.url_pattern, &failure); + EXPECT_EQ(test_case.expected_failure_function, failure); + } +} + +TEST(UrlPatternMatchingTest, IsMatch) { + const struct { + UrlPattern url_pattern; + const char* url; + bool expect_match; + } kTestCases[] = { + {{"xampl", proto::URL_PATTERN_TYPE_SUBSTRING}, + "http://example.com", + true}, + {{"example", proto::URL_PATTERN_TYPE_SUBSTRING}, + "http://example.com", + true}, + {{"/a?a"}, "http://ex.com/a?a", true}, + {{"^abc"}, "http://ex.com/abc?a", true}, + {{"^abc"}, "http://ex.com/a?abc", true}, + {{"^abc"}, "http://ex.com/abc?abc", true}, + + {{"http://ex", kBoundary, kAnchorNone}, "http://example.com", true}, + {{"mple.com/", kAnchorNone, kBoundary}, "http://example.com", true}, + + // Note: "example.com" will be normalized into "example.com/". + {{"http://*mpl", kBoundary, kAnchorNone}, "http://example.com", true}, + {{"mpl*com/", kAnchorNone, kBoundary}, "http://example.com", true}, + {{"example^com"}, "http://example.com", false}, + {{"example^com"}, "http://example/com", true}, + {{"example.com^"}, "http://example.com:8080", true}, + {{"http*.com/", kBoundary, kBoundary}, "http://example.com", true}, + {{"http*.org/", kBoundary, kBoundary}, "http://example.com", false}, + + {{"/path?*&p1=*&p2="}, "http://ex.com/aaa/path/bbb?k=v&p1=0&p2=1", false}, + {{"/path?*&p1=*&p2="}, "http://ex.com/aaa/path?k=v&p1=0&p2=1", true}, + {{"/path?*&p1=*&p2="}, "http://ex.com/aaa/path?k=v&k=v&p1=0&p2=1", true}, + {{"/path?*&p1=*&p2="}, + "http://ex.com/aaa/path?k=v&p1=0&p3=10&p2=1", + true}, + {{"/path?*&p1=*&p2="}, "http://ex.com/aaa/path&p1=0&p2=1", false}, + {{"/path?*&p1=*&p2="}, "http://ex.com/aaa/path?k=v&p2=0&p1=1", false}, + + {{"abc*def*ghijk*xyz"}, + "http://example.com/abcdeffffghijkmmmxyzzz", + true}, + {{"abc*cdef"}, "http://example.com/abcdef", false}, + + {{"^^a^^"}, "http://ex.com/?a=/", true}, + {{"^^a^^"}, "http://ex.com/?a=/&b=0", true}, + {{"^^a^^"}, "http://ex.com/?a=", false}, + + {{"ex.com^path^*k=v^"}, "http://ex.com/path/?k1=v1&ak=v&kk=vv", true}, + {{"ex.com^path^*k=v^"}, "http://ex.com/p/path/?k1=v1&ak=v&kk=vv", false}, + {{"a^a&a^a&"}, "http://ex.com/a/a/a/a/?a&a&a&a&a", true}, + + {{"abc*def^"}, "http://ex.com/abc/a/ddef/", true}, + }; + + for (const auto& test_case : kTestCases) { + SCOPED_TRACE(testing::Message() + << "Rule: " << test_case.url_pattern.url_pattern + << "; Anchors: " + << static_cast<int>(test_case.url_pattern.anchor_left) << ", " + << static_cast<int>(test_case.url_pattern.anchor_right) + << "; URL: " << GURL(test_case.url)); + + std::vector<size_t> failure; + BuildFailureFunction(test_case.url_pattern, &failure); + const bool is_match = + IsMatch(GURL(test_case.url), test_case.url_pattern, failure); + EXPECT_EQ(test_case.expect_match, is_match); + } +} + +} // namespace subresource_filter
diff --git a/components/test/data/password_manager/login_db_v16.sql b/components/test/data/password_manager/login_db_v16.sql index e52bd253..9cd7455 100644 --- a/components/test/data/password_manager/login_db_v16.sql +++ b/components/test/data/password_manager/login_db_v16.sql
@@ -2,7 +2,7 @@ BEGIN TRANSACTION; CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); INSERT INTO "meta" VALUES('last_compatible_version','14'); -INSERT INTO "meta" VALUES('version','15'); +INSERT INTO "meta" VALUES('version','16'); CREATE TABLE logins ( origin_url VARCHAR NOT NULL, action_url VARCHAR,
diff --git a/components/test/data/password_manager/login_db_v17.sql b/components/test/data/password_manager/login_db_v17.sql index 471f24d6..0823367 100644 --- a/components/test/data/password_manager/login_db_v17.sql +++ b/components/test/data/password_manager/login_db_v17.sql
@@ -2,7 +2,7 @@ BEGIN TRANSACTION; CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); INSERT INTO "meta" VALUES('last_compatible_version','14'); -INSERT INTO "meta" VALUES('version','15'); +INSERT INTO "meta" VALUES('version','17'); CREATE TABLE logins ( origin_url VARCHAR NOT NULL, action_url VARCHAR,
diff --git a/components/test_runner/test_runner.cc b/components/test_runner/test_runner.cc index 3c6fa3c..a410ad4 100644 --- a/components/test_runner/test_runner.cc +++ b/components/test_runner/test_runner.cc
@@ -843,45 +843,45 @@ if (!runner_) return; - bool has_acceleration_x; - double acceleration_x; - bool has_acceleration_y; - double acceleration_y; - bool has_acceleration_z; - double acceleration_z; - bool has_acceleration_including_gravity_x; - double acceleration_including_gravity_x; - bool has_acceleration_including_gravity_y; - double acceleration_including_gravity_y; - bool has_acceleration_including_gravity_z; - double acceleration_including_gravity_z; - bool has_rotation_rate_alpha; - double rotation_rate_alpha; - bool has_rotation_rate_beta; - double rotation_rate_beta; - bool has_rotation_rate_gamma; - double rotation_rate_gamma; - double interval; + bool has_acceleration_x = false; + double acceleration_x = 0.0; + bool has_acceleration_y = false; + double acceleration_y = 0.0; + bool has_acceleration_z = false; + double acceleration_z = 0.0; + bool has_acceleration_including_gravity_x = false; + double acceleration_including_gravity_x = 0.0; + bool has_acceleration_including_gravity_y = false; + double acceleration_including_gravity_y = 0.0; + bool has_acceleration_including_gravity_z = false; + double acceleration_including_gravity_z = 0.0; + bool has_rotation_rate_alpha = false; + double rotation_rate_alpha = 0.0; + bool has_rotation_rate_beta = false; + double rotation_rate_beta = 0.0; + bool has_rotation_rate_gamma = false; + double rotation_rate_gamma = 0.0; + double interval = false; args->GetNext(&has_acceleration_x); - args->GetNext(& acceleration_x); + args->GetNext(&acceleration_x); args->GetNext(&has_acceleration_y); - args->GetNext(& acceleration_y); + args->GetNext(&acceleration_y); args->GetNext(&has_acceleration_z); - args->GetNext(& acceleration_z); + args->GetNext(&acceleration_z); args->GetNext(&has_acceleration_including_gravity_x); - args->GetNext(& acceleration_including_gravity_x); + args->GetNext(&acceleration_including_gravity_x); args->GetNext(&has_acceleration_including_gravity_y); - args->GetNext(& acceleration_including_gravity_y); + args->GetNext(&acceleration_including_gravity_y); args->GetNext(&has_acceleration_including_gravity_z); - args->GetNext(& acceleration_including_gravity_z); + args->GetNext(&acceleration_including_gravity_z); args->GetNext(&has_rotation_rate_alpha); - args->GetNext(& rotation_rate_alpha); + args->GetNext(&rotation_rate_alpha); args->GetNext(&has_rotation_rate_beta); - args->GetNext(& rotation_rate_beta); + args->GetNext(&rotation_rate_beta); args->GetNext(&has_rotation_rate_gamma); - args->GetNext(& rotation_rate_gamma); - args->GetNext(& interval); + args->GetNext(&rotation_rate_gamma); + args->GetNext(&interval); runner_->SetMockDeviceMotion(has_acceleration_x, acceleration_x, has_acceleration_y, acceleration_y,
diff --git a/components/test_runner/test_runner_for_specific_view.h b/components/test_runner/test_runner_for_specific_view.h index 06c245c..e0c6d5e 100644 --- a/components/test_runner/test_runner_for_specific_view.h +++ b/components/test_runner/test_runner_for_specific_view.h
@@ -171,8 +171,7 @@ // Dump current PageImportanceSignals for the page. void DumpPageImportanceSignals(); - // WebPageOverlay related functions. Permits the adding and removing of only - // one opaque overlay. + // Permits the adding and removing of only one opaque overlay. void AddWebPageOverlay(); void RemoveWebPageOverlay();
diff --git a/components/tools/metrics/browser_components_metrics.py b/components/tools/metrics/browser_components_metrics.py deleted file mode 100755 index c1f5b4b0..0000000 --- a/components/tools/metrics/browser_components_metrics.py +++ /dev/null
@@ -1,65 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 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. - -"""Generates the metrics collected weekly for the Browser Components project. - -See -http://www.chromium.org/developers/design-documents/browser-components -for details. -""" - -import os -import sys - - -# This is done so that we can import checkdeps. If not invoked as -# main, our user must ensure it is in PYTHONPATH. -if __name__ == '__main__': - sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', - 'buildtools', 'checkdeps')) - - -import count_ifdefs -import checkdeps -import results - - -# Preprocessor pattern to find OS_XYZ defines. -PREPROCESSOR_PATTERN = 'OS_[A-Z]+' - - -class BrowserComponentsMetricsGenerator(object): - def __init__(self, checkout_root): - self.checkout_root = checkout_root - self.chrome_browser = os.path.join(checkout_root, 'chrome', 'browser') - - def CountIfdefs(self, skip_tests): - return count_ifdefs.CountIfdefs( - PREPROCESSOR_PATTERN, self.chrome_browser, skip_tests) - - def CountViolations(self, skip_tests): - deps_checker = checkdeps.DepsChecker(self.checkout_root, - ignore_temp_rules=True, - skip_tests=skip_tests) - deps_checker.results_formatter = results.CountViolationsFormatter() - deps_checker.CheckDirectory(os.path.join('chrome', 'browser')) - return int(deps_checker.results_formatter.GetResults()) - - -def main(): - generator = BrowserComponentsMetricsGenerator( - os.path.join(os.path.dirname(__file__), '..', '..', '..')) - - print "All metrics are for chrome/browser.\n" - print "OS ifdefs, all: %d" % generator.CountIfdefs(False) - print "OS ifdefs, -tests: %d" % generator.CountIfdefs(True) - print ("Intended DEPS violations, all: %d" % - generator.CountViolations(False)) - print "Intended DEPS violations, -tests: %d" % generator.CountViolations(True) - return 0 - - -if __name__ == '__main__': - sys.exit(main())
diff --git a/components/tools/metrics/count_ifdefs.py b/components/tools/metrics/count_ifdefs.py deleted file mode 100755 index 2e3c2ad..0000000 --- a/components/tools/metrics/count_ifdefs.py +++ /dev/null
@@ -1,77 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 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. - -"""Counts the number of #if or #ifdef lines containing at least one -preprocessor token that is a full match for the given pattern, in the -given directory. -""" - - -import optparse -import os -import re -import sys - - -# Filename extensions we know will be handled by the C preprocessor. -# We ignore files not matching these. -CPP_EXTENSIONS = [ - '.h', - '.cc', - '.m', - '.mm', -] - - -def _IsTestFile(filename): - """Does a rudimentary check to try to skip test files; this could be - improved but is good enough for basic metrics generation. - """ - return re.match('(test|mock|dummy)_.*|.*_[a-z]*test\.(h|cc|mm)', filename) - - -def CountIfdefs(token_pattern, directory, skip_tests=False): - """Returns the number of lines in files in |directory| and its - subdirectories that have an extension from |CPP_EXTENSIONS| and are - an #if or #ifdef line with a preprocessor token fully matching - the string |token_pattern|. - - If |skip_tests| is true, a best effort is made to ignore test files. - """ - token_line_re = re.compile(r'^#if(def)?.*\b(%s)\b.*$' % token_pattern) - count = 0 - for root, dirs, files in os.walk(directory): - for filename in files: - if os.path.splitext(filename)[1] in CPP_EXTENSIONS: - if not skip_tests or not _IsTestFile(filename): - with open(os.path.join(root, filename)) as f: - for line in f: - line = line.strip() - if token_line_re.match(line): - count += 1 - return count - - -def PrintUsage(): - print "Usage: %s [--skip-tests] TOKEN_PATTERN DIRECTORY" % sys.argv[0] - - -def main(): - option_parser = optparse.OptionParser() - option_parser.add_option('', '--skip-tests', action='store_true', - dest='skip_tests', default=False, - help='Skip test files.') - options, args = option_parser.parse_args() - - if len(args) < 2: - PrintUsage() - return 1 - else: - print CountIfdefs(args[0], args[1], options.skip_tests) - return 0 - - -if __name__ == '__main__': - sys.exit(main())
diff --git a/components/tools/metrics/count_ifdefs_unittest.py b/components/tools/metrics/count_ifdefs_unittest.py deleted file mode 100755 index 9b8c322..0000000 --- a/components/tools/metrics/count_ifdefs_unittest.py +++ /dev/null
@@ -1,30 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 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. - -"""Tests for count_ifdefs. -""" - -import os -import unittest - -import count_ifdefs - - -class CountIfdefsTest(unittest.TestCase): - - def setUp(self): - self.root = os.path.join(os.path.dirname(__file__), 'testdata') - - def testNormal(self): - count = count_ifdefs.CountIfdefs('OS_[A-Z]+', self.root) - self.failUnless(count == 6) - - def testSkipTests(self): - count = count_ifdefs.CountIfdefs('OS_[A-Z]+', self.root, True) - self.failUnless(count == 4) - - -if __name__ == '__main__': - unittest.main()
diff --git a/components/tools/metrics/testdata/foo.cc b/components/tools/metrics/testdata/foo.cc deleted file mode 100644 index bd3d3c71..0000000 --- a/components/tools/metrics/testdata/foo.cc +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright (c) 2012 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. - -// Should not match -#ifndef FOO_OS_ANDROID_BLAT -#define FOO_OS_ANDROID_BLAT - -#if defined(OS_ANDROID) - -#if defined(OS_ANDROID) || defined(OS_IOS) || defined(OS_CHROMEOS) - -#if !defined(OS_CAT) - -#if defined(OS_WIN) - -#endif // !OS_ANDROID && !OS_IOS -#endif // OS_CAT - -#endif // FOO_OS_ANDROID_BLAT
diff --git a/components/tools/metrics/testdata/foo_ignored.txt b/components/tools/metrics/testdata/foo_ignored.txt deleted file mode 100644 index 2b186f93..0000000 --- a/components/tools/metrics/testdata/foo_ignored.txt +++ /dev/null
@@ -1,4 +0,0 @@ -#if defined(OS_ANDROID) - -#if defined(OS_WIN) -
diff --git a/components/tools/metrics/testdata/subdir/foo_test.mm b/components/tools/metrics/testdata/subdir/foo_test.mm deleted file mode 100644 index adf1f891..0000000 --- a/components/tools/metrics/testdata/subdir/foo_test.mm +++ /dev/null
@@ -1,8 +0,0 @@ -// Copyright (c) 2011 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(OS_ANDROID) - -#if defined(OS_WIN) -
diff --git a/components/tracing.gyp b/components/tracing.gyp index 1e6a230..f742bace 100644 --- a/components/tracing.gyp +++ b/components/tracing.gyp
@@ -57,5 +57,41 @@ }], ] }, + { + 'target_name': 'proto_zero_plugin', + 'type': 'executable', + 'toolsets': ['host'], + 'sources': [ + 'tracing/tools/proto_zero_plugin/proto_zero_generator.cc', + 'tracing/tools/proto_zero_plugin/proto_zero_generator.h', + 'tracing/tools/proto_zero_plugin/proto_zero_plugin.cc', + ], + 'include_dirs': [ + '..', + '../third_party/protobuf/src', + ], + 'dependencies': [ + '../third_party/protobuf/protobuf.gyp:protoc_lib', + ], + }, + { + 'target_name': 'proto_zero_testing_messages', + 'type': 'static_library', + 'variables': { + 'proto_in_dir': 'tracing/test', + 'proto_out_dir': 'components/tracing/test', + 'generator_plugin': 'proto_zero_plugin', + 'generator_plugin_suffix': '.pbzero', + 'generate_cc': 0, + 'generate_python': 0, + }, + 'sources': [ + 'tracing/test/example_messages.proto', + ], + 'dependencies': [ + 'proto_zero_plugin#host', + ], + 'includes': ['../build/protoc.gypi'], + }, ], }
diff --git a/components/tracing/BUILD.gn b/components/tracing/BUILD.gn index 9376463a..8f066a5 100644 --- a/components/tracing/BUILD.gn +++ b/components/tracing/BUILD.gn
@@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//third_party/protobuf/proto_library.gni") + component("tracing") { sources = [ "child/child_memory_dump_manager_delegate_impl.cc", @@ -52,6 +54,38 @@ ] } +# For unit testing of generated stubs. +proto_library("proto_zero_testing_messages") { + visibility = [ "//components/tracing/*" ] + + sources = [ + "test/example_messages.proto", + ] + + generator_plugin_label = "tools/proto_zero_plugin:proto_zero_plugin" + generator_plugin_suffix = ".pbzero" + generate_cc = false + generate_python = false + + # TODO(kraynov) Move away this complex path evaluation and dependency + # injection to proto_library.gni. All lines below should be removed. + # The problem is that root_out_dir and root_build_dir may differ in case of + # cross compilation. Also .exe will be appended on Windows. + + plugin_host_label = generator_plugin_label + "($host_toolchain)" + generator_plugin = + rebase_path(get_label_info(plugin_host_label, "root_out_dir") + "/" + + get_label_info(plugin_host_label, "name"), + root_build_dir) + if (is_win) { + generator_plugin += ".exe" + } + + deps = [ + plugin_host_label, + ] +} + source_set("unit_tests") { testonly = true @@ -62,9 +96,12 @@ "core/proto_utils_unittest.cc", "core/scattered_stream_writer_unittest.cc", "core/trace_ring_buffer_unittest.cc", + "test/fake_scattered_buffer.cc", + "test/proto_zero_generation_unittest.cc", ] deps = [ + ":proto_zero_testing_messages", ":tracing", "//base/test:test_support", "//ipc",
diff --git a/components/tracing/core/scattered_stream_writer_unittest.cc b/components/tracing/core/scattered_stream_writer_unittest.cc index 7cb52ac5..0ce18241 100644 --- a/components/tracing/core/scattered_stream_writer_unittest.cc +++ b/components/tracing/core/scattered_stream_writer_unittest.cc
@@ -7,36 +7,18 @@ #include <string.h> #include <memory> -#include <vector> -#include "base/strings/string_number_conversions.h" +#include "components/tracing/test/fake_scattered_buffer.h" #include "testing/gtest/include/gtest/gtest.h" namespace tracing { namespace v2 { namespace { -class MockDelegate : public ScatteredStreamWriter::Delegate { - public: - static const size_t kChunkSize = 8; - - ContiguousMemoryRange GetNewBuffer() override { - std::unique_ptr<uint8_t[]> chunk(new uint8_t[kChunkSize]); - uint8_t* begin = chunk.get(); - memset(begin, 0, kChunkSize); - chunks.push_back(std::move(chunk)); - return {begin, begin + kChunkSize}; - } - - std::string GetChunkAsString(int chunk_index) { - return base::HexEncode(chunks[chunk_index].get(), kChunkSize); - } - - std::vector<std::unique_ptr<uint8_t[]>> chunks; -}; +const size_t kChunkSize = 8; TEST(ScatteredStreamWriterTest, ScatteredWrites) { - MockDelegate delegate; + FakeScatteredBuffer delegate(kChunkSize); ScatteredStreamWriter ssw(&delegate); const uint8_t kOneByteBuf[] = {0x40}; @@ -47,38 +29,38 @@ kTwentyByteBuf[i] = 0xA0 + i; // Writing up to the chunk size should cause only the initial extension. - for (uint8_t i = 0; i < MockDelegate::kChunkSize; ++i) { + for (uint8_t i = 0; i < kChunkSize; ++i) { ssw.WriteByte(i); - EXPECT_EQ(MockDelegate::kChunkSize - i - 1, ssw.bytes_available()); + EXPECT_EQ(kChunkSize - i - 1, ssw.bytes_available()); } - EXPECT_EQ(1u, delegate.chunks.size()); + EXPECT_EQ(1u, delegate.chunks().size()); EXPECT_EQ(0u, ssw.bytes_available()); // This extra write will cause the first extension. ssw.WriteBytes(kOneByteBuf, sizeof(kOneByteBuf)); - EXPECT_EQ(2u, delegate.chunks.size()); + EXPECT_EQ(2u, delegate.chunks().size()); EXPECT_EQ(7u, ssw.bytes_available()); // This starts at offset 1, to make sure we don't hardcode any assumption // about alignment. ContiguousMemoryRange reserved_range_1 = ssw.ReserveBytes(4); - EXPECT_EQ(2u, delegate.chunks.size()); + EXPECT_EQ(2u, delegate.chunks().size()); EXPECT_EQ(3u, ssw.bytes_available()); ssw.WriteByte(0xFF); ssw.WriteBytes(kThreeByteBuf, sizeof(kThreeByteBuf)); - EXPECT_EQ(3u, delegate.chunks.size()); + EXPECT_EQ(3u, delegate.chunks().size()); EXPECT_EQ(7u, ssw.bytes_available()); ContiguousMemoryRange reserved_range_2 = ssw.ReserveBytes(4); ssw.WriteBytes(kTwentyByteBuf, sizeof(kTwentyByteBuf)); - EXPECT_EQ(6u, delegate.chunks.size()); + EXPECT_EQ(6u, delegate.chunks().size()); EXPECT_EQ(7u, ssw.bytes_available()); // Writing reserved bytes should not change the bytes_available(). memcpy(reserved_range_1.begin, kFourByteBuf, sizeof(kFourByteBuf)); memcpy(reserved_range_2.begin, kFourByteBuf, sizeof(kFourByteBuf)); - EXPECT_EQ(6u, delegate.chunks.size()); + EXPECT_EQ(6u, delegate.chunks().size()); EXPECT_EQ(7u, ssw.bytes_available()); // Check that reserving more bytes than what left creates a brand new chunk @@ -86,7 +68,7 @@ for (uint8_t i = 0; i < 5; ++i) ssw.WriteByte(0xFF); memcpy(ssw.ReserveBytes(4).begin, kFourByteBuf, sizeof(kFourByteBuf)); - EXPECT_EQ(7u, delegate.chunks.size()); + EXPECT_EQ(7u, delegate.chunks().size()); EXPECT_EQ(4u, ssw.bytes_available()); EXPECT_EQ("0001020304050607", delegate.GetChunkAsString(0));
diff --git a/components/tracing/test/example_messages.proto b/components/tracing/test/example_messages.proto new file mode 100644 index 0000000..ad2054c0 --- /dev/null +++ b/components/tracing/test/example_messages.proto
@@ -0,0 +1,11 @@ +// 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. + +syntax = "proto2"; +package foo.bar; + +// This file contains comprehensive set of supported message structures and +// data types. Unit tests depends on the plugin-processed version of this file. + +// TODO(kraynov) Populate in the next CL.
diff --git a/components/tracing/test/fake_scattered_buffer.cc b/components/tracing/test/fake_scattered_buffer.cc new file mode 100644 index 0000000..18e16e7 --- /dev/null +++ b/components/tracing/test/fake_scattered_buffer.cc
@@ -0,0 +1,48 @@ +// 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 "components/tracing/test/fake_scattered_buffer.h" + +#include <string.h> + +#include "base/strings/string_number_conversions.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace tracing { +namespace v2 { + +FakeScatteredBuffer::FakeScatteredBuffer(size_t chunk_size) + : chunk_size_(chunk_size) {} + +FakeScatteredBuffer::~FakeScatteredBuffer() {} + +ContiguousMemoryRange FakeScatteredBuffer::GetNewBuffer() { + std::unique_ptr<uint8_t[]> chunk(new uint8_t[chunk_size_]); + uint8_t* begin = chunk.get(); + memset(begin, 0, chunk_size_); + chunks_.push_back(std::move(chunk)); + return {begin, begin + chunk_size_}; +} + +std::string FakeScatteredBuffer::GetChunkAsString(int chunk_index) { + return base::HexEncode(chunks_[chunk_index].get(), chunk_size_); +} + +std::string FakeScatteredBuffer::GetBytesAsString(size_t start, size_t length) { + std::string hexstr; + EXPECT_LE(start + length, chunks_.size() * chunk_size_); + for (size_t pos = start; pos < start + length; ++pos) { + const size_t chunk_idx = pos / chunk_size_; + const size_t chunk_off = pos % chunk_size_; + if (chunk_idx >= chunks_.size()) { + hexstr += " <OUT OF BOUND @ pos=" + base::SizeTToString(pos) + ">"; + return hexstr; + } + hexstr += base::HexEncode(&chunks_[chunk_idx].get()[chunk_off], 1); + } + return hexstr; +} + +} // namespace v2 +} // namespace tracing
diff --git a/components/tracing/test/fake_scattered_buffer.h b/components/tracing/test/fake_scattered_buffer.h new file mode 100644 index 0000000..5089765 --- /dev/null +++ b/components/tracing/test/fake_scattered_buffer.h
@@ -0,0 +1,47 @@ +// 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 COMPONENTS_TRACING_TEST_FAKE_SCATTERED_BUFFER_H_ +#define COMPONENTS_TRACING_TEST_FAKE_SCATTERED_BUFFER_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "base/macros.h" +#include "components/tracing/core/scattered_stream_writer.h" +#include "components/tracing/tracing_export.h" + +namespace tracing { +namespace v2 { + +// A simple ScatteredStreamWriter::Delegate implementation which just allocates +// chunks of a fixed size. +class FakeScatteredBuffer : public ScatteredStreamWriter::Delegate { + public: + explicit FakeScatteredBuffer(size_t chunk_size); + ~FakeScatteredBuffer(); + + // ScatteredStreamWriter::Delegate implementation. + ContiguousMemoryRange GetNewBuffer() override; + + std::string GetChunkAsString(int chunk_index); + + std::string GetBytesAsString(size_t start, size_t length); + + const std::vector<std::unique_ptr<uint8_t[]>>& chunks() const { + return chunks_; + } + + private: + const size_t chunk_size_; + std::vector<std::unique_ptr<uint8_t[]>> chunks_; + + DISALLOW_COPY_AND_ASSIGN(FakeScatteredBuffer); +}; + +} // namespace v2 +} // namespace tracing + +#endif // COMPONENTS_TRACING_TEST_FAKE_SCATTERED_BUFFER_H_
diff --git a/components/tracing/test/proto_zero_generation_unittest.cc b/components/tracing/test/proto_zero_generation_unittest.cc new file mode 100644 index 0000000..31fb8ea --- /dev/null +++ b/components/tracing/test/proto_zero_generation_unittest.cc
@@ -0,0 +1,16 @@ +// 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 "components/tracing/test/example_messages.pbzero.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace tracing { +namespace proto { + +TEST(ProtoZeroTest, Simple) { + // TODO(kraynov) Put tests in the next CL (crbug.com/608721). +} + +} // namespace proto +} // namespace tracing
diff --git a/components/tracing/tools/proto_zero_plugin/BUILD.gn b/components/tracing/tools/proto_zero_plugin/BUILD.gn new file mode 100644 index 0000000..cdf0eb1 --- /dev/null +++ b/components/tracing/tools/proto_zero_plugin/BUILD.gn
@@ -0,0 +1,16 @@ +# 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. + +if (current_toolchain == host_toolchain) { + executable("proto_zero_plugin") { + sources = [ + "proto_zero_generator.cc", + "proto_zero_generator.h", + "proto_zero_plugin.cc", + ] + deps = [ + "//third_party/protobuf:protoc_lib", + ] + } +}
diff --git a/components/tracing/tools/proto_zero_plugin/DEPS b/components/tracing/tools/proto_zero_plugin/DEPS new file mode 100644 index 0000000..97db67c --- /dev/null +++ b/components/tracing/tools/proto_zero_plugin/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+third_party/protobuf", +]
diff --git a/components/tracing/tools/proto_zero_plugin/proto_zero_generator.cc b/components/tracing/tools/proto_zero_plugin/proto_zero_generator.cc new file mode 100644 index 0000000..28fc997 --- /dev/null +++ b/components/tracing/tools/proto_zero_plugin/proto_zero_generator.cc
@@ -0,0 +1,103 @@ +// 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 "proto_zero_generator.h" + +#include <memory> +#include <string> + +#include "third_party/protobuf/src/google/protobuf/descriptor.h" +#include "third_party/protobuf/src/google/protobuf/io/printer.h" +#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream.h" +#include "third_party/protobuf/src/google/protobuf/stubs/strutil.h" + +namespace tracing { +namespace proto { + +using google::protobuf::FileDescriptor; +using google::protobuf::StripSuffixString; +using google::protobuf::compiler::GeneratorContext; +using google::protobuf::io::Printer; +using google::protobuf::io::ZeroCopyOutputStream; + +namespace { + +class GeneratorJob { + public: + GeneratorJob(const FileDescriptor *file, + Printer* stub_h_printer, + Printer* stub_cc_printer) + : file_(file), + stub_h_(stub_h_printer), + stub_cc_(stub_cc_printer) {} + + bool GenerateStubs() { + stub_h_->Print( + "// Autogenerated. DO NOT EDIT.\n" + "// Generated by: //components/tracing/proto_zero_plugin.\n\n" + "// Package: $package$\n", + "package", file_->package()); + stub_cc_->Print( + "// Autogenerated. DO NOT EDIT.\n" + "// Generated by: //components/tracing/proto_zero_plugin.\n\n" + "// This file intentionally left blank.\n"); + // TODO(kraynov) Implement in the next CL (crbug.com/608721). + return true; + } + + // If generator fails to produce stubs for a particular proto definitions + // it finishes with undefined output and writes the first error occured. + const std::string& GetFirstError() const { + return error_; + } + + private: + // Only the first error will be recorded. + void Abort(const std::string& reason) { + if (error_.empty()) { + error_ = reason; + } + } + + const FileDescriptor* const file_; + Printer* const stub_h_; + Printer* const stub_cc_; + std::string error_; +}; + +} // namespace + +ProtoZeroGenerator::ProtoZeroGenerator() { +} + +ProtoZeroGenerator::~ProtoZeroGenerator() { +} + +bool ProtoZeroGenerator::Generate(const FileDescriptor* file, + const std::string& options, + GeneratorContext* context, + std::string* error) const { + + const std::string proto_stubs_name = + StripSuffixString(file->name(), ".proto") + ".pbzero"; + + const std::unique_ptr<ZeroCopyOutputStream> stub_h_file_stream( + context->Open(proto_stubs_name + ".h")); + const std::unique_ptr<ZeroCopyOutputStream> stub_cc_file_stream( + context->Open(proto_stubs_name + ".cc")); + + // Variables are delimited by $. + Printer stub_h_printer(stub_h_file_stream.get(), '$'); + Printer stub_cc_printer(stub_cc_file_stream.get(), '$'); + + GeneratorJob job(file, &stub_h_printer, &stub_cc_printer); + if (!job.GenerateStubs()) { + *error = job.GetFirstError(); + return false; + } + return true; +} + +} // namespace proto +} // namespace tracing
diff --git a/components/tracing/tools/proto_zero_plugin/proto_zero_generator.h b/components/tracing/tools/proto_zero_plugin/proto_zero_generator.h new file mode 100644 index 0000000..6bdaf1e4 --- /dev/null +++ b/components/tracing/tools/proto_zero_plugin/proto_zero_generator.h
@@ -0,0 +1,30 @@ +// 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 COMPONENTS_TRACING_PROTO_ZERO_PLUGIN_PROTO_ZERO_GENERATOR_H_ +#define COMPONENTS_TRACING_PROTO_ZERO_PLUGIN_PROTO_ZERO_GENERATOR_H_ + +#include <string> + +#include "third_party/protobuf/src/google/protobuf/compiler/code_generator.h" + +namespace tracing { +namespace proto { + +class ProtoZeroGenerator : public google::protobuf::compiler::CodeGenerator { + public: + explicit ProtoZeroGenerator(); + ~ProtoZeroGenerator() override; + + // CodeGenerator implementation + bool Generate(const google::protobuf::FileDescriptor* file, + const std::string& options, + google::protobuf::compiler::GeneratorContext* context, + std::string* error) const override; +}; + +} // namesapce proto +} // namespace tracing + +#endif // COMPONENTS_TRACING_PROTO_ZERO_PLUGIN_PROTO_ZERO_GENERATOR_H_
diff --git a/components/tracing/tools/proto_zero_plugin/proto_zero_plugin.cc b/components/tracing/tools/proto_zero_plugin/proto_zero_plugin.cc new file mode 100644 index 0000000..5ed63a82 --- /dev/null +++ b/components/tracing/tools/proto_zero_plugin/proto_zero_plugin.cc
@@ -0,0 +1,12 @@ +// 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 "third_party/protobuf/src/google/protobuf/compiler/plugin.h" + +#include "proto_zero_generator.h" + +int main(int argc, char* argv[]) { + tracing::proto::ProtoZeroGenerator generator; + return google::protobuf::compiler::PluginMain(argc, argv, &generator); +}
diff --git a/components/translate/core/browser/options_menu_model.cc b/components/translate/core/browser/options_menu_model.cc index d369f63..f56ddb0 100644 --- a/components/translate/core/browser/options_menu_model.cc +++ b/components/translate/core/browser/options_menu_model.cc
@@ -102,7 +102,7 @@ bool OptionsMenuModel::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; }
diff --git a/components/translate/core/browser/options_menu_model.h b/components/translate/core/browser/options_menu_model.h index 44fc5b2..165fdff 100644 --- a/components/translate/core/browser/options_menu_model.h +++ b/components/translate/core/browser/options_menu_model.h
@@ -33,7 +33,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; private:
diff --git a/components/translate/core/browser/translate_manager.cc b/components/translate/core/browser/translate_manager.cc index 689b70a..9de6910 100644 --- a/components/translate/core/browser/translate_manager.cc +++ b/components/translate/core/browser/translate_manager.cc
@@ -167,12 +167,6 @@ return; } - // In the 2016Q2 UI, enable the translate in language state once we reach - // the above check and let omnibar to display the translate icon. - if (base::FeatureList::IsEnabled(kTranslateUI2016Q2)) { - language_state_.SetTranslateEnabled(true); - } - TranslateAcceptLanguages* accept_languages = translate_client_->GetTranslateAcceptLanguages(); // Don't translate any user black-listed languages.
diff --git a/components/translate/core/browser/translate_ui_delegate.cc b/components/translate/core/browser/translate_ui_delegate.cc index c3e26406c..7caffe1 100644 --- a/components/translate/core/browser/translate_ui_delegate.cc +++ b/components/translate/core/browser/translate_ui_delegate.cc
@@ -256,12 +256,7 @@ void TranslateUIDelegate::SetLanguageBlocked(bool value) { if (value) { prefs_->BlockLanguage(GetOriginalLanguageCode()); - // In the new UI, we will keep showing the translate omnibar icon - // even if the language is blocked so in case the user just wants to - // translate that page the user can invoke the translate bubble from - // the omnibar icon. - if (!base::FeatureList::IsEnabled(kTranslateUI2016Q2) && - translate_manager_) { + if (translate_manager_) { translate_manager_->GetLanguageState().SetTranslateEnabled(false); } } else { @@ -283,12 +278,7 @@ if (value) { prefs_->BlacklistSite(host); - // In the new UI, we will keep showing the translate omnibar icon - // even if the site is blocked so in case the user just wants to - // translate that page the user can invoke the translate bubble from - // the omnibar icon. - if (!base::FeatureList::IsEnabled(kTranslateUI2016Q2) && - translate_manager_) { + if (translate_manager_) { translate_manager_->GetLanguageState().SetTranslateEnabled(false); } } else {
diff --git a/components/translate/core/browser/translate_ui_delegate_unittest.cc b/components/translate/core/browser/translate_ui_delegate_unittest.cc index 6d556f9..415f67d 100644 --- a/components/translate/core/browser/translate_ui_delegate_unittest.cc +++ b/components/translate/core/browser/translate_ui_delegate_unittest.cc
@@ -173,29 +173,6 @@ EXPECT_TRUE(manager_->GetLanguageState().translate_enabled()); } -TEST_F(TranslateUIDelegateTest, SetLanguageBlockedIn2016Q2UI) { - TurnOnTranslate2016Q2UIFlag(); - std::unique_ptr<TranslatePrefs> prefs(client_->GetTranslatePrefs()); - manager_->GetLanguageState().SetTranslateEnabled(true); - EXPECT_TRUE(manager_->GetLanguageState().translate_enabled()); - prefs->UnblockLanguage("ar"); - EXPECT_FALSE(prefs->IsBlockedLanguage("ar")); - - delegate_->SetLanguageBlocked(true); - - EXPECT_TRUE(prefs->IsBlockedLanguage("ar")); - EXPECT_TRUE(manager_->GetLanguageState().translate_enabled()); - - // Reset it to true again after delegate_->SetLanguageBlocked(true) - // turn it to false. - manager_->GetLanguageState().SetTranslateEnabled(true); - - delegate_->SetLanguageBlocked(false); - - EXPECT_FALSE(prefs->IsBlockedLanguage("ar")); - EXPECT_TRUE(manager_->GetLanguageState().translate_enabled()); -} - TEST_F(TranslateUIDelegateTest, ShouldAlwaysTranslateBeCheckedByDefaultNever) { std::unique_ptr<TranslatePrefs> prefs(client_->GetTranslatePrefs()); prefs->ResetTranslationAcceptedCount("ar");
diff --git a/components/webcrypto/fuzzer_support.cc b/components/webcrypto/fuzzer_support.cc index f44f8bc..6b1d4959 100644 --- a/components/webcrypto/fuzzer_support.cc +++ b/components/webcrypto/fuzzer_support.cc
@@ -6,6 +6,7 @@ #include "base/command_line.h" #include "base/lazy_instance.h" +#include "base/numerics/safe_conversions.h" #include "components/test_runner/test_common.h" #include "components/webcrypto/algorithm_dispatch.h" #include "components/webcrypto/crypto_data.h" @@ -83,7 +84,7 @@ blink::WebCryptoKey key; webcrypto::Status status = webcrypto::ImportKey( - format, webcrypto::CryptoData(data, size), + format, webcrypto::CryptoData(data, base::checked_cast<uint32_t>(size)), CreateEcImportAlgorithm(algorithm_id, curve), true, usages, &key); // These errors imply a bad setup of parameters, and means ImportKey() may not @@ -116,7 +117,7 @@ blink::WebCryptoKey key; webcrypto::Status status = webcrypto::ImportKey( - format, webcrypto::CryptoData(data, size), + format, webcrypto::CryptoData(data, base::checked_cast<uint32_t>(size)), CreateRsaHashedImportAlgorithm(algorithm_id, hash_id), true, usages, &key);
diff --git a/components/webcrypto/webcrypto_impl.cc b/components/webcrypto/webcrypto_impl.cc index 7986b77..9f47270 100644 --- a/components/webcrypto/webcrypto_impl.cc +++ b/components/webcrypto/webcrypto_impl.cc
@@ -763,9 +763,9 @@ } } -blink::WebCryptoDigestor* WebCryptoImpl::createDigestor( +std::unique_ptr<blink::WebCryptoDigestor> WebCryptoImpl::createDigestor( blink::WebCryptoAlgorithmId algorithm_id) { - return webcrypto::CreateDigestor(algorithm_id).release(); + return webcrypto::CreateDigestor(algorithm_id); } bool WebCryptoImpl::deserializeKeyForClone(
diff --git a/components/webcrypto/webcrypto_impl.h b/components/webcrypto/webcrypto_impl.h index af5f6fcc..b551213 100644 --- a/components/webcrypto/webcrypto_impl.h +++ b/components/webcrypto/webcrypto_impl.h
@@ -96,10 +96,8 @@ // This method returns a digestor object that can be used to synchronously // compute a digest one chunk at a time. Thus, the consume does not need to // hold onto a large buffer with all the data to digest. Chunks can be given - // one at a time and the digest will be computed piecemeal. The allocated - // WebCrytpoDigestor that is returned by createDigestor must be freed by the - // caller. - blink::WebCryptoDigestor* createDigestor( + // one at a time and the digest will be computed piecemeal. + std::unique_ptr<blink::WebCryptoDigestor> createDigestor( blink::WebCryptoAlgorithmId algorithm_id) override; bool deserializeKeyForClone(const blink::WebCryptoKeyAlgorithm& algorithm,
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index b8ffbbe..4143cc1 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -37,6 +37,7 @@ "//components/filesystem:lib", "//components/leveldb:lib", "//components/link_header_util", + "//components/memory_coordinator/browser", "//components/mime_util", "//components/scheduler:common", "//components/tracing", @@ -507,6 +508,14 @@ if (enable_ipc_fuzzer) { configs += [ "//tools/ipc_fuzzer:ipc_fuzzer_config" ] } + + if (use_minikin_hyphenation) { + sources += [ + "hyphenation/hyphenation_impl.cc", + "hyphenation/hyphenation_impl.h", + ] + defines += [ "USE_MINIKIN_HYPHENATION=1" ] + } } # See comment at the top of //content/BUILD.gn for how this works.
diff --git a/content/browser/DEPS b/content/browser/DEPS index 5cd8d769..96021ad 100644 --- a/content/browser/DEPS +++ b/content/browser/DEPS
@@ -4,6 +4,8 @@ "+components/filesystem", "+components/leveldb", "+components/link_header_util", + "+components/memory_coordinator/browser", + "+components/memory_coordinator/common", "+components/mime_util", "+components/network_session_configurator/switches.h", "+components/profile_service",
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc index b3bbe94d5..e486341 100644 --- a/content/browser/android/content_view_core_impl.cc +++ b/content/browser/android/content_view_core_impl.cc
@@ -1007,10 +1007,6 @@ : rwhv->OnTouchEvent(event); } -float ContentViewCoreImpl::GetDpiScale() const { - return dpi_scale_; -} - jboolean ContentViewCoreImpl::SendMouseMoveEvent( JNIEnv* env, const JavaParamRef<jobject>& obj,
diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h index 28ac05f0..ae645d3 100644 --- a/content/browser/android/content_view_core_impl.h +++ b/content/browser/android/content_view_core_impl.h
@@ -65,7 +65,6 @@ const override; cc::Layer* GetLayer() const override; bool ShowPastePopup(int x, int y) override; - float GetDpiScale() const override; void PauseOrResumeGeolocation(bool should_pause) override; void RequestTextSurroundingSelection( int max_length,
diff --git a/content/browser/android/overscroll_controller_android.cc b/content/browser/android/overscroll_controller_android.cc index 8feda1c..5e89172 100644 --- a/content/browser/android/overscroll_controller_android.cc +++ b/content/browser/android/overscroll_controller_android.cc
@@ -97,9 +97,10 @@ } // namespace OverscrollControllerAndroid::OverscrollControllerAndroid( - ContentViewCoreImpl* content_view_core) + ContentViewCoreImpl* content_view_core, + float dpi_scale) : compositor_(content_view_core->GetWindowAndroid()->GetCompositor()), - dpi_scale_(content_view_core->GetDpiScale()), + dpi_scale_(dpi_scale), enabled_(true), glow_effect_(CreateGlowEffect(this, dpi_scale_)), refresh_effect_(CreateRefreshEffect(content_view_core)) {
diff --git a/content/browser/android/overscroll_controller_android.h b/content/browser/android/overscroll_controller_android.h index 564754eb..7db37c9b 100644 --- a/content/browser/android/overscroll_controller_android.h +++ b/content/browser/android/overscroll_controller_android.h
@@ -37,7 +37,8 @@ // Note that all input coordinates (both for events and overscroll) are in DIPs. class OverscrollControllerAndroid : public ui::OverscrollGlowClient { public: - explicit OverscrollControllerAndroid(ContentViewCoreImpl* content_view_core); + explicit OverscrollControllerAndroid(ContentViewCoreImpl* content_view_core, + float dpi_scale); ~OverscrollControllerAndroid() override; // Returns true if |event| is consumed by an overscroll effect, in which
diff --git a/content/browser/android/popup_touch_handle_drawable.cc b/content/browser/android/popup_touch_handle_drawable.cc index e5cce037..14b12302 100644 --- a/content/browser/android/popup_touch_handle_drawable.cc +++ b/content/browser/android/popup_touch_handle_drawable.cc
@@ -11,7 +11,8 @@ // static std::unique_ptr<PopupTouchHandleDrawable> PopupTouchHandleDrawable::Create( - ContentViewCore* content_view_core) { + ContentViewCore* content_view_core, + float dpi_scale) { DCHECK(content_view_core); base::android::ScopedJavaLocalRef<jobject> content_view_core_obj = content_view_core->GetJavaObject(); @@ -20,8 +21,8 @@ JNIEnv* env = base::android::AttachCurrentThread(); base::android::ScopedJavaLocalRef<jobject> drawable_obj( Java_PopupTouchHandleDrawable_create(env, content_view_core_obj.obj())); - return std::unique_ptr<PopupTouchHandleDrawable>(new PopupTouchHandleDrawable( - env, drawable_obj.obj(), content_view_core->GetDpiScale())); + return std::unique_ptr<PopupTouchHandleDrawable>( + new PopupTouchHandleDrawable(env, drawable_obj.obj(), dpi_scale)); } PopupTouchHandleDrawable::PopupTouchHandleDrawable(JNIEnv* env,
diff --git a/content/browser/android/popup_touch_handle_drawable.h b/content/browser/android/popup_touch_handle_drawable.h index 9ba4093a..f64a61a2 100644 --- a/content/browser/android/popup_touch_handle_drawable.h +++ b/content/browser/android/popup_touch_handle_drawable.h
@@ -21,7 +21,8 @@ class PopupTouchHandleDrawable : public ui::TouchHandleDrawable { public: static std::unique_ptr<PopupTouchHandleDrawable> Create( - ContentViewCore* content_view_core); + ContentViewCore* content_view_core, + float dpi_scale); ~PopupTouchHandleDrawable() override; // ui::TouchHandleDrawable implementation.
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 80c84a73..dd8a090 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -36,6 +36,8 @@ #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" +#include "components/memory_coordinator/browser/memory_coordinator.h" +#include "components/memory_coordinator/common/memory_coordinator_features.h" #include "components/tracing/browser/trace_config_file.h" #include "components/tracing/common/process_metrics_memory_dump_provider.h" #include "components/tracing/common/trace_to_console.h" @@ -721,6 +723,10 @@ parsed_command_line_)); #endif + if (memory_coordinator::IsEnabled()) { + memory_coordinator_.reset(new memory_coordinator::MemoryCoordinator); + } + #if defined(ENABLE_PLUGINS) // Prior to any processing happening on the IO thread, we create the // plugin service as it is predominantly used from the IO thread, @@ -997,6 +1003,7 @@ } memory_pressure_monitor_.reset(); + memory_coordinator_.reset(); #if defined(OS_MACOSX) BrowserCompositorMac::DisableRecyclingForShutdown(); @@ -1079,6 +1086,11 @@ } case BrowserThread::IO: { TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:IOThread"); + // At this point we should have removed all tabs which will lead to all + // RenderProcessHostImpl instances getting terminated. + // It is suspected that this is not happening: crbug.com/608049. + // TODO(alokp): Remove this after fixing the issue. + RenderProcessHostImpl::CheckAllTerminated(); ResetThread_IO(std::move(io_thread_)); break; }
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h index 62ba7ac9..d05d176e 100644 --- a/content/browser/browser_main_loop.h +++ b/content/browser/browser_main_loop.h
@@ -50,6 +50,10 @@ } // namespace midi } // namespace media +namespace memory_coordinator { +class MemoryCoordinator; +} // namespace memory_coordinator + namespace mojo { namespace edk { class ScopedIPCSupport; @@ -143,6 +147,10 @@ void StopStartupTracingTimer(); + memory_coordinator::MemoryCoordinator* memory_coordinator() const { + return memory_coordinator_.get(); + } + #if defined(OS_MACOSX) && !defined(OS_IOS) media::DeviceMonitorMac* device_monitor_mac() const { return device_monitor_mac_.get(); @@ -249,6 +257,7 @@ // Members initialized in |PreCreateThreads()| ------------------------------- // Torn down in ShutdownThreadsAndCleanUp. std::unique_ptr<base::MemoryPressureMonitor> memory_pressure_monitor_; + std::unique_ptr<memory_coordinator::MemoryCoordinator> memory_coordinator_; // Members initialized in |CreateThreads()| ---------------------------------- std::unique_ptr<BrowserProcessSubThread> db_thread_;
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc index 2f6fd0e3..ceeaaa3 100644 --- a/content/browser/browser_plugin/browser_plugin_guest.cc +++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -409,7 +409,7 @@ std::vector<uint32_t> sequences; sequences.push_back(sequence.sequence); cc::SurfaceManager* manager = GetSurfaceManager(); - manager->DidSatisfySequences(sequence.id_namespace, &sequences); + manager->DidSatisfySequences(sequence.client_id, &sequences); } void BrowserPluginGuest::OnRequireSequence(
diff --git a/content/browser/compositor/gpu_browser_compositor_output_surface.cc b/content/browser/compositor/gpu_browser_compositor_output_surface.cc index 84cee90..5a9da8e 100644 --- a/content/browser/compositor/gpu_browser_compositor_output_surface.cc +++ b/content/browser/compositor/gpu_browser_compositor_output_surface.cc
@@ -103,8 +103,6 @@ context_provider_->ContextSupport()->PartialSwapBuffers( frame.gl_frame_data->sub_buffer_rect); } - - client_->DidSwapBuffers(); } void GpuBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc index eb8a142..f40a64bc 100644 --- a/content/browser/compositor/gpu_process_transport_factory.cc +++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -180,7 +180,7 @@ }; GpuProcessTransportFactory::GpuProcessTransportFactory() - : next_surface_id_namespace_(1u), + : next_surface_client_id_(1u), task_graph_runner_(new cc::SingleThreadTaskGraphRunner), callback_factory_(this) { cc::SetClientNameForMetrics("Browser"); @@ -581,7 +581,7 @@ surface_manager_.get(), HostSharedBitmapManager::current(), BrowserGpuMemoryBufferManager::current(), compositor->GetRendererSettings(), - compositor->surface_id_allocator()->id_namespace(), + compositor->surface_id_allocator()->client_id(), std::move(begin_frame_source), std::move(display_output_surface), std::move(scheduler), base::MakeUnique<cc::TextureMailboxDeleter>( compositor->task_runner().get())); @@ -692,10 +692,10 @@ std::unique_ptr<cc::SurfaceIdAllocator> GpuProcessTransportFactory::CreateSurfaceIdAllocator() { - std::unique_ptr<cc::SurfaceIdAllocator> allocator = base::WrapUnique( - new cc::SurfaceIdAllocator(next_surface_id_namespace_++)); + std::unique_ptr<cc::SurfaceIdAllocator> allocator = + base::WrapUnique(new cc::SurfaceIdAllocator(next_surface_client_id_++)); if (GetSurfaceManager()) - allocator->RegisterSurfaceIdNamespace(GetSurfaceManager()); + allocator->RegisterSurfaceClientId(GetSurfaceManager()); return allocator; }
diff --git a/content/browser/compositor/gpu_process_transport_factory.h b/content/browser/compositor/gpu_process_transport_factory.h index 0cad211..0db60467 100644 --- a/content/browser/compositor/gpu_process_transport_factory.h +++ b/content/browser/compositor/gpu_process_transport_factory.h
@@ -103,7 +103,7 @@ std::unique_ptr<display_compositor::GLHelper> gl_helper_; base::ObserverList<ui::ContextFactoryObserver> observer_list_; std::unique_ptr<cc::SurfaceManager> surface_manager_; - uint32_t next_surface_id_namespace_; + uint32_t next_surface_client_id_; std::unique_ptr<cc::SingleThreadTaskGraphRunner> task_graph_runner_; scoped_refptr<ContextProviderCommandBuffer> shared_worker_context_provider_;
diff --git a/content/browser/compositor/offscreen_browser_compositor_output_surface.cc b/content/browser/compositor/offscreen_browser_compositor_output_surface.cc index 3b06fb0..ab2a12f 100644 --- a/content/browser/compositor/offscreen_browser_compositor_output_surface.cc +++ b/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
@@ -146,8 +146,6 @@ reflector_->OnSourcePostSubBuffer(frame.gl_frame_data->sub_buffer_rect); } - client_->DidSwapBuffers(); - // TODO(oshima): sync with the reflector's SwapBuffersComplete // (crbug.com/520567). // The original implementation had a flickering issue (crbug.com/515332).
diff --git a/content/browser/compositor/software_browser_compositor_output_surface.cc b/content/browser/compositor/software_browser_compositor_output_surface.cc index 250a9ce..2ef0c42e 100644 --- a/content/browser/compositor/software_browser_compositor_output_surface.cc +++ b/content/browser/compositor/software_browser_compositor_output_surface.cc
@@ -54,7 +54,6 @@ weak_factory_.GetWeakPtr())); } PostSwapBuffersComplete(); - client_->DidSwapBuffers(); } void SoftwareBrowserCompositorOutputSurface::BindFramebuffer() {
diff --git a/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc b/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc index 8a6fd7dc..6553c38 100644 --- a/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc +++ b/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
@@ -120,8 +120,6 @@ cc::CompositorFrame frame; output_surface_->SwapBuffers(std::move(frame)); - - EXPECT_EQ(1, output_surface_client.swap_count()); EXPECT_EQ(NULL, output_surface_->software_device()->GetVSyncProvider()); } @@ -138,7 +136,5 @@ cc::CompositorFrame frame; output_surface_->SwapBuffers(std::move(frame)); - - EXPECT_EQ(1, output_surface_client.swap_count()); EXPECT_EQ(1, vsync_provider->call_count()); }
diff --git a/content/browser/compositor/vulkan_browser_compositor_output_surface.cc b/content/browser/compositor/vulkan_browser_compositor_output_surface.cc index de0edfdf..b06f9f22 100644 --- a/content/browser/compositor/vulkan_browser_compositor_output_surface.cc +++ b/content/browser/compositor/vulkan_browser_compositor_output_surface.cc
@@ -55,7 +55,6 @@ cc::CompositorFrame* frame) { surface_->SwapBuffers(); PostSwapBuffersComplete(); - client_->DidSwapBuffers(); } } // namespace content
diff --git a/content/browser/devtools/devtools_manager.cc b/content/browser/devtools/devtools_manager.cc index f3004a3e..d4889002 100644 --- a/content/browser/devtools/devtools_manager.cc +++ b/content/browser/devtools/devtools_manager.cc
@@ -34,7 +34,8 @@ BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, - base::Bind(&NetLogObserver::Attach)); + base::Bind(&NetLogObserver::Attach, + GetContentClient()->browser()->GetNetLog())); } ++attached_hosts_count_; } else {
diff --git a/content/browser/devtools/protocol/input_handler.cc b/content/browser/devtools/protocol/input_handler.cc index 120314bf..e77697f 100644 --- a/content/browser/devtools/protocol/input_handler.cc +++ b/content/browser/devtools/protocol/input_handler.cc
@@ -166,6 +166,7 @@ const bool* is_keypad, const bool* is_system_key) { NativeWebKeyboardEvent event; + event.skip_in_browser = true; if (type == dispatch_key_event::kTypeKeyDown) { event.type = blink::WebInputEvent::KeyDown;
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc index e086016..5c4cc63 100644 --- a/content/browser/download/download_browsertest.cc +++ b/content/browser/download/download_browsertest.cc
@@ -575,6 +575,10 @@ make_scoped_refptr(content::BrowserThread::GetBlockingPool()))); } + void SetUpCommandLine(base::CommandLine* commnad_line) override { + IsolateAllSitesForTesting(commnad_line); + } + TestShellDownloadManagerDelegate* GetDownloadManagerDelegate() { return test_delegate_.get(); } @@ -2479,4 +2483,43 @@ downloads[0]->GetTargetFilePath().BaseName().value()); } +IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeSameOriginIFrame) { + ASSERT_TRUE(embedded_test_server()->Start()); + + GURL frame_url = embedded_test_server()->GetURL( + "/download/download-attribute.html?target=/download/download-test.lib"); + GURL document_url = embedded_test_server()->GetURL( + "/download/iframe-host.html?target=" + frame_url.spec()); + DownloadItem* download = StartDownloadAndReturnItem(shell(), document_url); + WaitForCompletion(download); + + EXPECT_STREQ(FILE_PATH_LITERAL("suggested-filename"), + download->GetTargetFilePath().BaseName().value().c_str()); +} + +IN_PROC_BROWSER_TEST_F(DownloadContentTest, + DownloadAttributeCrossOriginIFrame) { + net::EmbeddedTestServer origin_one; + net::EmbeddedTestServer origin_two; + ASSERT_TRUE(origin_one.Start()); + ASSERT_TRUE(origin_two.Start()); + + origin_one.ServeFilesFromDirectory(GetTestFilePath("download", "")); + origin_two.ServeFilesFromDirectory(GetTestFilePath("download", "")); + + GURL frame_url = + origin_one.GetURL("/download-attribute.html?target=" + + origin_two.GetURL("/download-test.lib").spec()); + GURL::Replacements replacements; + replacements.SetHostStr("localhost"); + frame_url = frame_url.ReplaceComponents(replacements); + GURL document_url = + origin_two.GetURL("/iframe-host.html?target=" + frame_url.spec()); + DownloadItem* download = StartDownloadAndReturnItem(shell(), document_url); + WaitForCompletion(download); + + EXPECT_STREQ(FILE_PATH_LITERAL("download-test.lib"), + download->GetTargetFilePath().BaseName().value().c_str()); +} + } // namespace content
diff --git a/content/browser/download/download_item_impl.cc b/content/browser/download/download_item_impl.cc index be68b07..674cc90dd 100644 --- a/content/browser/download/download_item_impl.cc +++ b/content/browser/download/download_item_impl.cc
@@ -766,10 +766,6 @@ open_when_complete_ = open; } -void DownloadItemImpl::SetIsTemporary(bool temporary) { - is_temporary_ = temporary; -} - void DownloadItemImpl::SetOpened(bool opened) { opened_ = opened; }
diff --git a/content/browser/download/download_item_impl.h b/content/browser/download/download_item_impl.h index 802c5af..abf382e 100644 --- a/content/browser/download/download_item_impl.h +++ b/content/browser/download/download_item_impl.h
@@ -161,7 +161,6 @@ WebContents* GetWebContents() const override; void OnContentCheckCompleted(DownloadDangerType danger_type) override; void SetOpenWhenComplete(bool open) override; - void SetIsTemporary(bool temporary) override; void SetOpened(bool opened) override; void SetDisplayName(const base::FilePath& name) override; std::string DebugString(bool verbose) const override;
diff --git a/content/browser/download/download_item_impl_unittest.cc b/content/browser/download/download_item_impl_unittest.cc index c9389638..a68eca8 100644 --- a/content/browser/download/download_item_impl_unittest.cc +++ b/content/browser/download/download_item_impl_unittest.cc
@@ -1309,10 +1309,12 @@ } TEST_F(DownloadItemTest, EnabledActionsForTemporaryDownload) { + // A download created with a non-empty FilePath is considered a temporary + // download. + create_info()->save_info->file_path = base::FilePath(kDummyTargetPath); DownloadItemImpl* item = CreateDownloadItem(); MockDownloadFile* download_file = DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS); - item->SetIsTemporary(true); // InProgress Temporary ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
diff --git a/content/browser/download/download_manager_impl_unittest.cc b/content/browser/download/download_manager_impl_unittest.cc index e17656e..52933ca 100644 --- a/content/browser/download/download_manager_impl_unittest.cc +++ b/content/browser/download/download_manager_impl_unittest.cc
@@ -177,7 +177,6 @@ MOCK_CONST_METHOD0(HasUserGesture, bool()); MOCK_CONST_METHOD0(GetTransitionType, ui::PageTransition()); MOCK_CONST_METHOD0(IsTemporary, bool()); - MOCK_METHOD1(SetIsTemporary, void(bool)); MOCK_METHOD1(SetOpened, void(bool)); MOCK_CONST_METHOD0(GetOpened, bool()); MOCK_CONST_METHOD0(GetLastModifiedTime, const std::string&());
diff --git a/content/browser/frame_host/PRESUBMIT.py b/content/browser/frame_host/PRESUBMIT.py index d3afe71..a6d6fbf 100644 --- a/content/browser/frame_host/PRESUBMIT.py +++ b/content/browser/frame_host/PRESUBMIT.py
@@ -12,7 +12,7 @@ def _GetTryMasters(project, change): return { - 'tryserver.chromium.linux': { + 'master.tryserver.chromium.linux': { 'linux_site_isolation': [], }, }
diff --git a/content/browser/frame_host/cross_process_frame_connector.cc b/content/browser/frame_host/cross_process_frame_connector.cc index 8fd9e87..4b3c12d6 100644 --- a/content/browser/frame_host/cross_process_frame_connector.cc +++ b/content/browser/frame_host/cross_process_frame_connector.cc
@@ -97,7 +97,7 @@ std::vector<uint32_t> sequences; sequences.push_back(sequence.sequence); cc::SurfaceManager* manager = GetSurfaceManager(); - manager->DidSatisfySequences(sequence.id_namespace, &sequences); + manager->DidSatisfySequences(sequence.client_id, &sequences); } void CrossProcessFrameConnector::OnRequireSequence( @@ -203,6 +203,12 @@ return false; } +void CrossProcessFrameConnector::UnlockMouse() { + RenderWidgetHostViewBase* root_view = GetRootRenderWidgetHostView(); + if (root_view) + root_view->UnlockMouse(); +} + void CrossProcessFrameConnector::OnForwardInputEvent( const blink::WebInputEvent* event) { if (!view_)
diff --git a/content/browser/frame_host/cross_process_frame_connector.h b/content/browser/frame_host/cross_process_frame_connector.h index c553fca..0af9c831 100644 --- a/content/browser/frame_host/cross_process_frame_connector.h +++ b/content/browser/frame_host/cross_process_frame_connector.h
@@ -114,6 +114,9 @@ // Locks the mouse. Returns true if mouse is locked. bool LockMouse(); + // Unlocks the mouse if the mouse is locked. + void UnlockMouse(); + // Returns the parent RenderWidgetHostView or nullptr it it doesn't have one. virtual RenderWidgetHostViewBase* GetParentRenderWidgetHostView();
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 67dfe7d..e3807d9 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
@@ -48,7 +48,7 @@ frame_connector_(nullptr), begin_frame_source_(nullptr), observing_begin_frame_source_(false), - parent_surface_id_namespace_(0), + parent_surface_client_id_(0), weak_factory_(this) { id_allocator_ = CreateSurfaceIdAllocator(); RegisterSurfaceNamespaceId(); @@ -67,28 +67,35 @@ return; if (frame_connector_) { - if (parent_surface_id_namespace_) { + if (parent_surface_client_id_) { GetSurfaceManager()->UnregisterSurfaceNamespaceHierarchy( - parent_surface_id_namespace_, GetSurfaceIdNamespace()); + parent_surface_client_id_, GetSurfaceClientId()); } // Unregister the client here, as it is not guaranteed in tests that the // destructor will be called. GetSurfaceManager()->UnregisterSurfaceFactoryClient( - id_allocator_->id_namespace()); + id_allocator_->client_id()); - parent_surface_id_namespace_ = 0; + parent_surface_client_id_ = 0; + + // After the RenderWidgetHostViewChildFrame loses the frame_connector, it + // won't be able to walk up the frame tree anymore. Clean up anything that + // needs to be done through the CrossProcessFrameConnector before it's gone. + + // Unlocks the mouse if this RenderWidgetHostView holds the lock. + UnlockMouse(); } frame_connector_ = frame_connector; if (frame_connector_) { GetSurfaceManager()->RegisterSurfaceFactoryClient( - id_allocator_->id_namespace(), this); + id_allocator_->client_id(), this); RenderWidgetHostViewBase* parent_view = frame_connector_->GetParentRenderWidgetHostView(); if (parent_view) { - parent_surface_id_namespace_ = parent_view->GetSurfaceIdNamespace(); - DCHECK_NE(parent_surface_id_namespace_, 0u); + parent_surface_client_id_ = parent_view->GetSurfaceClientId(); + DCHECK_NE(parent_surface_client_id_, 0u); GetSurfaceManager()->RegisterSurfaceNamespaceHierarchy( - parent_surface_id_namespace_, GetSurfaceIdNamespace()); + parent_surface_client_id_, GetSurfaceClientId()); } } } @@ -262,7 +269,7 @@ } void RenderWidgetHostViewChildFrame::Destroy() { - // SurfaceIdNamespaces registered with RenderWidgetHostInputEventRouter + // SurfaceClientIds registered with RenderWidgetHostInputEventRouter // have already been cleared when RenderWidgetHostViewBase notified its // observers of our impending destruction. if (frame_connector_) { @@ -304,16 +311,16 @@ if (host_ && host_->delegate() && host_->delegate()->GetInputEventRouter()) { RenderWidgetHostInputEventRouter* router = host_->delegate()->GetInputEventRouter(); - if (!router->is_registered(GetSurfaceIdNamespace())) - router->AddSurfaceIdNamespaceOwner(GetSurfaceIdNamespace(), this); + if (!router->is_registered(GetSurfaceClientId())) + router->AddSurfaceClientIdOwner(GetSurfaceClientId(), this); } } void RenderWidgetHostViewChildFrame::UnregisterSurfaceNamespaceId() { DCHECK(host_); if (host_->delegate() && host_->delegate()->GetInputEventRouter()) { - host_->delegate()->GetInputEventRouter()->RemoveSurfaceIdNamespaceOwner( - GetSurfaceIdNamespace()); + host_->delegate()->GetInputEventRouter()->RemoveSurfaceClientIdOwner( + GetSurfaceClientId()); } } @@ -392,7 +399,7 @@ surface_factory_->Create(surface_id_); cc::SurfaceSequence sequence = cc::SurfaceSequence( - id_allocator_->id_namespace(), next_surface_sequence_++); + id_allocator_->client_id(), next_surface_sequence_++); // The renderer process will satisfy this dependency when it creates a // SurfaceLayer. cc::SurfaceManager* manager = GetSurfaceManager(); @@ -458,23 +465,20 @@ } void RenderWidgetHostViewChildFrame::UnlockMouse() { + if (host_->delegate() && host_->delegate()->HasMouseLock(host_) && + frame_connector_) + frame_connector_->UnlockMouse(); } bool RenderWidgetHostViewChildFrame::IsMouseLocked() { - if (!frame_connector_) + if (!host_->delegate()) return false; - RenderWidgetHostViewBase* root_view = - frame_connector_->GetRootRenderWidgetHostView(); - - if (root_view) - return root_view->IsMouseLocked(); - - return false; + return host_->delegate()->HasMouseLock(host_); } -uint32_t RenderWidgetHostViewChildFrame::GetSurfaceIdNamespace() { - return id_allocator_->id_namespace(); +uint32_t RenderWidgetHostViewChildFrame::GetSurfaceClientId() { + return id_allocator_->client_id(); } void RenderWidgetHostViewChildFrame::ProcessKeyboardEvent(
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.h b/content/browser/frame_host/render_widget_host_view_child_frame.h index dc9bd12..74d535b 100644 --- a/content/browser/frame_host/render_widget_host_view_child_frame.h +++ b/content/browser/frame_host/render_widget_host_view_child_frame.h
@@ -127,7 +127,7 @@ InputEventAckState ack_result) override; bool LockMouse() override; void UnlockMouse() override; - uint32_t GetSurfaceIdNamespace() override; + uint32_t GetSurfaceClientId() override; void ProcessKeyboardEvent(const NativeWebKeyboardEvent& event) override; void ProcessMouseEvent(const blink::WebMouseEvent& event, const ui::LatencyInfo& latency) override; @@ -234,8 +234,8 @@ cc::BeginFrameSource* begin_frame_source_; cc::BeginFrameArgs last_begin_frame_args_; bool observing_begin_frame_source_; - // The surface id namespace of the parent RenderWidgetHostView. 0 if none. - uint32_t parent_surface_id_namespace_; + // The surface client ID of the parent RenderWidgetHostView. 0 if none. + uint32_t parent_surface_client_id_; base::WeakPtrFactory<RenderWidgetHostViewChildFrame> weak_factory_; DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewChildFrame);
diff --git a/content/browser/frame_host/render_widget_host_view_guest.cc b/content/browser/frame_host/render_widget_host_view_guest.cc index b4557c2..82c0da9 100644 --- a/content/browser/frame_host/render_widget_host_view_guest.cc +++ b/content/browser/frame_host/render_widget_host_view_guest.cc
@@ -115,7 +115,7 @@ // the renderer. if (!surface_id_.is_null()) { cc::SurfaceSequence sequence = cc::SurfaceSequence( - id_allocator_->id_namespace(), next_surface_sequence_++); + id_allocator_->client_id(), next_surface_sequence_++); GetSurfaceManager() ->GetSurfaceForId(surface_id_) ->AddDestructionDependency(sequence); @@ -295,7 +295,7 @@ surface_factory_->Create(surface_id_); cc::SurfaceSequence sequence = cc::SurfaceSequence( - id_allocator_->id_namespace(), next_surface_sequence_++); + id_allocator_->client_id(), next_surface_sequence_++); // The renderer process will satisfy this dependency when it creates a // SurfaceLayer. cc::SurfaceManager* manager = GetSurfaceManager();
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 8c3a201..be40e527 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -559,8 +559,9 @@ TRACE_EVENT_INSTANT0("gpu", "LaunchGpuProcess", TRACE_EVENT_SCOPE_THREAD); - std::string channel_id = process_->GetHost()->CreateChannel(); - if (channel_id.empty()) + const std::string mojo_channel_token = + process_->GetHost()->CreateChannelMojo(child_token_); + if (mojo_channel_token.empty()) return false; DCHECK(!mojo_child_connection_); @@ -576,8 +577,8 @@ DCHECK(g_gpu_main_thread_factory); in_process_gpu_thread_.reset(g_gpu_main_thread_factory( InProcessChildThreadParams( - channel_id, base::ThreadTaskRunnerHandle::Get(), std::string(), - mojo_child_connection_->service_token()), + std::string(), base::ThreadTaskRunnerHandle::Get(), + mojo_channel_token, mojo_child_connection_->service_token()), gpu_preferences)); base::Thread::Options options; #if defined(OS_WIN) @@ -590,7 +591,7 @@ in_process_gpu_thread_->StartWithOptions(options); OnProcessLaunched(); // Fake a callback that the process is ready. - } else if (!LaunchGpuProcess(channel_id, &gpu_preferences)) { + } else if (!LaunchGpuProcess(mojo_channel_token, &gpu_preferences)) { return false; } @@ -963,7 +964,7 @@ Send(new GpuMsg_Finalize()); } -bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id, +bool GpuProcessHost::LaunchGpuProcess(const std::string& mojo_channel_token, gpu::GpuPreferences* gpu_preferences) { if (!(gpu_enabled_ && GpuDataManagerImpl::GetInstance()->ShouldUseSwiftShader()) && @@ -999,7 +1000,7 @@ base::CommandLine* cmd_line = new base::CommandLine(exe_path); #endif cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess); - cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); + cmd_line->AppendSwitchASCII(switches::kMojoChannelToken, mojo_channel_token); cmd_line->AppendSwitchASCII(switches::kMojoApplicationChannelToken, mojo_child_connection_->service_token()); BrowserChildProcessHostImpl::CopyFeatureAndFieldTrialFlags(cmd_line);
diff --git a/content/browser/hyphenation/DEPS b/content/browser/hyphenation/DEPS new file mode 100644 index 0000000..1f557f4 --- /dev/null +++ b/content/browser/hyphenation/DEPS
@@ -0,0 +1,5 @@ +include_rules = [ + "-content", + "+content/browser/hyphenation", + "+third_party/WebKit/public/platform/modules/hyphenation/hyphenation.mojom.h", +]
diff --git a/content/browser/hyphenation/OWNERS b/content/browser/hyphenation/OWNERS new file mode 100644 index 0000000..bdb7149 --- /dev/null +++ b/content/browser/hyphenation/OWNERS
@@ -0,0 +1,4 @@ +eae@chromium.org +drott@chromium.org +kojii@chromium.org +szager@chromium.org
diff --git a/content/browser/hyphenation/hyphenation_impl.cc b/content/browser/hyphenation/hyphenation_impl.cc new file mode 100644 index 0000000..5049836 --- /dev/null +++ b/content/browser/hyphenation/hyphenation_impl.cc
@@ -0,0 +1,72 @@ +// 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 "content/browser/hyphenation/hyphenation_impl.h" + +#include <algorithm> +#include <map> +#include <utility> + +#include "base/files/file.h" +#include "base/files/file_path.h" +#include "base/strings/stringprintf.h" +#include "mojo/public/cpp/system/platform_handle.h" + +namespace { + +using DictionaryFileMap = std::unordered_map<std::string, base::File>; + +static bool IsValidLocale(const std::string& locale) { + return std::all_of(locale.cbegin(), locale.cend(), + [](const char ch) { return isalpha(ch) || ch == '-'; }); +} + +static base::File& GetDictionaryFile(const std::string& locale) { + // Keep Files open in the cache for subsequent calls. + CR_DEFINE_STATIC_LOCAL(DictionaryFileMap, cache, ()); + + const auto& it = cache.find(locale); + if (it != cache.end()) + return it->second; + const auto& inserted = cache.insert(std::make_pair(locale, base::File())); + base::File& file = inserted.first->second; + DCHECK(!file.IsValid()); + +#if defined(OS_ANDROID) + base::FilePath dir("/system/usr/hyphen-data"); +#else +#error "This configuration is not supported." +#endif + std::string filename = base::StringPrintf("hyph-%s.hyb", locale.c_str()); + base::FilePath path = dir.AppendASCII(filename); + file.Initialize(path, base::File::FLAG_OPEN | base::File::FLAG_READ); + return file; +} + +} // namespace + +namespace hyphenation { + +HyphenationImpl::HyphenationImpl(blink::mojom::HyphenationRequest request) + : binding_(this, std::move(request)) {} + +HyphenationImpl::~HyphenationImpl() {} + +// static +void HyphenationImpl::Create(blink::mojom::HyphenationRequest request) { + new HyphenationImpl(std::move(request)); +} + +void HyphenationImpl::OpenDictionary(const mojo::String& locale, + const OpenDictionaryCallback& callback) { + mojo::ScopedHandle handle; + if (IsValidLocale(locale)) { + base::File& file = GetDictionaryFile(locale); + if (file.IsValid()) + handle = mojo::WrapPlatformFile(file.Duplicate().TakePlatformFile()); + } + callback.Run(std::move(handle)); +} + +} // namespace hyphenation
diff --git a/content/browser/hyphenation/hyphenation_impl.h b/content/browser/hyphenation/hyphenation_impl.h new file mode 100644 index 0000000..9565d2bc --- /dev/null +++ b/content/browser/hyphenation/hyphenation_impl.h
@@ -0,0 +1,34 @@ +// 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 CONTENT_BROWSER_HYPHENATION_HYPHENATION_IMPL_H_ +#define CONTENT_BROWSER_HYPHENATION_HYPHENATION_IMPL_H_ + +#include "base/macros.h" +#include "mojo/public/cpp/bindings/interface_request.h" +#include "mojo/public/cpp/bindings/strong_binding.h" +#include "third_party/WebKit/public/platform/modules/hyphenation/hyphenation.mojom.h" + +namespace hyphenation { + +class HyphenationImpl : public blink::mojom::Hyphenation { + public: + static void Create(blink::mojom::HyphenationRequest); + + // Hyphenation: + void OpenDictionary(const mojo::String& locale, + const OpenDictionaryCallback& callback) override; + + private: + explicit HyphenationImpl(blink::mojom::HyphenationRequest); + ~HyphenationImpl() override; + + mojo::StrongBinding<blink::mojom::Hyphenation> binding_; + + DISALLOW_COPY_AND_ASSIGN(HyphenationImpl); +}; + +} // namespace hyphenation + +#endif // CONTENT_BROWSER_HYPHENATION_HYPHENATION_IMPL_H_
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc index 020126e..a2dccf46 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.cc +++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -819,18 +819,15 @@ const Origin& origin, const base::FilePath& path_base, net::URLRequestContext* request_context, - blink::WebIDBDataLoss* data_loss, - std::string* data_loss_message, + IndexedDBDataLossInfo* data_loss_info, bool* disk_full, base::SequencedTaskRunner* task_runner, bool clean_journal, leveldb::Status* status) { - *data_loss = blink::WebIDBDataLossNone; DefaultLevelDBFactory leveldb_factory; return IndexedDBBackingStore::Open( - indexed_db_factory, origin, path_base, request_context, data_loss, - data_loss_message, disk_full, &leveldb_factory, task_runner, - clean_journal, status); + indexed_db_factory, origin, path_base, request_context, data_loss_info, + disk_full, &leveldb_factory, task_runner, clean_journal, status); } static std::string OriginToCustomHistogramSuffix(const Origin& origin) { @@ -962,8 +959,7 @@ const Origin& origin, const base::FilePath& path_base, net::URLRequestContext* request_context, - blink::WebIDBDataLoss* data_loss, - std::string* data_loss_message, + IndexedDBDataLossInfo* data_loss_info, bool* is_disk_full, LevelDBFactory* leveldb_factory, base::SequencedTaskRunner* task_runner, @@ -971,10 +967,9 @@ leveldb::Status* status) { IDB_TRACE("IndexedDBBackingStore::Open"); DCHECK(!path_base.empty()); - *data_loss = blink::WebIDBDataLossNone; - *data_loss_message = ""; *is_disk_full = false; + data_loss_info->status = blink::WebIDBDataLossNone; *status = leveldb::Status::OK(); std::unique_ptr<LevelDBComparator> comparator(new Comparator()); @@ -1012,8 +1007,8 @@ if (leveldb_env::IndicatesDiskFull(*status)) { *is_disk_full = true; } else if (status->IsCorruption()) { - *data_loss = blink::WebIDBDataLossTotal; - *data_loss_message = leveldb_env::GetCorruptionMessage(*status); + data_loss_info->status = blink::WebIDBDataLossTotal; + data_loss_info->message = leveldb_env::GetCorruptionMessage(*status); } } @@ -1026,8 +1021,8 @@ HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_PRIOR_CORRUPTION, origin); db.reset(); - *data_loss = blink::WebIDBDataLossTotal; - *data_loss_message = + data_loss_info->status = blink::WebIDBDataLossTotal; + data_loss_info->message = "IndexedDB (database was corrupt): " + corruption_message; } else if (!IsSchemaKnown(db.get(), &is_schema_known)) { LOG(ERROR) << "IndexedDB had IO error checking schema, treating it as " @@ -1036,16 +1031,16 @@ INDEXED_DB_BACKING_STORE_OPEN_FAILED_IO_ERROR_CHECKING_SCHEMA, origin); db.reset(); - *data_loss = blink::WebIDBDataLossTotal; - *data_loss_message = "I/O error checking schema"; + data_loss_info->status = blink::WebIDBDataLossTotal; + data_loss_info->message = "I/O error checking schema"; } else if (!is_schema_known) { LOG(ERROR) << "IndexedDB backing store had unknown schema, treating it " "as failure to open"; HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_SCHEMA, origin); db.reset(); - *data_loss = blink::WebIDBDataLossTotal; - *data_loss_message = "Unknown schema"; + data_loss_info->status = blink::WebIDBDataLossTotal; + data_loss_info->message = "Unknown schema"; } }
diff --git a/content/browser/indexed_db/indexed_db_backing_store.h b/content/browser/indexed_db/indexed_db_backing_store.h index 7368eec..722a1d4 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.h +++ b/content/browser/indexed_db/indexed_db_backing_store.h
@@ -56,6 +56,7 @@ class LevelDBComparator; class LevelDBDatabase; class LevelDBFactory; +struct IndexedDBDataLossInfo; struct IndexedDBValue; class CONTENT_EXPORT IndexedDBBackingStore @@ -372,8 +373,7 @@ const url::Origin& origin, const base::FilePath& path_base, net::URLRequestContext* request_context, - blink::WebIDBDataLoss* data_loss, - std::string* data_loss_message, + IndexedDBDataLossInfo* data_loss_info, bool* disk_full, base::SequencedTaskRunner* task_runner, bool clean_journal, @@ -383,8 +383,7 @@ const url::Origin& origin, const base::FilePath& path_base, net::URLRequestContext* request_context, - blink::WebIDBDataLoss* data_loss, - std::string* data_loss_message, + IndexedDBDataLossInfo* data_loss_info, bool* disk_full, LevelDBFactory* leveldb_factory, base::SequencedTaskRunner* task_runner,
diff --git a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc index c049019d..644e608b 100644 --- a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc +++ b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
@@ -187,18 +187,12 @@ scoped_refptr<TestableIndexedDBBackingStore> OpenBackingStoreForTest( const Origin& origin, net::URLRequestContext* url_request_context) { - blink::WebIDBDataLoss data_loss; - std::string data_loss_reason; + IndexedDBDataLossInfo data_loss_info; bool disk_full; leveldb::Status status; scoped_refptr<IndexedDBBackingStore> backing_store = - OpenBackingStore(origin, - context()->data_path(), - url_request_context, - &data_loss, - &data_loss_reason, - &disk_full, - &status); + OpenBackingStore(origin, context()->data_path(), url_request_context, + &data_loss_info, &disk_full, &status); scoped_refptr<TestableIndexedDBBackingStore> testable_store = static_cast<TestableIndexedDBBackingStore*>(backing_store.get()); return testable_store; @@ -211,8 +205,7 @@ const Origin& origin, const base::FilePath& data_directory, net::URLRequestContext* request_context, - blink::WebIDBDataLoss* data_loss, - std::string* data_loss_message, + IndexedDBDataLossInfo* data_loss_info, bool* disk_full, bool first_time, leveldb::Status* status) override {
diff --git a/content/browser/indexed_db/indexed_db_callbacks.cc b/content/browser/indexed_db/indexed_db_callbacks.cc index 6c541b7..353fa45 100644 --- a/content/browser/indexed_db/indexed_db_callbacks.cc +++ b/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -7,6 +7,7 @@ #include <stddef.h> #include <algorithm> +#include <utility> #include "base/metrics/histogram.h" #include "base/strings/utf_string_conversions.h" @@ -49,7 +50,6 @@ host_transaction_id_(kNoTransaction), ipc_database_id_(kNoDatabase), ipc_database_callbacks_id_(kNoDatabaseCallbacks), - data_loss_(blink::WebIDBDataLossNone), sent_blocked_(false) {} IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host, @@ -63,7 +63,6 @@ host_transaction_id_(kNoTransaction), ipc_database_id_(kNoDatabase), ipc_database_callbacks_id_(kNoDatabaseCallbacks), - data_loss_(blink::WebIDBDataLossNone), sent_blocked_(false) {} IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host, @@ -80,7 +79,6 @@ origin_(origin), ipc_database_id_(kNoDatabase), ipc_database_callbacks_id_(ipc_database_callbacks_id), - data_loss_(blink::WebIDBDataLossNone), sent_blocked_(false) {} IndexedDBCallbacks::~IndexedDBCallbacks() {} @@ -107,7 +105,7 @@ DCHECK_EQ(kNoTransaction, host_transaction_id_); DCHECK_EQ(kNoDatabase, ipc_database_id_); DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); - DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); + DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status); std::vector<base::string16> list; for (unsigned i = 0; i < value.size(); ++i) @@ -142,11 +140,8 @@ } } -void IndexedDBCallbacks::OnDataLoss(blink::WebIDBDataLoss data_loss, - std::string data_loss_message) { - DCHECK_NE(blink::WebIDBDataLossNone, data_loss); - data_loss_ = data_loss; - data_loss_message_ = data_loss_message; +void IndexedDBCallbacks::OnDataLoss(const IndexedDBDataLossInfo& info) { + data_loss_info_ = info; } void IndexedDBCallbacks::OnUpgradeNeeded( @@ -173,8 +168,8 @@ params.ipc_database_callbacks_id = ipc_database_callbacks_id_; params.old_version = old_version; params.idb_metadata = IndexedDBDispatcherHost::ConvertMetadata(metadata); - params.data_loss = data_loss_; - params.data_loss_message = data_loss_message_; + params.data_loss = data_loss_info_.status; + params.data_loss_message = data_loss_info_.message; dispatcher_host_->Send(new IndexedDBMsg_CallbacksUpgradeNeeded(params)); if (!connection_open_start_time_.is_null()) { @@ -345,7 +340,7 @@ DCHECK_EQ(kNoTransaction, host_transaction_id_); DCHECK_EQ(kNoDatabase, ipc_database_id_); DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); - DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); + DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status); int32_t ipc_object_id = dispatcher_host_->Add(cursor.get()); std::unique_ptr<IndexedDBMsg_CallbacksSuccessIDBCursor_Params> params( @@ -384,7 +379,7 @@ DCHECK_EQ(kNoTransaction, host_transaction_id_); DCHECK_EQ(kNoDatabase, ipc_database_id_); DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); - DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); + DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status); IndexedDBCursor* idb_cursor = dispatcher_host_->GetCursorFromId(ipc_cursor_id_); @@ -435,7 +430,7 @@ DCHECK_EQ(kNoTransaction, host_transaction_id_); DCHECK_EQ(kNoDatabase, ipc_database_id_); DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); - DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); + DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status); std::vector<IndexedDBKey> msg_keys; std::vector<IndexedDBKey> msg_primary_keys; @@ -493,7 +488,7 @@ DCHECK_EQ(kNoTransaction, host_transaction_id_); DCHECK_EQ(kNoDatabase, ipc_database_id_); DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); - DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); + DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status); std::unique_ptr<IndexedDBMsg_CallbacksSuccessValue_Params> params( new IndexedDBMsg_CallbacksSuccessValue_Params()); @@ -529,7 +524,7 @@ DCHECK_EQ(kNoTransaction, host_transaction_id_); DCHECK_EQ(kNoDatabase, ipc_database_id_); DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); - DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); + DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status); std::unique_ptr<IndexedDBMsg_CallbacksSuccessArray_Params> params( new IndexedDBMsg_CallbacksSuccessArray_Params()); @@ -573,7 +568,7 @@ DCHECK_EQ(kNoTransaction, host_transaction_id_); DCHECK_EQ(kNoDatabase, ipc_database_id_); DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); - DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); + DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status); dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIndexedDBKey( ipc_thread_id_, ipc_callbacks_id_, value)); @@ -587,7 +582,7 @@ DCHECK_EQ(kNoTransaction, host_transaction_id_); DCHECK_EQ(kNoDatabase, ipc_database_id_); DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); - DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); + DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status); dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessInteger( ipc_thread_id_, ipc_callbacks_id_, value)); @@ -601,7 +596,7 @@ DCHECK_EQ(kNoTransaction, host_transaction_id_); DCHECK_EQ(kNoDatabase, ipc_database_id_); DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_); - DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_); + DCHECK_EQ(blink::WebIDBDataLossNone, data_loss_info_.status); dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessUndefined( ipc_thread_id_, ipc_callbacks_id_));
diff --git a/content/browser/indexed_db/indexed_db_callbacks.h b/content/browser/indexed_db/indexed_db_callbacks.h index 4895c3b..683a15e7 100644 --- a/content/browser/indexed_db/indexed_db_callbacks.h +++ b/content/browser/indexed_db/indexed_db_callbacks.h
@@ -31,6 +31,11 @@ struct IndexedDBReturnValue; struct IndexedDBValue; +struct IndexedDBDataLossInfo { + blink::WebIDBDataLoss status = blink::WebIDBDataLossNone; + std::string message; +}; + class CONTENT_EXPORT IndexedDBCallbacks : public base::RefCounted<IndexedDBCallbacks> { public: @@ -62,8 +67,7 @@ virtual void OnBlocked(int64_t existing_version); // IndexedDBFactory::Open - virtual void OnDataLoss(blink::WebIDBDataLoss data_loss, - std::string data_loss_message); + virtual void OnDataLoss(const IndexedDBDataLossInfo& data_loss_info); virtual void OnUpgradeNeeded( int64_t old_version, std::unique_ptr<IndexedDBConnection> connection, @@ -107,7 +111,9 @@ // IndexedDBCursor::Continue / Advance (when complete) virtual void OnSuccess(); - blink::WebIDBDataLoss data_loss() const { return data_loss_; } + const IndexedDBDataLossInfo& data_loss_info() const { + return data_loss_info_; + } void SetConnectionOpenStartTime(const base::TimeTicks& start_time); @@ -134,9 +140,8 @@ int32_t ipc_database_id_; int32_t ipc_database_callbacks_id_; - // Stored in OnDataLoss, merged with OnUpgradeNeeded response. - blink::WebIDBDataLoss data_loss_; - std::string data_loss_message_; + // Used to assert that OnSuccess is only called if there was no data loss. + IndexedDBDataLossInfo data_loss_info_; // The "blocked" event should be sent at most once per request. bool sent_blocked_;
diff --git a/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc b/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc index a922cffa..d6660df 100644 --- a/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc +++ b/content/browser/indexed_db/indexed_db_cleanup_on_io_error_unittest.cc
@@ -11,6 +11,7 @@ #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" #include "content/browser/indexed_db/indexed_db_backing_store.h" +#include "content/browser/indexed_db/indexed_db_callbacks.h" #include "content/browser/indexed_db/leveldb/leveldb_database.h" #include "content/browser/indexed_db/leveldb/mock_leveldb_factory.h" #include "testing/gmock/include/gmock/gmock.h" @@ -98,24 +99,15 @@ EXPECT_CALL(mock_leveldb_factory, OpenLevelDB(_, _, _, _)).Times(Exactly(1)); EXPECT_CALL(mock_leveldb_factory, DestroyLevelDB(_)).Times(Exactly(1)); - blink::WebIDBDataLoss data_loss = blink::WebIDBDataLossNone; - std::string data_loss_message; + content::IndexedDBDataLossInfo data_loss_info; bool disk_full = false; base::SequencedTaskRunner* task_runner = NULL; bool clean_journal = false; leveldb::Status s; scoped_refptr<IndexedDBBackingStore> backing_store = - IndexedDBBackingStore::Open(factory, - origin, - path, - request_context, - &data_loss, - &data_loss_message, - &disk_full, - &mock_leveldb_factory, - task_runner, - clean_journal, - &s); + IndexedDBBackingStore::Open( + factory, origin, path, request_context, &data_loss_info, &disk_full, + &mock_leveldb_factory, task_runner, clean_journal, &s); } TEST(IndexedDBNonRecoverableIOErrorTest, NuancedCleanupTest) { @@ -125,9 +117,7 @@ base::ScopedTempDir temp_directory; ASSERT_TRUE(temp_directory.CreateUniqueTempDir()); const base::FilePath path = temp_directory.path(); - blink::WebIDBDataLoss data_loss = - blink::WebIDBDataLossNone; - std::string data_loss_reason; + content::IndexedDBDataLossInfo data_loss_info; bool disk_full = false; base::SequencedTaskRunner* task_runner = NULL; bool clean_journal = false; @@ -147,17 +137,9 @@ leveldb_env::kNewLogger, base::File::FILE_ERROR_NO_SPACE)); scoped_refptr<IndexedDBBackingStore> backing_store = - IndexedDBBackingStore::Open(factory, - origin, - path, - request_context, - &data_loss, - &data_loss_reason, - &disk_full, - &mock_leveldb_factory, - task_runner, - clean_journal, - &s); + IndexedDBBackingStore::Open( + factory, origin, path, request_context, &data_loss_info, &disk_full, + &mock_leveldb_factory, task_runner, clean_journal, &s); ASSERT_TRUE(s.IsIOError()); busted_factory.SetOpenError(MakeIOError("some filename", @@ -165,34 +147,18 @@ leveldb_env::kNewLogger, base::File::FILE_ERROR_NO_MEMORY)); scoped_refptr<IndexedDBBackingStore> backing_store2 = - IndexedDBBackingStore::Open(factory, - origin, - path, - request_context, - &data_loss, - &data_loss_reason, - &disk_full, - &mock_leveldb_factory, - task_runner, - clean_journal, - &s); + IndexedDBBackingStore::Open( + factory, origin, path, request_context, &data_loss_info, &disk_full, + &mock_leveldb_factory, task_runner, clean_journal, &s); ASSERT_TRUE(s.IsIOError()); busted_factory.SetOpenError(MakeIOError("some filename", "some message", leveldb_env::kNewLogger, base::File::FILE_ERROR_IO)); scoped_refptr<IndexedDBBackingStore> backing_store3 = - IndexedDBBackingStore::Open(factory, - origin, - path, - request_context, - &data_loss, - &data_loss_reason, - &disk_full, - &mock_leveldb_factory, - task_runner, - clean_journal, - &s); + IndexedDBBackingStore::Open( + factory, origin, path, request_context, &data_loss_info, &disk_full, + &mock_leveldb_factory, task_runner, clean_journal, &s); ASSERT_TRUE(s.IsIOError()); busted_factory.SetOpenError(MakeIOError("some filename", @@ -200,17 +166,9 @@ leveldb_env::kNewLogger, base::File::FILE_ERROR_FAILED)); scoped_refptr<IndexedDBBackingStore> backing_store4 = - IndexedDBBackingStore::Open(factory, - origin, - path, - request_context, - &data_loss, - &data_loss_reason, - &disk_full, - &mock_leveldb_factory, - task_runner, - clean_journal, - &s); + IndexedDBBackingStore::Open( + factory, origin, path, request_context, &data_loss_info, &disk_full, + &mock_leveldb_factory, task_runner, clean_journal, &s); ASSERT_TRUE(s.IsIOError()); }
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc index 3b4b7173..82f3609c0 100644 --- a/content/browser/indexed_db/indexed_db_database.cc +++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -1740,7 +1740,8 @@ // The backing store only detects data loss when it is first opened. The // presence of existing connections means we didn't even check for data loss // so there'd better not be any. - DCHECK_NE(blink::WebIDBDataLossTotal, connection.callbacks->data_loss()); + DCHECK_NE(blink::WebIDBDataLossTotal, + connection.callbacks->data_loss_info().status); pending_open_calls_.push(connection); return; } @@ -1830,7 +1831,7 @@ DCHECK(callbacks.get()); DCHECK(connections_.count(connection.get())); if (ConnectionCount() > 1) { - DCHECK_NE(blink::WebIDBDataLossTotal, callbacks->data_loss()); + DCHECK_NE(blink::WebIDBDataLossTotal, callbacks->data_loss_info().status); // Front end ensures the event is not fired at connections that have // close_pending set. for (const auto* iter : connections_) {
diff --git a/content/browser/indexed_db/indexed_db_factory.h b/content/browser/indexed_db/indexed_db_factory.h index 1ac6625..3b64fb2 100644 --- a/content/browser/indexed_db/indexed_db_factory.h +++ b/content/browser/indexed_db/indexed_db_factory.h
@@ -31,6 +31,7 @@ class IndexedDBBackingStore; struct IndexedDBPendingConnection; +struct IndexedDBDataLossInfo; class CONTENT_EXPORT IndexedDBFactory : NON_EXPORTED_BASE(public base::RefCountedThreadSafe<IndexedDBFactory>) { @@ -91,8 +92,7 @@ const url::Origin& origin, const base::FilePath& data_directory, net::URLRequestContext* request_context, - blink::WebIDBDataLoss* data_loss, - std::string* data_loss_reason, + IndexedDBDataLossInfo* data_loss_info, bool* disk_full, leveldb::Status* status) = 0; @@ -100,8 +100,7 @@ const url::Origin& origin, const base::FilePath& data_directory, net::URLRequestContext* request_context, - blink::WebIDBDataLoss* data_loss, - std::string* data_loss_message, + IndexedDBDataLossInfo* data_loss_info, bool* disk_full, bool first_time, leveldb::Status* status) = 0;
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.cc b/content/browser/indexed_db/indexed_db_factory_impl.cc index 38836c1..1ddb6d4 100644 --- a/content/browser/indexed_db/indexed_db_factory_impl.cc +++ b/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -175,14 +175,12 @@ net::URLRequestContext* request_context) { IDB_TRACE("IndexedDBFactoryImpl::GetDatabaseNames"); // TODO(dgrogan): Plumb data_loss back to script eventually? - blink::WebIDBDataLoss data_loss; - std::string data_loss_message; + IndexedDBDataLossInfo data_loss_info; bool disk_full; leveldb::Status s; // TODO(cmumford): Handle this error - scoped_refptr<IndexedDBBackingStore> backing_store = - OpenBackingStore(origin, data_directory, request_context, &data_loss, - &data_loss_message, &disk_full, &s); + scoped_refptr<IndexedDBBackingStore> backing_store = OpenBackingStore( + origin, data_directory, request_context, &data_loss_info, &disk_full, &s); if (!backing_store.get()) { callbacks->OnError( IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError, @@ -225,13 +223,11 @@ } // TODO(dgrogan): Plumb data_loss back to script eventually? - blink::WebIDBDataLoss data_loss; - std::string data_loss_message; + IndexedDBDataLossInfo data_loss_info; bool disk_full = false; leveldb::Status s; - scoped_refptr<IndexedDBBackingStore> backing_store = - OpenBackingStore(origin, data_directory, request_context, &data_loss, - &data_loss_message, &disk_full, &s); + scoped_refptr<IndexedDBBackingStore> backing_store = OpenBackingStore( + origin, data_directory, request_context, &data_loss_info, &disk_full, &s); if (!backing_store.get()) { IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, ASCIIToUTF16( @@ -346,22 +342,20 @@ const Origin& origin, const base::FilePath& data_directory, net::URLRequestContext* request_context, - blink::WebIDBDataLoss* data_loss, - std::string* data_loss_message, + IndexedDBDataLossInfo* data_loss_info, bool* disk_full, bool first_time, leveldb::Status* status) { return IndexedDBBackingStore::Open( - this, origin, data_directory, request_context, data_loss, - data_loss_message, disk_full, context_->TaskRunner(), first_time, status); + this, origin, data_directory, request_context, data_loss_info, disk_full, + context_->TaskRunner(), first_time, status); } scoped_refptr<IndexedDBBackingStore> IndexedDBFactoryImpl::OpenBackingStore( const Origin& origin, const base::FilePath& data_directory, net::URLRequestContext* request_context, - blink::WebIDBDataLoss* data_loss, - std::string* data_loss_message, + IndexedDBDataLossInfo* data_loss_info, bool* disk_full, leveldb::Status* status) { const bool open_in_memory = data_directory.empty(); @@ -380,9 +374,9 @@ } else { first_time = !backends_opened_since_boot_.count(origin); - backing_store = OpenBackingStoreHelper( - origin, data_directory, request_context, data_loss, data_loss_message, - disk_full, first_time, status); + backing_store = + OpenBackingStoreHelper(origin, data_directory, request_context, + data_loss_info, disk_full, first_time, status); } if (backing_store.get()) { @@ -412,15 +406,14 @@ scoped_refptr<IndexedDBDatabase> database; IndexedDBDatabase::Identifier unique_identifier(origin, name); const auto& it = database_map_.find(unique_identifier); - blink::WebIDBDataLoss data_loss = blink::WebIDBDataLossNone; - std::string data_loss_message; + IndexedDBDataLossInfo data_loss_info; bool disk_full = false; bool was_open = (it != database_map_.end()); if (!was_open) { leveldb::Status s; scoped_refptr<IndexedDBBackingStore> backing_store = - OpenBackingStore(origin, data_directory, request_context, &data_loss, - &data_loss_message, &disk_full, &s); + OpenBackingStore(origin, data_directory, request_context, + &data_loss_info, &disk_full, &s); if (!backing_store.get()) { if (disk_full) { connection.callbacks->OnError( @@ -461,8 +454,8 @@ database = it->second; } - if (data_loss != blink::WebIDBDataLossNone) - connection.callbacks->OnDataLoss(data_loss, data_loss_message); + if (data_loss_info.status != blink::WebIDBDataLossNone) + connection.callbacks->OnDataLoss(data_loss_info); database->OpenConnection(connection);
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.h b/content/browser/indexed_db/indexed_db_factory_impl.h index ce224d3..345f9282 100644 --- a/content/browser/indexed_db/indexed_db_factory_impl.h +++ b/content/browser/indexed_db/indexed_db_factory_impl.h
@@ -76,8 +76,7 @@ const url::Origin& origin, const base::FilePath& data_directory, net::URLRequestContext* request_context, - blink::WebIDBDataLoss* data_loss, - std::string* data_loss_reason, + IndexedDBDataLossInfo* data_loss_info, bool* disk_full, leveldb::Status* s) override; @@ -85,8 +84,7 @@ const url::Origin& origin, const base::FilePath& data_directory, net::URLRequestContext* request_context, - blink::WebIDBDataLoss* data_loss, - std::string* data_loss_message, + IndexedDBDataLossInfo* data_loss_info, bool* disk_full, bool first_time, leveldb::Status* s) override;
diff --git a/content/browser/indexed_db/indexed_db_factory_unittest.cc b/content/browser/indexed_db/indexed_db_factory_unittest.cc index cc4cb3c..3baab1d 100644 --- a/content/browser/indexed_db/indexed_db_factory_unittest.cc +++ b/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -39,20 +39,13 @@ scoped_refptr<IndexedDBBackingStore> TestOpenBackingStore( const Origin& origin, const base::FilePath& data_directory) { - blink::WebIDBDataLoss data_loss = - blink::WebIDBDataLossNone; - std::string data_loss_message; + IndexedDBDataLossInfo data_loss_info; bool disk_full; leveldb::Status s; scoped_refptr<IndexedDBBackingStore> backing_store = - OpenBackingStore(origin, - data_directory, - NULL /* request_context */, - &data_loss, - &data_loss_message, - &disk_full, - &s); - EXPECT_EQ(blink::WebIDBDataLossNone, data_loss); + OpenBackingStore(origin, data_directory, NULL /* request_context */, + &data_loss_info, &disk_full, &s); + EXPECT_EQ(blink::WebIDBDataLossNone, data_loss_info.status); return backing_store; } @@ -221,8 +214,7 @@ const Origin& origin, const base::FilePath& data_directory, net::URLRequestContext* request_context, - blink::WebIDBDataLoss* data_loss, - std::string* data_loss_message, + IndexedDBDataLossInfo* data_loss_info, bool* disk_full, leveldb::Status* s) override { *disk_full = true; @@ -447,7 +439,7 @@ ErrorCallbacks() : MockIndexedDBCallbacks(false), saw_error_(false) {} void OnError(const IndexedDBDatabaseError& error) override { - saw_error_= true; + saw_error_ = true; } bool saw_error() const { return saw_error_; }
diff --git a/content/browser/indexed_db/mock_indexed_db_factory.h b/content/browser/indexed_db/mock_indexed_db_factory.h index 120c96a..ca073516 100644 --- a/content/browser/indexed_db/mock_indexed_db_factory.h +++ b/content/browser/indexed_db/mock_indexed_db_factory.h
@@ -57,23 +57,21 @@ protected: virtual ~MockIndexedDBFactory(); - MOCK_METHOD7(OpenBackingStore, + MOCK_METHOD6(OpenBackingStore, scoped_refptr<IndexedDBBackingStore>( const url::Origin& origin, const base::FilePath& data_directory, net::URLRequestContext* request_context, - blink::WebIDBDataLoss* data_loss, - std::string* data_loss_reason, + IndexedDBDataLossInfo* data_loss_info, bool* disk_full, leveldb::Status* s)); - MOCK_METHOD8(OpenBackingStoreHelper, + MOCK_METHOD7(OpenBackingStoreHelper, scoped_refptr<IndexedDBBackingStore>( const url::Origin& origin, const base::FilePath& data_directory, net::URLRequestContext* request_context, - blink::WebIDBDataLoss* data_loss, - std::string* data_loss_message, + IndexedDBDataLossInfo* data_loss_info, bool* disk_full, bool first_time, leveldb::Status* s));
diff --git a/content/browser/loader/async_resource_handler.cc b/content/browser/loader/async_resource_handler.cc index d038898..91d0350b 100644 --- a/content/browser/loader/async_resource_handler.cc +++ b/content/browser/loader/async_resource_handler.cc
@@ -29,6 +29,7 @@ #include "content/public/browser/resource_dispatcher_host_delegate.h" #include "content/public/common/content_features.h" #include "content/public/common/resource_response.h" +#include "ipc/ipc_message_macros.h" #include "net/base/io_buffer.h" #include "net/base/load_flags.h" #include "net/log/net_log.h" @@ -72,6 +73,14 @@ GetNumericArg("resource-buffer-max-allocation-size", &kMaxAllocationSize); } +// Updates |*cached| to |updated| and returns the difference from the old +// value. +int TrackDifference(int64_t updated, int64_t* cached) { + int difference = updated - *cached; + *cached = updated; + return difference; +} + } // namespace // Used when kOptimizeLoadingIPCForSmallResources is enabled. @@ -117,6 +126,7 @@ // Returns true if the received data is sent to the consumer. bool SendInlinedDataIfApplicable(int bytes_read, int encoded_data_length, + int encoded_body_length, IPC::Sender* sender, int request_id) { DCHECK(sender); @@ -129,7 +139,7 @@ leading_chunk_buffer_ = nullptr; sender->Send(new ResourceMsg_InlinedDataChunkReceived( - request_id, data, encoded_data_length)); + request_id, data, encoded_data_length, encoded_body_length)); return true; } @@ -206,7 +216,8 @@ inlining_helper_(new InliningHelper), last_upload_position_(0), waiting_for_upload_progress_ack_(false), - reported_transfer_size_(0) { + reported_transfer_size_(0), + reported_encoded_body_length_(0) { InitializeResourceBufferConstants(); } @@ -338,8 +349,8 @@ } if (rdh_->delegate()) { - rdh_->delegate()->OnResponseStarted( - request(), info->GetContext(), response, info->filter()); + rdh_->delegate()->OnResponseStarted(request(), info->GetContext(), + response); } NetLogObserver::PopulateResponseInfo(request(), response); @@ -439,10 +450,12 @@ return false; int encoded_data_length = CalculateEncodedDataLengthToReport(); + int encoded_body_length = CalculateEncodedBodyLengthToReport(); // Return early if InliningHelper handled the received data. if (inlining_helper_->SendInlinedDataIfApplicable( - bytes_read, encoded_data_length, filter, GetRequestID())) + bytes_read, encoded_data_length, encoded_body_length, filter, + GetRequestID())) return true; buffer_->ShrinkLastAllocation(bytes_read); @@ -460,8 +473,9 @@ int data_offset = buffer_->GetLastAllocationOffset(); - filter->Send(new ResourceMsg_DataReceived( - GetRequestID(), data_offset, bytes_read, encoded_data_length)); + filter->Send(new ResourceMsg_DataReceived(GetRequestID(), data_offset, + bytes_read, encoded_data_length, + encoded_body_length)); ++pending_data_count_; if (!buffer_->CanAllocate()) { @@ -565,10 +579,13 @@ } int AsyncResourceHandler::CalculateEncodedDataLengthToReport() { - int64_t current_transfer_size = request()->GetTotalReceivedBytes(); - int encoded_data_length = current_transfer_size - reported_transfer_size_; - reported_transfer_size_ = current_transfer_size; - return encoded_data_length; + return TrackDifference(request()->GetTotalReceivedBytes(), + &reported_transfer_size_); +} + +int AsyncResourceHandler::CalculateEncodedBodyLengthToReport() { + return TrackDifference(request()->GetRawBodyBytes(), + &reported_encoded_body_length_); } void AsyncResourceHandler::RecordHistogram() {
diff --git a/content/browser/loader/async_resource_handler.h b/content/browser/loader/async_resource_handler.h index 0991021..c087f16 100644 --- a/content/browser/loader/async_resource_handler.h +++ b/content/browser/loader/async_resource_handler.h
@@ -14,6 +14,7 @@ #include "base/timer/timer.h" #include "content/browser/loader/resource_handler.h" #include "content/browser/loader/resource_message_delegate.h" +#include "content/common/content_export.h" #include "net/base/io_buffer.h" #include "url/gurl.h" @@ -30,8 +31,8 @@ // Used to complete an asynchronous resource request in response to resource // load events from the resource dispatcher host. -class AsyncResourceHandler : public ResourceHandler, - public ResourceMessageDelegate { +class CONTENT_EXPORT AsyncResourceHandler : public ResourceHandler, + public ResourceMessageDelegate { public: AsyncResourceHandler(net::URLRequest* request, ResourceDispatcherHostImpl* rdh); @@ -70,6 +71,7 @@ void OnDefer(); bool CheckForSufficientResource(); int CalculateEncodedDataLengthToReport(); + int CalculateEncodedBodyLengthToReport(); void RecordHistogram(); scoped_refptr<ResourceBuffer> buffer_; @@ -96,6 +98,7 @@ base::RepeatingTimer progress_timer_; int64_t reported_transfer_size_; + int64_t reported_encoded_body_length_; DISALLOW_COPY_AND_ASSIGN(AsyncResourceHandler); };
diff --git a/content/browser/loader/async_resource_handler_unittest.cc b/content/browser/loader/async_resource_handler_unittest.cc new file mode 100644 index 0000000..69f2f59 --- /dev/null +++ b/content/browser/loader/async_resource_handler_unittest.cc
@@ -0,0 +1,339 @@ +// 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 "content/browser/loader/async_resource_handler.h" + +#include <stddef.h> +#include <stdint.h> +#include <memory> +#include <string> +#include <tuple> +#include <utility> +#include <vector> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/feature_list.h" +#include "base/format_macros.h" +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/process/process.h" +#include "base/run_loop.h" +#include "base/strings/stringprintf.h" +#include "content/browser/loader/resource_dispatcher_host_impl.h" +#include "content/browser/loader/resource_loader.h" +#include "content/browser/loader/resource_loader_delegate.h" +#include "content/browser/loader/resource_message_filter.h" +#include "content/browser/loader/resource_request_info_impl.h" +#include "content/common/resource_messages.h" +#include "content/common/resource_request.h" +#include "content/public/browser/resource_context.h" +#include "content/public/browser/resource_request_info.h" +#include "content/public/common/content_features.h" +#include "content/public/common/process_type.h" +#include "content/public/common/resource_type.h" +#include "content/public/test/mock_resource_context.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "ipc/ipc_message.h" +#include "ipc/ipc_message_macros.h" +#include "net/http/http_response_headers.h" +#include "net/http/http_util.h" +#include "net/ssl/client_cert_store.h" +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_job_factory_impl.h" +#include "net/url_request/url_request_test_job.h" +#include "net/url_request/url_request_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/page_transition_types.h" +#include "url/gurl.h" + +namespace content { + +namespace { + +std::string GenerateHeader(size_t response_data_size) { + return base::StringPrintf( + "HTTP/1.1 200 OK\n" + "Content-type: text/html\n" + "Content-Length: %" PRIuS "\n", + response_data_size); +} + +std::string GenerateData(size_t response_data_size) { + return std::string(response_data_size, 'a'); +} + +// This test job adds a Content-Length header and implements +// GetTotalReceivedBytes(). +class TestJob : public net::URLRequestTestJob { + public: + TestJob(net::URLRequest* request, + net::NetworkDelegate* network_delegate, + size_t response_data_size) + : net::URLRequestTestJob(request, + network_delegate, + GenerateHeader(response_data_size), + GenerateData(response_data_size), + true) {} + + static TestJob* CreateJob(net::URLRequest* request, + net::NetworkDelegate* network_delegate, + size_t response_data_size) { + return new TestJob(request, network_delegate, response_data_size); + } + + // URLRequestJob implementation: + // TODO(ricea): Move this to URLRequestTestJob. + int64_t GetTotalReceivedBytes() const override { + std::string http_headers = net::HttpUtil::ConvertHeadersBackToHTTPResponse( + response_headers_->raw_headers()); + return http_headers.size() + offset_; + } + + private: + DISALLOW_COPY_AND_ASSIGN(TestJob); +}; + +class TestJobProtocolHandler + : public net::URLRequestJobFactory::ProtocolHandler { + public: + TestJobProtocolHandler(size_t response_data_size) + : response_data_size_(response_data_size) {} + + net::URLRequestJob* MaybeCreateJob( + net::URLRequest* request, + net::NetworkDelegate* network_delegate) const override { + return TestJob::CreateJob(request, network_delegate, response_data_size_); + } + + private: + size_t response_data_size_; +}; + +// A subclass of ResourceMessageFilter that records IPC messages that are sent. +class RecordingResourceMessageFilter : public ResourceMessageFilter { + public: + RecordingResourceMessageFilter(ResourceContext* resource_context, + net::URLRequestContext* request_context) + : ResourceMessageFilter( + 0, + PROCESS_TYPE_RENDERER, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + base::Bind(&RecordingResourceMessageFilter::GetContexts, + base::Unretained(this))), + resource_context_(resource_context), + request_context_(request_context) { + set_peer_process_for_testing(base::Process::Current()); + } + + const std::vector<std::unique_ptr<IPC::Message>>& messages() const { + return messages_; + } + + // IPC::Sender implementation: + bool Send(IPC::Message* message) override { + // Unpickle the base::SharedMemoryHandle to avoid warnings about + // "MessageAttachmentSet destroyed with unconsumed descriptors". + if (message->type() == ResourceMsg_SetDataBuffer::ID) { + ResourceMsg_SetDataBuffer::Param params; + ResourceMsg_SetDataBuffer::Read(message, ¶ms); + } + messages_.push_back(base::WrapUnique(message)); + return true; + } + + private: + ~RecordingResourceMessageFilter() override {} + + void GetContexts(ResourceType resource_type, + int origin_pid, + ResourceContext** resource_context, + net::URLRequestContext** request_context) { + *resource_context = resource_context_; + *request_context = request_context_; + } + + ResourceContext* const resource_context_; + net::URLRequestContext* const request_context_; + std::vector<std::unique_ptr<IPC::Message>> messages_; +}; + +class AsyncResourceHandlerTest : public ::testing::Test, + public ResourceLoaderDelegate { + protected: + AsyncResourceHandlerTest() + : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP), context_(true) {} + + void TearDown() override { + // Prevent memory leaks. + rdh_.Shutdown(); + base::RunLoop().RunUntilIdle(); + } + + void CreateRequestWithResponseDataSize(size_t response_data_size) { + test_job_factory_.SetProtocolHandler( + "test", base::MakeUnique<TestJobProtocolHandler>(response_data_size)); + context_.set_job_factory(&test_job_factory_); + context_.Init(); + std::unique_ptr<net::URLRequest> request = context_.CreateRequest( + GURL("test:test"), net::DEFAULT_PRIORITY, nullptr); + resource_context_ = base::MakeUnique<MockResourceContext>(&context_); + filter_ = + new RecordingResourceMessageFilter(resource_context_.get(), &context_); + ResourceRequestInfoImpl* info = new ResourceRequestInfoImpl( + PROCESS_TYPE_RENDERER, // process_type + 0, // child_id + 0, // route_id + -1, // frame_tree_node_id + 0, // origin_pid + 0, // request_id + 0, // render_frame_id + false, // is_main_frame + false, // parent_is_main_frame + RESOURCE_TYPE_IMAGE, // resource_type + ui::PAGE_TRANSITION_LINK, // transition_type + false, // should_replace_current_entry + false, // is_download + false, // is_stream + false, // allow_download + false, // has_user_gesture + false, // enable load timing + false, // enable upload progress + false, // do_not_prompt_for_login + blink::WebReferrerPolicyDefault, // referrer_policy + blink::WebPageVisibilityStateVisible, // visibility_state + resource_context_.get(), // context + filter_->GetWeakPtr(), // filter + false, // report_raw_headers + true, // is_async + false, // is_using_lofi + std::string(), // original_headers + nullptr, // body + false); // initiated_in_secure_context + info->AssociateWithRequest(request.get()); + std::unique_ptr<AsyncResourceHandler> handler = + base::MakeUnique<AsyncResourceHandler>(request.get(), &rdh_); + loader_ = base::MakeUnique<ResourceLoader>( + std::move(request), std::move(handler), nullptr, this); + } + + void StartRequestAndWaitWithResponseDataSize(size_t response_data_size) { + CreateRequestWithResponseDataSize(response_data_size); + loader_->StartRequest(); + finish_waiter_.reset(new base::RunLoop); + finish_waiter_->Run(); + } + + scoped_refptr<RecordingResourceMessageFilter> filter_; + + private: + // ResourceLoaderDelegate implementation: + ResourceDispatcherHostLoginDelegate* CreateLoginDelegate( + ResourceLoader* loader, + net::AuthChallengeInfo* auth_info) override { + return nullptr; + } + + bool HandleExternalProtocol(ResourceLoader* loader, + const GURL& url) override { + return false; + } + void DidStartRequest(ResourceLoader* loader) override {} + void DidReceiveRedirect(ResourceLoader* loader, + const GURL& new_url) override {} + void DidReceiveResponse(ResourceLoader* loader) override {} + void DidFinishLoading(ResourceLoader* loader) override { + loader_.reset(); + finish_waiter_->Quit(); + } + std::unique_ptr<net::ClientCertStore> CreateClientCertStore( + ResourceLoader* loader) override { + return nullptr; + } + + TestBrowserThreadBundle thread_bundle_; + ResourceDispatcherHostImpl rdh_; + net::TestURLRequestContext context_; + net::URLRequestJobFactoryImpl test_job_factory_; + std::unique_ptr<MockResourceContext> resource_context_; + std::unique_ptr<ResourceLoader> loader_; + std::unique_ptr<base::RunLoop> finish_waiter_; +}; + +TEST_F(AsyncResourceHandlerTest, Construct) { + CreateRequestWithResponseDataSize(1); +} + +TEST_F(AsyncResourceHandlerTest, OneChunkLengths) { + // Larger than kInlinedLeadingChunkSize and smaller than + // kMaxAllocationSize. + StartRequestAndWaitWithResponseDataSize(4096); + const auto& messages = filter_->messages(); + ASSERT_EQ(4u, messages.size()); + ASSERT_EQ(ResourceMsg_DataReceived::ID, messages[2]->type()); + ResourceMsg_DataReceived::Param params; + ResourceMsg_DataReceived::Read(messages[2].get(), ¶ms); + + int encoded_data_length = std::get<3>(params); + EXPECT_EQ(4162, encoded_data_length); + int encoded_body_length = std::get<4>(params); + EXPECT_EQ(4096, encoded_body_length); +} + +TEST_F(AsyncResourceHandlerTest, InlinedChunkLengths) { + // TODO(ricea): Remove this Feature-enabling code once the feature is on by + // default. + auto feature_list = base::MakeUnique<base::FeatureList>(); + feature_list->InitializeFromCommandLine( + features::kOptimizeLoadingIPCForSmallResources.name, ""); + base::FeatureList::ClearInstanceForTesting(); + base::FeatureList::SetInstance(std::move(feature_list)); + + // Smaller than kInlinedLeadingChunkSize. + StartRequestAndWaitWithResponseDataSize(8); + const auto& messages = filter_->messages(); + ASSERT_EQ(3u, messages.size()); + ASSERT_EQ(ResourceMsg_InlinedDataChunkReceived::ID, messages[1]->type()); + ResourceMsg_InlinedDataChunkReceived::Param params; + ResourceMsg_InlinedDataChunkReceived::Read(messages[1].get(), ¶ms); + + int encoded_data_length = std::get<2>(params); + EXPECT_EQ(71, encoded_data_length); + int encoded_body_length = std::get<3>(params); + EXPECT_EQ(8, encoded_body_length); +} + +TEST_F(AsyncResourceHandlerTest, TwoChunksLengths) { + // Larger than kMaxAllocationSize. + StartRequestAndWaitWithResponseDataSize(64*1024); + const auto& messages = filter_->messages(); + ASSERT_EQ(5u, messages.size()); + ASSERT_EQ(ResourceMsg_DataReceived::ID, messages[2]->type()); + ResourceMsg_DataReceived::Param params; + ResourceMsg_DataReceived::Read(messages[2].get(), ¶ms); + + int encoded_data_length = std::get<3>(params); + EXPECT_EQ(32835, encoded_data_length); + int encoded_body_length = std::get<4>(params); + EXPECT_EQ(32768, encoded_body_length); + + ASSERT_EQ(ResourceMsg_DataReceived::ID, messages[3]->type()); + ResourceMsg_DataReceived::Read(messages[3].get(), ¶ms); + + encoded_data_length = std::get<3>(params); + EXPECT_EQ(32768, encoded_data_length); + encoded_body_length = std::get<4>(params); + EXPECT_EQ(32768, encoded_body_length); +} + +} // namespace + +} // namespace content
diff --git a/content/browser/loader/netlog_observer.cc b/content/browser/loader/netlog_observer.cc index 3f9405a..7799ce0 100644 --- a/content/browser/loader/netlog_observer.cc +++ b/content/browser/loader/netlog_observer.cc
@@ -9,8 +9,6 @@ #include "base/strings/string_util.h" #include "base/values.h" #include "content/browser/loader/resource_request_info_impl.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/content_browser_client.h" #include "content/public/common/resource_response.h" #include "net/base/load_flags.h" #include "net/http/http_response_headers.h" @@ -22,8 +20,13 @@ namespace content { const size_t kMaxNumEntries = 1000; +// static NetLogObserver* NetLogObserver::instance_ = NULL; +// static +base::LazyInstance<std::unique_ptr<base::ThreadChecker>>::Leaky + NetLogObserver::io_thread_checker_; + NetLogObserver::NetLogObserver() {} NetLogObserver::~NetLogObserver() {} @@ -36,8 +39,10 @@ } void NetLogObserver::OnAddEntry(const net::NetLog::Entry& entry) { + DCHECK(io_thread_checker_.Get().get()); + // The events that the Observer is interested in only occur on the IO thread. - if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) + if (!io_thread_checker_.Get()->CalledOnValidThread()) return; if (entry.source().type == net::NetLog::SOURCE_URL_REQUEST) @@ -45,8 +50,6 @@ } void NetLogObserver::OnAddURLRequestEntry(const net::NetLog::Entry& entry) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - bool is_begin = entry.phase() == net::NetLog::PHASE_BEGIN; bool is_end = entry.phase() == net::NetLog::PHASE_END; @@ -153,9 +156,9 @@ } } -void NetLogObserver::Attach() { +void NetLogObserver::Attach(net::NetLog* net_log) { DCHECK(!instance_); - net::NetLog* net_log = GetContentClient()->browser()->GetNetLog(); + io_thread_checker_.Get().reset(new base::ThreadChecker()); if (net_log) { instance_ = new NetLogObserver(); net_log->DeprecatedAddObserver( @@ -164,8 +167,9 @@ } void NetLogObserver::Detach() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - + DCHECK(io_thread_checker_.Get().get() && + io_thread_checker_.Get()->CalledOnValidThread()); + io_thread_checker_.Get().reset(); if (instance_) { // Safest not to do this in the destructor to maintain thread safety across // refactorings. @@ -176,7 +180,10 @@ } NetLogObserver* NetLogObserver::GetInstance() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); + if (!io_thread_checker_.Get().get()) + return nullptr; + + DCHECK(io_thread_checker_.Get()->CalledOnValidThread()); return instance_; }
diff --git a/content/browser/loader/netlog_observer.h b/content/browser/loader/netlog_observer.h index 330a502..eed2233 100644 --- a/content/browser/loader/netlog_observer.h +++ b/content/browser/loader/netlog_observer.h
@@ -8,8 +8,10 @@ #include <stdint.h> #include "base/containers/hash_tables.h" +#include "base/lazy_instance.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/threading/thread_checker.h" #include "content/public/common/resource_devtools_info.h" #include "net/log/net_log.h" @@ -34,9 +36,9 @@ // net::NetLog::ThreadSafeObserver implementation: void OnAddEntry(const net::NetLog::Entry& entry) override; - void OnAddURLRequestEntry(const net::NetLog::Entry& entry); + // The NetLog instance is passed in via the |net_log| parameter. + static void Attach(net::NetLog* net_log); - static void Attach(); static void Detach(); // Must be called on the IO thread. May return NULL if no observers @@ -52,10 +54,17 @@ ResourceInfo* GetResourceInfo(uint32_t id); + void OnAddURLRequestEntry(const net::NetLog::Entry& entry); + typedef base::hash_map<uint32_t, scoped_refptr<ResourceInfo>> RequestToInfoMap; RequestToInfoMap request_to_info_; + // Used to validate that calls to the NetLogObserver methods occur on the + // thread it was instantiated on. Typically the IO thread. + static base::LazyInstance<std::unique_ptr<base::ThreadChecker>>::Leaky + io_thread_checker_; + DISALLOW_COPY_AND_ASSIGN(NetLogObserver); };
diff --git a/content/browser/loader/resource_dispatcher_host_browsertest.cc b/content/browser/loader/resource_dispatcher_host_browsertest.cc index 12614843..b96cc73 100644 --- a/content/browser/loader/resource_dispatcher_host_browsertest.cc +++ b/content/browser/loader/resource_dispatcher_host_browsertest.cc
@@ -818,18 +818,56 @@ }; IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest, Basic) { - GURL top_url(embedded_test_server()->GetURL("/simple_page.html")); + GURL top_url(embedded_test_server()->GetURL("/page_with_subresources.html")); url::Origin top_origin(top_url); NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1); - EXPECT_EQ(1u, delegate_->data().size()); + EXPECT_EQ(8u, delegate_->data().size()); - // User-initiated top-level navigations have a first-party and initiator that - // matches the URL to which they navigate. + // All resources loaded directly by the top-level document (including the + // top-level document itself) should have a |first_party| and |initiator| + // that match the URL of the top-level document. + for (const auto& request : delegate_->data()) { + SCOPED_TRACE(request->url); + EXPECT_EQ(top_url, request->first_party); + EXPECT_EQ(top_origin, request->initiator); + } +} + +IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest, + BasicCrossSite) { + host_resolver()->AddRule("*", "127.0.0.1"); + GURL top_url(embedded_test_server()->GetURL( + "a.com", "/nested_page_with_subresources.html")); + GURL nested_url(embedded_test_server()->GetURL( + "not-a.com", "/page_with_subresources.html")); + url::Origin top_origin(top_url); + url::Origin nested_origin(nested_url); + + NavigateToURLBlockUntilNavigationsComplete(shell(), top_url, 1); + + EXPECT_EQ(9u, delegate_->data().size()); + + // The first items loaded are the top-level and nested documents. These should + // both have a |first_party| and |initiator| that match the URL of the + // top-level document: EXPECT_EQ(top_url, delegate_->data()[0]->url); EXPECT_EQ(top_url, delegate_->data()[0]->first_party); EXPECT_EQ(top_origin, delegate_->data()[0]->initiator); + + EXPECT_EQ(nested_url, delegate_->data()[1]->url); + EXPECT_EQ(top_url, delegate_->data()[1]->first_party); + EXPECT_EQ(top_origin, delegate_->data()[1]->initiator); + + // The remaining items are loaded as subresources in the nested document, and + // should have a unique first-party, and an initiator that matches the + // document in which they're embedded. + for (size_t i = 2; i < delegate_->data().size(); i++) { + SCOPED_TRACE(delegate_->data()[i]->url); + EXPECT_EQ(kURLWithUniqueOrigin, delegate_->data()[i]->first_party); + EXPECT_EQ(nested_origin, delegate_->data()[i]->initiator); + } } IN_PROC_BROWSER_TEST_F(RequestDataResourceDispatcherHostBrowserTest,
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc index 175ac72..8b3637ca 100644 --- a/content/browser/loader/resource_dispatcher_host_unittest.cc +++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -740,7 +740,7 @@ // Waits for a ShareableFileReference to be released. class ShareableFileReleaseWaiter { public: - ShareableFileReleaseWaiter(const base::FilePath& path) { + explicit ShareableFileReleaseWaiter(const base::FilePath& path) { scoped_refptr<ShareableFileReference> file = ShareableFileReference::Get(path); file->AddFinalReleaseCallback( @@ -766,7 +766,7 @@ // ResourceDispatcherHostImpl. class TestWebContentsObserver : public WebContentsObserver { public: - TestWebContentsObserver(WebContents* web_contents) + explicit TestWebContentsObserver(WebContents* web_contents) : WebContentsObserver(web_contents), resource_request_redirect_count_(0), resource_response_start_count_(0) {} @@ -1836,7 +1836,7 @@ // Now that the async IO path is in place, the IO always completes on the // initial call; so the requests have already completed. This basically // breaks the whole test. - //EXPECT_EQ(3, host_.pending_requests()); + // EXPECT_EQ(3, host_.pending_requests()); // Process test_url_2 and test_url_3 for one level so one callback is called. // We'll cancel test_url_4 (detachable) before processing it to verify that it @@ -2212,8 +2212,7 @@ // ResourceDispatcherHost::CalculateApproximateMemoryCost(). int kMemoryCostOfTest2Req = ResourceDispatcherHostImpl::kAvgBytesPerOutstandingRequest + - std::string("GET").size() + - net::URLRequestTestJob::test_url_2().spec().size(); + net::URLRequestTestJob::test_url_2().spec().size() + sizeof("GET") - 1; // Tighten the bound on the ResourceDispatcherHost, to speed things up. int kMaxCostPerProcess = 440000;
diff --git a/content/browser/loader/sync_resource_handler.cc b/content/browser/loader/sync_resource_handler.cc index 36eec61..c4217b29 100644 --- a/content/browser/loader/sync_resource_handler.cc +++ b/content/browser/loader/sync_resource_handler.cc
@@ -73,8 +73,8 @@ return false; if (rdh_->delegate()) { - rdh_->delegate()->OnResponseStarted( - request(), info->GetContext(), response, info->filter()); + rdh_->delegate()->OnResponseStarted(request(), info->GetContext(), + response); } NetLogObserver::PopulateResponseInfo(request(), response); @@ -127,6 +127,7 @@ int total_transfer_size = request()->GetTotalReceivedBytes(); result_.encoded_data_length = total_transfer_size_ + total_transfer_size; + result_.encoded_body_length = request()->GetRawBodyBytes(); ResourceHostMsg_SyncLoad::WriteReplyParams(result_message_, result_); filter->Send(result_message_);
diff --git a/content/browser/manifest/manifest_browsertest.cc b/content/browser/manifest/manifest_browsertest.cc index 0666eb4..7a9d1079 100644 --- a/content/browser/manifest/manifest_browsertest.cc +++ b/content/browser/manifest/manifest_browsertest.cc
@@ -50,7 +50,7 @@ protected: friend MockWebContentsDelegate; - ManifestBrowserTest() : console_error_count_(0), has_manifest_(false) { + ManifestBrowserTest() : console_error_count_(0) { cors_embedded_test_server_.reset(new net::EmbeddedTestServer); cors_embedded_test_server_->ServeFilesFromSourceDirectory( "content/test/data"); @@ -76,31 +76,18 @@ message_loop_runner_->Run(); } - void HasManifestAndWait() { - shell()->web_contents()->HasManifest( - base::Bind(&ManifestBrowserTest::OnHasManifest, - base::Unretained(this))); - - message_loop_runner_ = new MessageLoopRunner(); - message_loop_runner_->Run(); - } - void OnGetManifest(const GURL& manifest_url, const Manifest& manifest) { + manifest_url_ = manifest_url; manifest_ = manifest; message_loop_runner_->Quit(); } - void OnHasManifest(bool has_manifest) { - has_manifest_ = has_manifest; - message_loop_runner_->Quit(); - } - const Manifest& manifest() const { return manifest_; } - bool has_manifest() const { - return has_manifest_; + const GURL& manifest_url() const { + return manifest_url_; } unsigned int console_error_count() const { @@ -119,9 +106,9 @@ scoped_refptr<MessageLoopRunner> message_loop_runner_; std::unique_ptr<MockWebContentsDelegate> mock_web_contents_delegate_; std::unique_ptr<net::EmbeddedTestServer> cors_embedded_test_server_; + GURL manifest_url_; Manifest manifest_; int console_error_count_; - bool has_manifest_; DISALLOW_COPY_AND_ASSIGN(ManifestBrowserTest); }; @@ -142,7 +129,7 @@ } // If a page has no manifest, requesting a manifest should return the empty -// manifest. +// manifest. The URL should be empty. IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, NoManifest) { GURL test_url = GetTestUrl("manifest", "no-manifest.html"); @@ -152,14 +139,12 @@ GetManifestAndWait(); EXPECT_TRUE(manifest().IsEmpty()); - - HasManifestAndWait(); - EXPECT_FALSE(has_manifest()); + EXPECT_TRUE(manifest_url().is_empty()); EXPECT_EQ(0u, console_error_count()); } // If a page manifest points to a 404 URL, requesting the manifest should return -// the empty manifest. However, HasManifest will return true. +// the empty manifest. However, the manifest URL will be non-empty. IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, 404Manifest) { GURL test_url = GetTestUrl("manifest", "404-manifest.html"); @@ -169,14 +154,12 @@ GetManifestAndWait(); EXPECT_TRUE(manifest().IsEmpty()); - - HasManifestAndWait(); - EXPECT_TRUE(has_manifest()); + EXPECT_FALSE(manifest_url().is_empty()); EXPECT_EQ(0u, console_error_count()); } // If a page has an empty manifest, requesting the manifest should return the -// empty manifest. +// empty manifest. The manifest URL should be non-empty. IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, EmptyManifest) { GURL test_url = GetTestUrl("manifest", "empty-manifest.html"); @@ -186,14 +169,12 @@ GetManifestAndWait(); EXPECT_TRUE(manifest().IsEmpty()); - - HasManifestAndWait(); - EXPECT_TRUE(has_manifest()); + EXPECT_FALSE(manifest_url().is_empty()); EXPECT_EQ(0u, console_error_count()); } // If a page's manifest can't be parsed correctly, requesting the manifest -// should return an empty manifest. +// should return an empty manifest. The manifest URL should be non-empty. IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, ParseErrorManifest) { GURL test_url = GetTestUrl("manifest", "parse-error-manifest.html"); @@ -203,14 +184,13 @@ GetManifestAndWait(); EXPECT_TRUE(manifest().IsEmpty()); - - HasManifestAndWait(); - EXPECT_TRUE(has_manifest()); + EXPECT_FALSE(manifest_url().is_empty()); EXPECT_EQ(1u, console_error_count()); } // If a page has a manifest that can be fetched and parsed, requesting the -// manifest should return a properly filled manifest. +// manifest should return a properly filled manifest. The manifest URL should be +// non-empty. IN_PROC_BROWSER_TEST_F(ManifestBrowserTest, DummyManifest) { GURL test_url = GetTestUrl("manifest", "dummy-manifest.html"); @@ -220,9 +200,8 @@ GetManifestAndWait(); EXPECT_FALSE(manifest().IsEmpty()); + EXPECT_FALSE(manifest_url().is_empty()); - HasManifestAndWait(); - EXPECT_TRUE(has_manifest()); EXPECT_EQ(0u, console_error_count()); } @@ -238,35 +217,29 @@ { GetManifestAndWait(); EXPECT_TRUE(manifest().IsEmpty()); - - HasManifestAndWait(); - EXPECT_FALSE(has_manifest()); + EXPECT_TRUE(manifest_url().is_empty()); } { - std::string manifest_url = + std::string manifest_link = GetTestUrl("manifest", "dummy-manifest.json").spec(); ASSERT_TRUE(content::ExecuteScript( - shell(), "setManifestTo('" + manifest_url + "')")); + shell(), "setManifestTo('" + manifest_link + "')")); GetManifestAndWait(); EXPECT_FALSE(manifest().IsEmpty()); - - HasManifestAndWait(); - EXPECT_TRUE(has_manifest()); + EXPECT_FALSE(manifest_url().is_empty()); } { - std::string manifest_url = + std::string manifest_link = GetTestUrl("manifest", "empty-manifest.json").spec(); ASSERT_TRUE(content::ExecuteScript( - shell(), "setManifestTo('" + manifest_url + "')")); + shell(), "setManifestTo('" + manifest_link + "')")); GetManifestAndWait(); EXPECT_TRUE(manifest().IsEmpty()); - - HasManifestAndWait(); - EXPECT_TRUE(has_manifest()); + EXPECT_FALSE(manifest_url().is_empty()); } EXPECT_EQ(0u, console_error_count()); @@ -288,16 +261,14 @@ shell()->LoadURL(test_url); navigation_observer.Wait(); - std::string manifest_url = cors_embedded_test_server()->GetURL( + std::string manifest_link = cors_embedded_test_server()->GetURL( "/manifest/dummy-manifest.json").spec(); - ASSERT_TRUE( - content::ExecuteScript(shell(), "setManifestTo('" + manifest_url + "')")); + ASSERT_TRUE(content::ExecuteScript(shell(), + "setManifestTo('" + manifest_link + "')")); GetManifestAndWait(); EXPECT_TRUE(manifest().IsEmpty()); - - HasManifestAndWait(); - EXPECT_TRUE(has_manifest()); + EXPECT_FALSE(manifest_url().is_empty()); EXPECT_EQ(0u, console_error_count()); // The purpose of this second load is to make sure the first load is fully @@ -306,10 +277,10 @@ // reliable way to know when the fetch is finished from the browser test // except by fetching the same file from same origin, making it succeed when // it is actually fully loaded. - manifest_url = + manifest_link = embedded_test_server()->GetURL("/manifest/dummy-manifest.json").spec(); - ASSERT_TRUE( - content::ExecuteScript(shell(), "setManifestTo('" + manifest_url + "')")); + ASSERT_TRUE(content::ExecuteScript(shell(), + "setManifestTo('" + manifest_link + "')")); GetManifestAndWait(); } @@ -328,16 +299,14 @@ shell()->LoadURL(test_url); navigation_observer.Wait(); - std::string manifest_url = cors_embedded_test_server()->GetURL( + std::string manifest_link = cors_embedded_test_server()->GetURL( "/manifest/manifest-cors.json").spec(); - ASSERT_TRUE( - content::ExecuteScript(shell(), "setManifestTo('" + manifest_url + "')")); + ASSERT_TRUE(content::ExecuteScript(shell(), + "setManifestTo('" + manifest_link + "')")); GetManifestAndWait(); EXPECT_FALSE(manifest().IsEmpty()); - - HasManifestAndWait(); - EXPECT_TRUE(has_manifest()); + EXPECT_FALSE(manifest_url().is_empty()); EXPECT_EQ(0u, console_error_count()); } @@ -358,16 +327,14 @@ shell()->LoadURL(test_url); navigation_observer.Wait(); - std::string manifest_url = + std::string manifest_link = https_server->GetURL("/manifest/dummy-manifest.json").spec(); - ASSERT_TRUE( - content::ExecuteScript(shell(), "setManifestTo('" + manifest_url + "')")); + ASSERT_TRUE(content::ExecuteScript(shell(), + "setManifestTo('" + manifest_link + "')")); GetManifestAndWait(); EXPECT_TRUE(manifest().IsEmpty()); - - HasManifestAndWait(); - EXPECT_TRUE(has_manifest()); + EXPECT_FALSE(manifest_url().is_empty()); EXPECT_EQ(0u, console_error_count()); } @@ -382,10 +349,8 @@ GetManifestAndWait(); EXPECT_TRUE(manifest().IsEmpty()); + EXPECT_FALSE(manifest_url().is_empty()); EXPECT_EQ(6u, console_error_count()); - - HasManifestAndWait(); - EXPECT_TRUE(has_manifest()); } // If a page has a manifest and the page is navigated to a page without a @@ -402,9 +367,7 @@ GetManifestAndWait(); EXPECT_FALSE(manifest().IsEmpty()); - - HasManifestAndWait(); - EXPECT_TRUE(has_manifest()); + EXPECT_FALSE(manifest_url().is_empty()); EXPECT_EQ(0u, console_error_count()); } @@ -419,9 +382,7 @@ GetManifestAndWait(); EXPECT_TRUE(manifest().IsEmpty()); EXPECT_EQ(0u, console_error_count()); - - HasManifestAndWait(); - EXPECT_FALSE(has_manifest()); + EXPECT_TRUE(manifest_url().is_empty()); } } @@ -447,9 +408,7 @@ GetManifestAndWait(); EXPECT_FALSE(manifest().IsEmpty()); - - HasManifestAndWait(); - EXPECT_TRUE(has_manifest()); + EXPECT_FALSE(manifest_url().is_empty()); EXPECT_EQ(0u, console_error_count()); } @@ -477,10 +436,7 @@ GetManifestAndWait(); EXPECT_FALSE(manifest().IsEmpty()); - EXPECT_EQ(0u, console_error_count()); - - HasManifestAndWait(); - EXPECT_TRUE(has_manifest()); + EXPECT_FALSE(manifest_url().is_empty()); EXPECT_EQ(0u, console_error_count()); } @@ -536,9 +492,7 @@ GetManifestAndWait(); EXPECT_FALSE(manifest().IsEmpty()); - - HasManifestAndWait(); - EXPECT_TRUE(has_manifest()); + EXPECT_FALSE(manifest_url().is_empty()); EXPECT_EQ(0u, console_error_count()); // The custom embedded test server will fill the name field with the cookie @@ -595,9 +549,7 @@ GetManifestAndWait(); EXPECT_FALSE(manifest().IsEmpty()); - - HasManifestAndWait(); - EXPECT_TRUE(has_manifest()); + EXPECT_FALSE(manifest_url().is_empty()); EXPECT_EQ(0u, console_error_count()); // The custom embedded test server will fill set the name to 'no cookies' if
diff --git a/content/browser/manifest/manifest_manager_host.cc b/content/browser/manifest/manifest_manager_host.cc index 112c3344..ea6557f 100644 --- a/content/browser/manifest/manifest_manager_host.cc +++ b/content/browser/manifest/manifest_manager_host.cc
@@ -34,7 +34,6 @@ ManifestManagerHost::~ManifestManagerHost() { STLDeleteValues(&pending_get_callbacks_); - STLDeleteValues(&pending_has_callbacks_); } ManifestManagerHost::GetCallbackMap* @@ -45,49 +44,22 @@ return it != pending_get_callbacks_.end() ? it->second : nullptr; } -ManifestManagerHost::HasCallbackMap* -ManifestManagerHost::HasCallbackMapForFrame( - RenderFrameHost* render_frame_host) { - FrameHasCallbackMap::iterator it = - pending_has_callbacks_.find(render_frame_host); - return it != pending_has_callbacks_.end() ? it->second : nullptr; -} - void ManifestManagerHost::RenderFrameDeleted( RenderFrameHost* render_frame_host) { + GetCallbackMap* callbacks = GetCallbackMapForFrame(render_frame_host); + if (!callbacks) + return; + + // Call the callbacks with a failure state before deleting them. Do this in + // a block so the iterator is destroyed before |callbacks|. { - GetCallbackMap* callbacks = GetCallbackMapForFrame(render_frame_host); - if (!callbacks) - return; - - // Call the callbacks with a failure state before deleting them. Do this in - // a block so the iterator is destroyed before |callbacks|. - { - GetCallbackMap::const_iterator it(callbacks); - for (; !it.IsAtEnd(); it.Advance()) - it.GetCurrentValue()->Run(GURL(), Manifest()); - } - - delete callbacks; - pending_get_callbacks_.erase(render_frame_host); + GetCallbackMap::const_iterator it(callbacks); + for (; !it.IsAtEnd(); it.Advance()) + it.GetCurrentValue()->Run(GURL(), Manifest()); } - { - HasCallbackMap* callbacks = HasCallbackMapForFrame(render_frame_host); - if (!callbacks) - return; - - // Call the callbacks with a failure state before deleting them. Do this in - // a block so the iterator is destroyed before |callbacks|. - { - HasCallbackMap::const_iterator it(callbacks); - for (; !it.IsAtEnd(); it.Advance()) - it.GetCurrentValue()->Run(false); - } - - delete callbacks; - pending_has_callbacks_.erase(render_frame_host); - } + delete callbacks; + pending_get_callbacks_.erase(render_frame_host); } void ManifestManagerHost::GetManifest(RenderFrameHost* render_frame_host, @@ -104,20 +76,6 @@ render_frame_host->GetRoutingID(), request_id)); } -void ManifestManagerHost::HasManifest(RenderFrameHost* render_frame_host, - const HasManifestCallback& callback) { - HasCallbackMap* callbacks = HasCallbackMapForFrame(render_frame_host); - if (!callbacks) { - callbacks = new HasCallbackMap(); - pending_has_callbacks_[render_frame_host] = callbacks; - } - - int request_id = callbacks->Add(new HasManifestCallback(callback)); - - render_frame_host->Send(new ManifestManagerMsg_HasManifest( - render_frame_host->GetRoutingID(), request_id)); -} - bool ManifestManagerHost::OnMessageReceived( const IPC::Message& message, RenderFrameHost* render_frame_host) { bool handled = true; @@ -126,8 +84,6 @@ render_frame_host) IPC_MESSAGE_HANDLER(ManifestManagerHostMsg_RequestManifestResponse, OnRequestManifestResponse) - IPC_MESSAGE_HANDLER(ManifestManagerHostMsg_HasManifestResponse, - OnHasManifestResponse) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -203,32 +159,4 @@ } } -void ManifestManagerHost::OnHasManifestResponse( - RenderFrameHost* render_frame_host, - int request_id, - bool has_manifest) { - HasCallbackMap* callbacks = HasCallbackMapForFrame(render_frame_host); - if (!callbacks) { - DVLOG(1) << "Unexpected HasManifestResponse from renderer. " - "Killing renderer."; - KillRenderer(render_frame_host); - return; - } - - HasManifestCallback* callback = callbacks->Lookup(request_id); - if (!callback) { - DVLOG(1) << "Received a request_id (" << request_id << ") from renderer " - "with no associated callback. Killing renderer."; - KillRenderer(render_frame_host); - return; - } - - callback->Run(has_manifest); - callbacks->Remove(request_id); - if (callbacks->IsEmpty()) { - delete callbacks; - pending_has_callbacks_.erase(render_frame_host); - } -} - } // namespace content
diff --git a/content/browser/manifest/manifest_manager_host.h b/content/browser/manifest/manifest_manager_host.h index 810f525a..ce593ecc 100644 --- a/content/browser/manifest/manifest_manager_host.h +++ b/content/browser/manifest/manifest_manager_host.h
@@ -26,38 +26,27 @@ using GetManifestCallback = base::Callback<void(const GURL&, const Manifest&)>; - using HasManifestCallback = base::Callback<void(bool)>; // Calls the given callback with the manifest associated with the // given RenderFrameHost. If the frame has no manifest or if getting it failed // the callback will have an empty manifest. void GetManifest(RenderFrameHost*, const GetManifestCallback&); - // Calls the given callback with a bool indicating whether or not the document - // associated with the given RenderFrameHost has a manifest. - void HasManifest(RenderFrameHost*, const HasManifestCallback&); - // WebContentsObserver bool OnMessageReceived(const IPC::Message&, RenderFrameHost*) override; void RenderFrameDeleted(RenderFrameHost*) override; private: using GetCallbackMap = IDMap<GetManifestCallback, IDMapOwnPointer>; - using HasCallbackMap = IDMap<HasManifestCallback, IDMapOwnPointer>; using FrameGetCallbackMap = base::hash_map<RenderFrameHost*, GetCallbackMap*>; - using FrameHasCallbackMap = base::hash_map<RenderFrameHost*, HasCallbackMap*>; void OnRequestManifestResponse( RenderFrameHost*, int request_id, const GURL&, const Manifest&); - void OnHasManifestResponse( - RenderFrameHost*, int request_id, bool); // Returns the CallbackMap associated with the given RenderFrameHost, or null. GetCallbackMap* GetCallbackMapForFrame(RenderFrameHost*); - HasCallbackMap* HasCallbackMapForFrame(RenderFrameHost*); FrameGetCallbackMap pending_get_callbacks_; - FrameHasCallbackMap pending_has_callbacks_; DISALLOW_COPY_AND_ASSIGN(ManifestManagerHost); };
diff --git a/content/browser/media/webrtc/webrtc_eventlog_host.cc b/content/browser/media/webrtc/webrtc_eventlog_host.cc index 279ed48..80aec9a 100644 --- a/content/browser/media/webrtc/webrtc_eventlog_host.cc +++ b/content/browser/media/webrtc/webrtc_eventlog_host.cc
@@ -78,14 +78,15 @@ void WebRTCEventLogHost::PeerConnectionAdded(int peer_connection_local_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK(std::find(active_peer_connection_local_ids_.begin(), - active_peer_connection_local_ids_.end(), - peer_connection_local_id) == - active_peer_connection_local_ids_.end()); - active_peer_connection_local_ids_.push_back(peer_connection_local_id); - if (rtc_event_logging_enabled_ && - number_active_log_files_ < kMaxNumberLogFiles) { - StartEventLogForPeerConnection(peer_connection_local_id); + if (std::find(active_peer_connection_local_ids_.begin(), + active_peer_connection_local_ids_.end(), + peer_connection_local_id) == + active_peer_connection_local_ids_.end()) { + active_peer_connection_local_ids_.push_back(peer_connection_local_id); + if (rtc_event_logging_enabled_ && + number_active_log_files_ < kMaxNumberLogFiles) { + StartEventLogForPeerConnection(peer_connection_local_id); + } } } @@ -94,8 +95,9 @@ const auto found = std::find(active_peer_connection_local_ids_.begin(), active_peer_connection_local_ids_.end(), peer_connection_local_id); - DCHECK(found != active_peer_connection_local_ids_.end()); - active_peer_connection_local_ids_.erase(found); + if (found != active_peer_connection_local_ids_.end()) { + active_peer_connection_local_ids_.erase(found); + } } bool WebRTCEventLogHost::StartWebRTCEventLog(const base::FilePath& file_path) {
diff --git a/content/browser/memory/memory_coordinator_browsertest.cc b/content/browser/memory/memory_coordinator_browsertest.cc new file mode 100644 index 0000000..6000ce94 --- /dev/null +++ b/content/browser/memory/memory_coordinator_browsertest.cc
@@ -0,0 +1,36 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/memory_coordinator/browser/memory_coordinator.h" +#include "components/memory_coordinator/common/memory_coordinator_features.h" +#include "content/browser/browser_main_loop.h" +#include "content/public/test/content_browser_test.h" +#include "content/public/test/content_browser_test_utils.h" + +namespace content { + +class MemoryCoordinatorTest : public ContentBrowserTest { + public: + MemoryCoordinatorTest() {} + + void SetUp() override { + memory_coordinator::EnableForTesting(); + ContentBrowserTest::SetUp(); + } + + protected: + memory_coordinator::MemoryCoordinator* memory_coordinator() { + return BrowserMainLoop::GetInstance()->memory_coordinator(); + } + + DISALLOW_COPY_AND_ASSIGN(MemoryCoordinatorTest); +}; + +IN_PROC_BROWSER_TEST_F(MemoryCoordinatorTest, HandleAdded) { + GURL url = GetTestUrl("", "simple_page.html"); + NavigateToURL(shell(), url); + EXPECT_EQ(1u, memory_coordinator()->NumChildrenForTesting()); +} + +} // namespace content
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.h b/content/browser/renderer_host/browser_compositor_view_mac.h index e2bb10e..119a3b3 100644 --- a/content/browser/renderer_host/browser_compositor_view_mac.h +++ b/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -122,6 +122,7 @@ const base::TimeTicks& timebase, const base::TimeDelta& interval) override; void SetBeginFrameSource(cc::BeginFrameSource* source) override; + bool IsAutoResizeEnabled() const override; // cc::BeginFrameObserver implementation. void OnBeginFrame(const cc::BeginFrameArgs& args) override;
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.mm b/content/browser/renderer_host/browser_compositor_view_mac.mm index a8e2fa9..a83fc5a 100644 --- a/content/browser/renderer_host/browser_compositor_view_mac.mm +++ b/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -451,6 +451,11 @@ begin_frame_source_->AddObserver(this); } +bool BrowserCompositorMac::IsAutoResizeEnabled() const { + NOTREACHED(); + return false; +} + //////////////////////////////////////////////////////////////////////////////// // cc::BeginFrameSourceBase, public:
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index 838ec057..21519727a 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -183,7 +183,6 @@ gfx::Rect(frame.gl_frame_data->size)); context_provider_->ContextSupport()->Swap(); } - client_->DidSwapBuffers(); } bool BindToClient(cc::OutputSurfaceClient* client) override { @@ -267,7 +266,6 @@ void SwapBuffers(cc::CompositorFrame frame) override { surface_->SwapBuffers(); PostSwapBuffersComplete(); - client_->DidSwapBuffers(); } void Destroy() { @@ -298,7 +296,7 @@ base::LazyInstance<cc::SurfaceManager> g_surface_manager = LAZY_INSTANCE_INITIALIZER; -int g_surface_id_namespace = 0; +int g_surface_client_id = 0; class SingleThreadTaskGraphRunner : public cc::SingleThreadTaskGraphRunner { public: @@ -342,10 +340,10 @@ std::unique_ptr<cc::SurfaceIdAllocator> CompositorImpl::CreateSurfaceIdAllocator() { std::unique_ptr<cc::SurfaceIdAllocator> allocator( - new cc::SurfaceIdAllocator(++g_surface_id_namespace)); + new cc::SurfaceIdAllocator(++g_surface_client_id)); cc::SurfaceManager* manager = GetSurfaceManager(); DCHECK(manager); - allocator->RegisterSurfaceIdNamespace(manager); + allocator->RegisterSurfaceClientId(manager); return allocator; } @@ -475,7 +473,7 @@ host_ = cc::LayerTreeHost::CreateSingleThreaded(this, ¶ms); DCHECK(!host_->visible()); host_->SetRootLayer(root_layer_); - host_->set_surface_id_namespace(surface_id_allocator_->id_namespace()); + host_->set_surface_client_id(surface_id_allocator_->client_id()); host_->SetViewportSize(size_); host_->set_has_transparent_background(has_transparent_background_); host_->SetDeviceScaleFactor(device_scale_factor_); @@ -705,9 +703,9 @@ display_.reset(new cc::Display( manager, HostSharedBitmapManager::current(), BrowserGpuMemoryBufferManager::current(), - host_->settings().renderer_settings, - surface_id_allocator_->id_namespace(), std::move(begin_frame_source), - std::move(display_output_surface), std::move(scheduler), + host_->settings().renderer_settings, surface_id_allocator_->client_id(), + std::move(begin_frame_source), std::move(display_output_surface), + std::move(scheduler), base::MakeUnique<cc::TextureMailboxDeleter>(task_runner))); std::unique_ptr<cc::SurfaceDisplayOutputSurface> delegated_output_surface(
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc index 78e5ca7..43dd42fd 100644 --- a/content/browser/renderer_host/delegated_frame_host.cc +++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -44,7 +44,7 @@ const cc::SurfaceSequence& sequence) { std::vector<uint32_t> sequences; sequences.push_back(sequence.sequence); - manager->DidSatisfySequences(sequence.id_namespace, &sequences); + manager->DidSatisfySequences(sequence.client_id, &sequences); } void RequireCallback(cc::SurfaceManager* manager, @@ -78,7 +78,7 @@ factory->GetContextFactory()->AddObserver(this); id_allocator_ = factory->GetContextFactory()->CreateSurfaceIdAllocator(); factory->GetSurfaceManager()->RegisterSurfaceFactoryClient( - id_allocator_->id_namespace(), this); + id_allocator_->client_id(), this); } void DelegatedFrameHost::WasShown(const ui::LatencyInfo& latency_info) { @@ -204,8 +204,8 @@ frame_subscriber_.reset(); } -uint32_t DelegatedFrameHost::GetSurfaceIdNamespace() { - return id_allocator_->id_namespace(); +uint32_t DelegatedFrameHost::GetSurfaceClientId() { + return id_allocator_->client_id(); } cc::SurfaceId DelegatedFrameHost::SurfaceIdAtPoint( @@ -226,7 +226,7 @@ void DelegatedFrameHost::TransformPointToLocalCoordSpace( const gfx::Point& point, - cc::SurfaceId original_surface, + const cc::SurfaceId& original_surface, gfx::Point* transformed_point) { *transformed_point = point; if (surface_id_.is_null() || original_surface == surface_id_) @@ -390,6 +390,9 @@ void DelegatedFrameHost::SwapDelegatedFrame(uint32_t output_surface_id, cc::CompositorFrame frame) { DCHECK(frame.delegated_frame_data.get()); +#if defined(OS_CHROMEOS) + DCHECK(!resize_lock_ || !client_->IsAutoResizeEnabled()); +#endif cc::DelegatedFrameData* frame_data = frame.delegated_frame_data.get(); float frame_device_scale_factor = frame.metadata.device_scale_factor; @@ -817,7 +820,7 @@ if (!surface_id_.is_null()) surface_factory_->Destroy(surface_id_); factory->GetSurfaceManager()->UnregisterSurfaceFactoryClient( - id_allocator_->id_namespace()); + id_allocator_->client_id()); DCHECK(!vsync_manager_.get()); } @@ -833,9 +836,9 @@ vsync_manager_->AddObserver(this); ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); - uint32_t parent = compositor->surface_id_allocator()->id_namespace(); + uint32_t parent = compositor->surface_id_allocator()->client_id(); factory->GetSurfaceManager()->RegisterSurfaceNamespaceHierarchy( - parent, id_allocator_->id_namespace()); + parent, id_allocator_->client_id()); } void DelegatedFrameHost::ResetCompositor() { @@ -853,9 +856,9 @@ } ImageTransportFactory* factory = ImageTransportFactory::GetInstance(); - uint32_t parent = compositor_->surface_id_allocator()->id_namespace(); + uint32_t parent = compositor_->surface_id_allocator()->client_id(); factory->GetSurfaceManager()->UnregisterSurfaceNamespaceHierarchy( - parent, id_allocator_->id_namespace()); + parent, id_allocator_->client_id()); compositor_ = nullptr; }
diff --git a/content/browser/renderer_host/delegated_frame_host.h b/content/browser/renderer_host/delegated_frame_host.h index d539e9e..3a91275 100644 --- a/content/browser/renderer_host/delegated_frame_host.h +++ b/content/browser/renderer_host/delegated_frame_host.h
@@ -81,6 +81,7 @@ const base::TimeTicks& timebase, const base::TimeDelta& interval) = 0; virtual void SetBeginFrameSource(cc::BeginFrameSource* source) = 0; + virtual bool IsAutoResizeEnabled() const = 0; }; // The DelegatedFrameHost is used to host all of the RenderWidgetHostView state @@ -158,7 +159,7 @@ std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber); void EndFrameSubscription(); bool HasFrameSubscriber() const { return !!frame_subscriber_; } - uint32_t GetSurfaceIdNamespace(); + uint32_t GetSurfaceClientId(); // Returns a null SurfaceId if this DelegatedFrameHost has not yet created // a compositor Surface. cc::SurfaceId SurfaceIdAtPoint(cc::SurfaceHittestDelegate* delegate, @@ -170,7 +171,7 @@ // to a point. If a Surface has not yet been created this returns the // same point with no transform applied. void TransformPointToLocalCoordSpace(const gfx::Point& point, - cc::SurfaceId original_surface, + const cc::SurfaceId& original_surface, gfx::Point* transformed_point); // Exposed for tests.
diff --git a/content/browser/renderer_host/input/synthetic_gesture.cc b/content/browser/renderer_host/input/synthetic_gesture.cc index b334af1..cbe9e145 100644 --- a/content/browser/renderer_host/input/synthetic_gesture.cc +++ b/content/browser/renderer_host/input/synthetic_gesture.cc
@@ -43,12 +43,10 @@ case SyntheticGestureParams::TAP_GESTURE: return CreateGesture<SyntheticTapGesture, SyntheticTapGestureParams>(gesture_params); - case SyntheticGestureParams::POINTER_ACTION: - return CreateGesture<SyntheticPointerAction, - SyntheticPointerActionParams>(gesture_params); + default: + NOTREACHED() << "Invalid synthetic gesture type"; + return nullptr; } - NOTREACHED() << "Invalid synthetic gesture type"; - return std::unique_ptr<SyntheticGesture>(); } } // namespace content
diff --git a/content/browser/renderer_host/input/synthetic_gesture.h b/content/browser/renderer_host/input/synthetic_gesture.h index f880e5d..90d4990 100644 --- a/content/browser/renderer_host/input/synthetic_gesture.h +++ b/content/browser/renderer_host/input/synthetic_gesture.h
@@ -17,7 +17,7 @@ class SyntheticGestureTarget; // Base class for synthetic gesture implementations. A synthetic gesture class -// is responsible for forwaring InputEvents, simulating the gesture, to a +// is responsible for forwarding InputEvents, simulating the gesture, to a // SyntheticGestureTarget. // // Adding new gesture types involved the following steps: @@ -38,6 +38,9 @@ enum Result { GESTURE_RUNNING, GESTURE_FINISHED, + // Received when the user input parameters for SyntheticPointerAction are + // invalid. + POINTER_ACTION_INPUT_INVALID, GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED, GESTURE_RESULT_MAX = GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED };
diff --git a/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc b/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc index 748f0ae..543cfdc 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc +++ b/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
@@ -1472,68 +1472,6 @@ base::TimeDelta::FromMilliseconds(params.duration_ms)); } -TEST_F(SyntheticGestureControllerTest, PointerTouchAction) { - CreateControllerAndTarget<MockSyntheticPointerTouchActionTarget>(); - - SyntheticPointerActionParams params = SyntheticPointerActionParams( - SyntheticPointerActionParams::PointerActionType::PRESS); - params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; - params.set_index(0); - params.set_position(gfx::PointF(54, 89)); - SyntheticTouchPointer synthetic_pointer; - - std::unique_ptr<SyntheticPointerAction> gesture( - new SyntheticPointerAction(params, &synthetic_pointer)); - QueueSyntheticGesture(std::move(gesture)); - FlushInputUntilComplete(); - - MockSyntheticPointerTouchActionTarget* pointer_touch_target = - static_cast<MockSyntheticPointerTouchActionTarget*>(target_); - EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchStart); - EXPECT_EQ(pointer_touch_target->positions(0), params.position()); - EXPECT_EQ(pointer_touch_target->states(0), WebTouchPoint::StatePressed); - ASSERT_EQ(pointer_touch_target->touch_length(), 1U); - - params.set_index(1); - params.set_position(gfx::PointF(79, 132)); - gesture.reset(new SyntheticPointerAction(params, &synthetic_pointer)); - QueueSyntheticGesture(std::move(gesture)); - FlushInputUntilComplete(); - - pointer_touch_target = - static_cast<MockSyntheticPointerTouchActionTarget*>(target_); - EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchStart); - EXPECT_EQ(pointer_touch_target->indexes(1), params.index()); - EXPECT_EQ(pointer_touch_target->positions(1), params.position()); - EXPECT_EQ(pointer_touch_target->states(1), WebTouchPoint::StatePressed); - ASSERT_EQ(pointer_touch_target->touch_length(), 2U); - - params.set_pointer_action_type( - SyntheticPointerActionParams::PointerActionType::MOVE); - params.set_position(gfx::PointF(133, 156)); - gesture.reset(new SyntheticPointerAction(params, &synthetic_pointer)); - QueueSyntheticGesture(std::move(gesture)); - FlushInputUntilComplete(); - - pointer_touch_target = - static_cast<MockSyntheticPointerTouchActionTarget*>(target_); - EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchMove); - EXPECT_EQ(pointer_touch_target->positions(1), params.position()); - EXPECT_EQ(pointer_touch_target->states(1), WebTouchPoint::StateMoved); - ASSERT_EQ(pointer_touch_target->touch_length(), 2U); - - params.set_pointer_action_type( - SyntheticPointerActionParams::PointerActionType::RELEASE); - gesture.reset(new SyntheticPointerAction(params, &synthetic_pointer)); - QueueSyntheticGesture(std::move(gesture)); - FlushInputUntilComplete(); - - pointer_touch_target = - static_cast<MockSyntheticPointerTouchActionTarget*>(target_); - EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchEnd); - EXPECT_EQ(pointer_touch_target->states(1), WebTouchPoint::StateReleased); -} - } // namespace -} // namespace content +} // namespace content \ No newline at end of file
diff --git a/content/browser/renderer_host/input/synthetic_gesture_target_base.cc b/content/browser/renderer_host/input/synthetic_gesture_target_base.cc index b6fed78..cb568bf 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_target_base.cc +++ b/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
@@ -56,13 +56,11 @@ static_cast<const WebTouchEvent&>(event); // Check that all touch pointers are within the content bounds. - if (web_touch.type == WebInputEvent::TouchStart) { - for (unsigned i = 0; i < web_touch.touchesLength; i++) - CHECK(web_touch.touches[i].state != WebTouchPoint::StatePressed || - PointIsWithinContents(web_touch.touches[i].position.x, - web_touch.touches[i].position.y)) - << "Touch coordinates are not within content bounds on TouchStart."; - } + for (unsigned i = 0; i < web_touch.touchesLength; i++) + CHECK(web_touch.touches[i].state != WebTouchPoint::StatePressed || + PointIsWithinContents(web_touch.touches[i].position.x, + web_touch.touches[i].position.y)) + << "Touch coordinates are not within content bounds on TouchStart."; DispatchWebTouchEventToPlatform(web_touch, latency_info); } else if (event.type == WebInputEvent::MouseWheel) {
diff --git a/content/browser/renderer_host/input/synthetic_mouse_pointer.cc b/content/browser/renderer_host/input/synthetic_mouse_pointer.cc index 042603fe..556d1fe 100644 --- a/content/browser/renderer_host/input/synthetic_mouse_pointer.cc +++ b/content/browser/renderer_host/input/synthetic_mouse_pointer.cc
@@ -46,4 +46,9 @@ mouse_event_.clickCount = 1; } +SyntheticGestureParams::GestureSourceType SyntheticMousePointer::SourceType() + const { + return SyntheticGestureParams::MOUSE_INPUT; +} + } // namespace content
diff --git a/content/browser/renderer_host/input/synthetic_mouse_pointer.h b/content/browser/renderer_host/input/synthetic_mouse_pointer.h index a5fbf04..fcd3961 100644 --- a/content/browser/renderer_host/input/synthetic_mouse_pointer.h +++ b/content/browser/renderer_host/input/synthetic_mouse_pointer.h
@@ -33,6 +33,8 @@ SyntheticGestureTarget* target, const base::TimeTicks& timestamp) override; + SyntheticGestureParams::GestureSourceType SourceType() const override; + private: blink::WebMouseEvent mouse_event_; DISALLOW_COPY_AND_ASSIGN(SyntheticMousePointer);
diff --git a/content/browser/renderer_host/input/synthetic_pointer.h b/content/browser/renderer_host/input/synthetic_pointer.h index b102a07..bdd1e82 100644 --- a/content/browser/renderer_host/input/synthetic_pointer.h +++ b/content/browser/renderer_host/input/synthetic_pointer.h
@@ -40,6 +40,8 @@ SyntheticGestureTarget* target, const base::TimeTicks& timestamp) = 0; + virtual SyntheticGestureParams::GestureSourceType SourceType() const = 0; + protected: static double ConvertTimestampToSeconds(const base::TimeTicks& timestamp);
diff --git a/content/browser/renderer_host/input/synthetic_pointer_action.cc b/content/browser/renderer_host/input/synthetic_pointer_action.cc index 6353f34..f19e8f6a 100644 --- a/content/browser/renderer_host/input/synthetic_pointer_action.cc +++ b/content/browser/renderer_host/input/synthetic_pointer_action.cc
@@ -15,45 +15,76 @@ : params_(params) {} SyntheticPointerAction::SyntheticPointerAction( - const SyntheticPointerActionParams& params, - SyntheticPointer* synthetic_pointer) - : params_(params), synthetic_pointer_(synthetic_pointer) {} + std::unique_ptr<std::vector<SyntheticPointerActionParams>> param_list, + SyntheticPointer* synthetic_pointer, + IndexMap* index_map) + : param_list_(std::move(param_list)), + synthetic_pointer_(synthetic_pointer), + index_map_(index_map) {} SyntheticPointerAction::~SyntheticPointerAction() {} SyntheticGesture::Result SyntheticPointerAction::ForwardInputEvents( const base::TimeTicks& timestamp, SyntheticGestureTarget* target) { - if (params_.gesture_source_type == SyntheticGestureParams::DEFAULT_INPUT) - params_.gesture_source_type = - target->GetDefaultSyntheticGestureSourceType(); - - DCHECK_NE(params_.gesture_source_type, SyntheticGestureParams::DEFAULT_INPUT); - - ForwardTouchOrMouseInputEvents(timestamp, target); - return SyntheticGesture::GESTURE_FINISHED; + DCHECK(synthetic_pointer_); + return ForwardTouchOrMouseInputEvents(timestamp, target); } -void SyntheticPointerAction::ForwardTouchOrMouseInputEvents( +SyntheticGesture::Result SyntheticPointerAction::ForwardTouchOrMouseInputEvents( const base::TimeTicks& timestamp, SyntheticGestureTarget* target) { - switch (params_.pointer_action_type()) { - case SyntheticPointerActionParams::PointerActionType::PRESS: - synthetic_pointer_->Press(params_.position().x(), params_.position().y(), - target, timestamp); - break; - case SyntheticPointerActionParams::PointerActionType::MOVE: - synthetic_pointer_->Move(params_.index(), params_.position().x(), - params_.position().y(), target, timestamp); - break; - case SyntheticPointerActionParams::PointerActionType::RELEASE: - synthetic_pointer_->Release(params_.index(), target, timestamp); - break; - default: - NOTREACHED(); - break; + int point_index; + for (const SyntheticPointerActionParams& params : *param_list_) { + if (!UserInputCheck(params)) + return POINTER_ACTION_INPUT_INVALID; + + switch (params.pointer_action_type()) { + case SyntheticPointerActionParams::PointerActionType::PRESS: + point_index = synthetic_pointer_->Press( + params.position().x(), params.position().y(), target, timestamp); + SetPointIndex(params.index(), point_index); + break; + case SyntheticPointerActionParams::PointerActionType::MOVE: + point_index = GetPointIndex(params.index()); + synthetic_pointer_->Move(point_index, params.position().x(), + params.position().y(), target, timestamp); + break; + case SyntheticPointerActionParams::PointerActionType::RELEASE: + point_index = GetPointIndex(params.index()); + synthetic_pointer_->Release(point_index, target, timestamp); + SetPointIndex(params.index(), -1); + break; + default: + return POINTER_ACTION_INPUT_INVALID; + } } synthetic_pointer_->DispatchEvent(target, timestamp); + return GESTURE_FINISHED; +} + +bool SyntheticPointerAction::UserInputCheck( + const SyntheticPointerActionParams& params) { + if (params.index() < 0 || params.index() >= WebTouchEvent::touchesLengthCap) + return false; + + if (synthetic_pointer_->SourceType() != params.gesture_source_type) + return false; + + if (params.pointer_action_type() == + SyntheticPointerActionParams::PointerActionType::PRESS && + GetPointIndex(params.index()) >= 0) { + return false; + } + + if ((params.pointer_action_type() == + SyntheticPointerActionParams::PointerActionType::MOVE || + params.pointer_action_type() == + SyntheticPointerActionParams::PointerActionType::RELEASE) && + GetPointIndex(params.index()) < 0) { + return false; + } + return true; } } // namespace content
diff --git a/content/browser/renderer_host/input/synthetic_pointer_action.h b/content/browser/renderer_host/input/synthetic_pointer_action.h index 23b23fa..683d1b7 100644 --- a/content/browser/renderer_host/input/synthetic_pointer_action.h +++ b/content/browser/renderer_host/input/synthetic_pointer_action.h
@@ -5,6 +5,7 @@ #ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_POINTER_ACTION_H_ #define CONTENT_BROWSER_RENDERER_HOST_INPUT_SYNTHETIC_POINTER_ACTION_H_ +#include <array> #include "base/macros.h" #include "content/browser/renderer_host/input/synthetic_gesture.h" #include "content/browser/renderer_host/input/synthetic_gesture_target.h" @@ -12,25 +13,51 @@ #include "content/common/content_export.h" #include "content/common/input/synthetic_pointer_action_params.h" +using blink::WebTouchEvent; + namespace content { class CONTENT_EXPORT SyntheticPointerAction : public SyntheticGesture { public: - explicit SyntheticPointerAction(const SyntheticPointerActionParams& params); - SyntheticPointerAction(const SyntheticPointerActionParams& params, - SyntheticPointer* synthetic_pointer); + using IndexMap = std::array<int, WebTouchEvent::touchesLengthCap>; + + SyntheticPointerAction( + std::unique_ptr<std::vector<SyntheticPointerActionParams>> param_list, + SyntheticPointer* synthetic_pointer, + IndexMap* index_map); ~SyntheticPointerAction() override; SyntheticGesture::Result ForwardInputEvents( const base::TimeTicks& timestamp, SyntheticGestureTarget* target) override; - void ForwardTouchOrMouseInputEvents(const base::TimeTicks& timestamp, - SyntheticGestureTarget* target); - private: - SyntheticPointerActionParams params_; + explicit SyntheticPointerAction(const SyntheticPointerActionParams& params); + SyntheticGesture::Result ForwardTouchOrMouseInputEvents( + const base::TimeTicks& timestamp, + SyntheticGestureTarget* target); + int GetPointIndex(int index) const { return (*index_map_)[index]; } + void SetPointIndex(int index, int point_index) { + (*index_map_)[index] = point_index; + } + + // Check if the user inputs in the SyntheticPointerActionParams can generate + // a valid sequence of pointer actions. + bool UserInputCheck(const SyntheticPointerActionParams& params); + + // SyntheticGestureController is responsible to create the + // SyntheticPointerActions and control when to forward them. + // This will be passed from SyntheticGestureController, which will reset its + // value to push a new batch of action parameters. + // This contains a list of pointer actions which will be dispatched together. + const std::unique_ptr<std::vector<SyntheticPointerActionParams>> param_list_; + // These two objects will be owned by SyntheticGestureController, which + // will manage their lifetime by initiating them when it starts processing a + // pointer action sequence and resetting them when it finishes. SyntheticPointer* synthetic_pointer_; + IndexMap* index_map_; + + SyntheticPointerActionParams params_; DISALLOW_COPY_AND_ASSIGN(SyntheticPointerAction); };
diff --git a/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc b/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc new file mode 100644 index 0000000..06701fdb --- /dev/null +++ b/content/browser/renderer_host/input/synthetic_pointer_action_unittest.cc
@@ -0,0 +1,333 @@ +// 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 "base/bind.h" +#include "base/time/time.h" +#include "content/browser/renderer_host/input/synthetic_gesture.h" +#include "content/browser/renderer_host/input/synthetic_gesture_target.h" +#include "content/browser/renderer_host/input/synthetic_pointer_action.h" +#include "content/browser/renderer_host/input/synthetic_touch_pointer.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/gfx/geometry/point.h" +#include "ui/gfx/geometry/point_f.h" + +using blink::WebInputEvent; +using blink::WebTouchEvent; +using blink::WebTouchPoint; + +namespace content { + +namespace { + +class MockSyntheticPointerActionTarget : public SyntheticGestureTarget { + public: + MockSyntheticPointerActionTarget() {} + ~MockSyntheticPointerActionTarget() override {} + + // SyntheticGestureTarget: + void SetNeedsFlush() override { NOTIMPLEMENTED(); } + + base::TimeDelta PointerAssumedStoppedTime() const override { + NOTIMPLEMENTED(); + return base::TimeDelta(); + } + + float GetTouchSlopInDips() const override { + NOTIMPLEMENTED(); + return 0.0f; + } + + float GetMinScalingSpanInDips() const override { + NOTIMPLEMENTED(); + return 0.0f; + } + + WebInputEvent::Type type() const { return type_; } + + protected: + WebInputEvent::Type type_; +}; + +class MockSyntheticPointerTouchActionTarget + : public MockSyntheticPointerActionTarget { + public: + MockSyntheticPointerTouchActionTarget() {} + ~MockSyntheticPointerTouchActionTarget() override {} + + void DispatchInputEventToPlatform(const WebInputEvent& event) override { + ASSERT_TRUE(WebInputEvent::isTouchEventType(event.type)); + const WebTouchEvent& touch_event = static_cast<const WebTouchEvent&>(event); + type_ = touch_event.type; + for (size_t i = 0; i < touch_event.touchesLength; ++i) { + indexes_[i] = touch_event.touches[i].id; + positions_[i] = gfx::PointF(touch_event.touches[i].position); + states_[i] = touch_event.touches[i].state; + } + touch_length_ = touch_event.touchesLength; + } + + SyntheticGestureParams::GestureSourceType + GetDefaultSyntheticGestureSourceType() const override { + return SyntheticGestureParams::TOUCH_INPUT; + } + + gfx::PointF positions(int index) const { return positions_[index]; } + int indexes(int index) const { return indexes_[index]; } + WebTouchPoint::State states(int index) { return states_[index]; } + unsigned touch_length() const { return touch_length_; } + + private: + gfx::PointF positions_[WebTouchEvent::touchesLengthCap]; + unsigned touch_length_; + int indexes_[WebTouchEvent::touchesLengthCap]; + WebTouchPoint::State states_[WebTouchEvent::touchesLengthCap]; +}; + +class SyntheticPointerActionTest : public testing::Test { + public: + SyntheticPointerActionTest() { + target_.reset(new MockSyntheticPointerTouchActionTarget()); + synthetic_pointer_ = + SyntheticPointer::Create(SyntheticGestureParams::TOUCH_INPUT); + action_param_list_.reset(new std::vector<SyntheticPointerActionParams>()); + std::fill(index_map_.begin(), index_map_.end(), -1); + num_success_ = 0; + num_failure_ = 0; + } + ~SyntheticPointerActionTest() override {} + + protected: + void ForwardSyntheticPointerAction() { + pointer_action_.reset(new SyntheticPointerAction( + std::move(action_param_list_), synthetic_pointer_.get(), &index_map_)); + + SyntheticGesture::Result result = pointer_action_->ForwardInputEvents( + base::TimeTicks::Now(), target_.get()); + + if (result == SyntheticGesture::GESTURE_FINISHED) + num_success_++; + else + num_failure_++; + } + + int num_success_; + int num_failure_; + std::unique_ptr<MockSyntheticPointerActionTarget> target_; + std::unique_ptr<SyntheticGesture> pointer_action_; + std::unique_ptr<SyntheticPointer> synthetic_pointer_; + std::unique_ptr<std::vector<SyntheticPointerActionParams>> action_param_list_; + SyntheticPointerAction::IndexMap index_map_; +}; + +TEST_F(SyntheticPointerActionTest, PointerTouchAction) { + // Send a touch press for one finger. + SyntheticPointerActionParams params0 = SyntheticPointerActionParams( + SyntheticPointerActionParams::PointerActionType::PRESS); + params0.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; + params0.set_index(0); + params0.set_position(gfx::PointF(54, 89)); + action_param_list_->push_back(params0); + ForwardSyntheticPointerAction(); + + MockSyntheticPointerTouchActionTarget* pointer_touch_target = + static_cast<MockSyntheticPointerTouchActionTarget*>(target_.get()); + EXPECT_EQ(1, num_success_); + EXPECT_EQ(0, num_failure_); + EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchStart); + EXPECT_EQ(pointer_touch_target->indexes(0), 0); + EXPECT_EQ(index_map_[0], 0); + EXPECT_EQ(pointer_touch_target->positions(0), gfx::PointF(54, 89)); + EXPECT_EQ(pointer_touch_target->states(0), WebTouchPoint::StatePressed); + ASSERT_EQ(pointer_touch_target->touch_length(), 1U); + + // Send a touch move for the first finger and a touch press for the second + // finger. + action_param_list_.reset(new std::vector<SyntheticPointerActionParams>()); + params0.set_pointer_action_type( + SyntheticPointerActionParams::PointerActionType::MOVE); + params0.set_position(gfx::PointF(133, 156)); + SyntheticPointerActionParams params1 = SyntheticPointerActionParams( + SyntheticPointerActionParams::PointerActionType::PRESS); + params1.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; + params1.set_index(1); + params1.set_position(gfx::PointF(79, 132)); + action_param_list_->push_back(params0); + action_param_list_->push_back(params1); + ForwardSyntheticPointerAction(); + + pointer_touch_target = + static_cast<MockSyntheticPointerTouchActionTarget*>(target_.get()); + EXPECT_EQ(2, num_success_); + EXPECT_EQ(0, num_failure_); + // The type of the SyntheticWebTouchEvent is the action of the last finger. + EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchStart); + EXPECT_EQ(pointer_touch_target->indexes(0), 0); + EXPECT_EQ(index_map_[0], 0); + EXPECT_EQ(pointer_touch_target->positions(0), gfx::PointF(133, 156)); + EXPECT_EQ(pointer_touch_target->states(0), WebTouchPoint::StateMoved); + EXPECT_EQ(pointer_touch_target->indexes(1), 1); + EXPECT_EQ(index_map_[1], 1); + EXPECT_EQ(pointer_touch_target->positions(1), gfx::PointF(79, 132)); + EXPECT_EQ(pointer_touch_target->states(1), WebTouchPoint::StatePressed); + ASSERT_EQ(pointer_touch_target->touch_length(), 2U); + + // Send a touch move for the second finger. + action_param_list_.reset(new std::vector<SyntheticPointerActionParams>()); + params1.set_pointer_action_type( + SyntheticPointerActionParams::PointerActionType::MOVE); + params1.set_position(gfx::PointF(87, 253)); + action_param_list_->push_back(params1); + ForwardSyntheticPointerAction(); + + pointer_touch_target = + static_cast<MockSyntheticPointerTouchActionTarget*>(target_.get()); + EXPECT_EQ(3, num_success_); + EXPECT_EQ(0, num_failure_); + EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchMove); + EXPECT_EQ(pointer_touch_target->indexes(1), 1); + EXPECT_EQ(index_map_[1], 1); + EXPECT_EQ(pointer_touch_target->positions(1), gfx::PointF(87, 253)); + EXPECT_EQ(pointer_touch_target->states(1), WebTouchPoint::StateMoved); + ASSERT_EQ(pointer_touch_target->touch_length(), 2U); + + // Send touch releases for both fingers. + action_param_list_.reset(new std::vector<SyntheticPointerActionParams>()); + params0.set_pointer_action_type( + SyntheticPointerActionParams::PointerActionType::RELEASE); + params1.set_pointer_action_type( + SyntheticPointerActionParams::PointerActionType::RELEASE); + action_param_list_->push_back(params0); + action_param_list_->push_back(params1); + ForwardSyntheticPointerAction(); + + EXPECT_EQ(4, num_success_); + EXPECT_EQ(0, num_failure_); + EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchEnd); + EXPECT_EQ(pointer_touch_target->indexes(0), 0); + EXPECT_EQ(index_map_[0], -1); + EXPECT_EQ(pointer_touch_target->states(0), WebTouchPoint::StateReleased); + EXPECT_EQ(pointer_touch_target->indexes(1), 1); + EXPECT_EQ(index_map_[1], -1); + EXPECT_EQ(pointer_touch_target->states(1), WebTouchPoint::StateReleased); + ASSERT_EQ(pointer_touch_target->touch_length(), 2U); +} + +TEST_F(SyntheticPointerActionTest, PointerTouchActionIndexInvalid) { + // Users sent a wrong index for the touch action. + SyntheticPointerActionParams params0 = SyntheticPointerActionParams( + SyntheticPointerActionParams::PointerActionType::PRESS); + params0.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; + params0.set_index(-1); + params0.set_position(gfx::PointF(54, 89)); + action_param_list_->push_back(params0); + ForwardSyntheticPointerAction(); + + EXPECT_EQ(0, num_success_); + EXPECT_EQ(1, num_failure_); + + action_param_list_.reset(new std::vector<SyntheticPointerActionParams>()); + params0.set_index(0); + action_param_list_->push_back(params0); + ForwardSyntheticPointerAction(); + + MockSyntheticPointerTouchActionTarget* pointer_touch_target = + static_cast<MockSyntheticPointerTouchActionTarget*>(target_.get()); + EXPECT_EQ(1, num_success_); + EXPECT_EQ(1, num_failure_); + EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchStart); + EXPECT_EQ(pointer_touch_target->indexes(0), 0); + EXPECT_EQ(index_map_[0], 0); + EXPECT_EQ(pointer_touch_target->positions(0), gfx::PointF(54, 89)); + EXPECT_EQ(pointer_touch_target->states(0), WebTouchPoint::StatePressed); + ASSERT_EQ(pointer_touch_target->touch_length(), 1U); +} + +TEST_F(SyntheticPointerActionTest, PointerTouchActionSourceTypeInvalid) { + // Users' gesture source type does not match with the touch action. + SyntheticPointerActionParams params0 = SyntheticPointerActionParams( + SyntheticPointerActionParams::PointerActionType::PRESS); + params0.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT; + params0.set_index(0); + params0.set_position(gfx::PointF(54, 89)); + action_param_list_->push_back(params0); + ForwardSyntheticPointerAction(); + + EXPECT_EQ(0, num_success_); + EXPECT_EQ(1, num_failure_); + + action_param_list_.reset(new std::vector<SyntheticPointerActionParams>()); + params0.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; + action_param_list_->push_back(params0); + ForwardSyntheticPointerAction(); + + MockSyntheticPointerTouchActionTarget* pointer_touch_target = + static_cast<MockSyntheticPointerTouchActionTarget*>(target_.get()); + EXPECT_EQ(1, num_success_); + EXPECT_EQ(1, num_failure_); + EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchStart); + EXPECT_EQ(pointer_touch_target->indexes(0), 0); + EXPECT_EQ(index_map_[0], 0); + EXPECT_EQ(pointer_touch_target->positions(0), gfx::PointF(54, 89)); + EXPECT_EQ(pointer_touch_target->states(0), WebTouchPoint::StatePressed); + ASSERT_EQ(pointer_touch_target->touch_length(), 1U); +} + +TEST_F(SyntheticPointerActionTest, PointerTouchActionTypeInvalid) { + // Cannot send a touch move or touch release without sending a touch press + // first. + SyntheticPointerActionParams params0 = SyntheticPointerActionParams( + SyntheticPointerActionParams::PointerActionType::MOVE); + params0.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; + params0.set_index(0); + params0.set_position(gfx::PointF(54, 89)); + action_param_list_->push_back(params0); + ForwardSyntheticPointerAction(); + + EXPECT_EQ(0, num_success_); + EXPECT_EQ(1, num_failure_); + + action_param_list_.reset(new std::vector<SyntheticPointerActionParams>()); + params0.set_pointer_action_type( + SyntheticPointerActionParams::PointerActionType::RELEASE); + action_param_list_->push_back(params0); + ForwardSyntheticPointerAction(); + + EXPECT_EQ(0, num_success_); + EXPECT_EQ(2, num_failure_); + + // Send a touch press for one finger. + action_param_list_.reset(new std::vector<SyntheticPointerActionParams>()); + params0.set_pointer_action_type( + SyntheticPointerActionParams::PointerActionType::PRESS); + action_param_list_->push_back(params0); + ForwardSyntheticPointerAction(); + + MockSyntheticPointerTouchActionTarget* pointer_touch_target = + static_cast<MockSyntheticPointerTouchActionTarget*>(target_.get()); + EXPECT_EQ(1, num_success_); + EXPECT_EQ(2, num_failure_); + EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchStart); + EXPECT_EQ(pointer_touch_target->indexes(0), 0); + EXPECT_EQ(index_map_[0], 0); + EXPECT_EQ(pointer_touch_target->positions(0), gfx::PointF(54, 89)); + EXPECT_EQ(pointer_touch_target->states(0), WebTouchPoint::StatePressed); + ASSERT_EQ(pointer_touch_target->touch_length(), 1U); + + // Cannot send a touch press again without releasing the finger. + action_param_list_.reset(new std::vector<SyntheticPointerActionParams>()); + params0.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; + params0.set_index(0); + params0.set_pointer_action_type( + SyntheticPointerActionParams::PointerActionType::PRESS); + action_param_list_->push_back(params0); + ForwardSyntheticPointerAction(); + + EXPECT_EQ(1, num_success_); + EXPECT_EQ(3, num_failure_); +} + +} // namespace + +} // namespace content
diff --git a/content/browser/renderer_host/input/synthetic_touch_pointer.cc b/content/browser/renderer_host/input/synthetic_touch_pointer.cc index ca4637a6..2b1fa64 100644 --- a/content/browser/renderer_host/input/synthetic_touch_pointer.cc +++ b/content/browser/renderer_host/input/synthetic_touch_pointer.cc
@@ -43,4 +43,9 @@ touch_event_.ReleasePoint(index); } +SyntheticGestureParams::GestureSourceType SyntheticTouchPointer::SourceType() + const { + return SyntheticGestureParams::TOUCH_INPUT; +} + } // namespace content
diff --git a/content/browser/renderer_host/input/synthetic_touch_pointer.h b/content/browser/renderer_host/input/synthetic_touch_pointer.h index abd579e..728ec4c8 100644 --- a/content/browser/renderer_host/input/synthetic_touch_pointer.h +++ b/content/browser/renderer_host/input/synthetic_touch_pointer.h
@@ -34,6 +34,8 @@ SyntheticGestureTarget* target, const base::TimeTicks& timestamp) override; + SyntheticGestureParams::GestureSourceType SourceType() const override; + private: SyntheticWebTouchEvent touch_event_;
diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc index 947c00cd..61647894 100644 --- a/content/browser/renderer_host/media/audio_renderer_host.cc +++ b/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -109,6 +109,13 @@ *params = media::AudioParameters::UnavailableDeviceParams(); } +void UMALogDeviceAuthorizationTime(base::TimeTicks auth_start_time) { + UMA_HISTOGRAM_CUSTOM_TIMES("Media.Audio.OutputDeviceAuthorizationTime", + base::TimeTicks::Now() - auth_start_time, + base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromMilliseconds(5000), 50); +} + } // namespace class AudioRendererHost::AudioEntry @@ -398,6 +405,8 @@ const std::string& device_id, const url::Origin& security_origin) { DCHECK_CURRENTLY_ON(BrowserThread::IO); + const base::TimeTicks auth_start_time = base::TimeTicks::Now(); + DVLOG(1) << "AudioRendererHost@" << this << "::OnRequestDeviceAuthorization" << "(stream_id=" << stream_id << ", render_frame_id=" << render_frame_id @@ -408,6 +417,7 @@ return; if (!IsValidDeviceId(device_id)) { + UMALogDeviceAuthorizationTime(auth_start_time); Send(new AudioMsg_NotifyDeviceAuthorized( stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, media::AudioParameters::UnavailableDeviceParams(), std::string())); @@ -432,6 +442,7 @@ authorizations_.insert(MakeAuthorizationData( stream_id, true, info->device.matched_output_device_id)); MaybeFixAudioParameters(&output_params); + UMALogDeviceAuthorizationTime(auth_start_time); // Hash matched device id and pass it to the renderer Send(new AudioMsg_NotifyDeviceAuthorized( stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, @@ -446,22 +457,26 @@ CheckOutputDeviceAccess( render_frame_id, device_id, security_origin, base::Bind(&AudioRendererHost::OnDeviceAuthorized, this, stream_id, - device_id, security_origin)); + device_id, security_origin, auth_start_time)); } void AudioRendererHost::OnDeviceAuthorized(int stream_id, const std::string& device_id, const url::Origin& security_origin, + base::TimeTicks auth_start_time, bool have_access) { DCHECK_CURRENTLY_ON(BrowserThread::IO); const auto& auth_data = authorizations_.find(stream_id); // A close request was received while access check was in progress. - if (auth_data == authorizations_.end()) + if (auth_data == authorizations_.end()) { + UMALogDeviceAuthorizationTime(auth_start_time); return; + } if (!have_access) { authorizations_.erase(auth_data); + UMALogDeviceAuthorizationTime(auth_start_time); Send(new AudioMsg_NotifyDeviceAuthorized( stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED, media::AudioParameters::UnavailableDeviceParams(), std::string())); @@ -479,29 +494,33 @@ audio_manager_->GetTaskRunner(), FROM_HERE, base::Bind(&GetDefaultDeviceInfoOnDeviceThread, audio_manager_), base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, stream_id, - true)); + auth_start_time, true)); } else { media_stream_manager_->audio_output_device_enumerator()->Enumerate( base::Bind(&AudioRendererHost::TranslateDeviceID, this, device_id, security_origin, base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, - stream_id))); + stream_id, auth_start_time))); } } void AudioRendererHost::OnDeviceIDTranslated( int stream_id, + base::TimeTicks auth_start_time, bool device_found, const AudioOutputDeviceInfo& device_info) { DCHECK_CURRENTLY_ON(BrowserThread::IO); const auto& auth_data = authorizations_.find(stream_id); // A close request was received while translation was in progress - if (auth_data == authorizations_.end()) + if (auth_data == authorizations_.end()) { + UMALogDeviceAuthorizationTime(auth_start_time); return; + } if (!device_found) { authorizations_.erase(auth_data); + UMALogDeviceAuthorizationTime(auth_start_time); Send(new AudioMsg_NotifyDeviceAuthorized( stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, media::AudioParameters::UnavailableDeviceParams(), std::string())); @@ -513,6 +532,7 @@ media::AudioParameters output_params = device_info.output_params; MaybeFixAudioParameters(&output_params); + UMALogDeviceAuthorizationTime(auth_start_time); Send(new AudioMsg_NotifyDeviceAuthorized( stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, std::string())); }
diff --git a/content/browser/renderer_host/media/audio_renderer_host.h b/content/browser/renderer_host/media/audio_renderer_host.h index 7252086..3e5374a 100644 --- a/content/browser/renderer_host/media/audio_renderer_host.h +++ b/content/browser/renderer_host/media/audio_renderer_host.h
@@ -174,10 +174,12 @@ void OnDeviceAuthorized(int stream_id, const std::string& device_id, const url::Origin& security_origin, + base::TimeTicks auth_start_time, bool have_access); // Proceed with device authorization after translating device ID. void OnDeviceIDTranslated(int stream_id, + base::TimeTicks auth_start_time, bool device_found, const AudioOutputDeviceInfo& device_info);
diff --git a/content/browser/renderer_host/media/video_capture_device_client.cc b/content/browser/renderer_host/media/video_capture_device_client.cc index f6f8cba..cd39c5f 100644 --- a/content/browser/renderer_host/media/video_capture_device_client.cc +++ b/content/browser/renderer_host/media/video_capture_device_client.cc
@@ -138,10 +138,14 @@ std::unique_ptr<Buffer> buffer( ReserveI420OutputBuffer(dimensions, output_pixel_storage, &y_plane_data, &u_plane_data, &v_plane_data)); - if (!buffer.get()) { - DLOG(WARNING) << "Failed to reserve I420 output buffer."; +#if DCHECK_IS_ON() + dropped_frame_counter_ = buffer.get() ? 0 : dropped_frame_counter_ + 1; + if (dropped_frame_counter_ >= kMaxDroppedFrames) + OnError(FROM_HERE, "Too many frames dropped"); +#endif + // Failed to reserve I420 output buffer, so drop the frame. + if (!buffer.get()) return; - } const int yplane_stride = dimensions.width(); const int uv_plane_stride = yplane_stride / 2;
diff --git a/content/browser/renderer_host/media/video_capture_device_client.h b/content/browser/renderer_host/media/video_capture_device_client.h index 2d6cccc..c5447ca 100644 --- a/content/browser/renderer_host/media/video_capture_device_client.h +++ b/content/browser/renderer_host/media/video_capture_device_client.h
@@ -103,6 +103,14 @@ // The pool of shared-memory buffers used for capturing. const scoped_refptr<VideoCaptureBufferPool> buffer_pool_; +#if DCHECK_IS_ON() + // Counter used to track the number of times consecutive capture buffers are + // dropped. + int dropped_frame_counter_ = 0; + + static const int kMaxDroppedFrames = 150; +#endif // DCHECK_IS_ON() + // Indication to the Client to copy-transform the incoming data into // GpuMemoryBuffers. const bool use_gpu_memory_buffers_;
diff --git a/content/browser/renderer_host/offscreen_canvas_surface_impl.cc b/content/browser/renderer_host/offscreen_canvas_surface_impl.cc index 8e56b014..5689bff4 100644 --- a/content/browser/renderer_host/offscreen_canvas_surface_impl.cc +++ b/content/browser/renderer_host/offscreen_canvas_surface_impl.cc
@@ -69,7 +69,7 @@ std::vector<uint32_t> sequences; sequences.push_back(sequence.sequence); cc::SurfaceManager* manager = GetSurfaceManager(); - manager->DidSatisfySequences(sequence.id_namespace, &sequences); + manager->DidSatisfySequences(sequence.client_id, &sequences); } // TODO(619136): Implement cc::SurfaceFactoryClient functions for resources
diff --git a/content/browser/renderer_host/p2p/socket_dispatcher_host.cc b/content/browser/renderer_host/p2p/socket_dispatcher_host.cc index 1204067..8cbb0d6 100644 --- a/content/browser/renderer_host/p2p/socket_dispatcher_host.cc +++ b/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
@@ -64,8 +64,8 @@ // Add period at the end to make sure that we only resolve // fully-qualified names. - if (host_name_.at(host_name_.size() - 1) != '.') - host_name_ = host_name_ + '.'; + if (host_name_.back() != '.') + host_name_ += '.'; net::HostResolver::RequestInfo info(net::HostPortPair(host_name_, 0)); int result = resolver_.Resolve(
diff --git a/content/browser/renderer_host/p2p/socket_host.cc b/content/browser/renderer_host/p2p/socket_host.cc index d2ef8f5..6b9a6ce2 100644 --- a/content/browser/renderer_host/p2p/socket_host.cc +++ b/content/browser/renderer_host/p2p/socket_host.cc
@@ -11,11 +11,25 @@ #include "content/browser/renderer_host/p2p/socket_host_udp.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/public/browser/browser_thread.h" +#include "net/base/net_errors.h" #include "third_party/webrtc/media/base/rtputils.h" #include "third_party/webrtc/media/base/turnutils.h" namespace { +// Used to back histogram value of "WebRTC.ICE.TcpSocketErrorCode" and +// "WebRTC.ICE.UdpSocketErrorCode". +enum class SocketErrorCode { + ERR_MSG_TOO_BIG, + ERR_ADDRESS_UNREACHABLE, + ERR_ADDRESS_INVALID, + ERR_INTERNET_DISCONNECTED, + ERR_TIMED_OUT, + ERR_INSUFFICIENT_RESOURCES, + ERR_OUT_OF_MEMORY, + ERR_OTHER // For all the others +}; + const uint32_t kStunMagicCookie = 0x2112A442; const size_t kMinRtcpHeaderLength = 8; const size_t kDtlsRecordHeaderLength = 13; @@ -34,6 +48,31 @@ return (type >= 64 && type < 96); } +// Map the network error to SocketErrorCode for the UMA histogram. +// static +static SocketErrorCode MapNetErrorToSocketErrorCode(int net_err) { + switch (net_err) { + case net::OK: + NOTREACHED(); + return SocketErrorCode::ERR_OTHER; + case net::ERR_MSG_TOO_BIG: + return SocketErrorCode::ERR_MSG_TOO_BIG; + case net::ERR_ADDRESS_UNREACHABLE: + return SocketErrorCode::ERR_ADDRESS_UNREACHABLE; + case net::ERR_ADDRESS_INVALID: + return SocketErrorCode::ERR_ADDRESS_INVALID; + case net::ERR_INTERNET_DISCONNECTED: + return SocketErrorCode::ERR_INTERNET_DISCONNECTED; + case net::ERR_TIMED_OUT: + return SocketErrorCode::ERR_TIMED_OUT; + case net::ERR_INSUFFICIENT_RESOURCES: + return SocketErrorCode::ERR_INSUFFICIENT_RESOURCES; + case net::ERR_OUT_OF_MEMORY: + return SocketErrorCode::ERR_OUT_OF_MEMORY; + default: + return SocketErrorCode::ERR_OTHER; + } +} } // namespace namespace content { @@ -129,6 +168,13 @@ } // static +void P2PSocketHost::ReportSocketError(int result, const char* histogram_name) { + SocketErrorCode error_code = MapNetErrorToSocketErrorCode(result); + UMA_HISTOGRAM_ENUMERATION(histogram_name, static_cast<int>(error_code), + static_cast<int>(SocketErrorCode::ERR_OTHER) + 1); +} + +// static P2PSocketHost* P2PSocketHost::Create(IPC::Sender* message_sender, int socket_id, P2PSocketType type,
diff --git a/content/browser/renderer_host/p2p/socket_host.h b/content/browser/renderer_host/p2p/socket_host.h index 70e7276..632a2b6 100644 --- a/content/browser/renderer_host/p2p/socket_host.h +++ b/content/browser/renderer_host/p2p/socket_host.h
@@ -115,6 +115,8 @@ StunMessageType* type); static bool IsRequestOrResponse(StunMessageType type); + static void ReportSocketError(int result, const char* histogram_name); + // Calls |packet_dump_callback_| to record the RTP header. void DumpRtpPacket(const char* packet, size_t length, bool incoming);
diff --git a/content/browser/renderer_host/p2p/socket_host_tcp.cc b/content/browser/renderer_host/p2p/socket_host_tcp.cc index 1687a3a..2369e4b 100644 --- a/content/browser/renderer_host/p2p/socket_host_tcp.cc +++ b/content/browser/renderer_host/p2p/socket_host_tcp.cc
@@ -435,6 +435,8 @@ } else if (result == net::ERR_IO_PENDING) { write_pending_ = true; } else { + ReportSocketError(result, "WebRTC.ICE.TcpSocketWriteErrorCode"); + LOG(ERROR) << "Error when sending data in TCP socket: " << result; OnError(); }
diff --git a/content/browser/renderer_host/p2p/socket_host_udp.cc b/content/browser/renderer_host/p2p/socket_host_udp.cc index 451353603..45bfcb38 100644 --- a/content/browser/renderer_host/p2p/socket_host_udp.cc +++ b/content/browser/renderer_host/p2p/socket_host_udp.cc
@@ -352,6 +352,8 @@ TRACE_EVENT_ASYNC_END1("p2p", "Send", packet_id, "result", result); if (result < 0) { + ReportSocketError(result, "WebRTC.ICE.UdpSocketWriteErrorCode"); + if (!IsTransientError(result)) { LOG(ERROR) << "Error when sending data in UDP socket: " << result; OnError();
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index de830f4..c0d9d721 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -44,6 +44,8 @@ #include "base/tracked_objects.h" #include "build/build_config.h" #include "cc/base/switches.h" +#include "components/memory_coordinator/browser/memory_coordinator.h" +#include "components/memory_coordinator/common/memory_coordinator_features.h" #include "components/scheduler/common/scheduler_switches.h" #include "components/tracing/common/tracing_switches.h" #include "components/webmessaging/broadcast_channel_provider.h" @@ -234,6 +236,10 @@ #include "services/ui/common/switches.h" // nogncheck #endif +#if defined(USE_MINIKIN_HYPHENATION) +#include "content/browser/hyphenation/hyphenation_impl.h" +#endif + #if defined(OS_WIN) #define IntToStringType base::IntToString16 #else @@ -446,6 +452,13 @@ return str; } +void CreateMemoryCoordinatorHandle( + int render_process_id, + memory_coordinator::mojom::MemoryCoordinatorHandleRequest request) { + BrowserMainLoop::GetInstance()->memory_coordinator()->CreateHandle( + render_process_id, std::move(request)); +} + } // namespace RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL; @@ -1074,9 +1087,15 @@ base::Unretained( storage_partition_impl_->GetBroadcastChannelProvider()))); + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner = + BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE); GetInterfaceRegistry()->AddInterface( - base::Bind(&MimeRegistryImpl::Create), - BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE)); + base::Bind(&MimeRegistryImpl::Create), file_task_runner); + +#if defined(USE_MINIKIN_HYPHENATION) + GetInterfaceRegistry()->AddInterface( + base::Bind(&hyphenation::HyphenationImpl::Create), file_task_runner); +#endif scoped_refptr<base::SingleThreadTaskRunner> io_task_runner = BrowserThread::GetTaskRunnerForThread(BrowserThread::IO); @@ -1089,6 +1108,11 @@ GetInterfaceRegistry()->AddInterface( base::Bind(&DeviceOrientationAbsoluteHost::Create), io_task_runner); + if (memory_coordinator::IsEnabled()) { + GetInterfaceRegistry()->AddInterface( + base::Bind(&CreateMemoryCoordinatorHandle, GetID())); + } + #if defined(OS_ANDROID) ServiceRegistrarAndroid::RegisterProcessHostServices( mojo_child_connection_->service_registry_android()); @@ -2108,6 +2132,20 @@ } // static +void RenderProcessHostImpl::CheckAllTerminated() { + iterator iter(AllHostsIterator()); + while (!iter.IsAtEnd()) { + // The leftover hosts must have reset IPC channel and getting deleted soon. + RenderProcessHostImpl* host = + static_cast<RenderProcessHostImpl*>(iter.GetCurrentValue()); + CHECK(host->listeners_.IsEmpty()); + CHECK_EQ(0, host->worker_ref_count_); + CHECK(!host->channel_); + CHECK(host->deleting_soon_); + } +} + +// static void RenderProcessHostImpl::FilterURL(RenderProcessHost* rph, bool empty_allowed, GURL* url) {
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index 3c754893..cdb8ee4 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -204,6 +204,10 @@ static void RegisterHost(int host_id, RenderProcessHost* host); static void UnregisterHost(int host_id); + // CHECKs that all hosts have terminated. + // Added temporarily to diagnose crbug.com/608049. + static void CheckAllTerminated(); + // Implementation of FilterURL below that can be shared with the mock class. static void FilterURL(RenderProcessHost* rph, bool empty_allowed, GURL* url); @@ -441,10 +445,6 @@ // RenderFrames. bool is_for_guests_only_; - // Forwards messages between WebRTCInternals in the browser process - // and PeerConnectionTracker in the renderer process. - scoped_refptr<PeerConnectionTrackerHost> peer_connection_tracker_host_; - // Prevents the class from being added as a GpuDataManagerImpl observer more // than once. bool gpu_observer_registered_; @@ -479,6 +479,12 @@ WebRTCEventLogHost webrtc_eventlog_host_; #endif + // Forwards messages between WebRTCInternals in the browser process + // and PeerConnectionTracker in the renderer process. + // It holds a raw pointer to webrtc_eventlog_host_, and therefore should be + // defined below it so it is destructed first. + scoped_refptr<PeerConnectionTrackerHost> peer_connection_tracker_host_; + int worker_ref_count_; // Records the time when the process starts surviving for workers for UMA.
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 1b43ff2..023cb5fa 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -381,8 +381,8 @@ // If the RWHV has not yet been set, the surface ID namespace will get // passed down by the call to SetView(). if (GetWidget()->GetView()) { - Send(new ViewMsg_SetSurfaceIdNamespace( - GetRoutingID(), GetWidget()->GetView()->GetSurfaceIdNamespace())); + Send(new ViewMsg_SetSurfaceClientId( + GetRoutingID(), GetWidget()->GetView()->GetSurfaceClientId())); } // If it's enabled, tell the renderer to set up the Javascript bindings for
diff --git a/content/browser/renderer_host/render_widget_host_delegate.cc b/content/browser/renderer_host/render_widget_host_delegate.cc index 9e9b876..abdf8fae 100644 --- a/content/browser/renderer_host/render_widget_host_delegate.cc +++ b/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -62,6 +62,11 @@ return blink::WebDisplayModeBrowser; } +bool RenderWidgetHostDelegate::HasMouseLock( + RenderWidgetHostImpl* render_widget_host) { + return false; +} + TextInputManager* RenderWidgetHostDelegate::GetTextInputManager() { return nullptr; }
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h index 6777b9c9..a72360c 100644 --- a/content/browser/renderer_host/render_widget_host_delegate.h +++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -144,10 +144,12 @@ // Requests to lock the mouse. Once the request is approved or rejected, // GotResponseToLockMouseRequest() will be called on the requesting render - // widget host. + // widget host. |privileged| means that the request is always granted, used + // for Pepper Flash. virtual void RequestToLockMouse(RenderWidgetHostImpl* render_widget_host, bool user_gesture, - bool last_unlocked_by_target) {} + bool last_unlocked_by_target, + bool privileged) {} // Return the rect where to display the resize corner, if any, otherwise // an empty rect. @@ -167,6 +169,9 @@ // Notification that the widget has lost the mouse lock. virtual void LostMouseLock(RenderWidgetHostImpl* render_widget_host) {} + // Returns true if |render_widget_host| holds the mouse lock. + virtual bool HasMouseLock(RenderWidgetHostImpl* render_widget_host); + // Called when the widget has sent a compositor proto. This is used in Btlimp // mode with the RemoteChannel compositor. virtual void ForwardCompositorProto(RenderWidgetHostImpl* render_widget_host,
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 00ebb223..b0c562e 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -330,8 +330,8 @@ // If the renderer has not yet been initialized, then the surface ID // namespace will be sent during initialization. if (view_ && renderer_initialized_) { - Send(new ViewMsg_SetSurfaceIdNamespace(routing_id_, - view_->GetSurfaceIdNamespace())); + Send(new ViewMsg_SetSurfaceClientId(routing_id_, + view_->GetSurfaceClientId())); } synthetic_gesture_controller_.reset(); @@ -403,8 +403,8 @@ // If the RWHV has not yet been set, the surface ID namespace will get // passed down by the call to SetView(). if (view_) { - Send(new ViewMsg_SetSurfaceIdNamespace(routing_id_, - view_->GetSurfaceIdNamespace())); + Send(new ViewMsg_SetSurfaceClientId(routing_id_, + view_->GetSurfaceClientId())); } SendScreenRects(); @@ -1568,9 +1568,7 @@ view_->DidReceiveRendererFrame(); } else { cc::CompositorFrameAck ack; - if (frame.gl_frame_data) { - ack.gl_frame_data = std::move(frame.gl_frame_data); - } else if (frame.delegated_frame_data) { + if (frame.delegated_frame_data) { cc::TransferableResource::ReturnResources( frame.delegated_frame_data->resource_list, &ack.resources); } @@ -1733,16 +1731,17 @@ } pending_mouse_lock_request_ = true; + if (delegate_) { + delegate_->RequestToLockMouse(this, user_gesture, last_unlocked_by_target, + privileged && allow_privileged_mouse_lock_); + return; + } + if (privileged && allow_privileged_mouse_lock_) { // Directly approve to lock the mouse. GotResponseToLockMouseRequest(true); } else { - if (delegate_) { - delegate_->RequestToLockMouse(this, user_gesture, - last_unlocked_by_target); - return; - } - // If there's no delegate, just reject it. + // Otherwise, just reject it. GotResponseToLockMouseRequest(false); } }
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc index 0df21e1e..9786dad 100644 --- a/content/browser/renderer_host/render_widget_host_input_event_router.cc +++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -122,10 +122,10 @@ // hit testing, and reflect transformations that would normally be applied in // the renderer process if the event was being routed between frames within a // single process with only one RenderWidgetHost. - uint32_t surface_id_namespace = - root_view->SurfaceIdNamespaceAtPoint(&delegate, point, transformed_point); - const SurfaceIdNamespaceOwnerMap::iterator iter = - owner_map_.find(surface_id_namespace); + uint32_t surface_client_id = + root_view->SurfaceClientIdAtPoint(&delegate, point, transformed_point); + const SurfaceClientIdOwnerMap::iterator iter = + owner_map_.find(surface_client_id); // If the point hit a Surface whose namspace is no longer in the map, then // it likely means the RenderWidgetHostView has been destroyed but its // parent frame has not sent a new compositor frame since that happened. @@ -345,7 +345,7 @@ } } -void RenderWidgetHostInputEventRouter::AddSurfaceIdNamespaceOwner( +void RenderWidgetHostInputEventRouter::AddSurfaceClientIdOwner( uint32_t id, RenderWidgetHostViewBase* owner) { DCHECK(owner_map_.find(id) == owner_map_.end()); @@ -355,8 +355,7 @@ owner_map_.insert(std::make_pair(id, owner)); } -void RenderWidgetHostInputEventRouter::RemoveSurfaceIdNamespaceOwner( - uint32_t id) { +void RenderWidgetHostInputEventRouter::RemoveSurfaceClientIdOwner(uint32_t id) { auto it_to_remove = owner_map_.find(id); if (it_to_remove != owner_map_.end()) { it_to_remove->second->RemoveObserver(this); @@ -364,7 +363,7 @@ } for (auto it = hittest_data_.begin(); it != hittest_data_.end();) { - if (it->first.id_namespace() == id) + if (it->first.client_id() == id) it = hittest_data_.erase(it); else ++it; @@ -373,7 +372,7 @@ void RenderWidgetHostInputEventRouter::OnHittestData( const FrameHostMsg_HittestData_Params& params) { - if (owner_map_.find(params.surface_id.id_namespace()) == owner_map_.end()) { + if (owner_map_.find(params.surface_id.client_id()) == owner_map_.end()) { return; } HittestData data;
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.h b/content/browser/renderer_host/render_widget_host_input_event_router.h index 18f7172..70f8b05b 100644 --- a/content/browser/renderer_host/render_widget_host_input_event_router.h +++ b/content/browser/renderer_host/render_widget_host_input_event_router.h
@@ -70,8 +70,8 @@ const blink::WebGestureEvent& event); void CancelScrollBubbling(RenderWidgetHostViewBase* target_view); - void AddSurfaceIdNamespaceOwner(uint32_t id, RenderWidgetHostViewBase* owner); - void RemoveSurfaceIdNamespaceOwner(uint32_t id); + void AddSurfaceClientIdOwner(uint32_t id, RenderWidgetHostViewBase* owner); + void RemoveSurfaceClientIdOwner(uint32_t id); bool is_registered(uint32_t id) { return owner_map_.find(id) != owner_map_.end(); @@ -98,7 +98,7 @@ hittest_data_; }; - using SurfaceIdNamespaceOwnerMap = + using SurfaceClientIdOwnerMap = base::hash_map<uint32_t, RenderWidgetHostViewBase*>; struct TargetData { RenderWidgetHostViewBase* target; @@ -129,7 +129,7 @@ void SendGestureScrollEnd(RenderWidgetHostViewBase* view, const blink::WebGestureEvent& event); - SurfaceIdNamespaceOwnerMap owner_map_; + SurfaceClientIdOwnerMap owner_map_; TargetQueue touchscreen_gesture_target_queue_; TargetData touch_target_; TargetData touchscreen_gesture_target_;
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 37703597..5916807 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -79,6 +79,7 @@ #include "third_party/skia/include/core/SkCanvas.h" #include "ui/android/window_android.h" #include "ui/android/window_android_compositor.h" +#include "ui/base/layout.h" #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/events/blink/blink_event_util.h" @@ -99,7 +100,7 @@ const cc::SurfaceSequence& sequence) { std::vector<uint32_t> sequences; sequences.push_back(sequence.sequence); - manager->DidSatisfySequences(sequence.id_namespace, &sequences); + manager->DidSatisfySequences(sequence.client_id, &sequences); } void RequireCallback(cc::SurfaceManager* manager, @@ -270,8 +271,10 @@ } std::unique_ptr<OverscrollControllerAndroid> CreateOverscrollController( - ContentViewCoreImpl* content_view_core) { - return base::WrapUnique(new OverscrollControllerAndroid(content_view_core)); + ContentViewCoreImpl* content_view_core, + float dpi_scale) { + return base::WrapUnique( + new OverscrollControllerAndroid(content_view_core, dpi_scale)); } gfx::RectF GetSelectionRect(const ui::TouchSelectionController& controller) { @@ -1184,11 +1187,13 @@ RenderWidgetHostViewAndroid::CreateDrawable() { DCHECK(content_view_core_); if (!using_browser_compositor_) - return PopupTouchHandleDrawable::Create(content_view_core_); + return PopupTouchHandleDrawable::Create( + content_view_core_, ui::GetScaleFactorForNativeView(GetNativeView())); return std::unique_ptr< ui::TouchHandleDrawable>(new CompositedTouchHandleDrawable( - content_view_core_->GetLayer(), content_view_core_->GetDpiScale(), + content_view_core_->GetLayer(), + ui::GetScaleFactorForNativeView(GetNativeView()), // Use the activity context (instead of the application context) to ensure // proper handle theming. content_view_core_->GetContext().obj())); @@ -1678,9 +1683,9 @@ content_view_core_->DidStopFlinging(); } -uint32_t RenderWidgetHostViewAndroid::GetSurfaceIdNamespace() { +uint32_t RenderWidgetHostViewAndroid::GetSurfaceClientId() { if (id_allocator_) - return id_allocator_->id_namespace(); + return id_allocator_->client_id(); return 0; } @@ -1735,7 +1740,8 @@ if (!overscroll_controller_ && content_view_core_->GetWindowAndroid()->GetCompositor()) { - overscroll_controller_ = CreateOverscrollController(content_view_core_); + overscroll_controller_ = CreateOverscrollController( + content_view_core_, ui::GetScaleFactorForNativeView(GetNativeView())); } if (!sync_compositor_) { @@ -1807,7 +1813,8 @@ void RenderWidgetHostViewAndroid::OnAttachCompositor() { DCHECK(content_view_core_); if (!overscroll_controller_) - overscroll_controller_ = CreateOverscrollController(content_view_core_); + overscroll_controller_ = CreateOverscrollController( + content_view_core_, ui::GetScaleFactorForNativeView(GetNativeView())); } void RenderWidgetHostViewAndroid::OnDetachCompositor() {
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h index ae0f8d5..1ecee2e 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.h +++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -155,7 +155,7 @@ void ClearCompositorFrame() override; void DidOverscroll(const DidOverscrollParams& params) override; void DidStopFlinging() override; - uint32_t GetSurfaceIdNamespace() override; + uint32_t GetSurfaceClientId() override; void ShowDisambiguationPopup(const gfx::Rect& rect_pixels, const SkBitmap& zoomed_bitmap) override; std::unique_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget()
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 94f1d0d..36b79f7 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -475,8 +475,8 @@ // Let the page-level input event router know about our surface ID // namespace for surface-based hit testing. if (host_->delegate() && host_->delegate()->GetInputEventRouter()) { - host_->delegate()->GetInputEventRouter()->AddSurfaceIdNamespaceOwner( - GetSurfaceIdNamespace(), this); + host_->delegate()->GetInputEventRouter()->AddSurfaceClientIdOwner( + GetSurfaceClientId(), this); } // We should start observing the TextInputManager for IME-related events as @@ -1994,7 +1994,7 @@ event->SetHandled(); } -uint32_t RenderWidgetHostViewAura::SurfaceIdNamespaceAtPoint( +uint32_t RenderWidgetHostViewAura::SurfaceClientIdAtPoint( cc::SurfaceHittestDelegate* delegate, const gfx::Point& point, gfx::Point* transformed_point) { @@ -2012,8 +2012,8 @@ // It is possible that the renderer has not yet produced a surface, in which // case we return our current namespace. if (id.is_null()) - return GetSurfaceIdNamespace(); - return id.id_namespace(); + return GetSurfaceClientId(); + return id.client_id(); } void RenderWidgetHostViewAura::ProcessMouseEvent( @@ -2042,7 +2042,7 @@ void RenderWidgetHostViewAura::TransformPointToLocalCoordSpace( const gfx::Point& point, - cc::SurfaceId original_surface, + const cc::SurfaceId& original_surface, gfx::Point* transformed_point) { // Transformations use physical pixels rather than DIP, so conversion // is necessary. @@ -2941,6 +2941,10 @@ begin_frame_source_->AddObserver(this); } +bool RenderWidgetHostViewAura::IsAutoResizeEnabled() const { + return host_->auto_resize_enabled(); +} + void RenderWidgetHostViewAura::OnDidNavigateMainFrameToNewPage() { ui::GestureRecognizer::Get()->CancelActiveTouches(window_); } @@ -2953,8 +2957,8 @@ NOTIMPLEMENTED(); } -uint32_t RenderWidgetHostViewAura::GetSurfaceIdNamespace() { - return delegated_frame_host_->GetSurfaceIdNamespace(); +uint32_t RenderWidgetHostViewAura::GetSurfaceClientId() { + return delegated_frame_host_->GetSurfaceClientId(); } cc::SurfaceId RenderWidgetHostViewAura::SurfaceIdForTesting() const {
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index 6c06169..1a4706b8 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -189,10 +189,10 @@ void OnDidNavigateMainFrameToNewPage() override; void LockCompositingSurface() override; void UnlockCompositingSurface() override; - uint32_t GetSurfaceIdNamespace() override; - uint32_t SurfaceIdNamespaceAtPoint(cc::SurfaceHittestDelegate* delegate, - const gfx::Point& point, - gfx::Point* transformed_point) override; + uint32_t GetSurfaceClientId() override; + uint32_t SurfaceClientIdAtPoint(cc::SurfaceHittestDelegate* delegate, + const gfx::Point& point, + gfx::Point* transformed_point) override; void ProcessMouseEvent(const blink::WebMouseEvent& event, const ui::LatencyInfo& latency) override; void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event, @@ -202,7 +202,7 @@ void ProcessGestureEvent(const blink::WebGestureEvent& event, const ui::LatencyInfo& latency) override; void TransformPointToLocalCoordSpace(const gfx::Point& point, - cc::SurfaceId original_surface, + const cc::SurfaceId& original_surface, gfx::Point* transformed_point) override; void FocusedNodeChanged(bool is_editable_node) override; @@ -463,6 +463,7 @@ const base::TimeTicks& timebase, const base::TimeDelta& interval) override; void SetBeginFrameSource(cc::BeginFrameSource* source) override; + bool IsAutoResizeEnabled() const override; // TextInputManager::Observer implementation. void OnUpdateTextInputStateCalled(TextInputManager* text_input_manager,
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 47c1db5..11a59b6 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
@@ -3863,20 +3863,20 @@ // Tests the RenderWidgetHostImpl sends the correct surface ID namespace to // the renderer process. -TEST_F(RenderWidgetHostViewAuraTest, SurfaceIdNamespaceInitialized) { +TEST_F(RenderWidgetHostViewAuraTest, SurfaceClientIdInitialized) { gfx::Size size(5, 5); const IPC::Message* msg = - sink_->GetUniqueMessageMatching(ViewMsg_SetSurfaceIdNamespace::ID); + sink_->GetUniqueMessageMatching(ViewMsg_SetSurfaceClientId::ID); EXPECT_TRUE(msg); - ViewMsg_SetSurfaceIdNamespace::Param params; - ViewMsg_SetSurfaceIdNamespace::Read(msg, ¶ms); + ViewMsg_SetSurfaceClientId::Param params; + ViewMsg_SetSurfaceClientId::Read(msg, ¶ms); view_->InitAsChild(NULL); view_->Show(); view_->SetSize(size); view_->OnSwapCompositorFrame(0, MakeDelegatedFrame(1.f, size, gfx::Rect(size))); - EXPECT_EQ(view_->GetSurfaceIdNamespace(), std::get<0>(params)); + EXPECT_EQ(view_->GetSurfaceClientId(), std::get<0>(params)); } // This class provides functionality to test a RenderWidgetHostViewAura
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc index ab346c0..baf93218 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.cc +++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -377,11 +377,11 @@ void RenderWidgetHostViewBase::OnDidNavigateMainFrameToNewPage() { } -uint32_t RenderWidgetHostViewBase::GetSurfaceIdNamespace() { +uint32_t RenderWidgetHostViewBase::GetSurfaceClientId() { return 0; } -uint32_t RenderWidgetHostViewBase::SurfaceIdNamespaceAtPoint( +uint32_t RenderWidgetHostViewBase::SurfaceClientIdAtPoint( cc::SurfaceHittestDelegate* delegate, const gfx::Point& point, gfx::Point* transformed_point) { @@ -402,7 +402,7 @@ void RenderWidgetHostViewBase::TransformPointToLocalCoordSpace( const gfx::Point& point, - cc::SurfaceId original_surface, + const cc::SurfaceId& original_surface, gfx::Point* transformed_point) { *transformed_point = point; }
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h index 185d11a6..232e30bd 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.h +++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -219,17 +219,16 @@ // Returns the compositing surface ID namespace, or 0 if Surfaces are not // enabled. - virtual uint32_t GetSurfaceIdNamespace(); + virtual uint32_t GetSurfaceClientId(); // When there are multiple RenderWidgetHostViews for a single page, input // events need to be targeted to the correct one for handling. The following // methods are invoked on the RenderWidgetHostView that should be able to // properly handle the event (i.e. it has focus for keyboard events, or has // been identified by hit testing mouse, touch or gesture events). - virtual uint32_t SurfaceIdNamespaceAtPoint( - cc::SurfaceHittestDelegate* delegate, - const gfx::Point& point, - gfx::Point* transformed_point); + virtual uint32_t SurfaceClientIdAtPoint(cc::SurfaceHittestDelegate* delegate, + const gfx::Point& point, + gfx::Point* transformed_point); virtual void ProcessKeyboardEvent(const NativeWebKeyboardEvent& event) {} virtual void ProcessMouseEvent(const blink::WebMouseEvent& event, const ui::LatencyInfo& latency) {} @@ -247,9 +246,10 @@ // to be translated to viewport coordinates for the root RWHV, in which case // this method is called on the root RWHV with the out-of-process iframe's // SurfaceId. - virtual void TransformPointToLocalCoordSpace(const gfx::Point& point, - cc::SurfaceId original_surface, - gfx::Point* transformed_point); + virtual void TransformPointToLocalCoordSpace( + const gfx::Point& point, + const cc::SurfaceId& original_surface, + gfx::Point* transformed_point); //---------------------------------------------------------------------------- // The following methods are related to IME.
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index 625346a..44bce77 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -330,10 +330,10 @@ std::unique_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget() override; - uint32_t GetSurfaceIdNamespace() override; - uint32_t SurfaceIdNamespaceAtPoint(cc::SurfaceHittestDelegate* delegate, - const gfx::Point& point, - gfx::Point* transformed_point) override; + uint32_t GetSurfaceClientId() override; + uint32_t SurfaceClientIdAtPoint(cc::SurfaceHittestDelegate* delegate, + const gfx::Point& point, + gfx::Point* transformed_point) override; // Returns true when we can do SurfaceHitTesting for the event type. bool ShouldRouteEvent(const blink::WebInputEvent& event) const; void ProcessMouseEvent(const blink::WebMouseEvent& event, @@ -345,7 +345,7 @@ void ProcessGestureEvent(const blink::WebGestureEvent& event, const ui::LatencyInfo& latency) override; void TransformPointToLocalCoordSpace(const gfx::Point& point, - cc::SurfaceId original_surface, + const cc::SurfaceId& original_surface, gfx::Point* transformed_point) override; // IPC::Sender implementation.
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index 79c311e0..cab4ebc 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -524,7 +524,7 @@ render_widget_host_->delegate()->GetInputEventRouter()) { render_widget_host_->delegate() ->GetInputEventRouter() - ->AddSurfaceIdNamespaceOwner(GetSurfaceIdNamespace(), this); + ->AddSurfaceClientIdOwner(GetSurfaceClientId(), this); } } @@ -920,7 +920,7 @@ } void RenderWidgetHostViewMac::Destroy() { - // SurfaceIdNamespaces registered with RenderWidgetHostInputEventRouter + // SurfaceClientIds registered with RenderWidgetHostInputEventRouter // have already been cleared when RenderWidgetHostViewBase notified its // observers of our impending destruction. [[NSNotificationCenter defaultCenter] @@ -1391,11 +1391,11 @@ new SyntheticGestureTargetMac(host, cocoa_view_)); } -uint32_t RenderWidgetHostViewMac::GetSurfaceIdNamespace() { - return browser_compositor_->GetDelegatedFrameHost()->GetSurfaceIdNamespace(); +uint32_t RenderWidgetHostViewMac::GetSurfaceClientId() { + return browser_compositor_->GetDelegatedFrameHost()->GetSurfaceClientId(); } -uint32_t RenderWidgetHostViewMac::SurfaceIdNamespaceAtPoint( +uint32_t RenderWidgetHostViewMac::SurfaceClientIdAtPoint( cc::SurfaceHittestDelegate* delegate, const gfx::Point& point, gfx::Point* transformed_point) { @@ -1413,8 +1413,8 @@ // It is possible that the renderer has not yet produced a surface, in which // case we return our current namespace. if (id.is_null()) - return GetSurfaceIdNamespace(); - return id.id_namespace(); + return GetSurfaceClientId(); + return id.client_id(); } bool RenderWidgetHostViewMac::ShouldRouteEvent( @@ -1454,7 +1454,7 @@ void RenderWidgetHostViewMac::TransformPointToLocalCoordSpace( const gfx::Point& point, - cc::SurfaceId original_surface, + const cc::SurfaceId& original_surface, gfx::Point* transformed_point) { // Transformations use physical pixels rather than DIP, so conversion // is necessary.
diff --git a/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc b/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc index 4544838b..4fd1f5c 100644 --- a/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc +++ b/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc
@@ -117,20 +117,17 @@ protected: // Adds |n| connections. Returns true if succeeded. bool AddMultipleChannels(int number_of_channels) { - GURL socket_url("ws://example.com/test"); - std::vector<std::string> requested_protocols; - url::Origin origin(GURL("http://example.com")); - int render_frame_id = -3; - for (int i = 0; i < number_of_channels; ++i) { int routing_id = next_routing_id_++; - WebSocketHostMsg_AddChannelRequest message( - routing_id, - socket_url, - requested_protocols, - origin, - "", - render_frame_id); + + WebSocketHostMsg_AddChannelRequest_Params params; + params.socket_url = GURL("ws://example.com/test"); + params.origin = url::Origin(GURL("http://example.com")); + params.first_party_for_cookies = GURL("http://example.com"); + params.user_agent_override = ""; + params.render_frame_id = -3; + + WebSocketHostMsg_AddChannelRequest message(routing_id, params); if (!dispatcher_host_->OnMessageReceived(message)) return false; } @@ -140,20 +137,18 @@ // Adds and cancels |n| connections. Returns true if succeeded. bool AddAndCancelMultipleChannels(int number_of_channels) { - GURL socket_url("ws://example.com/test"); - std::vector<std::string> requested_protocols; - url::Origin origin(GURL("http://example.com")); - int render_frame_id = -3; - for (int i = 0; i < number_of_channels; ++i) { int routing_id = next_routing_id_++; + + WebSocketHostMsg_AddChannelRequest_Params params; + params.socket_url = GURL("ws://example.com/test"); + params.origin = url::Origin(GURL("http://example.com")); + params.first_party_for_cookies = GURL("http://example.com"); + params.user_agent_override = ""; + params.render_frame_id = -3; + WebSocketHostMsg_AddChannelRequest messageAddChannelRequest( - routing_id, - socket_url, - requested_protocols, - origin, - "", - render_frame_id); + routing_id, params); if (!dispatcher_host_->OnMessageReceived(messageAddChannelRequest)) return false; @@ -222,13 +217,18 @@ TEST_F(WebSocketDispatcherHostTest, AddChannelRequest) { int routing_id = 123; - GURL socket_url("ws://example.com/test"); std::vector<std::string> requested_protocols; requested_protocols.push_back("hello"); - url::Origin origin(GURL("http://example.com")); - int render_frame_id = -2; - WebSocketHostMsg_AddChannelRequest message( - routing_id, socket_url, requested_protocols, origin, "", render_frame_id); + + WebSocketHostMsg_AddChannelRequest_Params params; + params.socket_url = GURL("ws://example.com/test"); + params.requested_protocols = requested_protocols; + params.origin = url::Origin(GURL("http://example.com")); + params.first_party_for_cookies = GURL("http://example.com"); + params.user_agent_override = ""; + params.render_frame_id = -2; + + WebSocketHostMsg_AddChannelRequest message(routing_id, params); ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message)); @@ -256,13 +256,18 @@ TEST_F(WebSocketDispatcherHostTest, SendFrame) { int routing_id = 123; - GURL socket_url("ws://example.com/test"); std::vector<std::string> requested_protocols; requested_protocols.push_back("hello"); - url::Origin origin(GURL("http://example.com")); - int render_frame_id = -2; - WebSocketHostMsg_AddChannelRequest add_channel_message( - routing_id, socket_url, requested_protocols, origin, "", render_frame_id); + + WebSocketHostMsg_AddChannelRequest_Params params; + params.socket_url = GURL("ws://example.com/test"); + params.requested_protocols = requested_protocols; + params.origin = url::Origin(GURL("http://example.com")); + params.first_party_for_cookies = GURL("http://example.com"); + params.user_agent_override = ""; + params.render_frame_id = -2; + + WebSocketHostMsg_AddChannelRequest add_channel_message(routing_id, params); ASSERT_TRUE(dispatcher_host_->OnMessageReceived(add_channel_message)); @@ -289,12 +294,25 @@ } TEST_F(WebSocketDispatcherHostTest, Destruct) { - WebSocketHostMsg_AddChannelRequest message1( - 123, GURL("ws://example.com/test"), std::vector<std::string>(), - url::Origin(GURL("http://example.com")), "", -1); - WebSocketHostMsg_AddChannelRequest message2( - 456, GURL("ws://example.com/test2"), std::vector<std::string>(), - url::Origin(GURL("http://example.com")), "", -1); + WebSocketHostMsg_AddChannelRequest_Params params1; + params1.socket_url = GURL("ws://example.com/test"); + params1.requested_protocols = std::vector<std::string>(); + params1.origin = url::Origin(GURL("http://example.com")); + params1.first_party_for_cookies = GURL("http://example.com"); + params1.user_agent_override = ""; + params1.render_frame_id = -1; + + WebSocketHostMsg_AddChannelRequest message1(123, params1); + + WebSocketHostMsg_AddChannelRequest_Params params2; + params2.socket_url = GURL("ws://example.com/test2"); + params2.requested_protocols = std::vector<std::string>(); + params2.origin = url::Origin(GURL("http://example.com")); + params2.first_party_for_cookies = GURL("http://example.com"); + params2.user_agent_override = ""; + params2.render_frame_id = -1; + + WebSocketHostMsg_AddChannelRequest message2(456, params2); ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message1)); ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message2)); @@ -415,13 +433,19 @@ // This is a regression test for https://crrev.com/998173003/. TEST_F(WebSocketDispatcherHostTest, InvalidScheme) { int routing_id = 123; - GURL socket_url("http://example.com/test"); + std::vector<std::string> requested_protocols; requested_protocols.push_back("hello"); - url::Origin origin(GURL("http://example.com")); - int render_frame_id = -2; - WebSocketHostMsg_AddChannelRequest message( - routing_id, socket_url, requested_protocols, origin, "", render_frame_id); + + WebSocketHostMsg_AddChannelRequest_Params params; + params.socket_url = GURL("http://example.com/test"); + params.requested_protocols = requested_protocols; + params.origin = url::Origin(GURL("http://example.com")); + params.first_party_for_cookies = GURL("http://example.com"); + params.user_agent_override = ""; + params.render_frame_id = -2; + + WebSocketHostMsg_AddChannelRequest message(routing_id, params); ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message));
diff --git a/content/browser/renderer_host/websocket_host.cc b/content/browser/renderer_host/websocket_host.cc index 6f1ebde..513789a 100644 --- a/content/browser/renderer_host/websocket_host.cc +++ b/content/browser/renderer_host/websocket_host.cc
@@ -396,16 +396,15 @@ } void WebSocketHost::OnAddChannelRequest( - const GURL& socket_url, - const std::vector<std::string>& requested_protocols, - const url::Origin& origin, - const std::string& user_agent_override, - int render_frame_id) { + const WebSocketHostMsg_AddChannelRequest_Params& params) { DVLOG(3) << "WebSocketHost::OnAddChannelRequest" - << " routing_id=" << routing_id_ << " socket_url=\"" << socket_url - << "\" requested_protocols=\"" - << base::JoinString(requested_protocols, ", ") << "\" origin=\"" - << origin << "\" user_agent_override=\"" << user_agent_override + << " routing_id=" << routing_id_ << " socket_url=\"" + << params.socket_url << "\" requested_protocols=\"" + << base::JoinString(params.requested_protocols, ", ") + << "\" origin=\"" << params.origin + << "\" first_party_for_cookies=\"" + << params.first_party_for_cookies << "\" user_agent_override=\"" + << params.user_agent_override << "\""; DCHECK(!channel_); @@ -413,12 +412,15 @@ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::Bind(&WebSocketHost::AddChannel, weak_ptr_factory_.GetWeakPtr(), - socket_url, requested_protocols, origin, - user_agent_override, render_frame_id), + params.socket_url, params.requested_protocols, + params.origin, params.first_party_for_cookies, + params.user_agent_override, params.render_frame_id), delay_); } else { - AddChannel(socket_url, requested_protocols, origin, - user_agent_override, render_frame_id); + AddChannel( + params.socket_url, params.requested_protocols, params.origin, + params.first_party_for_cookies, params.user_agent_override, + params.render_frame_id); } // |this| may have been deleted here. } @@ -427,13 +429,15 @@ const GURL& socket_url, const std::vector<std::string>& requested_protocols, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& user_agent_override, int render_frame_id) { DVLOG(3) << "WebSocketHost::AddChannel" << " routing_id=" << routing_id_ << " socket_url=\"" << socket_url << "\" requested_protocols=\"" << base::JoinString(requested_protocols, ", ") << "\" origin=\"" - << origin << "\" user_agent_override=\"" + << origin << "\" first_party_for_cookies=\"" + << first_party_for_cookies << "\" user_agent_override=\"" << user_agent_override << "\""; DCHECK(!channel_); @@ -469,8 +473,8 @@ user_agent_override.c_str()); } channel_->SendAddChannelRequest( - socket_url, requested_protocols, origin, - additional_headers); + socket_url, requested_protocols, origin, first_party_for_cookies, + additional_headers); // |this| may have been deleted here. }
diff --git a/content/browser/renderer_host/websocket_host.h b/content/browser/renderer_host/websocket_host.h index adbe3b9c..3488ef0 100644 --- a/content/browser/renderer_host/websocket_host.h +++ b/content/browser/renderer_host/websocket_host.h
@@ -18,6 +18,7 @@ #include "content/common/websocket.h" class GURL; +struct WebSocketHostMsg_AddChannelRequest_Params; namespace url { class Origin; @@ -66,15 +67,13 @@ // Handlers for each message type, dispatched by OnMessageReceived(), as // defined in content/common/websocket_messages.h - void OnAddChannelRequest(const GURL& socket_url, - const std::vector<std::string>& requested_protocols, - const url::Origin& origin, - const std::string& user_agent_override, - int render_frame_id); + void OnAddChannelRequest( + const WebSocketHostMsg_AddChannelRequest_Params& request); void AddChannel(const GURL& socket_url, const std::vector<std::string>& requested_protocols, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& user_agent_override, int render_frame_id);
diff --git a/content/browser/tracing/background_tracing_manager_impl.cc b/content/browser/tracing/background_tracing_manager_impl.cc index c5812f9..33f9531 100644 --- a/content/browser/tracing/background_tracing_manager_impl.cc +++ b/content/browser/tracing/background_tracing_manager_impl.cc
@@ -16,6 +16,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "content/browser/tracing/background_tracing_rule.h" +#include "content/browser/tracing/tracing_controller_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/tracing_delegate.h" @@ -478,8 +479,7 @@ RecordBackgroundTracingMetric(FINALIZATION_COMPLETE); } -void BackgroundTracingManagerImpl::AddCustomMetadata( - TracingControllerImpl::TraceDataSink* trace_data_sink) { +void BackgroundTracingManagerImpl::AddCustomMetadata() { base::DictionaryValue metadata_dict; std::unique_ptr<base::DictionaryValue> config_dict( @@ -489,7 +489,7 @@ if (last_triggered_rule_) metadata_dict.Set("last_triggered_rule", std::move(last_triggered_rule_)); - trace_data_sink->AddMetadata(metadata_dict); + TracingController::GetInstance()->AddMetadata(metadata_dict); } void BackgroundTracingManagerImpl::BeginFinalizing( @@ -506,12 +506,12 @@ scoped_refptr<TracingControllerImpl::TraceDataSink> trace_data_sink; if (is_allowed_finalization) { - trace_data_sink = content::TracingController::CreateCompressedStringSink( - content::TracingController::CreateCallbackEndpoint( + trace_data_sink = TracingControllerImpl::CreateCompressedStringSink( + TracingControllerImpl::CreateCallbackEndpoint( base::Bind(&BackgroundTracingManagerImpl::OnFinalizeStarted, base::Unretained(this)))); RecordBackgroundTracingMetric(FINALIZATION_ALLOWED); - AddCustomMetadata(trace_data_sink.get()); + AddCustomMetadata(); } else { RecordBackgroundTracingMetric(FINALIZATION_DISALLOWED); }
diff --git a/content/browser/tracing/background_tracing_manager_impl.h b/content/browser/tracing/background_tracing_manager_impl.h index 7b0ccba..8628a683 100644 --- a/content/browser/tracing/background_tracing_manager_impl.h +++ b/content/browser/tracing/background_tracing_manager_impl.h
@@ -63,7 +63,7 @@ void BeginFinalizing(StartedFinalizingCallback); void ValidateStartupScenario(); - void AddCustomMetadata(TracingControllerImpl::TraceDataSink*); + void AddCustomMetadata(); std::string GetTriggerNameFromHandle(TriggerHandle handle) const; bool IsTriggerHandleValid(TriggerHandle handle) const;
diff --git a/content/browser/tracing/tracing_controller_browsertest.cc b/content/browser/tracing/tracing_controller_browsertest.cc index 29fbba1..52401ee0 100644 --- a/content/browser/tracing/tracing_controller_browsertest.cc +++ b/content/browser/tracing/tracing_controller_browsertest.cc
@@ -12,11 +12,14 @@ #include "base/run_loop.h" #include "base/strings/pattern.h" #include "build/build_config.h" +#include "content/browser/tracing/tracing_controller_impl.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/trace_uploader.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" #include "content/shell/browser/shell.h" +#include "content/test/test_content_browser_client.h" using base::trace_event::RECORD_CONTINUOUSLY; using base::trace_event::RECORD_UNTIL_FULL; @@ -55,8 +58,7 @@ } // namespace -class TracingControllerTestEndpoint - : public TracingController::TraceDataEndpoint { +class TracingControllerTestEndpoint : public TraceDataEndpoint { public: TracingControllerTestEndpoint( base::Callback<void(std::unique_ptr<const base::DictionaryValue>, @@ -92,6 +94,25 @@ done_callback_; }; +class TracingTestBrowserClient : public TestContentBrowserClient { + public: + TracingDelegate* GetTracingDelegate() override { + return new TestTracingDelegate(); + }; + + private: + class TestTracingDelegate : public TracingDelegate { + public: + std::unique_ptr<TraceUploader> GetTraceUploader( + net::URLRequestContextGetter* request_context) override { + return nullptr; + } + MetadataFilterPredicate GetMetadataFilterPredicate() override { + return base::Bind(IsMetadataWhitelisted); + } + }; +}; + class TracingControllerTest : public ContentBrowserTest { public: TracingControllerTest() {} @@ -201,10 +222,13 @@ } void TestStartAndStopTracingStringWithFilter() { + TracingTestBrowserClient client; + ContentBrowserClient* old_client = SetBrowserClientForTesting(&client); Navigate(shell()); base::trace_event::TraceLog::GetInstance()->SetArgumentFilterPredicate( base::Bind(&IsTraceEventArgsWhitelisted)); + TracingController* controller = TracingController::GetInstance(); { @@ -234,17 +258,16 @@ scoped_refptr<TracingController::TraceDataSink> trace_data_sink = TracingController::CreateStringSink(callback); - trace_data_sink->SetMetadataFilterPredicate( - base::Bind(&IsMetadataWhitelisted)); base::DictionaryValue metadata; metadata.SetString("not-whitelisted", "this_not_found"); - trace_data_sink->AddMetadata(metadata); + controller->AddMetadata(metadata); bool result = controller->StopTracing(trace_data_sink); ASSERT_TRUE(result); run_loop.Run(); EXPECT_EQ(disable_recording_done_callback_count(), 1); } + SetBrowserClientForTesting(old_client); } void TestStartAndStopTracingCompressed() { @@ -271,7 +294,7 @@ &TracingControllerTest::StopTracingStringDoneCallbackTest, base::Unretained(this), run_loop.QuitClosure()); bool result = controller->StopTracing( - TracingController::CreateCompressedStringSink( + TracingControllerImpl::CreateCompressedStringSink( new TracingControllerTestEndpoint(callback))); ASSERT_TRUE(result); run_loop.Run(); @@ -279,38 +302,6 @@ } } - void TestStartAndStopTracingCompressedFile( - const base::FilePath& result_file_path) { - Navigate(shell()); - - TracingController* controller = TracingController::GetInstance(); - - { - base::RunLoop run_loop; - TracingController::StartTracingDoneCallback callback = - base::Bind(&TracingControllerTest::StartTracingDoneCallbackTest, - base::Unretained(this), run_loop.QuitClosure()); - bool result = controller->StartTracing(TraceConfig(), callback); - ASSERT_TRUE(result); - run_loop.Run(); - EXPECT_EQ(enable_recording_done_callback_count(), 1); - } - - { - base::RunLoop run_loop; - base::Closure callback = base::Bind( - &TracingControllerTest::StopTracingFileDoneCallbackTest, - base::Unretained(this), run_loop.QuitClosure(), result_file_path); - bool result = controller->StopTracing( - TracingController::CreateCompressedStringSink( - TracingController::CreateFileEndpoint(result_file_path, - callback))); - ASSERT_TRUE(result); - run_loop.Run(); - EXPECT_EQ(disable_recording_done_callback_count(), 1); - } - } - void TestStartAndStopTracingFile( const base::FilePath& result_file_path) { Navigate(shell()); @@ -443,14 +434,6 @@ } IN_PROC_BROWSER_TEST_F(TracingControllerTest, - EnableAndStopTracingToFileWithCompression) { - base::FilePath file_path; - base::CreateTemporaryFile(&file_path); - TestStartAndStopTracingCompressedFile(file_path); - EXPECT_EQ(file_path.value(), last_actual_recording_file_path().value()); -} - -IN_PROC_BROWSER_TEST_F(TracingControllerTest, EnableAndStopTracingWithEmptyFileAndNullCallback) { Navigate(shell());
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc index 5756c73..c36a633 100644 --- a/content/browser/tracing/tracing_controller_impl.cc +++ b/content/browser/tracing/tracing_controller_impl.cc
@@ -168,6 +168,13 @@ metadata_dict->SetBoolean("highres-ticks", base::TimeTicks::IsHighResolution()); + base::Time::Exploded ctime; + base::Time::Now().UTCExplode(&ctime); + std::string time_string = base::StringPrintf("%u-%u-%u %d:%d:%d", + ctime.year, ctime.month, ctime.day_of_month, ctime.hour, + ctime.minute, ctime.second); + metadata_dict->SetString("trace-capture-datetime", time_string); + return metadata_dict; } @@ -252,6 +259,7 @@ start_tracing_done_callback_ = callback; start_tracing_trace_config_.reset( new base::trace_event::TraceConfig(trace_config)); + metadata_.reset(new base::DictionaryValue()); pending_start_tracing_ack_count_ = 0; #if defined(OS_ANDROID) @@ -329,6 +337,10 @@ start_tracing_trace_config_.reset(); } +void TracingControllerImpl::AddMetadata(const base::DictionaryValue& data) { + metadata_->MergeDictionary(&data); +} + bool TracingControllerImpl::StopTracing( const scoped_refptr<TraceDataSink>& trace_data_sink) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -347,16 +359,20 @@ } if (trace_data_sink) { + MetadataFilterPredicate metadata_filter; if (TraceLog::GetInstance()->GetCurrentTraceConfig() .IsArgumentFilterEnabled()) { std::unique_ptr<TracingDelegate> delegate( GetContentClient()->browser()->GetTracingDelegate()); - if (delegate) { - trace_data_sink->SetMetadataFilterPredicate( - delegate->GetMetadataFilterPredicate()); - } + if (delegate) + metadata_filter = delegate->GetMetadataFilterPredicate(); } - trace_data_sink->AddMetadata(*GenerateTracingMetadataDict().get()); + AddFilteredMetadata(trace_data_sink.get(), GenerateTracingMetadataDict(), + metadata_filter); + AddFilteredMetadata(trace_data_sink.get(), std::move(metadata_), + metadata_filter); + } else { + metadata_.reset(); } trace_data_sink_ = trace_data_sink; @@ -912,6 +928,26 @@ } } +void TracingControllerImpl::AddFilteredMetadata( + TracingController::TraceDataSink* sink, + std::unique_ptr<base::DictionaryValue> metadata, + const MetadataFilterPredicate& filter) { + if (filter.is_null()) { + sink->AddMetadata(std::move(metadata)); + return; + } + std::unique_ptr<base::DictionaryValue> filtered_metadata( + new base::DictionaryValue); + for (base::DictionaryValue::Iterator it(*metadata); !it.IsAtEnd(); + it.Advance()) { + if (filter.Run(it.key())) + filtered_metadata->Set(it.key(), it.value().DeepCopy()); + else + filtered_metadata->SetString(it.key(), "__stripped__"); + } + sink->AddMetadata(std::move(filtered_metadata)); +} + void TracingControllerImpl::RequestGlobalMemoryDump( const base::trace_event::MemoryDumpRequestArgs& args, const base::trace_event::MemoryDumpCallback& callback) {
diff --git a/content/browser/tracing/tracing_controller_impl.h b/content/browser/tracing/tracing_controller_impl.h index a391cdb..326ec43 100644 --- a/content/browser/tracing/tracing_controller_impl.h +++ b/content/browser/tracing/tracing_controller_impl.h
@@ -30,11 +30,37 @@ class TraceMessageFilter; class TracingUI; +// An implementation of this interface is passed when constructing a +// TraceDataSink, and receives chunks of the final trace data as it's being +// constructed. +// Methods may be called from any thread. +class CONTENT_EXPORT TraceDataEndpoint + : public base::RefCountedThreadSafe<TraceDataEndpoint> { + public: + virtual void ReceiveTraceChunk(const std::string& chunk) {} + virtual void ReceiveTraceFinalContents( + std::unique_ptr<const base::DictionaryValue> metadata, + const std::string& contents) {} + + protected: + friend class base::RefCountedThreadSafe<TraceDataEndpoint>; + virtual ~TraceDataEndpoint() {} +}; + class TracingControllerImpl : public TracingController, public base::trace_event::MemoryDumpManagerDelegate, public base::trace_event::TracingAgent { public: + // Create an endpoint that may be supplied to any TraceDataSink to + // dump the trace data to a callback. + CONTENT_EXPORT static scoped_refptr<TraceDataEndpoint> CreateCallbackEndpoint( + const base::Callback<void(std::unique_ptr<const base::DictionaryValue>, + base::RefCountedString*)>& callback); + + CONTENT_EXPORT static scoped_refptr<TraceDataSink> CreateCompressedStringSink( + scoped_refptr<TraceDataEndpoint> endpoint); + static TracingControllerImpl* GetInstance(); // TracingController implementation. @@ -44,6 +70,8 @@ bool StopTracing(const scoped_refptr<TraceDataSink>& sink) override; bool GetTraceBufferUsage( const GetTraceBufferUsageCallback& callback) override; + void AddMetadata(const base::DictionaryValue& metadata) override; + bool SetWatchEvent(const std::string& category_name, const std::string& event_name, const WatchEventCallback& callback) override; @@ -177,6 +205,10 @@ const base::TimeTicks& issue_ts, const base::TimeTicks& issue_end_ts); + void AddFilteredMetadata(TracingController::TraceDataSink* sink, + std::unique_ptr<base::DictionaryValue> metadata, + const MetadataFilterPredicate& filter); + typedef std::set<scoped_refptr<TraceMessageFilter>> TraceMessageFilterSet; TraceMessageFilterSet trace_message_filters_; @@ -223,6 +255,7 @@ std::set<TracingUI*> tracing_uis_; scoped_refptr<TraceDataSink> trace_data_sink_; scoped_refptr<TraceDataSink> monitoring_data_sink_; + std::unique_ptr<base::DictionaryValue> metadata_; DISALLOW_COPY_AND_ASSIGN(TracingControllerImpl); };
diff --git a/content/browser/tracing/tracing_controller_impl_data_sinks.cc b/content/browser/tracing/tracing_controller_impl_data_sinks.cc index 4020df1..fc15fc1 100644 --- a/content/browser/tracing/tracing_controller_impl_data_sinks.cc +++ b/content/browser/tracing/tracing_controller_impl_data_sinks.cc
@@ -19,7 +19,7 @@ const char kChromeTraceLabel[] = "traceEvents"; const char kMetadataTraceLabel[] = "metadata"; -class StringTraceDataEndpoint : public TracingController::TraceDataEndpoint { +class StringTraceDataEndpoint : public TraceDataEndpoint { public: typedef base::Callback<void(std::unique_ptr<const base::DictionaryValue>, base::RefCountedString*)> @@ -49,7 +49,7 @@ DISALLOW_COPY_AND_ASSIGN(StringTraceDataEndpoint); }; -class FileTraceDataEndpoint : public TracingController::TraceDataEndpoint { +class FileTraceDataEndpoint : public TraceDataEndpoint { public: explicit FileTraceDataEndpoint(const base::FilePath& trace_file_path, const base::Closure& callback) @@ -115,10 +115,32 @@ DISALLOW_COPY_AND_ASSIGN(FileTraceDataEndpoint); }; -class StringTraceDataSink : public TracingController::TraceDataSink { +class TraceDataSinkImplBase : public TracingController::TraceDataSink { public: - explicit StringTraceDataSink( - scoped_refptr<TracingController::TraceDataEndpoint> endpoint) + void AddAgentTrace(const std::string& trace_label, + const std::string& trace_data) override; + void AddMetadata(std::unique_ptr<base::DictionaryValue> data) override; + + protected: + TraceDataSinkImplBase() : metadata_(new base::DictionaryValue()) {} + ~TraceDataSinkImplBase() override {} + + // Get a map of TracingAgent's data, which is previously added by + // AddAgentTrace(). The map's key is the trace label and the map's value is + // the trace data. + const std::map<std::string, std::string>& GetAgentTrace() const; + std::unique_ptr<base::DictionaryValue> TakeMetadata(); + + private: + std::map<std::string, std::string> additional_tracing_agent_trace_; + std::unique_ptr<base::DictionaryValue> metadata_; + + DISALLOW_COPY_AND_ASSIGN(TraceDataSinkImplBase); +}; + +class StringTraceDataSink : public TraceDataSinkImplBase { + public: + explicit StringTraceDataSink(scoped_refptr<TraceDataEndpoint> endpoint) : endpoint_(endpoint) {} void AddTraceChunk(const std::string& chunk) override { @@ -144,8 +166,10 @@ for (auto const &it : GetAgentTrace()) AddTraceChunkAndPassToEndpoint(",\"" + it.first + "\": " + it.second); + std::unique_ptr<base::DictionaryValue> metadata(TakeMetadata()); std::string metadataJSON; - if (base::JSONWriter::Write(*GetMetadataCopy(), &metadataJSON) && + + if (base::JSONWriter::Write(*metadata, &metadataJSON) && !metadataJSON.empty()) { AddTraceChunkAndPassToEndpoint( ",\"" + std::string(kMetadataTraceLabel) + "\": " + metadataJSON); @@ -153,22 +177,22 @@ AddTraceChunkAndPassToEndpoint("}"); - endpoint_->ReceiveTraceFinalContents(GetMetadataCopy(), trace_); + endpoint_->ReceiveTraceFinalContents(std::move(metadata), trace_); } private: ~StringTraceDataSink() override {} - scoped_refptr<TracingController::TraceDataEndpoint> endpoint_; + scoped_refptr<TraceDataEndpoint> endpoint_; std::string trace_; DISALLOW_COPY_AND_ASSIGN(StringTraceDataSink); }; -class CompressedStringTraceDataSink : public TracingController::TraceDataSink { +class CompressedStringTraceDataSink : public TraceDataSinkImplBase { public: explicit CompressedStringTraceDataSink( - scoped_refptr<TracingController::TraceDataEndpoint> endpoint) + scoped_refptr<TraceDataEndpoint> endpoint) : endpoint_(endpoint), already_tried_open_(false) {} void AddTraceChunk(const std::string& chunk) override { @@ -271,8 +295,9 @@ ",\"" + it.first + "\": " + it.second, false); } + std::unique_ptr<base::DictionaryValue> metadata(TakeMetadata()); std::string metadataJSON; - if (base::JSONWriter::Write(*GetMetadataCopy(), &metadataJSON) && + if (base::JSONWriter::Write(*metadata, &metadataJSON) && !metadataJSON.empty()) { AddTraceChunkAndCompressOnFileThread( ",\"" + std::string(kMetadataTraceLabel) + "\": " + metadataJSON, @@ -283,11 +308,11 @@ deflateEnd(stream_.get()); stream_.reset(); - endpoint_->ReceiveTraceFinalContents(GetMetadataCopy(), + endpoint_->ReceiveTraceFinalContents(std::move(metadata), compressed_trace_data_); } - scoped_refptr<TracingController::TraceDataEndpoint> endpoint_; + scoped_refptr<TraceDataEndpoint> endpoint_; std::unique_ptr<z_stream> stream_; bool already_tried_open_; std::string compressed_trace_data_; @@ -298,47 +323,27 @@ } // namespace TracingController::TraceDataSink::TraceDataSink() {} - TracingController::TraceDataSink::~TraceDataSink() {} -void TracingController::TraceDataSink::AddAgentTrace( - const std::string& trace_label, - const std::string& trace_data) { +void TraceDataSinkImplBase::AddAgentTrace(const std::string& trace_label, + const std::string& trace_data) { DCHECK(additional_tracing_agent_trace_.find(trace_label) == additional_tracing_agent_trace_.end()); additional_tracing_agent_trace_[trace_label] = trace_data; } -const std::map<std::string, std::string>& - TracingController::TraceDataSink::GetAgentTrace() const { +const std::map<std::string, std::string>& TraceDataSinkImplBase::GetAgentTrace() + const { return additional_tracing_agent_trace_; } -void TracingController::TraceDataSink::AddMetadata( - const base::DictionaryValue& data) { - metadata_.MergeDictionary(&data); +void TraceDataSinkImplBase::AddMetadata( + std::unique_ptr<base::DictionaryValue> data) { + metadata_->MergeDictionary(data.get()); } -void TracingController::TraceDataSink::SetMetadataFilterPredicate( - const MetadataFilterPredicate& metadata_filter_predicate) { - metadata_filter_predicate_ = metadata_filter_predicate; -} - -std::unique_ptr<const base::DictionaryValue> -TracingController::TraceDataSink::GetMetadataCopy() const { - if (metadata_filter_predicate_.is_null()) - return std::unique_ptr<const base::DictionaryValue>(metadata_.DeepCopy()); - - std::unique_ptr<base::DictionaryValue> metadata_copy( - new base::DictionaryValue); - for (base::DictionaryValue::Iterator it(metadata_); !it.IsAtEnd(); - it.Advance()) { - if (metadata_filter_predicate_.Run(it.key())) - metadata_copy->Set(it.key(), it.value().DeepCopy()); - else - metadata_copy->SetString(it.key(), "__stripped__"); - } - return std::move(metadata_copy); +std::unique_ptr<base::DictionaryValue> TraceDataSinkImplBase::TakeMetadata() { + return std::move(metadata_); } scoped_refptr<TracingController::TraceDataSink> @@ -349,29 +354,22 @@ } scoped_refptr<TracingController::TraceDataSink> -TracingController::CreateCompressedStringSink( - scoped_refptr<TracingController::TraceDataEndpoint> endpoint) { - return new CompressedStringTraceDataSink(endpoint); -} - -scoped_refptr<TracingController::TraceDataSink> TracingController::CreateFileSink(const base::FilePath& file_path, const base::Closure& callback) { return new StringTraceDataSink( - CreateFileEndpoint(file_path, callback)); + new FileTraceDataEndpoint(file_path, callback)); } -scoped_refptr<TracingController::TraceDataEndpoint> -TracingController::CreateCallbackEndpoint( +scoped_refptr<TracingController::TraceDataSink> +TracingControllerImpl::CreateCompressedStringSink( + scoped_refptr<TraceDataEndpoint> endpoint) { + return new CompressedStringTraceDataSink(endpoint); +} + +scoped_refptr<TraceDataEndpoint> TracingControllerImpl::CreateCallbackEndpoint( const base::Callback<void(std::unique_ptr<const base::DictionaryValue>, base::RefCountedString*)>& callback) { return new StringTraceDataEndpoint(callback); } -scoped_refptr<TracingController::TraceDataEndpoint> -TracingController::CreateFileEndpoint(const base::FilePath& file_path, - const base::Closure& callback) { - return new FileTraceDataEndpoint(file_path, callback); -} - } // namespace content
diff --git a/content/browser/tracing/tracing_ui.cc b/content/browser/tracing/tracing_ui.cc index 6619c3a..3e32838 100644 --- a/content/browser/tracing/tracing_ui.cc +++ b/content/browser/tracing/tracing_ui.cc
@@ -155,12 +155,12 @@ callback.Run(data_base64); } -void AddCustomMetadata(TracingControllerImpl::TraceDataSink* trace_data_sink) { +void AddCustomMetadata() { base::DictionaryValue metadata_dict; metadata_dict.SetString( "command_line", base::CommandLine::ForCurrentProcess()->GetCommandLineString()); - trace_data_sink->AddMetadata(metadata_dict); + TracingController::GetInstance()->AddMetadata(metadata_dict); } bool OnBeginJSONRequest(const std::string& path, @@ -185,11 +185,13 @@ base::Bind(OnTraceBufferStatusResult, callback)); } if (path == "json/end_recording_compressed") { + if (!TracingController::GetInstance()->IsTracing()) + return false; scoped_refptr<TracingControllerImpl::TraceDataSink> data_sink = - TracingController::CreateCompressedStringSink( - TracingController::CreateCallbackEndpoint( + TracingControllerImpl::CreateCompressedStringSink( + TracingControllerImpl::CreateCallbackEndpoint( base::Bind(TracingCallbackWrapperBase64, callback))); - AddCustomMetadata(data_sink.get()); + AddCustomMetadata(); return TracingController::GetInstance()->StopTracing(data_sink); }
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 23a03d9..9b445c8 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1707,8 +1707,7 @@ view_->RestoreFocus(); } - if (mouse_lock_widget_ == render_widget_host) - mouse_lock_widget_ = nullptr; + CHECK(mouse_lock_widget_ != render_widget_host); } void WebContentsImpl::RenderWidgetGotFocus( @@ -1897,12 +1896,19 @@ void WebContentsImpl::RequestToLockMouse( RenderWidgetHostImpl* render_widget_host, bool user_gesture, - bool last_unlocked_by_target) { + bool last_unlocked_by_target, + bool privileged) { if (mouse_lock_widget_) { render_widget_host->GotResponseToLockMouseRequest(false); return; } + if (privileged) { + mouse_lock_widget_ = render_widget_host; + render_widget_host->GotResponseToLockMouseRequest(true); + return; + } + bool widget_in_frame_tree = false; for (FrameTreeNode* node : frame_tree_.Nodes()) { if (node->current_frame_host()->GetRenderWidgetHost() == @@ -1929,6 +1935,14 @@ delegate_->LostMouseLock(); } +bool WebContentsImpl::HasMouseLock(RenderWidgetHostImpl* render_widget_host) { + // To verify if the mouse is locked, the mouse_lock_widget_ needs to be + // assigned to the widget that requested the mouse lock, and the top-level + // platform RenderWidgetHostView needs to hold the mouse lock from the OS. + return mouse_lock_widget_ == render_widget_host && + GetTopLevelRenderWidgetHostView()->IsMouseLocked(); +} + void WebContentsImpl::ForwardCompositorProto( RenderWidgetHostImpl* render_widget_host, const std::vector<uint8_t>& proto) { @@ -2986,8 +3000,11 @@ if (GetBrowserPluginGuest()) return GetBrowserPluginGuest()->LockMouse(allowed); - if (mouse_lock_widget_) - return mouse_lock_widget_->GotResponseToLockMouseRequest(allowed); + if (mouse_lock_widget_ && + mouse_lock_widget_->GotResponseToLockMouseRequest(allowed)) + return true; + + mouse_lock_widget_ = nullptr; return false; } @@ -3107,10 +3124,6 @@ manifest_manager_host_->GetManifest(GetMainFrame(), callback); } -void WebContentsImpl::HasManifest(const HasManifestCallback& callback) { - manifest_manager_host_->HasManifest(GetMainFrame(), callback); -} - void WebContentsImpl::ExitFullscreen(bool will_cause_resize) { // Clean up related state and initiate the fullscreen exit. GetRenderViewHost()->GetWidget()->RejectMouseLockOrUnlockIfNecessary();
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index ad392c7..dca061eb 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -391,7 +391,6 @@ void InsertCSS(const std::string& css) override; bool WasRecentlyAudible() override; void GetManifest(const GetManifestCallback& callback) override; - void HasManifest(const HasManifestCallback& callback) override; void ExitFullscreen(bool will_cause_resize) override; void ResumeLoadingCreatedWebContents() override; void OnMediaSessionStateChanged(); @@ -619,7 +618,8 @@ void RendererResponsive(RenderWidgetHostImpl* render_widget_host) override; void RequestToLockMouse(RenderWidgetHostImpl* render_widget_host, bool user_gesture, - bool last_unlocked_by_target) override; + bool last_unlocked_by_target, + bool privileged) override; gfx::Rect GetRootWindowResizerRect( RenderWidgetHostImpl* render_widget_host) const override; bool IsFullscreenForCurrentTab() const override; @@ -627,6 +627,7 @@ RenderWidgetHostImpl* render_widget_host) const override; void LostCapture(RenderWidgetHostImpl* render_widget_host) override; void LostMouseLock(RenderWidgetHostImpl* render_widget_host) override; + bool HasMouseLock(RenderWidgetHostImpl* render_widget_host) override; void ForwardCompositorProto(RenderWidgetHostImpl* render_widget_host, const std::vector<uint8_t>& proto) override; void OnRenderFrameProxyVisibilityChanged(bool visible) override;
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc index 2ac8745a..5c82189 100644 --- a/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/macros.h" +#include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "build/build_config.h" @@ -1207,6 +1208,18 @@ loop_runner->Run(); } +void ExpectNoValidImageCallback(const base::Closure& quit_closure, + int id, + int status_code, + const GURL& image_url, + const std::vector<SkBitmap>& bitmap, + const std::vector<gfx::Size>& sizes) { + EXPECT_EQ(200, status_code); + EXPECT_TRUE(bitmap.empty()); + EXPECT_TRUE(sizes.empty()); + quit_closure.Run(); +} + } // anonymous namespace IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, @@ -1224,4 +1237,16 @@ DownloadImageTestInternal(shell(), kImageUrl, 0); } +IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DownloadImage_NoValidImage) { + ASSERT_TRUE(embedded_test_server()->Start()); + const GURL kImageUrl = embedded_test_server()->GetURL("/invalid.ico"); + shell()->LoadURL(GURL("about:blank")); + base::RunLoop run_loop; + shell()->web_contents()->DownloadImage( + kImageUrl, false, 2, false, + base::Bind(&ExpectNoValidImageCallback, run_loop.QuitClosure())); + + run_loop.Run(); +} + } // namespace content
diff --git a/content/child/request_extra_data.cc b/content/child/request_extra_data.cc index be4d035..e71362b7 100644 --- a/content/child/request_extra_data.cc +++ b/content/child/request_extra_data.cc
@@ -24,7 +24,6 @@ transferred_request_request_id_(-1), service_worker_provider_id_(kInvalidServiceWorkerProviderId), originated_from_service_worker_(false), - lofi_state_(LOFI_UNSPECIFIED), initiated_in_secure_context_(false) {} RequestExtraData::~RequestExtraData() {
diff --git a/content/child/request_extra_data.h b/content/child/request_extra_data.h index 0fe21006..77c1646 100644 --- a/content/child/request_extra_data.h +++ b/content/child/request_extra_data.h
@@ -98,12 +98,6 @@ void set_originated_from_service_worker(bool originated_from_service_worker) { originated_from_service_worker_ = originated_from_service_worker; } - LoFiState lofi_state() const { - return lofi_state_; - } - void set_lofi_state(LoFiState lofi_state) { - lofi_state_ = lofi_state; - } // |custom_user_agent| is used to communicate an overriding custom user agent // to |RenderViewImpl::willSendRequest()|; set to a null string to indicate no // override and an empty string to indicate that there should be no user @@ -156,7 +150,6 @@ blink::WebString custom_user_agent_; blink::WebString requested_with_; std::unique_ptr<StreamOverrideParameters> stream_override_; - LoFiState lofi_state_; bool initiated_in_secure_context_; DISALLOW_COPY_AND_ASSIGN(RequestExtraData);
diff --git a/content/child/request_info.cc b/content/child/request_info.cc index 3ae2d36..2d69b51d5 100644 --- a/content/child/request_info.cc +++ b/content/child/request_info.cc
@@ -28,7 +28,8 @@ do_not_prompt_for_login(false), report_raw_headers(false), extra_data(NULL), - loading_web_task_runner(nullptr) {} + loading_web_task_runner(nullptr), + lofi_state(LOFI_UNSPECIFIED) {} RequestInfo::~RequestInfo() {}
diff --git a/content/child/request_info.h b/content/child/request_info.h index 8b64807db..f7d7339 100644 --- a/content/child/request_info.h +++ b/content/child/request_info.h
@@ -12,6 +12,7 @@ #include "base/macros.h" #include "content/common/content_export.h" +#include "content/common/navigation_params.h" #include "content/common/service_worker/service_worker_types.h" #include "content/public/common/referrer.h" #include "content/public/common/request_context_frame_type.h" @@ -128,6 +129,10 @@ // the ResourceBody that has already been fetched by the browser process. GURL resource_body_stream_url; + // Whether or not to request a LoFi version of the document or let the browser + // decide. + LoFiState lofi_state; + private: DISALLOW_COPY_AND_ASSIGN(RequestInfo); };
diff --git a/content/child/resource_dispatcher.cc b/content/child/resource_dispatcher.cc index 461da5c..28d35f2 100644 --- a/content/child/resource_dispatcher.cc +++ b/content/child/resource_dispatcher.cc
@@ -226,7 +226,8 @@ void ResourceDispatcher::OnReceivedInlinedDataChunk( int request_id, const std::vector<char>& data, - int encoded_data_length) { + int encoded_data_length, + int encoded_body_length) { TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedInlinedDataChunk"); DCHECK(!data.empty()); DCHECK(base::FeatureList::IsEnabled( @@ -254,7 +255,8 @@ void ResourceDispatcher::OnReceivedData(int request_id, int data_offset, int data_length, - int encoded_data_length) { + int encoded_data_length, + int encoded_body_length) { TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedData"); DCHECK_GT(data_length, 0); PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); @@ -764,6 +766,7 @@ request->enable_upload_progress = request_info.enable_upload_progress; request->do_not_prompt_for_login = request_info.do_not_prompt_for_login; request->report_raw_headers = request_info.report_raw_headers; + request->lofi_state = request_info.lofi_state; if ((request_info.referrer.policy == blink::WebReferrerPolicyDefault || request_info.referrer.policy == @@ -799,7 +802,6 @@ extra_data->service_worker_provider_id(); request->originated_from_service_worker = extra_data->originated_from_service_worker(); - request->lofi_state = extra_data->lofi_state(); request->request_body = request_body; request->resource_body_stream_url = request_info.resource_body_stream_url; request->initiated_in_secure_context =
diff --git a/content/child/resource_dispatcher.h b/content/child/resource_dispatcher.h index 11062c6..8a56030 100644 --- a/content/child/resource_dispatcher.h +++ b/content/child/resource_dispatcher.h
@@ -178,11 +178,13 @@ base::ProcessId renderer_pid); void OnReceivedInlinedDataChunk(int request_id, const std::vector<char>& data, - int encoded_data_length); + int encoded_data_length, + int encoded_body_length); void OnReceivedData(int request_id, int data_offset, int data_length, - int encoded_data_length); + int encoded_data_length, + int encoded_body_length); void OnDownloadedData(int request_id, int data_len, int encoded_data_length); void OnRequestComplete( int request_id,
diff --git a/content/child/resource_dispatcher_unittest.cc b/content/child/resource_dispatcher_unittest.cc index 07fbecf..5d072120 100644 --- a/content/child/resource_dispatcher_unittest.cc +++ b/content/child/resource_dispatcher_unittest.cc
@@ -13,6 +13,7 @@ #include <utility> #include <vector> +#include "base/feature_list.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/shared_memory.h" @@ -30,6 +31,7 @@ #include "content/public/child/fixed_received_data.h" #include "content/public/child/request_peer.h" #include "content/public/child/resource_dispatcher_delegate.h" +#include "content/public/common/content_features.h" #include "content/public/common/resource_response.h" #include "net/base/net_errors.h" #include "net/http/http_response_headers.h" @@ -275,11 +277,19 @@ memcpy(shared_memory_map_[request_id]->memory(), data.c_str(), data.length()); - EXPECT_TRUE(dispatcher_->OnMessageReceived( - ResourceMsg_DataReceived(request_id, 0, data.length(), data.length()))); + EXPECT_TRUE(dispatcher_->OnMessageReceived(ResourceMsg_DataReceived( + request_id, 0, data.length(), data.length(), data.length()))); } - void NotifyDataDownloaded(int request_id, int decoded_length, + void NotifyInlinedDataChunkReceived(int request_id, + const std::vector<char>& data) { + auto size = data.size(); + EXPECT_TRUE(dispatcher_->OnMessageReceived( + ResourceMsg_InlinedDataChunkReceived(request_id, data, size, size))); + } + + void NotifyDataDownloaded(int request_id, + int decoded_length, int encoded_length) { EXPECT_TRUE(dispatcher_->OnMessageReceived(ResourceMsg_DataDownloaded( request_id, decoded_length, encoded_length))); @@ -369,6 +379,35 @@ EXPECT_EQ(0u, queued_messages()); } +// A simple request with an inline data response. +TEST_F(ResourceDispatcherTest, ResponseWithInlinedData) { + auto feature_list = base::MakeUnique<base::FeatureList>(); + feature_list->InitializeFromCommandLine( + features::kOptimizeLoadingIPCForSmallResources.name, std::string()); + base::FeatureList::ClearInstanceForTesting(); + base::FeatureList::SetInstance(std::move(feature_list)); + std::unique_ptr<RequestInfo> request_info(CreateRequestInfo(false)); + TestRequestPeer::Context peer_context; + StartAsync(*request_info.get(), NULL, &peer_context); + + int id = ConsumeRequestResource(); + EXPECT_EQ(0u, queued_messages()); + + NotifyReceivedResponse(id); + EXPECT_EQ(0u, queued_messages()); + EXPECT_TRUE(peer_context.received_response); + + std::vector<char> data(kTestPageContents, + kTestPageContents + strlen(kTestPageContents)); + NotifyInlinedDataChunkReceived(id, data); + EXPECT_EQ(0u, queued_messages()); + + NotifyRequestComplete(id, strlen(kTestPageContents)); + EXPECT_EQ(kTestPageContents, peer_context.data); + EXPECT_TRUE(peer_context.complete); + EXPECT_EQ(0u, queued_messages()); +} + // Tests that the request IDs are straight when there are two interleaving // requests. TEST_F(ResourceDispatcherTest, MultipleRequests) {
diff --git a/content/child/web_url_loader_impl.cc b/content/child/web_url_loader_impl.cc index b3b2cdaf..6bc238d 100644 --- a/content/child/web_url_loader_impl.cc +++ b/content/child/web_url_loader_impl.cc
@@ -550,6 +550,7 @@ request_info.extra_data = request.getExtraData(); request_info.report_raw_headers = request.reportRawHeaders(); request_info.loading_web_task_runner.reset(web_task_runner_->clone()); + request_info.lofi_state = static_cast<LoFiState>(request.getLoFiState()); scoped_refptr<ResourceRequestBodyImpl> request_body = GetRequestBodyForWebURLRequest(request).get(); @@ -607,7 +608,6 @@ request_.reportRawHeaders()); WebURLRequest new_request; - new_request.initialize(); PopulateURLRequestForRedirect( request_, redirect_info, referrer_policy_, info.was_fetched_via_service_worker
diff --git a/content/child/web_url_loader_impl_unittest.cc b/content/child/web_url_loader_impl_unittest.cc index d71e1aa..8168d0f 100644 --- a/content/child/web_url_loader_impl_unittest.cc +++ b/content/child/web_url_loader_impl_unittest.cc
@@ -277,7 +277,6 @@ void DoStartAsyncRequest() { blink::WebURLRequest request; - request.initialize(); request.setURL(GURL(kTestURL)); client()->loader()->loadAsynchronously(request, client()); ASSERT_TRUE(peer()); @@ -286,7 +285,6 @@ void DoStartAsyncRequestWithPriority( blink::WebURLRequest::Priority priority) { blink::WebURLRequest request; - request.initialize(); request.setPriority(priority); request.setURL(GURL(kTestURL)); client()->loader()->loadAsynchronously(request, client()); @@ -446,7 +444,6 @@ TEST_F(WebURLLoaderImplTest, DeleteBeforeResponseDataURL) { blink::WebURLRequest request; - request.initialize(); request.setURL(GURL("data:text/html;charset=utf-8,blah!")); client()->loader()->loadAsynchronously(request, client()); client()->DeleteLoader(); @@ -458,7 +455,6 @@ TEST_F(WebURLLoaderImplTest, DataURL) { blink::WebURLRequest request; - request.initialize(); request.setURL(GURL("data:text/html;charset=utf-8,blah!")); client()->loader()->loadAsynchronously(request, client()); base::RunLoop().RunUntilIdle(); @@ -470,7 +466,6 @@ TEST_F(WebURLLoaderImplTest, DataURLDeleteOnReceiveResponse) { blink::WebURLRequest request; - request.initialize(); request.setURL(GURL("data:text/html;charset=utf-8,blah!")); client()->set_delete_on_receive_response(); client()->loader()->loadAsynchronously(request, client()); @@ -482,7 +477,6 @@ TEST_F(WebURLLoaderImplTest, DataURLDeleteOnReceiveData) { blink::WebURLRequest request; - request.initialize(); request.setURL(GURL("data:text/html;charset=utf-8,blah!")); client()->set_delete_on_receive_data(); client()->loader()->loadAsynchronously(request, client()); @@ -494,7 +488,6 @@ TEST_F(WebURLLoaderImplTest, DataURLDeleteOnFinish) { blink::WebURLRequest request; - request.initialize(); request.setURL(GURL("data:text/html;charset=utf-8,blah!")); client()->set_delete_on_finish(); client()->loader()->loadAsynchronously(request, client()); @@ -506,7 +499,6 @@ TEST_F(WebURLLoaderImplTest, DataURLDefersLoading) { blink::WebURLRequest request; - request.initialize(); request.setURL(GURL("data:text/html;charset=utf-8,blah!")); client()->loader()->loadAsynchronously(request, client()); @@ -614,7 +606,6 @@ const GURL kStreamURL = GURL("http://bar"); const std::string kMimeType = "text/html"; blink::WebURLRequest request; - request.initialize(); request.setURL(kNavigationURL); request.setFrameType(blink::WebURLRequest::FrameTypeTopLevel); request.setRequestContext(blink::WebURLRequest::RequestContextFrame);
diff --git a/content/child/websocket_bridge.cc b/content/child/websocket_bridge.cc index d603fc5..bd94b42 100644 --- a/content/child/websocket_bridge.cc +++ b/content/child/websocket_bridge.cc
@@ -206,6 +206,7 @@ void WebSocketBridge::connect(const WebURL& url, const WebVector<WebString>& protocols, const WebSecurityOrigin& origin, + const WebURL& first_party_for_cookies, const WebString& user_agent_override, WebSocketHandleClient* client) { DCHECK_EQ(kInvalidChannelId, channel_id_); @@ -222,10 +223,17 @@ << base::JoinString(protocols_to_pass, ", ") << "), " << origin.toString().utf8() << ")"; + WebSocketHostMsg_AddChannelRequest_Params params; + params.socket_url = url; + params.requested_protocols = protocols_to_pass; + params.origin = origin; + params.first_party_for_cookies = first_party_for_cookies; + params.user_agent_override = user_agent_override.latin1(); + params.render_frame_id = render_frame_id_; + // Headers (ie: User-Agent) are ISO Latin 1. ChildThreadImpl::current()->Send(new WebSocketHostMsg_AddChannelRequest( - channel_id_, url, protocols_to_pass, origin, - user_agent_override.latin1(), render_frame_id_)); + channel_id_, params)); } void WebSocketBridge::send(bool fin,
diff --git a/content/child/websocket_bridge.h b/content/child/websocket_bridge.h index ad2247e..d8ccc2b 100644 --- a/content/child/websocket_bridge.h +++ b/content/child/websocket_bridge.h
@@ -34,6 +34,7 @@ void connect(const blink::WebURL& url, const blink::WebVector<blink::WebString>& protocols, const blink::WebSecurityOrigin& origin, + const blink::WebURL& first_party_for_cookies, const blink::WebString& user_agent_override, blink::WebSocketHandleClient* client) override; void send(bool fin,
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index 47c31c8..90749ef0 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn
@@ -27,6 +27,7 @@ "//content:content_implementation", "//build/config:precompiled_headers", "//build/config/compiler:no_size_t_to_int_warning", + "//media/gpu:gpu_config", ] public_deps = [
diff --git a/content/common/input/OWNERS b/content/common/input/OWNERS index 6039fc4..5f0366a 100644 --- a/content/common/input/OWNERS +++ b/content/common/input/OWNERS
@@ -1,2 +1,5 @@ aelias@chromium.org tdresser@chromium.org + +per-file *_param_traits*.*=set noparent +per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS \ No newline at end of file
diff --git a/content/common/input/input_param_traits_unittest.cc b/content/common/input/input_param_traits_unittest.cc index 07a7ac3..01acafc 100644 --- a/content/common/input/input_param_traits_unittest.cc +++ b/content/common/input/input_param_traits_unittest.cc
@@ -7,6 +7,7 @@ #include <stddef.h> #include <utility> +#include "base/memory/ptr_util.h" #include "content/common/input/input_event.h" #include "content/common/input/synthetic_gesture_params.h" #include "content/common/input/synthetic_pinch_gesture_params.h" @@ -89,7 +90,9 @@ EXPECT_EQ(a->position(), b->position()); } if (a->pointer_action_type() != - SyntheticPointerActionParams::PointerActionType::PROCESS) { + SyntheticPointerActionParams::PointerActionType::PROCESS && + a->pointer_action_type() != + SyntheticPointerActionParams::PointerActionType::FINISH) { EXPECT_EQ(a->index(), b->index()); } } @@ -272,9 +275,9 @@ } TEST_F(InputParamTraitsTest, SyntheticPointerActionParamsMove) { - std::unique_ptr<SyntheticPointerActionParams> gesture_params( - new SyntheticPointerActionParams( - SyntheticPointerActionParams::PointerActionType::MOVE)); + std::unique_ptr<SyntheticPointerActionParams> gesture_params = + base::MakeUnique<SyntheticPointerActionParams>( + SyntheticPointerActionParams::PointerActionType::MOVE); gesture_params->gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; gesture_params->set_position(gfx::PointF(356, 287)); gesture_params->set_index(0); @@ -286,9 +289,9 @@ } TEST_F(InputParamTraitsTest, SyntheticPointerActionParamsRelease) { - std::unique_ptr<SyntheticPointerActionParams> gesture_params( - new SyntheticPointerActionParams( - SyntheticPointerActionParams::PointerActionType::RELEASE)); + std::unique_ptr<SyntheticPointerActionParams> gesture_params = + base::MakeUnique<SyntheticPointerActionParams>( + SyntheticPointerActionParams::PointerActionType::RELEASE); gesture_params->gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; gesture_params->set_index(0); ASSERT_EQ(SyntheticGestureParams::POINTER_ACTION, @@ -299,9 +302,21 @@ } TEST_F(InputParamTraitsTest, SyntheticPointerActionParamsProcess) { - std::unique_ptr<SyntheticPointerActionParams> gesture_params( - new SyntheticPointerActionParams( - SyntheticPointerActionParams::PointerActionType::PROCESS)); + std::unique_ptr<SyntheticPointerActionParams> gesture_params = + base::MakeUnique<SyntheticPointerActionParams>( + SyntheticPointerActionParams::PointerActionType::PROCESS); + gesture_params->gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; + ASSERT_EQ(SyntheticGestureParams::POINTER_ACTION, + gesture_params->GetGestureType()); + SyntheticGesturePacket packet_in; + packet_in.set_gesture_params(std::move(gesture_params)); + Verify(packet_in); +} + +TEST_F(InputParamTraitsTest, SyntheticPointerActionParamsFinish) { + std::unique_ptr<SyntheticPointerActionParams> gesture_params = + base::MakeUnique<SyntheticPointerActionParams>( + SyntheticPointerActionParams::PointerActionType::FINISH); gesture_params->gesture_source_type = SyntheticGestureParams::TOUCH_INPUT; ASSERT_EQ(SyntheticGestureParams::POINTER_ACTION, gesture_params->GetGestureType());
diff --git a/content/common/input/synthetic_pointer_action_params.h b/content/common/input/synthetic_pointer_action_params.h index fe6c9f9..641787c 100644 --- a/content/common/input/synthetic_pointer_action_params.h +++ b/content/common/input/synthetic_pointer_action_params.h
@@ -22,14 +22,16 @@ : public SyntheticGestureParams { public: // Actions are queued up until we receive a PROCESS action, at which point - // we'll dispatch all queued events. + // we'll dispatch all queued events. A FINISH action will be received when + // we reach the end of the action sequence. enum class PointerActionType { NOT_INITIALIZED, PRESS, MOVE, RELEASE, PROCESS, - POINTER_ACTION_TYPE_MAX = PROCESS + FINISH, + POINTER_ACTION_TYPE_MAX = FINISH }; SyntheticPointerActionParams(); @@ -47,7 +49,8 @@ } void set_index(int index) { - DCHECK(pointer_action_type_ != PointerActionType::PROCESS); + DCHECK(pointer_action_type_ != PointerActionType::PROCESS && + pointer_action_type_ != PointerActionType::FINISH); index_ = index; } @@ -60,7 +63,8 @@ PointerActionType pointer_action_type() const { return pointer_action_type_; } int index() const { - DCHECK(pointer_action_type_ != PointerActionType::PROCESS); + DCHECK(pointer_action_type_ != PointerActionType::PROCESS && + pointer_action_type_ != PointerActionType::FINISH); return index_; }
diff --git a/content/common/manifest_manager_messages.h b/content/common/manifest_manager_messages.h index c052f27..ae4a2d2 100644 --- a/content/common/manifest_manager_messages.h +++ b/content/common/manifest_manager_messages.h
@@ -48,24 +48,12 @@ IPC_MESSAGE_ROUTED1(ManifestManagerMsg_RequestManifest, int /* request_id */) -// The browser process requests whether the document loaded in the associated -// RenderFrame has a manifest link URL. The render process will respond with -// a HasManifestResponse IPC message, along with a bool indicating the presence -// of a manifest link, and the |request_id| that was initially given. -IPC_MESSAGE_ROUTED1(ManifestManagerMsg_HasManifest, - int /* request_id */) - // The render process' response to a RequestManifest. The |request_id| will -// match the one that was initially received. The |manifest_url| and |manifest| -// will be empty in case of any failure. +// match the one that was initially received. |manifest_url| will be empty if +// there is no manifest specified in the associated RenderFrame's document. +// |manifest| will be empty if a manifest was specified, but could not be +// parsed correctly. IPC_MESSAGE_ROUTED3(ManifestManagerHostMsg_RequestManifestResponse, int, /* request_id */ GURL, /* manifest URL */ content::Manifest /* manifest */) - -// The render process' response to a HasManifest. The |request_id| is the one -// sent from the browser. The |bool| will be true if the current document has a -// manifest link URL, and false otherwise. -IPC_MESSAGE_ROUTED2(ManifestManagerHostMsg_HasManifestResponse, - int, /* request_id */ - bool /* true if the document has a manifest link */)
diff --git a/content/common/resource_messages.h b/content/common/resource_messages.h index 0f343e72..a918d54 100644 --- a/content/common/resource_messages.h +++ b/content/common/resource_messages.h
@@ -159,6 +159,7 @@ IPC_STRUCT_TRAITS_MEMBER(has_major_certificate_errors) IPC_STRUCT_TRAITS_MEMBER(content_length) IPC_STRUCT_TRAITS_MEMBER(encoded_data_length) + IPC_STRUCT_TRAITS_MEMBER(encoded_body_length) IPC_STRUCT_TRAITS_MEMBER(appcache_id) IPC_STRUCT_TRAITS_MEMBER(appcache_manifest_url) IPC_STRUCT_TRAITS_MEMBER(load_timing) @@ -307,19 +308,21 @@ // Sent when a chunk of data from a resource request is ready, and the resource // is expected to be small enough to fit in the inlined buffer. // The data is sent as a part of IPC message. -IPC_MESSAGE_CONTROL3(ResourceMsg_InlinedDataChunkReceived, +IPC_MESSAGE_CONTROL4(ResourceMsg_InlinedDataChunkReceived, int /* request_id */, std::vector<char> /* data */, - int /* encoded_data_length */) + int /* encoded_data_length */, + int /* encoded_body_length */) // Sent when some data from a resource request is ready. The data offset and // length specify a byte range into the shared memory buffer provided by the // SetDataBuffer message. -IPC_MESSAGE_CONTROL4(ResourceMsg_DataReceived, +IPC_MESSAGE_CONTROL5(ResourceMsg_DataReceived, int /* request_id */, int /* data_offset */, int /* data_length */, - int /* encoded_data_length */) + int /* encoded_data_length */, + int /* encoded_body_length */) // Sent when some data from a resource request has been downloaded to // file. This is only called in the 'download_to_file' case and replaces
diff --git a/content/common/sandbox_linux/bpf_gpu_policy_linux.cc b/content/common/sandbox_linux/bpf_gpu_policy_linux.cc index d356897..7dc9fa7c 100644 --- a/content/common/sandbox_linux/bpf_gpu_policy_linux.cc +++ b/content/common/sandbox_linux/bpf_gpu_policy_linux.cc
@@ -78,8 +78,8 @@ #endif } -inline bool IsOzone() { -#if defined(USE_OZONE) +inline bool UseV4L2Codec() { +#if defined(USE_V4L2_CODEC) return true; #else return false; @@ -343,7 +343,7 @@ if (!IsChromeOS()) { permissions.push_back( BrokerFilePermission::ReadWriteCreateUnlinkRecursive(kDevShm)); - } else if (IsArchitectureArm() || IsOzone()){ + } else if (UseV4L2Codec()){ AddV4L2GpuWhitelist(&permissions); if (UseLibV4L2()) { dlopen("/usr/lib/libv4l2.so", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
diff --git a/content/common/sandbox_win.cc b/content/common/sandbox_win.cc index 35c33d5..baa2470 100644 --- a/content/common/sandbox_win.cc +++ b/content/common/sandbox_win.cc
@@ -797,10 +797,13 @@ TRACE_EVENT_BEGIN0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); PROCESS_INFORMATION temp_process_info = {}; + sandbox::ResultCode last_warning = sandbox::SBOX_ALL_OK; + DWORD last_error = ERROR_SUCCESS; result = g_broker_services->SpawnTarget( cmd_line->GetProgram().value().c_str(), - cmd_line->GetCommandLineString().c_str(), policy, &temp_process_info); - DWORD last_error = ::GetLastError(); + cmd_line->GetCommandLineString().c_str(), policy, &last_warning, + &last_error, &temp_process_info); + base::win::ScopedProcessInformation target(temp_process_info); TRACE_EVENT_END0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); @@ -815,6 +818,12 @@ return result; } + if (sandbox::SBOX_ALL_OK != last_warning) { + UMA_HISTOGRAM_SPARSE_SLOWLY("Process.Sandbox.Launch.WarningResultCode", + last_warning); + UMA_HISTOGRAM_SPARSE_SLOWLY("Process.Sandbox.Launch.Warning", last_error); + } + delegate->PostSpawnTarget(target.process_handle()); CHECK(ResumeThread(target.thread_handle()) != static_cast<DWORD>(-1));
diff --git a/content/common/view_messages.h b/content/common/view_messages.h index a70cb9c..4b65c5a 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h
@@ -816,7 +816,7 @@ // Sent by browser to give renderer compositor a new namespace ID for any // SurfaceSequences it has to create. -IPC_MESSAGE_ROUTED1(ViewMsg_SetSurfaceIdNamespace, +IPC_MESSAGE_ROUTED1(ViewMsg_SetSurfaceClientId, uint32_t /* surface_id_namespace */) IPC_MESSAGE_ROUTED0(ViewMsg_SelectWordAroundCaret)
diff --git a/content/common/websocket_messages.h b/content/common/websocket_messages.h index 2054354..ce250780b 100644 --- a/content/common/websocket_messages.h +++ b/content/common/websocket_messages.h
@@ -46,6 +46,15 @@ IPC_ENUM_TRAITS_MAX_VALUE(content::WebSocketMessageType, content::WEB_SOCKET_MESSAGE_TYPE_LAST) +IPC_STRUCT_BEGIN(WebSocketHostMsg_AddChannelRequest_Params) + IPC_STRUCT_MEMBER(GURL, socket_url) + IPC_STRUCT_MEMBER(std::vector<std::string>, requested_protocols) + IPC_STRUCT_MEMBER(url::Origin, origin) + IPC_STRUCT_MEMBER(GURL, first_party_for_cookies) + IPC_STRUCT_MEMBER(std::string, user_agent_override) + IPC_STRUCT_MEMBER(int, render_frame_id) +IPC_STRUCT_END() + IPC_STRUCT_TRAITS_BEGIN(content::WebSocketHandshakeRequest) IPC_STRUCT_TRAITS_MEMBER(url) IPC_STRUCT_TRAITS_MEMBER(headers) @@ -67,12 +76,8 @@ // Open new WebSocket connection to |socket_url|. |requested_protocols| is a // list of tokens identifying sub-protocols the renderer would like to use, as // described in RFC6455 "Subprotocols Using the WebSocket Protocol". -IPC_MESSAGE_ROUTED5(WebSocketHostMsg_AddChannelRequest, - GURL /* socket_url */, - std::vector<std::string> /* requested_protocols */, - url::Origin /* origin */, - std::string /* user_agent_override */, - int /* render_frame_id */) +IPC_MESSAGE_ROUTED1(WebSocketHostMsg_AddChannelRequest, + WebSocketHostMsg_AddChannelRequest_Params) // Send a complete binary WebSocket message consisting of the Blob identified by // |uuid|. The message will be split into frames as necessary. |expected_size|
diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 21fa35a..7a768ad 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi
@@ -8,6 +8,7 @@ '../cc/cc.gyp:cc', '../cc/cc.gyp:cc_surfaces', '../components/components.gyp:display_compositor', + '../components/components.gyp:memory_coordinator_browser', '../components/leveldb/leveldb.gyp:leveldb_lib', '../components/link_header_util/link_header_util.gyp:link_header_util', '../components/mime_util/mime_util.gyp:mime_util', @@ -2136,6 +2137,12 @@ '../third_party/boringssl/boringssl.gyp:boringssl', ], }], + ['use_minikin_hyphenation==1', { + 'private_browser_sources': [ + 'browser/hyphenation/hyphenation_impl.cc', + 'browser/hyphenation/hyphenation_impl.h', + ], + }], ['enable_webvr==1', { 'sources': [ 'browser/vr/vr_device.cc',
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index d56e782..a7467f4 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi
@@ -9,6 +9,7 @@ '../cc/cc.gyp:cc', '../cc/cc.gyp:cc_proto', '../cc/blink/cc_blink.gyp:cc_blink', + '../components/components.gyp:memory_coordinator_child', '../components/scheduler/scheduler.gyp:scheduler', '../components/url_formatter/url_formatter.gyp:url_formatter', '../device/battery/battery.gyp:device_battery',
diff --git a/content/content_tests.gypi b/content/content_tests.gypi index 1d634bc..d7aeed1 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi
@@ -254,6 +254,7 @@ 'browser/media/session/media_session_visibility_browsertest.cc', 'browser/media/session/mock_media_session_observer.cc', 'browser/media/session/mock_media_session_observer.h', + 'browser/memory/memory_coordinator_browsertest.cc', 'browser/memory/memory_pressure_controller_impl_browsertest.cc', 'browser/message_port_provider_browsertest.cc', 'browser/net_info_browsertest.cc', @@ -507,6 +508,7 @@ 'browser/indexed_db/mock_indexed_db_database_callbacks.h', 'browser/indexed_db/mock_indexed_db_factory.cc', 'browser/indexed_db/mock_indexed_db_factory.h', + 'browser/loader/async_resource_handler_unittest.cc', 'browser/loader/async_revalidation_driver_unittest.cc', 'browser/loader/async_revalidation_manager_unittest.cc', 'browser/loader/mime_type_resource_handler_unittest.cc', @@ -566,6 +568,7 @@ 'browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc', 'browser/renderer_host/input/stylus_text_selector_unittest.cc', 'browser/renderer_host/input/synthetic_gesture_controller_unittest.cc', + 'browser/renderer_host/input/synthetic_pointer_action_unittest.cc', 'browser/renderer_host/input/tap_suppression_controller_unittest.cc', 'browser/renderer_host/input/touch_action_filter_unittest.cc', 'browser/renderer_host/input/touch_emulator_unittest.cc', @@ -1394,6 +1397,7 @@ 'test_support_content', 'web_ui_test_mojo_bindings', '../base/base.gyp:test_support_base', + '../components/components.gyp:memory_coordinator_browser', '../device/battery/battery.gyp:device_battery', '../device/battery/battery.gyp:device_battery_mojo_bindings', '../device/power_save_blocker/power_save_blocker.gyp:device_power_save_blocker',
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc index af207ab..993265e 100644 --- a/content/gpu/gpu_child_thread.cc +++ b/content/gpu/gpu_child_thread.cc
@@ -173,6 +173,7 @@ gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory) : ChildThreadImpl(ChildThreadImpl::Options::Builder() .InBrowserProcess(params) + .UseMojoChannel(true) .AddStartupFilter(new GpuMemoryBufferMessageFilter( gpu_memory_buffer_factory)) .Build()),
diff --git a/content/public/browser/android/content_view_core.h b/content/public/browser/android/content_view_core.h index 44a2e3f..63921ec9 100644 --- a/content/public/browser/android/content_view_core.h +++ b/content/public/browser/android/content_view_core.h
@@ -46,7 +46,6 @@ virtual base::android::ScopedJavaLocalRef<jobject> GetJavaObject() = 0; virtual bool ShowPastePopup(int x, int y) = 0; - virtual float GetDpiScale() const = 0; virtual void PauseOrResumeGeolocation(bool should_pause) = 0; // Text surrounding selection.
diff --git a/content/public/browser/download_item.h b/content/public/browser/download_item.h index b499639..be2e77a9b 100644 --- a/content/public/browser/download_item.h +++ b/content/public/browser/download_item.h
@@ -328,10 +328,6 @@ // Mark the download to be auto-opened when completed. virtual void SetOpenWhenComplete(bool open) = 0; - // Mark the download as temporary (not visible in persisted store or - // SearchDownloads(), removed from main UI upon completion). - virtual void SetIsTemporary(bool temporary) = 0; - // Mark the download as having been opened (without actually opening it). virtual void SetOpened(bool opened) = 0;
diff --git a/content/public/browser/resource_dispatcher_host_delegate.cc b/content/public/browser/resource_dispatcher_host_delegate.cc index 26b2dcc..0ce62b3 100644 --- a/content/public/browser/resource_dispatcher_host_delegate.cc +++ b/content/public/browser/resource_dispatcher_host_delegate.cc
@@ -77,9 +77,7 @@ void ResourceDispatcherHostDelegate::OnResponseStarted( net::URLRequest* request, ResourceContext* resource_context, - ResourceResponse* response, - IPC::Sender* sender) { -} + ResourceResponse* response) {} void ResourceDispatcherHostDelegate::OnRequestRedirected( const GURL& redirect_url,
diff --git a/content/public/browser/resource_dispatcher_host_delegate.h b/content/public/browser/resource_dispatcher_host_delegate.h index 18681a0..f32fe44 100644 --- a/content/public/browser/resource_dispatcher_host_delegate.h +++ b/content/public/browser/resource_dispatcher_host_delegate.h
@@ -17,10 +17,6 @@ class GURL; template <class T> class ScopedVector; -namespace IPC { -class Sender; -} - namespace net { class AuthChallengeInfo; class ClientCertStore; @@ -115,8 +111,7 @@ // Informs the delegate that a response has started. virtual void OnResponseStarted(net::URLRequest* request, ResourceContext* resource_context, - ResourceResponse* response, - IPC::Sender* sender); + ResourceResponse* response); // Informs the delegate that a request has been redirected. virtual void OnRequestRedirected(const GURL& redirect_url,
diff --git a/content/public/browser/tracing_controller.h b/content/public/browser/tracing_controller.h index 0de1a16..4fe49b1c 100644 --- a/content/public/browser/tracing_controller.h +++ b/content/public/browser/tracing_controller.h
@@ -42,53 +42,17 @@ public: TraceDataSink(); - virtual void AddTraceChunk(const std::string& chunk) {} - - // Add a TracingAgent's trace to the data sink. - virtual void AddAgentTrace(const std::string& trace_label, - const std::string& trace_data); - - // Notice that TracingController adds some default metadata when - // StopTracing is called, which may override metadata that you would - // set beforehand in case of key collision. - virtual void AddMetadata(const base::DictionaryValue& data); - virtual std::unique_ptr<const base::DictionaryValue> GetMetadataCopy() - const; - virtual void SetMetadataFilterPredicate( - const MetadataFilterPredicate& metadata_filter_predicate); - virtual void Close() {} - protected: + friend class TracingControllerImpl; friend class base::RefCountedThreadSafe<TraceDataSink>; - // Get a map of TracingAgent's data, which is previously added by - // AddAgentTrace(). The map's key is the trace label and the map's value is - // the trace data. - virtual const std::map<std::string, std::string>& GetAgentTrace() const; - + virtual void AddTraceChunk(const std::string& chunk) = 0; + // Add a TracingAgent's trace to the data sink. + virtual void AddAgentTrace(const std::string& trace_label, + const std::string& trace_data) {} + virtual void AddMetadata(std::unique_ptr<base::DictionaryValue> data) {} + virtual void Close() {} virtual ~TraceDataSink(); - - private: - std::map<std::string, std::string> additional_tracing_agent_trace_; - MetadataFilterPredicate metadata_filter_predicate_; - base::DictionaryValue metadata_; - }; - - // An implementation of this interface is passed when constructing a - // TraceDataSink, and receives chunks of the final trace data as it's being - // constructed. - // Methods may be called from any thread. - class CONTENT_EXPORT TraceDataEndpoint - : public base::RefCountedThreadSafe<TraceDataEndpoint> { - public: - virtual void ReceiveTraceChunk(const std::string& chunk) {} - virtual void ReceiveTraceFinalContents( - std::unique_ptr<const base::DictionaryValue> metadata, - const std::string& contents) {} - - protected: - friend class base::RefCountedThreadSafe<TraceDataEndpoint>; - virtual ~TraceDataEndpoint() {} }; // Create a trace sink that may be supplied to StopTracing @@ -97,27 +61,12 @@ const base::Callback<void(std::unique_ptr<const base::DictionaryValue>, base::RefCountedString*)>& callback); - CONTENT_EXPORT static scoped_refptr<TraceDataSink> CreateCompressedStringSink( - scoped_refptr<TraceDataEndpoint> endpoint); - // Create a trace sink that may be supplied to StopTracing // to dump the trace data to a file. CONTENT_EXPORT static scoped_refptr<TraceDataSink> CreateFileSink( const base::FilePath& file_path, const base::Closure& callback); - // Create an endpoint that may be supplied to any TraceDataSink to - // dump the trace data to a callback. - CONTENT_EXPORT static scoped_refptr<TraceDataEndpoint> CreateCallbackEndpoint( - const base::Callback<void(std::unique_ptr<const base::DictionaryValue>, - base::RefCountedString*)>& callback); - - // Create an endpoint that may be supplied to any TraceDataSink to - // dump the trace data to a file. - CONTENT_EXPORT static scoped_refptr<TraceDataEndpoint> CreateFileEndpoint( - const base::FilePath& file_path, - const base::Closure& callback); - // Get a set of category groups. The category groups can change as // new code paths are reached. // @@ -171,6 +120,13 @@ virtual bool StopTracing( const scoped_refptr<TraceDataSink>& trace_data_sink) = 0; + // Appends metadata to the current tracing session. The metadata are + // subject to filtering according to current trace config. + // Note that TracingController adds some default metadata when + // StopTracing is called, which may override metadata that you would + // set beforehand in case of key collision. + virtual void AddMetadata(const base::DictionaryValue& metadata) = 0; + // Get the maximum across processes of trace buffer percent full state. // When the TraceBufferUsage value is determined, the callback is // called.
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h index 8cf454c..36996f0 100644 --- a/content/public/browser/web_contents.h +++ b/content/public/browser/web_contents.h
@@ -691,19 +691,15 @@ // Returns true if audio has recently been audible from the WebContents. virtual bool WasRecentlyAudible() = 0; + // The callback invoked when the renderer responds to a request for the main + // frame document's manifest. The url will be empty if the document specifies + // no manifest, and the manifest will be empty if any other failures occurred. typedef base::Callback<void(const GURL&, const Manifest&)> GetManifestCallback; // Requests the manifest URL and the Manifest of the main frame's document. virtual void GetManifest(const GetManifestCallback& callback) = 0; - typedef base::Callback<void(bool)> HasManifestCallback; - - // Returns true if the main frame has a <link> to a web manifest, otherwise - // false. This method does not guarantee that the manifest exists at the - // specified location or is valid. - virtual void HasManifest(const HasManifestCallback& callback) = 0; - // Requests the renderer to exit fullscreen. // |will_cause_resize| indicates whether the fullscreen change causes a // view resize. e.g. This will be false when going from tab fullscreen to
diff --git a/content/public/common/resource_response.cc b/content/public/common/resource_response.cc index 3633eba8..0b94574 100644 --- a/content/public/common/resource_response.cc +++ b/content/public/common/resource_response.cc
@@ -23,6 +23,7 @@ head.has_major_certificate_errors; new_response->head.content_length = head.content_length; new_response->head.encoded_data_length = head.encoded_data_length; + new_response->head.encoded_body_length = head.encoded_body_length; new_response->head.appcache_id = head.appcache_id; new_response->head.appcache_manifest_url = head.appcache_manifest_url; new_response->head.load_timing = head.load_timing;
diff --git a/content/public/common/resource_response_info.cc b/content/public/common/resource_response_info.cc index d471f2df..eed1a98ed 100644 --- a/content/public/common/resource_response_info.cc +++ b/content/public/common/resource_response_info.cc
@@ -13,6 +13,7 @@ : has_major_certificate_errors(false), content_length(-1), encoded_data_length(-1), + encoded_body_length(-1), appcache_id(kAppCacheNoCacheId), was_fetched_via_spdy(false), was_npn_negotiated(false),
diff --git a/content/public/common/resource_response_info.h b/content/public/common/resource_response_info.h index 9c004aa..3c7a9c5 100644 --- a/content/public/common/resource_response_info.h +++ b/content/public/common/resource_response_info.h
@@ -64,6 +64,10 @@ // no data, contains -1. int64_t encoded_data_length; + // Length of the response body data before decompression. -1 unless the body + // has been read to the end. + int64_t encoded_body_length; + // The appcache this response was loaded from, or kAppCacheNoCacheId. int64_t appcache_id;
diff --git a/content/public/test/mock_download_item.h b/content/public/test/mock_download_item.h index 2ac6bbcdc..6f9f2e2 100644 --- a/content/public/test/mock_download_item.h +++ b/content/public/test/mock_download_item.h
@@ -100,7 +100,6 @@ MOCK_CONST_METHOD0(GetWebContents, WebContents*()); MOCK_METHOD1(OnContentCheckCompleted, void(DownloadDangerType)); MOCK_METHOD1(SetOpenWhenComplete, void(bool)); - MOCK_METHOD1(SetIsTemporary, void(bool)); MOCK_METHOD1(SetOpened, void(bool)); MOCK_METHOD1(SetDisplayName, void(const base::FilePath&)); MOCK_CONST_METHOD1(DebugString, std::string(bool));
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index de54cbcb..973f1f84 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -37,6 +37,7 @@ "//cc/proto", "//cc/surfaces", "//cc/surfaces:surface_id", + "//components/memory_coordinator/child", "//components/scheduler:scheduler", "//components/url_formatter", "//content:resources",
diff --git a/content/renderer/DEPS b/content/renderer/DEPS index 2a875c3c..f728e88 100644 --- a/content/renderer/DEPS +++ b/content/renderer/DEPS
@@ -1,6 +1,7 @@ include_rules = [ # Allow inclusion of specific components that we depend on. # See comment in content/DEPS for which components are allowed. + "+components/memory_coordinator/child", "+components/scheduler", "+components/url_formatter",
diff --git a/content/renderer/android/synchronous_compositor_output_surface.cc b/content/renderer/android/synchronous_compositor_output_surface.cc index 7919e83a..993f1ec 100644 --- a/content/renderer/android/synchronous_compositor_output_surface.cc +++ b/content/renderer/android/synchronous_compositor_output_surface.cc
@@ -44,7 +44,7 @@ namespace { const int64_t kFallbackTickTimeoutInMilliseconds = 100; -const uint32_t kCompositorSurfaceNamespace = 1; +const uint32_t kCompositorClientId = 1; // Do not limit number of resources, so use an unrealistically high value. const size_t kNumResourcesLimit = 10 * 1000 * 1000; @@ -97,8 +97,7 @@ memory_policy_(0u), frame_swap_message_queue_(frame_swap_message_queue), surface_manager_(new cc::SurfaceManager), - surface_id_allocator_( - new cc::SurfaceIdAllocator(kCompositorSurfaceNamespace)), + surface_id_allocator_(new cc::SurfaceIdAllocator(kCompositorClientId)), surface_factory_(new cc::SurfaceFactory(surface_manager_.get(), this)) { DCHECK(registry_); DCHECK(sender_); @@ -107,7 +106,7 @@ capabilities_.delegated_rendering = true; memory_policy_.priority_cutoff_when_visible = gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE; - surface_id_allocator_->RegisterSurfaceIdNamespace(surface_manager_.get()); + surface_id_allocator_->RegisterSurfaceClientId(surface_manager_.get()); } SynchronousCompositorOutputSurface::~SynchronousCompositorOutputSurface() {} @@ -145,7 +144,7 @@ registered_ = true; surface_manager_->RegisterSurfaceFactoryClient( - surface_id_allocator_->id_namespace(), this); + surface_id_allocator_->client_id(), this); cc::RendererSettings software_renderer_settings; @@ -156,7 +155,7 @@ display_.reset(new cc::Display( surface_manager_.get(), nullptr /* shared_bitmap_manager */, nullptr /* gpu_memory_buffer_manager */, software_renderer_settings, - surface_id_allocator_->id_namespace(), nullptr /* begin_frame_source */, + surface_id_allocator_->client_id(), nullptr /* begin_frame_source */, base::MakeUnique<SoftwareOutputSurface>( base::MakeUnique<SoftwareDevice>(¤t_sw_canvas_)), nullptr /* scheduler */, nullptr /* texture_mailbox_deleter */)); @@ -173,7 +172,7 @@ if (!delegated_surface_id_.is_null()) surface_factory_->Destroy(delegated_surface_id_); surface_manager_->UnregisterSurfaceFactoryClient( - surface_id_allocator_->id_namespace()); + surface_id_allocator_->client_id()); display_ = nullptr; surface_factory_ = nullptr; surface_id_allocator_ = nullptr; @@ -198,11 +197,10 @@ DCHECK(sync_client_); if (fallback_tick_running_) { - client_->DidSwapBuffers(); - client_->DidSwapBuffersComplete(); DCHECK(frame.delegated_frame_data->resource_list.empty()); cc::ReturnedResourceArray return_resources; ReturnResources(return_resources); + did_swap_ = true; return; } @@ -236,7 +234,6 @@ sync_client_->SwapBuffers(output_surface_id_, std::move(swap_frame)); DeliverMessages(); - client_->DidSwapBuffers(); did_swap_ = true; } @@ -333,8 +330,12 @@ did_swap_ = false; client_->OnDraw(adjusted_transform, viewport, clip, in_software_draw_); - if (did_swap_) + if (did_swap_) { + // This must happen after unwinding the stack and leaving the compositor. + // Usually it is a separate task but we just defer it until OnDraw completes + // instead. client_->DidSwapBuffersComplete(); + } } void SynchronousCompositorOutputSurface::OnReclaimResources(
diff --git a/content/renderer/child_frame_compositing_helper.cc b/content/renderer/child_frame_compositing_helper.cc index 9b98bc69..80e0b67 100644 --- a/content/renderer/child_frame_compositing_helper.cc +++ b/content/renderer/child_frame_compositing_helper.cc
@@ -67,13 +67,6 @@ ChildFrameCompositingHelper::~ChildFrameCompositingHelper() { } -BrowserPluginManager* ChildFrameCompositingHelper::GetBrowserPluginManager() { - if (!browser_plugin_) - return nullptr; - - return BrowserPluginManager::Get(); -} - blink::WebPluginContainer* ChildFrameCompositingHelper::GetContainer() { if (!browser_plugin_) return nullptr; @@ -81,13 +74,6 @@ return browser_plugin_->container(); } -int ChildFrameCompositingHelper::GetInstanceID() { - if (!browser_plugin_) - return 0; - - return browser_plugin_->browser_plugin_instance_id(); -} - void ChildFrameCompositingHelper::UpdateWebLayer(blink::WebLayer* layer) { if (GetContainer()) { GetContainer()->setWebLayer(layer);
diff --git a/content/renderer/child_frame_compositing_helper.h b/content/renderer/child_frame_compositing_helper.h index 09548c71..bd33dde 100644 --- a/content/renderer/child_frame_compositing_helper.h +++ b/content/renderer/child_frame_compositing_helper.h
@@ -84,9 +84,7 @@ virtual ~ChildFrameCompositingHelper(); - BrowserPluginManager* GetBrowserPluginManager(); blink::WebPluginContainer* GetContainer(); - int GetInstanceID(); void CheckSizeAndAdjustLayerProperties(const gfx::Size& new_size, float device_scale_factor,
diff --git a/content/renderer/fetchers/resource_fetcher_impl.cc b/content/renderer/fetchers/resource_fetcher_impl.cc index 5187849..a1a760fd 100644 --- a/content/renderer/fetchers/resource_fetcher_impl.cc +++ b/content/renderer/fetchers/resource_fetcher_impl.cc
@@ -122,8 +122,8 @@ } loader_->loadAsynchronously(request_, this); - // No need to hold on to the request. - request_.reset(); + // No need to hold on to the request; reset it now. + request_ = blink::WebURLRequest(); } void ResourceFetcherImpl::SetTimeout(const base::TimeDelta& timeout) {
diff --git a/content/renderer/fetchers/resource_fetcher_impl.h b/content/renderer/fetchers/resource_fetcher_impl.h index 731ca48..1dfa0510 100644 --- a/content/renderer/fetchers/resource_fetcher_impl.h +++ b/content/renderer/fetchers/resource_fetcher_impl.h
@@ -66,7 +66,7 @@ // Options to send to the loader. blink::WebURLLoaderOptions options_; - // Request to send. Released once Start() is called. + // Request to send. blink::WebURLRequest request_; // Callback when we're done.
diff --git a/content/renderer/gpu/compositor_output_surface.cc b/content/renderer/gpu/compositor_output_surface.cc index a240b19..d67c63b 100644 --- a/content/renderer/gpu/compositor_output_surface.cc +++ b/content/renderer/gpu/compositor_output_surface.cc
@@ -118,7 +118,6 @@ messages_to_deliver_with_frame)); // ~send_message_scope. } - client_->DidSwapBuffers(); } void CompositorOutputSurface::BindFramebuffer() {
diff --git a/content/renderer/gpu/gpu_benchmarking_extension.cc b/content/renderer/gpu/gpu_benchmarking_extension.cc index 42f6995..82f1603 100644 --- a/content/renderer/gpu/gpu_benchmarking_extension.cc +++ b/content/renderer/gpu/gpu_benchmarking_extension.cc
@@ -955,7 +955,8 @@ std::vector<std::string> gpu_driver_bug_workarounds; gpu::GpuChannelHost* gpu_channel = RenderThreadImpl::current()->GetGpuChannel(); - if (!gpu_channel->Send(new GpuChannelMsg_GetDriverBugWorkArounds( + if (!gpu_channel || + !gpu_channel->Send(new GpuChannelMsg_GetDriverBugWorkArounds( &gpu_driver_bug_workarounds))) { return; }
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index c73ca064..513c8a6 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -1125,9 +1125,8 @@ delegate_->ForwardCompositorProto(serialized); } -void RenderWidgetCompositor::SetSurfaceIdNamespace( - uint32_t surface_id_namespace) { - layer_tree_host_->set_surface_id_namespace(surface_id_namespace); +void RenderWidgetCompositor::SetSurfaceClientId(uint32_t surface_client_id) { + layer_tree_host_->set_surface_client_id(surface_client_id); } void RenderWidgetCompositor::OnHandleCompositorProto(
diff --git a/content/renderer/gpu/render_widget_compositor.h b/content/renderer/gpu/render_widget_compositor.h index 68349ec..5ed5908 100644 --- a/content/renderer/gpu/render_widget_compositor.h +++ b/content/renderer/gpu/render_widget_compositor.h
@@ -97,7 +97,7 @@ std::unique_ptr<base::Value> value, const base::Callback<void(std::unique_ptr<base::Value>)>& callback); bool SendMessageToMicroBenchmark(int id, std::unique_ptr<base::Value> value); - void SetSurfaceIdNamespace(uint32_t surface_id_namespace); + void SetSurfaceClientId(uint32_t surface_id_namespace); void OnHandleCompositorProto(const std::vector<uint8_t>& proto); void SetPaintedDeviceScaleFactor(float device_scale);
diff --git a/content/renderer/image_downloader/image_downloader_impl.cc b/content/renderer/image_downloader/image_downloader_impl.cc index 139abbc..3c67180f 100644 --- a/content/renderer/image_downloader/image_downloader_impl.cc +++ b/content/renderer/image_downloader/image_downloader_impl.cc
@@ -107,7 +107,11 @@ return; // Proportionally resize the minimal image to fit in a box of size // |max_image_size|. - images->push_back(ResizeImage(*min_image, max_image_size)); + SkBitmap resized = ResizeImage(*min_image, max_image_size); + // Drop null or empty SkBitmap. + if (resized.drawsNothing()) + return; + images->push_back(resized); original_image_sizes->push_back( gfx::Size(min_image->width(), min_image->height())); } @@ -154,8 +158,10 @@ if (image_url.SchemeIs(url::kDataScheme)) { SkBitmap data_image = ImageFromDataUrl(image_url); - if (!data_image.empty()) { - result_images.push_back(ResizeImage(data_image, max_bitmap_size)); + SkBitmap resized = ResizeImage(data_image, max_bitmap_size); + // Drop null or empty SkBitmap. + if (!resized.drawsNothing()) { + result_images.push_back(resized); result_original_image_sizes.push_back( gfx::Size(data_image.width(), data_image.height())); }
diff --git a/content/renderer/manifest/manifest_manager.cc b/content/renderer/manifest/manifest_manager.cc index 6e78236..e23c99af 100644 --- a/content/renderer/manifest/manifest_manager.cc +++ b/content/renderer/manifest/manifest_manager.cc
@@ -38,7 +38,6 @@ bool handled = true; IPC_BEGIN_MESSAGE_MAP(ManifestManager, message) - IPC_MESSAGE_HANDLER(ManifestManagerMsg_HasManifest, OnHasManifest) IPC_MESSAGE_HANDLER(ManifestManagerMsg_RequestManifest, OnRequestManifest) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -46,14 +45,6 @@ return handled; } -void ManifestManager::OnHasManifest(int request_id) { - GURL url(render_frame()->GetWebFrame()->document().manifestURL()); - - bool has_manifest = may_have_manifest_ && !url.is_empty(); - Send(new ManifestManagerHostMsg_HasManifestResponse( - routing_id(), request_id, has_manifest)); -} - void ManifestManager::OnRequestManifest(int request_id) { GetManifest(base::Bind(&ManifestManager::OnRequestManifestComplete, base::Unretained(this), request_id)); @@ -115,6 +106,7 @@ void ManifestManager::DidChangeManifest() { may_have_manifest_ = true; manifest_dirty_ = true; + manifest_url_ = GURL(); } void ManifestManager::DidCommitProvisionalLoad( @@ -125,18 +117,19 @@ may_have_manifest_ = false; manifest_dirty_ = true; + manifest_url_ = GURL(); } void ManifestManager::FetchManifest() { - GURL url(render_frame()->GetWebFrame()->document().manifestURL()); + manifest_url_ = render_frame()->GetWebFrame()->document().manifestURL(); - if (url.is_empty()) { + if (manifest_url_.is_empty()) { ManifestUmaUtil::FetchFailed(ManifestUmaUtil::FETCH_EMPTY_URL); ResolveCallbacks(ResolveStateFailure); return; } - fetcher_.reset(new ManifestFetcher(url)); + fetcher_.reset(new ManifestFetcher(manifest_url_)); fetcher_->Start( render_frame()->GetWebFrame(), render_frame()->GetWebFrame()->document().manifestUseCredentials(), @@ -194,10 +187,14 @@ } void ManifestManager::ResolveCallbacks(ResolveState state) { - if (state == ResolveStateFailure) { - manifest_url_ = GURL(); + // Do not reset |manifest_url_| on failure here. If manifest_url_ is + // non-empty, that means the link 404s, we failed to fetch it, or it was + // unparseable. However, the site still tried to specify a manifest, so + // preserve that information in the URL for the callbacks. + // |manifest_url| will be reset on navigation or if we receive a didchange + // event. + if (state == ResolveStateFailure) manifest_ = Manifest(); - } manifest_dirty_ = state != ResolveStateSuccess;
diff --git a/content/renderer/manifest/manifest_manager.h b/content/renderer/manifest/manifest_manager.h index 2c62a9e..fec22fdf 100644 --- a/content/renderer/manifest/manifest_manager.h +++ b/content/renderer/manifest/manifest_manager.h
@@ -60,7 +60,6 @@ // Called when receiving a ManifestManagerMsg_RequestManifest from the browser // process. - void OnHasManifest(int request_id); void OnRequestManifest(int request_id); void OnRequestManifestComplete(int request_id, const GURL&,
diff --git a/content/renderer/media/android/renderer_surface_view_manager.cc b/content/renderer/media/android/renderer_surface_view_manager.cc index a405a4a..48fd548 100644 --- a/content/renderer/media/android/renderer_surface_view_manager.cc +++ b/content/renderer/media/android/renderer_surface_view_manager.cc
@@ -42,9 +42,10 @@ void RendererSurfaceViewManager::OnFullscreenSurfaceCreated(int surface_id) { DVLOG(3) << __FUNCTION__ << ": surface_id: " << surface_id; - DCHECK(!pending_surface_created_cb_.is_null()); - pending_surface_created_cb_.Run(surface_id); - pending_surface_created_cb_.Reset(); + if (!pending_surface_created_cb_.is_null()) { + pending_surface_created_cb_.Run(surface_id); + pending_surface_created_cb_.Reset(); + } } void RendererSurfaceViewManager::OnDestruct() {
diff --git a/content/renderer/media/audio_device_factory.cc b/content/renderer/media/audio_device_factory.cc index 9f9b8c1..d192fbf 100644 --- a/content/renderer/media/audio_device_factory.cc +++ b/content/renderer/media/audio_device_factory.cc
@@ -7,6 +7,7 @@ #include <algorithm> #include "base/logging.h" +#include "base/metrics/histogram_macros.h" #include "build/build_config.h" #include "content/common/content_constants_internal.h" #include "content/renderer/media/audio_input_message_filter.h" @@ -128,6 +129,8 @@ return NewMixableSink(source_type, render_frame_id, session_id, device_id, security_origin); + UMA_HISTOGRAM_BOOLEAN("Media.Audio.Render.SinkCache.UsedForSinkCreation", + false); return NewFinalAudioRendererSink(render_frame_id, session_id, device_id, security_origin); }
diff --git a/content/renderer/media/audio_renderer_sink_cache_impl.cc b/content/renderer/media/audio_renderer_sink_cache_impl.cc index 9fef7d0..4b427323 100644 --- a/content/renderer/media/audio_renderer_sink_cache_impl.cc +++ b/content/renderer/media/audio_renderer_sink_cache_impl.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/location.h" #include "base/memory/ptr_util.h" +#include "base/metrics/histogram_macros.h" #include "base/synchronization/lock.h" #include "base/threading/thread_task_runner_handle.h" #include "content/renderer/media/audio_device_factory.h" @@ -19,6 +20,25 @@ constexpr int kDeleteTimeoutMs = 5000; +namespace { + +enum GetOutputDeviceInfoCacheUtilization { + // No cached sink found. + SINK_CACHE_MISS_NO_SINK = 0, + + // If session id is used to specify a device, we always have to create and + // cache a new sink. + SINK_CACHE_MISS_CANNOT_LOOKUP_BY_SESSION_ID = 1, + + // Output parmeters for an already-cached sink are requested. + SINK_CACHE_HIT = 2, + + // For UMA. + SINK_CACHE_LAST_ENTRY +}; + +} // namespace + // Cached sink data. struct AudioRendererSinkCacheImpl::CacheEntry { int source_render_frame_id; @@ -74,6 +94,9 @@ // Cache a newly-created sink. base::AutoLock auto_lock(cache_lock_); cache_.push_back(cache_entry); + UMA_HISTOGRAM_ENUMERATION( + "Media.Audio.Render.SinkCache.GetOutputDeviceInfoCacheUtilization", + SINK_CACHE_MISS_CANNOT_LOOKUP_BY_SESSION_ID, SINK_CACHE_LAST_ENTRY); } else { // Ignore session id. @@ -88,6 +111,9 @@ DVLOG(1) << "GetSinkInfo: address: " << cache_iter->sink.get() << " - reused a cached sink."; + UMA_HISTOGRAM_ENUMERATION( + "Media.Audio.Render.SinkCache.GetOutputDeviceInfoCacheUtilization", + SINK_CACHE_HIT, SINK_CACHE_LAST_ENTRY); return cache_iter->sink->GetOutputDeviceInfo(); } @@ -101,6 +127,9 @@ // Cache a newly-created sink. cache_.push_back(cache_entry); + UMA_HISTOGRAM_ENUMERATION( + "Media.Audio.Render.SinkCache.GetOutputDeviceInfoCacheUtilization", + SINK_CACHE_MISS_NO_SINK, SINK_CACHE_LAST_ENTRY); } // Schedule it for deletion. @@ -118,6 +147,9 @@ int source_render_frame_id, const std::string& device_id, const url::Origin& security_origin) { + UMA_HISTOGRAM_BOOLEAN("Media.Audio.Render.SinkCache.UsedForSinkCreation", + true); + base::AutoLock auto_lock(cache_lock_); auto cache_iter = @@ -130,6 +162,8 @@ << " - found unused cached sink, reusing it."; cache_iter->used = true; + UMA_HISTOGRAM_BOOLEAN( + "Media.Audio.Renderer.SinkCache.InfoSinkReusedForOutput", true); return cache_iter->sink; } @@ -205,8 +239,11 @@ // To stop the sink before deletion if it's not used, we need to hold // a ref to it. - if (!cache_iter->used) + if (!cache_iter->used) { sink_to_stop = cache_iter->sink; + UMA_HISTOGRAM_BOOLEAN( + "Media.Audio.Renderer.SinkCache.InfoSinkReusedForOutput", false); + } cache_.erase(cache_iter); DVLOG(1) << "DeleteSink: address: " << sink_ptr;
diff --git a/content/renderer/media/image_capture_frame_grabber.cc b/content/renderer/media/image_capture_frame_grabber.cc index faeb43f8..5d39b3e 100644 --- a/content/renderer/media/image_capture_frame_grabber.cc +++ b/content/renderer/media/image_capture_frame_grabber.cc
@@ -25,16 +25,44 @@ callbacks->onError(); } -// This internal method receives a |frame| and converts its pixels into a -// SkImage via an internal SkSurface and SkPixmap. Alpha channel, if any, is -// copied. -void OnVideoFrame(const ImageCaptureFrameGrabber::SkImageDeliverCB& callback, - const scoped_refptr<media::VideoFrame>& frame, - base::TimeTicks /* current_time */) { +} // anonymous namespace + +// Ref-counted class to receive a single VideoFrame on IO thread, convert it and +// send it to |main_task_runner_|, where this class is created and destroyed. +class ImageCaptureFrameGrabber::SingleShotFrameHandler + : public base::RefCountedThreadSafe<SingleShotFrameHandler> { + public: + SingleShotFrameHandler() : first_frame_received_(false) {} + + // Receives a |frame| and converts its pixels into a SkImage via an internal + // SkSurface and SkPixmap. Alpha channel, if any, is copied. + void OnVideoFrameOnIOThread(SkImageDeliverCB callback, + const scoped_refptr<media::VideoFrame>& frame, + base::TimeTicks current_time); + + private: + friend class base::RefCountedThreadSafe<SingleShotFrameHandler>; + virtual ~SingleShotFrameHandler() {} + + // Flag to indicate that the first frames has been processed, and subsequent + // ones can be safely discarded. + bool first_frame_received_; + + DISALLOW_COPY_AND_ASSIGN(SingleShotFrameHandler); +}; + +void ImageCaptureFrameGrabber::SingleShotFrameHandler::OnVideoFrameOnIOThread( + SkImageDeliverCB callback, + const scoped_refptr<media::VideoFrame>& frame, + base::TimeTicks /* current_time */) { DCHECK(frame->format() == media::PIXEL_FORMAT_YV12 || frame->format() == media::PIXEL_FORMAT_I420 || frame->format() == media::PIXEL_FORMAT_YV12A); + if (first_frame_received_) + return; + first_frame_received_ = true; + const SkAlphaType alpha = media::IsOpaque(frame->format()) ? kOpaque_SkAlphaType : kPremul_SkAlphaType; @@ -73,8 +101,6 @@ callback.Run(surface->makeImageSnapshot()); } -} // anonymous namespace - ImageCaptureFrameGrabber::ImageCaptureFrameGrabber() : weak_factory_(this) {} ImageCaptureFrameGrabber::~ImageCaptureFrameGrabber() { @@ -84,7 +110,6 @@ void ImageCaptureFrameGrabber::grabFrame( blink::WebMediaStreamTrack* track, WebImageCaptureGrabFrameCallbacks* callbacks) { - DVLOG(1) << __FUNCTION__; DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!!callbacks); @@ -94,22 +119,24 @@ ScopedWebCallbacks<WebImageCaptureGrabFrameCallbacks> scoped_callbacks = make_scoped_web_callbacks(callbacks, base::Bind(&OnError)); - // ConnectToTrack() must happen on render's Main Thread, whereas VideoFrames - // are delivered on a background thread though, so we Bind the callback to our - // current thread. + // A SingleShotFrameHandler is bound and given to the Track to guarantee that + // only one VideoFrame is converted and delivered to OnSkImage(), otherwise + // SKImages might be sent to resolved |callbacks| while DisconnectFromTrack() + // is being processed, which might be further held up if UI is busy, see + // https://crbug.com/623042. MediaStreamVideoSink::ConnectToTrack( - *track, - base::Bind(&OnVideoFrame, media::BindToCurrentLoop(base::Bind( - &ImageCaptureFrameGrabber::OnSkImage, - weak_factory_.GetWeakPtr(), - base::Passed(&scoped_callbacks)))), + *track, base::Bind(&SingleShotFrameHandler::OnVideoFrameOnIOThread, + make_scoped_refptr(new SingleShotFrameHandler), + media::BindToCurrentLoop( + base::Bind(&ImageCaptureFrameGrabber::OnSkImage, + weak_factory_.GetWeakPtr(), + base::Passed(&scoped_callbacks)))), false); } void ImageCaptureFrameGrabber::OnSkImage( - ScopedWebCallbacks<WebImageCaptureGrabFrameCallbacks> callbacks, + ScopedWebCallbacks<blink::WebImageCaptureGrabFrameCallbacks> callbacks, sk_sp<SkImage> image) { - DVLOG(1) << __FUNCTION__; DCHECK(thread_checker_.CalledOnValidThread()); MediaStreamVideoSink::DisconnectFromTrack();
diff --git a/content/renderer/media/image_capture_frame_grabber.h b/content/renderer/media/image_capture_frame_grabber.h index 78543e4a..df33626 100644 --- a/content/renderer/media/image_capture_frame_grabber.h +++ b/content/renderer/media/image_capture_frame_grabber.h
@@ -18,17 +18,13 @@ class WebMediaStreamTrack; } -namespace media { -class VideoFrame; -} - namespace content { // This class grabs Video Frames from a given Media Stream Video Track, binding -// a function every time grabFrame() is called. This function receives an -// incoming VideoFrame on a background thread and converts it into the -// appropriate SkBitmap which is sent back to OnSkBitmap(). This class is single -// threaded throughout. +// a method of an ephemeral SingleShotFrameHandler every time grabFrame() is +// called. This method receives an incoming media::VideoFrame on a background +// thread and converts it into the appropriate SkBitmap which is sent back to +// OnSkBitmap(). This class is single threaded throughout. class CONTENT_EXPORT ImageCaptureFrameGrabber final : NON_EXPORTED_BASE(public blink::WebImageCaptureFrameGrabber), NON_EXPORTED_BASE(public MediaStreamVideoSink) { @@ -43,6 +39,9 @@ blink::WebImageCaptureGrabFrameCallbacks* callbacks) override; private: + // Internal class to receive, convert and forward one frame. + class SingleShotFrameHandler; + void OnSkImage( ScopedWebCallbacks<blink::WebImageCaptureGrabFrameCallbacks> callbacks, sk_sp<SkImage> image);
diff --git a/content/renderer/media/media_interface_provider.cc b/content/renderer/media/media_interface_provider.cc index 8e3968e..51ac79b 100644 --- a/content/renderer/media/media_interface_provider.cc +++ b/content/renderer/media/media_interface_provider.cc
@@ -4,6 +4,8 @@ #include "content/renderer/media/media_interface_provider.h" +#include <string> + #include "base/bind.h" #include "media/mojo/interfaces/content_decryption_module.mojom.h" #include "media/mojo/interfaces/renderer.mojom.h" @@ -33,6 +35,7 @@ std::move(pipe))); } else if (interface_name == media::mojom::Renderer::Name_) { GetMediaServiceFactory()->CreateRenderer( + std::string(), mojo::MakeRequest<media::mojom::Renderer>(std::move(pipe))); } else if (interface_name == media::mojom::AudioDecoder::Name_) { GetMediaServiceFactory()->CreateAudioDecoder(
diff --git a/content/renderer/media/video_track_recorder.cc b/content/renderer/media/video_track_recorder.cc index d65e238..e5d477a 100644 --- a/content/renderer/media/video_track_recorder.cc +++ b/content/renderer/media/video_track_recorder.cc
@@ -39,13 +39,13 @@ using media::VideoFrame; using media::VideoFrameMetadata; +using video_track_recorder::kVEAEncoderMinResolutionWidth; +using video_track_recorder::kVEAEncoderMinResolutionHeight; namespace content { namespace { -const int kVEAEncoderMinResolutionWidth = 640; -const int kVEAEncoderMinResolutionHeight = 480; const int kVEAEncoderOutputBufferCount = 4; static struct { @@ -71,13 +71,15 @@ #if defined(OS_CHROMEOS) return media::VIDEO_CODEC_PROFILE_UNKNOWN; #endif // defined(OS_CHROMEOS) - content::RenderThreadImpl* render_thread_impl = + content::RenderThreadImpl* const render_thread_impl = content::RenderThreadImpl::current(); - if (!render_thread_impl) + if (!render_thread_impl) { + DVLOG(3) << "Couldn't access the render thread"; return media::VIDEO_CODEC_PROFILE_UNKNOWN; + } - media::GpuVideoAcceleratorFactories* gpu_factories = - content::RenderThreadImpl::current()->GetGpuFactories(); + media::GpuVideoAcceleratorFactories* const gpu_factories = + render_thread_impl->GetGpuFactories(); if (!gpu_factories || !gpu_factories->IsGpuVideoAcceleratorEnabled()) { DVLOG(3) << "Couldn't initialize GpuVideoAcceleratorFactories"; return media::VIDEO_CODEC_PROFILE_UNKNOWN; @@ -250,7 +252,8 @@ VEAEncoder( const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, int32_t bits_per_second, - media::VideoCodecProfile codec); + media::VideoCodecProfile codec, + const gfx::Size& size); // media::VideoEncodeAccelerator::Client implementation. void RequireBitstreamBuffers(unsigned int input_count, @@ -291,8 +294,8 @@ // Tracks error status. bool error_notified_; - // Tracks the first frame to encode. - std::unique_ptr<VideoFrameAndTimestamp> first_frame_; + // Tracks the last frame that we delay the encode. + std::unique_ptr<VideoFrameAndTimestamp> last_frame_; // Size used to initialize encoder. gfx::Size input_size_; @@ -392,7 +395,8 @@ VEAEncoder::VEAEncoder( const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_callback, int32_t bits_per_second, - media::VideoCodecProfile codec) + media::VideoCodecProfile codec, + const gfx::Size& size) : Encoder(on_encoded_video_callback, bits_per_second, RenderThreadImpl::current()->GetGpuFactories()->GetTaskRunner()), @@ -400,6 +404,12 @@ codec_(codec), error_notified_(false) { DCHECK(gpu_factories_); + DCHECK_GE(size.width(), kVEAEncoderMinResolutionWidth); + DCHECK_GE(size.height(), kVEAEncoderMinResolutionHeight); + + encoding_task_runner_->PostTask( + FROM_HERE, base::Bind(&VEAEncoder::ConfigureEncoderOnEncodingTaskRunner, + this, size)); } VEAEncoder::~VEAEncoder() { @@ -485,12 +495,8 @@ video_encoder_.reset(); } - if (!video_encoder_) { + if (!video_encoder_) ConfigureEncoderOnEncodingTaskRunner(frame->visible_rect().size()); - first_frame_.reset( - new std::pair<scoped_refptr<VideoFrame>, base::TimeTicks>( - frame, capture_timestamp)); - } if (error_notified_) { DVLOG(3) << "An error occurred in VEA encoder"; @@ -500,14 +506,17 @@ // Drop frames if there is no output buffers available. if (output_buffers_.empty()) { // TODO(emircan): Investigate if resetting encoder would help. - DVLOG(3) << "Dropped frame."; + DVLOG(3) << "Might drop frame."; + last_frame_.reset( + new std::pair<scoped_refptr<VideoFrame>, base::TimeTicks>( + frame, capture_timestamp)); return; } // If first frame hasn't been encoded, do it first. - if (first_frame_) { - std::unique_ptr<VideoFrameAndTimestamp> first_frame(first_frame_.release()); - EncodeOnEncodingTaskRunner(first_frame->first, first_frame->second); + if (last_frame_) { + std::unique_ptr<VideoFrameAndTimestamp> last_frame(last_frame_.release()); + EncodeOnEncodingTaskRunner(last_frame->first, last_frame->second); } // Lower resolutions may fall back to SW encoder in some platforms, i.e. Mac. @@ -936,21 +945,81 @@ const blink::WebMediaStreamTrack& track, const OnEncodedVideoCB& on_encoded_video_callback, int32_t bits_per_second) - : track_(track) { + : track_(track), + paused_before_init_(false), + weak_ptr_factory_(this) { DCHECK(main_render_thread_checker_.CalledOnValidThread()); DCHECK(!track_.isNull()); DCHECK(track_.getTrackData()); + initialize_encoder_callback_ = base::Bind( + &VideoTrackRecorder::InitializeEncoder, weak_ptr_factory_.GetWeakPtr(), + codec, on_encoded_video_callback, bits_per_second); + + // InitializeEncoder() will be called on Render Main thread. + MediaStreamVideoSink::ConnectToTrack( + track_, media::BindToCurrentLoop(initialize_encoder_callback_), false); +} + +VideoTrackRecorder::~VideoTrackRecorder() { + DCHECK(main_render_thread_checker_.CalledOnValidThread()); + MediaStreamVideoSink::DisconnectFromTrack(); + track_.reset(); +} + +void VideoTrackRecorder::Pause() { + DCHECK(main_render_thread_checker_.CalledOnValidThread()); + if (encoder_) + encoder_->SetPaused(true); + else + paused_before_init_ = true; +} + +void VideoTrackRecorder::Resume() { + DCHECK(main_render_thread_checker_.CalledOnValidThread()); + if (encoder_) + encoder_->SetPaused(false); + else + paused_before_init_ = false; +} + +void VideoTrackRecorder::OnVideoFrameForTesting( + const scoped_refptr<media::VideoFrame>& frame, + base::TimeTicks timestamp) { + DVLOG(3) << __FUNCTION__; + + if (!encoder_) { + DCHECK(!initialize_encoder_callback_.is_null()); + initialize_encoder_callback_.Run(frame, timestamp); + } + + encoder_->StartFrameEncode(frame, timestamp); +} + +void VideoTrackRecorder::InitializeEncoder( + CodecId codec, + const OnEncodedVideoCB& on_encoded_video_callback, + int32_t bits_per_second, + const scoped_refptr<media::VideoFrame>& frame, + base::TimeTicks capture_time) { + DVLOG(3) << __FUNCTION__ << frame->visible_rect().size().ToString(); + DCHECK(main_render_thread_checker_.CalledOnValidThread()); + + MediaStreamVideoSink::DisconnectFromTrack(); + + const gfx::Size& input_size = frame->visible_rect().size(); const auto& vea_supported_profile = CodecIdToVEAProfile(codec); - // TODO(emircan): Prioritize software based encoders in lower resolutions. - if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN) { + if (vea_supported_profile != media::VIDEO_CODEC_PROFILE_UNKNOWN && + input_size.width() >= kVEAEncoderMinResolutionWidth && + input_size.height() >= kVEAEncoderMinResolutionHeight) { encoder_ = new VEAEncoder(on_encoded_video_callback, bits_per_second, - vea_supported_profile); + vea_supported_profile, input_size); } else { switch (codec) { #if BUILDFLAG(RTC_USE_H264) case CodecId::H264: - encoder_ = new H264Encoder(on_encoded_video_callback, bits_per_second); + encoder_ = + new H264Encoder(on_encoded_video_callback, bits_per_second); break; #endif case CodecId::VP8: @@ -963,6 +1032,9 @@ } } + if (paused_before_init_) + encoder_->SetPaused(paused_before_init_); + // StartFrameEncode() will be called on Render IO thread. MediaStreamVideoSink::ConnectToTrack( track_, @@ -970,28 +1042,4 @@ false); } -VideoTrackRecorder::~VideoTrackRecorder() { - DCHECK(main_render_thread_checker_.CalledOnValidThread()); - MediaStreamVideoSink::DisconnectFromTrack(); - track_.reset(); -} - -void VideoTrackRecorder::Pause() { - DCHECK(main_render_thread_checker_.CalledOnValidThread()); - DCHECK(encoder_); - encoder_->SetPaused(true); -} - -void VideoTrackRecorder::Resume() { - DCHECK(main_render_thread_checker_.CalledOnValidThread()); - DCHECK(encoder_); - encoder_->SetPaused(false); -} - -void VideoTrackRecorder::OnVideoFrameForTesting( - const scoped_refptr<media::VideoFrame>& frame, - base::TimeTicks timestamp) { - encoder_->StartFrameEncode(frame, timestamp); -} - } // namespace content
diff --git a/content/renderer/media/video_track_recorder.h b/content/renderer/media/video_track_recorder.h index 5e6245492..e8de7d96 100644 --- a/content/renderer/media/video_track_recorder.h +++ b/content/renderer/media/video_track_recorder.h
@@ -9,6 +9,8 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" #include "base/threading/thread_checker.h" #include "content/public/common/features.h" #include "content/public/renderer/media_stream_video_sink.h" @@ -18,6 +20,11 @@ class VideoFrame; } // namespace media +namespace video_track_recorder { +const int kVEAEncoderMinResolutionWidth = 640; +const int kVEAEncoderMinResolutionHeight = 480; +} // namespace video_track_recorder + namespace content { // VideoTrackRecorder is a MediaStreamVideoSink that encodes the video frames @@ -56,6 +63,12 @@ private: friend class VideoTrackRecorderTest; + void InitializeEncoder(CodecId codec, + const OnEncodedVideoCB& on_encoded_video_callback, + int32_t bits_per_second, + const scoped_refptr<media::VideoFrame>& frame, + base::TimeTicks capture_time); + // Used to check that we are destroyed on the same thread we were created. base::ThreadChecker main_render_thread_checker_; @@ -65,6 +78,15 @@ // Inner class to encode using whichever codec is configured. scoped_refptr<Encoder> encoder_; + base::Callback<void(const scoped_refptr<media::VideoFrame>& frame, + base::TimeTicks capture_time)> + initialize_encoder_callback_; + + // Used to track the paused state during the initialization process. + bool paused_before_init_; + + base::WeakPtrFactory<VideoTrackRecorder> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(VideoTrackRecorder); };
diff --git a/content/renderer/media/video_track_recorder_unittest.cc b/content/renderer/media/video_track_recorder_unittest.cc index a839082..6d6808c 100644 --- a/content/renderer/media/video_track_recorder_unittest.cc +++ b/content/renderer/media/video_track_recorder_unittest.cc
@@ -24,6 +24,8 @@ #include "third_party/WebKit/public/web/WebHeap.h" using media::VideoFrame; +using video_track_recorder::kVEAEncoderMinResolutionWidth; +using video_track_recorder::kVEAEncoderMinResolutionHeight; using ::testing::_; using ::testing::DoAll; @@ -47,9 +49,15 @@ , VideoTrackRecorder::CodecId::H264 #endif }; +const gfx::Size kTrackRecorderTestSize[] = { + gfx::Size(kVEAEncoderMinResolutionWidth / 2, + kVEAEncoderMinResolutionHeight / 2), + gfx::Size(kVEAEncoderMinResolutionWidth, kVEAEncoderMinResolutionHeight)}; +static const int kTrackRecorderTestSizeDiff = 20; class VideoTrackRecorderTest - : public TestWithParam<VideoTrackRecorder::CodecId> { + : public TestWithParam< + testing::tuple<VideoTrackRecorder::CodecId, gfx::Size>> { public: VideoTrackRecorderTest() : mock_source_(new MockMediaStreamVideoSource(false)) { @@ -68,7 +76,7 @@ blink_track_.setTrackData(track_); video_track_recorder_.reset(new VideoTrackRecorder( - GetParam() /* codec */, blink_track_, + testing::get<0>(GetParam()) /* codec */, blink_track_, base::Bind(&VideoTrackRecorderTest::OnEncodedVideo, base::Unretained(this)), 0 /* bits_per_second */)); @@ -130,7 +138,7 @@ // of larger size is sent and is expected to be encoded as a keyframe. TEST_P(VideoTrackRecorderTest, VideoEncoding) { // |frame_size| cannot be arbitrarily small, should be reasonable. - const gfx::Size frame_size(160, 80); + const gfx::Size& frame_size = testing::get<1>(GetParam()); const scoped_refptr<VideoFrame> video_frame = VideoFrame::CreateBlackFrame(frame_size); const double kFrameRate = 60.0f; @@ -154,7 +162,8 @@ Encode(video_frame, timeticks_later); // Send another Video Frame and expect only an DoOnEncodedVideo() callback. - const gfx::Size frame_size2(180, 80); + const gfx::Size frame_size2(frame_size.width() + kTrackRecorderTestSizeDiff, + frame_size.height()); const scoped_refptr<VideoFrame> video_frame2 = VideoFrame::CreateBlackFrame(frame_size2); @@ -180,6 +189,7 @@ INSTANTIATE_TEST_CASE_P(, VideoTrackRecorderTest, - ValuesIn(kTrackRecorderTestCodec)); + ::testing::Combine(ValuesIn(kTrackRecorderTestCodec), + ValuesIn(kTrackRecorderTestSize))); } // namespace content
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc index 29625e4..452a35b 100644 --- a/content/renderer/pepper/pepper_plugin_instance_impl.cc +++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -179,6 +179,7 @@ using blink::WebUserGestureIndicator; using blink::WebUserGestureToken; using blink::WebView; +using blink::WebWidget; namespace content { @@ -2190,8 +2191,9 @@ void PepperPluginInstanceImpl::SimulateInputEvent( const InputEventData& input_event) { - WebView* web_view = container()->document().frame()->view(); - if (!web_view) { + WebWidget* widget = + container()->document().frame()->localRoot()->frameWidget(); + if (!widget) { NOTREACHED(); return; } @@ -2207,7 +2209,7 @@ for (std::vector<std::unique_ptr<WebInputEvent>>::iterator it = events.begin(); it != events.end(); ++it) { - web_view->handleInputEvent(*it->get()); + widget->handleInputEvent(*it->get()); } }
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.cc b/content/renderer/pepper/ppb_graphics_3d_impl.cc index 30cf4f68..a7bed46 100644 --- a/content/renderer/pepper/ppb_graphics_3d_impl.cc +++ b/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -175,8 +175,7 @@ } int32_t PPB_Graphics3D_Impl::DoSwapBuffers(const gpu::SyncToken& sync_token, - int32_t width, - int32_t height) { + const gfx::Size& size) { DCHECK(command_buffer_); if (taken_front_buffer_.IsZero()) { DLOG(ERROR) << "TakeFrontBuffer should be called before DoSwapBuffers"; @@ -191,16 +190,11 @@ // // Don't need to check for NULL from GetPluginInstance since when we're // bound, we know our instance is valid. - if (width < 0 || height < 0) { - width = original_width_; - height = original_height_; - } bool is_overlay_candidate = use_image_chromium_; GLenum target = is_overlay_candidate ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D; cc::TextureMailbox texture_mailbox(taken_front_buffer_, sync_token, target, - gfx::Size(width, height), - is_overlay_candidate, false); + size, is_overlay_candidate, false); taken_front_buffer_.SetZero(); HostGlobals::Get() ->GetInstance(pp_instance()) @@ -268,8 +262,6 @@ std::move(channel), gpu::kNullSurfaceHandle, share_buffer, gpu::GPU_STREAM_DEFAULT, gpu::GpuStreamPriority::NORMAL, attrib_helper, GURL::EmptyGURL(), base::ThreadTaskRunnerHandle::Get()); - original_width_ = attrib_helper.offscreen_framebuffer_size.width(); - original_height_ = attrib_helper.offscreen_framebuffer_size.height(); if (!command_buffer_) return false;
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.h b/content/renderer/pepper/ppb_graphics_3d_impl.h index 9255e02..dca5aaa 100644 --- a/content/renderer/pepper/ppb_graphics_3d_impl.h +++ b/content/renderer/pepper/ppb_graphics_3d_impl.h
@@ -75,8 +75,7 @@ gpu::CommandBuffer* GetCommandBuffer() override; gpu::GpuControl* GetGpuControl() override; int32_t DoSwapBuffers(const gpu::SyncToken& sync_token, - int32_t width, - int32_t height) override; + const gfx::Size& size) override; private: explicit PPB_Graphics3D_Impl(PP_Instance instance); @@ -116,12 +115,6 @@ bool lost_context_ = false; #endif - // The width and height of the command buffer back buffer are first sized from - // this process, but then resized by the pepper process. Cache the original - // size. - int32_t original_width_ = 0; - int32_t original_height_ = 0; - bool has_alpha_; bool use_image_chromium_; std::unique_ptr<gpu::CommandBufferProxyImpl> command_buffer_;
diff --git a/content/renderer/pepper/url_request_info_util.cc b/content/renderer/pepper/url_request_info_util.cc index 4d8aa14..952994a 100644 --- a/content/renderer/pepper/url_request_info_util.cc +++ b/content/renderer/pepper/url_request_info_util.cc
@@ -169,7 +169,6 @@ name_version = "internal_testing_only"; } - dest->initialize(); dest->setURL(frame->document().completeURL(WebString::fromUTF8(data->url))); dest->setDownloadToFile(data->stream_to_file); dest->setReportUploadProgress(data->record_upload_progress);
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index db7242b..1ababbbe 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -536,10 +536,11 @@ } request.setHTTPMethod(WebString::fromUTF8(common_params.method)); + request.setLoFiState( + static_cast<WebURLRequest::LoFiState>(common_params.lofi_state)); RequestExtraData* extra_data = new RequestExtraData(); extra_data->set_stream_override(std::move(stream_override)); - extra_data->set_lofi_state(common_params.lofi_state); request.setExtraData(extra_data); // Set the ui timestamp for this navigation. Currently the timestamp here is @@ -587,11 +588,11 @@ // PlzNavigate CommonNavigationParams MakeCommonNavigationParams( - blink::WebURLRequest* request, - bool should_replace_current_entry) { + const blink::WebFrameClient::NavigationPolicyInfo& info) { Referrer referrer( - GURL(request->httpHeaderField(WebString::fromUTF8("Referer")).latin1()), - request->referrerPolicy()); + GURL(info.urlRequest.httpHeaderField( + WebString::fromUTF8("Referer")).latin1()), + info.urlRequest.referrerPolicy()); // Set the ui timestamp for this navigation. Currently the timestamp here is // only non empty when the navigation was triggered by an Android intent, or @@ -600,20 +601,27 @@ // CommitNavigation IPC, and then back to the browser again in the // DidCommitProvisionalLoad and the DocumentLoadComplete IPCs. base::TimeTicks ui_timestamp = - base::TimeTicks() + base::TimeDelta::FromSecondsD(request->uiStartTime()); + base::TimeTicks() + + base::TimeDelta::FromSecondsD(info.urlRequest.uiStartTime()); FrameMsg_UILoadMetricsReportType::Value report_type = static_cast<FrameMsg_UILoadMetricsReportType::Value>( - request->inputPerfMetricReportPolicy()); + info.urlRequest.inputPerfMetricReportPolicy()); + + FrameMsg_Navigate_Type::Value navigation_type = + info.navigationType == blink::WebNavigationTypeReload + ? FrameMsg_Navigate_Type::RELOAD + : FrameMsg_Navigate_Type::NORMAL; const RequestExtraData* extra_data = - static_cast<RequestExtraData*>(request->getExtraData()); + static_cast<RequestExtraData*>(info.urlRequest.getExtraData()); DCHECK(extra_data); return CommonNavigationParams( - request->url(), referrer, extra_data->transition_type(), - FrameMsg_Navigate_Type::NORMAL, true, should_replace_current_entry, - ui_timestamp, report_type, GURL(), GURL(), extra_data->lofi_state(), - base::TimeTicks::Now(), request->httpMethod().latin1(), - GetRequestBodyForWebURLRequest(*request)); + info.urlRequest.url(), referrer, extra_data->transition_type(), + navigation_type, true, info.replacesCurrentHistoryItem, ui_timestamp, + report_type, GURL(), GURL(), + static_cast<LoFiState>(info.urlRequest.getLoFiState()), + base::TimeTicks::Now(), info.urlRequest.httpMethod().latin1(), + GetRequestBodyForWebURLRequest(info.urlRequest)); } media::Context3D GetSharedMainThreadContext3D( @@ -3932,7 +3940,7 @@ // // TODO(mkwst): It would be cleaner to adjust blink::ResourceRequest to // initialize itself with a `nullptr` initiator so that this can be a simple - // `isNull()` check. + // `isNull()` check. https://crbug.com/625969 if (request.requestorOrigin().isUnique() && !frame->document().getSecurityOrigin().isUnique()) { request.setRequestorOrigin(frame->document().getSecurityOrigin()); @@ -4058,17 +4066,21 @@ navigation_state->start_params().transferred_request_request_id); extra_data->set_service_worker_provider_id(provider_id); extra_data->set_stream_override(std::move(stream_override)); - if (request.getLoFiState() != WebURLRequest::LoFiUnspecified) - extra_data->set_lofi_state(static_cast<LoFiState>(request.getLoFiState())); - else if (is_main_frame_ && !navigation_state->request_committed()) - extra_data->set_lofi_state(navigation_state->common_params().lofi_state); - else - extra_data->set_lofi_state(is_using_lofi_ ? LOFI_ON : LOFI_OFF); WebString error; extra_data->set_initiated_in_secure_context( frame->document().isSecureContext(error)); request.setExtraData(extra_data); + if (request.getLoFiState() == WebURLRequest::LoFiUnspecified) { + if (is_main_frame_ && !navigation_state->request_committed()) { + request.setLoFiState(static_cast<WebURLRequest::LoFiState>( + navigation_state->common_params().lofi_state)); + } else { + request.setLoFiState( + is_using_lofi_ ? WebURLRequest::LoFiOn : WebURLRequest::LoFiOff); + } + } + // TODO(creis): Update prefetching to work with out-of-process iframes. WebFrame* top_frame = frame->top(); if (top_frame && top_frame->isWebLocalFrame()) { @@ -4428,14 +4440,12 @@ FOR_EACH_OBSERVER(RenderFrameObserver, observers_, DidChangeManifest()); } -bool RenderFrameImpl::enterFullscreen() { +void RenderFrameImpl::enterFullscreen() { Send(new FrameHostMsg_ToggleFullscreen(routing_id_, true)); - return true; } -bool RenderFrameImpl::exitFullscreen() { +void RenderFrameImpl::exitFullscreen() { Send(new FrameHostMsg_ToggleFullscreen(routing_id_, false)); - return true; } blink::WebPermissionClient* RenderFrameImpl::permissionClient() { @@ -5064,8 +5074,7 @@ if (IsBrowserSideNavigationEnabled() && info.urlRequest.checkForBrowserSideNavigation() && ShouldMakeNetworkRequestForURL(url)) { - BeginNavigation(&info.urlRequest, info.replacesCurrentHistoryItem, - info.isClientRedirect); + BeginNavigation(info); return blink::WebNavigationPolicyHandledByClient; } @@ -5778,11 +5787,8 @@ } } -void RenderFrameImpl::BeginNavigation(blink::WebURLRequest* request, - bool should_replace_current_entry, - bool is_client_redirect) { +void RenderFrameImpl::BeginNavigation(const NavigationPolicyInfo& info) { CHECK(IsBrowserSideNavigationEnabled()); - DCHECK(request); // Note: At this stage, the goal is to apply all the modifications the // renderer wants to make to the request, and then send it to the browser, so @@ -5794,14 +5800,14 @@ // TODO(clamy): Apply devtools override. // TODO(clamy): Make sure that navigation requests are not modified somewhere // else in blink. - willSendRequest(frame_, 0, *request, blink::WebURLResponse()); + willSendRequest(frame_, 0, info.urlRequest, blink::WebURLResponse()); // Update the transition type of the request for client side redirects. - if (!request->getExtraData()) - request->setExtraData(new RequestExtraData()); - if (is_client_redirect) { + if (!info.urlRequest.getExtraData()) + info.urlRequest.setExtraData(new RequestExtraData()); + if (info.isClientRedirect) { RequestExtraData* extra_data = - static_cast<RequestExtraData*>(request->getExtraData()); + static_cast<RequestExtraData*>(info.urlRequest.getExtraData()); extra_data->set_transition_type(ui::PageTransitionFromInt( extra_data->transition_type() | ui::PAGE_TRANSITION_CLIENT_REDIRECT)); } @@ -5812,27 +5818,28 @@ // These values are assumed on the browser side for navigations. These checks // ensure the renderer has the correct values. DCHECK_EQ(FETCH_REQUEST_MODE_NAVIGATE, - GetFetchRequestModeForWebURLRequest(*request)); + GetFetchRequestModeForWebURLRequest(info.urlRequest)); DCHECK_EQ(FETCH_CREDENTIALS_MODE_INCLUDE, - GetFetchCredentialsModeForWebURLRequest(*request)); - DCHECK(GetFetchRedirectModeForWebURLRequest(*request) == + GetFetchCredentialsModeForWebURLRequest(info.urlRequest)); + DCHECK(GetFetchRedirectModeForWebURLRequest(info.urlRequest) == FetchRedirectMode::MANUAL_MODE); DCHECK(frame_->parent() || - GetRequestContextFrameTypeForWebURLRequest(*request) == + GetRequestContextFrameTypeForWebURLRequest(info.urlRequest) == REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL); DCHECK(!frame_->parent() || - GetRequestContextFrameTypeForWebURLRequest(*request) == + GetRequestContextFrameTypeForWebURLRequest(info.urlRequest) == REQUEST_CONTEXT_FRAME_TYPE_NESTED); Send(new FrameHostMsg_BeginNavigation( routing_id_, - MakeCommonNavigationParams(request, should_replace_current_entry), - BeginNavigationParams(GetWebURLRequestHeaders(*request), - GetLoadFlagsForWebURLRequest(*request), - request->hasUserGesture(), - request->skipServiceWorker() != - blink::WebURLRequest::SkipServiceWorker::None, - GetRequestContextTypeForWebURLRequest(*request)))); + MakeCommonNavigationParams(info), + BeginNavigationParams( + GetWebURLRequestHeaders(info.urlRequest), + GetLoadFlagsForWebURLRequest(info.urlRequest), + info.urlRequest.hasUserGesture(), + info.urlRequest.skipServiceWorker() != + blink::WebURLRequest::SkipServiceWorker::None, + GetRequestContextTypeForWebURLRequest(info.urlRequest)))); } void RenderFrameImpl::LoadDataURL(
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 2ff0dd7..cf19ac8 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -623,8 +623,8 @@ const blink::WebAXObject& end_object, int end_offset) override; void didChangeManifest() override; - bool enterFullscreen() override; - bool exitFullscreen() override; + void enterFullscreen() override; + void exitFullscreen() override; blink::WebPermissionClient* permissionClient() override; blink::WebAppBannerClient* appBannerClient() override; void registerProtocolHandler(const blink::WebString& scheme, @@ -960,18 +960,8 @@ const RequestNavigationParams& request_params); // PlzNavigate - // Sends a FrameHostMsg_BeginNavigation to the browser based on the contents - // of the WebURLRequest. - // |should_replace_current_entry| indicates that the current history entry - // will be replaced when the navigation commits. |is_client_redirect| - // indicates that the navigation originated as a client redirect. - // Note: those two concepts are separate. For example, a location.assign is a - // client redirect but it only replaces the current entry if called before - // load stop. location.replace on the other hand is a client redirect and - // always replaces the current entry. - void BeginNavigation(blink::WebURLRequest* request, - bool should_replace_current_entry, - bool is_client_redirect); + // Sends a FrameHostMsg_BeginNavigation to the browser + void BeginNavigation(const NavigationPolicyInfo& info); // Loads a data url. void LoadDataURL(const CommonNavigationParams& params,
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index 74bcd08..344692b 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -380,7 +380,7 @@ } void RenderFrameProxy::OnWillEnterFullscreen() { - web_frame_->willEnterFullScreen(); + web_frame_->willEnterFullscreen(); } void RenderFrameProxy::frameDetached(DetachType type) {
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 660b52b..1a4a0260 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -46,6 +46,7 @@ #include "cc/raster/task_graph_runner.h" #include "cc/trees/layer_tree_host_common.h" #include "cc/trees/layer_tree_settings.h" +#include "components/memory_coordinator/child/child_memory_coordinator_impl.h" #include "components/scheduler/child/compositor_worker_scheduler.h" #include "components/scheduler/child/webthread_base.h" #include "components/scheduler/child/webthread_impl_for_worker_scheduler.h" @@ -823,6 +824,15 @@ base::Bind(&RenderThreadImpl::OnSyncMemoryPressure, base::Unretained(this)))); + if (memory_coordinator::IsEnabled()) { + // TODO(bashi): Revisit how to manage the lifetime of + // ChildMemoryCoordinatorImpl. + // https://codereview.chromium.org/2094583002/#msg52 + memory_coordinator_.reset( + new memory_coordinator::ChildMemoryCoordinatorImpl( + GetRemoteInterfaces())); + } + int num_raster_threads = 0; std::string string_value = command_line.GetSwitchValueASCII(switches::kNumRasterThreads);
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index 9a3795f..b7ad13a 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h
@@ -79,6 +79,10 @@ class GpuVideoAcceleratorFactories; } +namespace memory_coordinator { +class ChildMemoryCoordinatorImpl; +} + namespace scheduler { class WebThreadBase; } @@ -643,6 +647,8 @@ std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; std::unique_ptr<MemoryObserver> memory_observer_; + std::unique_ptr<memory_coordinator::ChildMemoryCoordinatorImpl> + memory_coordinator_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_compositor_task_runner_;
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 9f2142a..2004d48 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -2020,10 +2020,6 @@ RenderWidget::didAutoResize(newSize); } -void RenderViewImpl::didChangeCursor(const blink::WebCursorInfo& info) { - RenderWidget::didChangeCursor(info); -} - void RenderViewImpl::didInvalidateRect(const blink::WebRect& rect) { RenderWidget::didInvalidateRect(rect); }
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index 3bbb0c5d..591f8cb 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h
@@ -298,7 +298,6 @@ void convertViewportToWindow(blink::WebRect* rect) override; void convertWindowToViewport(blink::WebFloatRect* rect) override; void didAutoResize(const blink::WebSize& newSize) override; - void didChangeCursor(const blink::WebCursorInfo& info) override; void didInvalidateRect(const blink::WebRect& rect) override; void didOverscroll(const blink::WebFloatSize& overscrollDelta, const blink::WebFloatSize& accumulatedOverscroll,
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 129ed07..1bc7b2f 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -490,7 +490,7 @@ IPC_MESSAGE_HANDLER(ViewMsg_SetTextDirection, OnSetTextDirection) IPC_MESSAGE_HANDLER(ViewMsg_Move_ACK, OnRequestMoveAck) IPC_MESSAGE_HANDLER(ViewMsg_UpdateScreenRects, OnUpdateScreenRects) - IPC_MESSAGE_HANDLER(ViewMsg_SetSurfaceIdNamespace, OnSetSurfaceIdNamespace) + IPC_MESSAGE_HANDLER(ViewMsg_SetSurfaceClientId, OnSetSurfaceClientId) IPC_MESSAGE_HANDLER(ViewMsg_WaitForNextFrameForTests, OnWaitNextFrameForTests) #if defined(OS_ANDROID) @@ -1449,9 +1449,9 @@ } } -void RenderWidget::OnSetSurfaceIdNamespace(uint32_t surface_id_namespace) { +void RenderWidget::OnSetSurfaceClientId(uint32_t surface_id_namespace) { if (compositor_) - compositor_->SetSurfaceIdNamespace(surface_id_namespace); + compositor_->SetSurfaceClientId(surface_id_namespace); } void RenderWidget::OnHandleCompositorProto(const std::vector<uint8_t>& proto) { @@ -1618,9 +1618,9 @@ return; if (is_fullscreen_granted_) { - webwidget_->didEnterFullScreen(); + webwidget_->didEnterFullscreen(); } else { - webwidget_->didExitFullScreen(); + webwidget_->didExitFullscreen(); } }
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index 8cb00106..f3d391a 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -469,7 +469,7 @@ const gfx::Rect& window_screen_rect); void OnUpdateWindowScreenRect(const gfx::Rect& window_screen_rect); void OnShowImeIfNeeded(); - void OnSetSurfaceIdNamespace(uint32_t surface_id_namespace); + void OnSetSurfaceClientId(uint32_t surface_id_namespace); void OnHandleCompositorProto(const std::vector<uint8_t>& proto); #if defined(OS_ANDROID)
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index 7990efe5..0e1d607 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -49,6 +49,7 @@ #include "content/public/common/webplugininfo.h" #include "content/public/renderer/content_renderer_client.h" #include "content/public/renderer/media_stream_utils.h" +#include "content/public/renderer/render_frame.h" #include "content/renderer/cache_storage/webserviceworkercachestorage_impl.h" #include "content/renderer/device_sensors/device_light_event_pump.h" #include "content/renderer/device_sensors/device_motion_event_pump.h" @@ -58,6 +59,7 @@ #include "content/renderer/dom_storage/webstoragenamespace_impl.h" #include "content/renderer/gamepad_shared_memory_reader.h" #include "content/renderer/media/audio_decoder.h" +#include "content/renderer/media/audio_device_factory.h" #include "content/renderer/media/canvas_capture_handler.h" #include "content/renderer/media/html_audio_element_capturer_source.h" #include "content/renderer/media/html_video_element_capturer_source.h" @@ -79,7 +81,6 @@ #include "gpu/ipc/common/gpu_stream_constants.h" #include "ipc/ipc_sync_message_filter.h" #include "media/audio/audio_output_device.h" -#include "media/base/audio_hardware_config.h" #include "media/base/mime_util.h" #include "media/blink/webcontentdecryptionmodule_impl.h" #include "media/filters/stream_parser_factory.h" @@ -102,6 +103,7 @@ #include "third_party/WebKit/public/platform/mime_registry.mojom.h" #include "third_party/WebKit/public/platform/modules/device_orientation/WebDeviceMotionListener.h" #include "third_party/WebKit/public/platform/modules/device_orientation/WebDeviceOrientationListener.h" +#include "third_party/WebKit/public/web/WebLocalFrame.h" #include "url/gurl.h" #if defined(OS_MACOSX) @@ -178,6 +180,16 @@ base::LazyInstance<blink::WebDeviceOrientationData>::Leaky g_test_device_orientation_data = LAZY_INSTANCE_INITIALIZER; +media::AudioParameters GetAudioHardwareParams() { + blink::WebLocalFrame* const web_frame = + blink::WebLocalFrame::frameForCurrentContext(); + RenderFrame* const render_frame = RenderFrame::FromWebFrame(web_frame); + return AudioDeviceFactory::GetOutputDeviceInfo(render_frame->GetRoutingID(), + 0, std::string(), + web_frame->getSecurityOrigin()) + .output_params(); +} + } // namespace //------------------------------------------------------------------------------ @@ -685,18 +697,15 @@ } double RendererBlinkPlatformImpl::audioHardwareSampleRate() { - RenderThreadImpl* thread = RenderThreadImpl::current(); - return thread->GetAudioHardwareConfig()->GetOutputSampleRate(); + return GetAudioHardwareParams().sample_rate(); } size_t RendererBlinkPlatformImpl::audioHardwareBufferSize() { - RenderThreadImpl* thread = RenderThreadImpl::current(); - return thread->GetAudioHardwareConfig()->GetOutputBufferSize(); + return GetAudioHardwareParams().frames_per_buffer(); } unsigned RendererBlinkPlatformImpl::audioHardwareOutputChannels() { - RenderThreadImpl* thread = RenderThreadImpl::current(); - return thread->GetAudioHardwareConfig()->GetOutputChannels(); + return GetAudioHardwareParams().channels(); } WebDatabaseObserver* RendererBlinkPlatformImpl::databaseObserver() {
diff --git a/content/renderer/text_input_client_observer.cc b/content/renderer/text_input_client_observer.cc index d738e546..c18d127 100644 --- a/content/renderer/text_input_client_observer.cc +++ b/content/renderer/text_input_client_observer.cc
@@ -88,9 +88,14 @@ #endif { blink::WebLocalFrame* frame = webview()->focusedFrame(); - blink::WebRect web_rect; - frame->firstRectForCharacterRange(range.start(), range.length(), web_rect); - rect = web_rect; + // TODO(yabinh): Null check should not be necessary. + // See crbug.com/304341 + if (frame) { + blink::WebRect web_rect; + frame->firstRectForCharacterRange(range.start(), range.length(), + web_rect); + rect = web_rect; + } } Send(new TextInputClientReplyMsg_GotFirstRectForRange(routing_id(), rect)); } @@ -100,8 +105,12 @@ blink::WebPoint baselinePoint; NSAttributedString* string = nil; blink::WebLocalFrame* frame = webview()->focusedFrame(); - string = blink::WebSubstringUtil::attributedSubstringInRange( - frame, range.start(), range.length(), &baselinePoint); + // TODO(yabinh): Null check should not be necessary. + // See crbug.com/304341 + if (frame) { + string = blink::WebSubstringUtil::attributedSubstringInRange( + frame, range.start(), range.length(), &baselinePoint); + } std::unique_ptr<const mac::AttributedStringCoder::EncodedString> encoded( mac::AttributedStringCoder::Encode(string)); Send(new TextInputClientReplyMsg_GotStringForRange(routing_id(),
diff --git a/content/shell/BUILD.gn b/content/shell/BUILD.gn index 8804c4a..01ad049 100644 --- a/content/shell/BUILD.gn +++ b/content/shell/BUILD.gn
@@ -17,6 +17,8 @@ import("//build/config/mac/rules.gni") import("//build_overrides/v8.gni") import("//build/mac/tweak_info_plist.gni") +} else if (is_win) { + import("//build/win/syzygy/syzygy.gni") } declare_args() { @@ -532,6 +534,17 @@ configs -= [ "//build/config/win:console" ] configs += [ "//build/config/win:windowed" ] } + + if (is_syzyasan) { + syzygy_asan("content_shell_syzyasan") { + binary_name = "content_shell.exe" + dest_dir = "$root_out_dir/syzygy" + deps = [ + "//content/shell:content_shell", + ] + testonly = true + } + } } if (is_mac) {
diff --git a/content/shell/browser/shell_views.cc b/content/shell/browser/shell_views.cc index e8e4552..5dcc775 100644 --- a/content/shell/browser/shell_views.cc +++ b/content/shell/browser/shell_views.cc
@@ -71,7 +71,7 @@ bool IsCommandIdChecked(int command_id) const override { return false; } bool IsCommandIdEnabled(int command_id) const override { return true; } bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override { + ui::Accelerator* accelerator) const override { return false; } void ExecuteCommand(int command_id, int event_flags) override {
diff --git a/content/shell/renderer/layout_test/blink_test_runner.cc b/content/shell/renderer/layout_test/blink_test_runner.cc index 1f808fe..3041462 100644 --- a/content/shell/renderer/layout_test/blink_test_runner.cc +++ b/content/shell/renderer/layout_test/blink_test_runner.cc
@@ -543,19 +543,20 @@ std::string BlinkTestRunner::PathToLocalResource(const std::string& resource) { #if defined(OS_WIN) - if (resource.find("/tmp/") == 0) { + if (base::StartsWith(resource, "/tmp/", base::CompareCase::SENSITIVE)) { // We want a temp file. GURL base_url = net::FilePathToFileURL(test_config_.temp_path); - return base_url.Resolve(resource.substr(strlen("/tmp/"))).spec(); + return base_url.Resolve(resource.substr(sizeof("/tmp/") - 1)).spec(); } #endif // Some layout tests use file://// which we resolve as a UNC path. Normalize // them to just file:///. std::string result = resource; - while (base::ToLowerASCII(result).find("file:////") == 0) { - result = result.substr(0, strlen("file:///")) + - result.substr(strlen("file:////")); + static const size_t kFileLen = sizeof("file:///") - 1; + while (base::StartsWith(base::ToLowerASCII(result), "file:////", + base::CompareCase::SENSITIVE)) { + result = result.substr(0, kFileLen) + result.substr(kFileLen + 1); } return RewriteLayoutTestsURL(result, false /* is_wpt_mode */).string().utf8(); } @@ -657,13 +658,13 @@ const GURL& origin, const GURL& embedding_origin) { blink::mojom::PermissionStatus status; - if (value == "granted") + if (value == "granted") { status = blink::mojom::PermissionStatus::GRANTED; - else if (value == "prompt") + } else if (value == "prompt") { status = blink::mojom::PermissionStatus::ASK; - else if (value == "denied") + } else if (value == "denied") { status = blink::mojom::PermissionStatus::DENIED; - else { + } else { NOTREACHED(); status = blink::mojom::PermissionStatus::DENIED; }
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index bab905c..83a74d0 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -449,6 +449,7 @@ ":content_test_mojo_bindings", ":web_ui_test_mojo_bindings", "//base/test:test_support", + "//components/memory_coordinator/browser", "//components/scheduler", "//content:resources", "//content/app:both_for_content_tests",
diff --git a/content/test/data/download/iframe-host.html b/content/test/data/download/iframe-host.html new file mode 100644 index 0000000..0c9b4542 --- /dev/null +++ b/content/test/data/download/iframe-host.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> + <body> + <iframe id="frame"></iframe> + <script> +var iframeElement = document.querySelector('#frame'); +url = window.location.href; +iframeElement.src = url.substr(url.indexOf('=') + 1); + </script> + </body> +</html>
diff --git a/content/test/data/download/iframe-host.html.mock-http-headers b/content/test/data/download/iframe-host.html.mock-http-headers new file mode 100644 index 0000000..524e3d8c --- /dev/null +++ b/content/test/data/download/iframe-host.html.mock-http-headers
@@ -0,0 +1,2 @@ +HTTP/1.1 200 OK +Content-Type: text/html
diff --git a/content/test/data/invalid.ico b/content/test/data/invalid.ico new file mode 100644 index 0000000..f6c9094 --- /dev/null +++ b/content/test/data/invalid.ico Binary files differ
diff --git a/content/test/data/nested_page_with_subresources.html b/content/test/data/nested_page_with_subresources.html new file mode 100644 index 0000000..e6c2c98 --- /dev/null +++ b/content/test/data/nested_page_with_subresources.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<body> +<script> + var i = document.createElement("iframe"); + i.src = location.protocol + "//not-" + location.hostname + (location.port ? (":" + location.port) : "") + "/page_with_subresources.html"; + document.body.appendChild(i); +</script> +</body>
diff --git a/content/test/data/page_with_subresources.html b/content/test/data/page_with_subresources.html new file mode 100644 index 0000000..314cdba --- /dev/null +++ b/content/test/data/page_with_subresources.html
@@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> +<head> + <link rel="stylesheet" href="style"></link> + <link rel="prefetch" href="prefetch"></link> +</head> +<body> + <img src="image-inline"> + <a href="javascript:" ping="ping">link</a> + + <!-- All script-based loading at the bottom to avoid duplicating requests + due to the preload scanner --> + <script src="script"></script> + <script> + // <img> + var i = document.createElement('img'); + i.src = "image-script"; + + // <a ping> + document.querySelector('a').click(); + + // Beacon + navigator.sendBeacon("/beacon", "foo"); + </script> +</body> +</html>
diff --git a/content/test/gpu/PRESUBMIT.py b/content/test/gpu/PRESUBMIT.py index b8fa696b..c1725d63 100644 --- a/content/test/gpu/PRESUBMIT.py +++ b/content/test/gpu/PRESUBMIT.py
@@ -73,9 +73,9 @@ return [] bots = [ - 'tryserver.chromium.linux:linux_optional_gpu_tests_rel', - 'tryserver.chromium.mac:mac_optional_gpu_tests_rel', - 'tryserver.chromium.win:win_optional_gpu_tests_rel', + 'master.tryserver.chromium.linux:linux_optional_gpu_tests_rel', + 'master.tryserver.chromium.mac:mac_optional_gpu_tests_rel', + 'master.tryserver.chromium.win:win_optional_gpu_tests_rel', ] results = []
diff --git a/content/test/gpu/generate_buildbot_json.py b/content/test/gpu/generate_buildbot_json.py index 61db377..da23fe0 100755 --- a/content/test/gpu/generate_buildbot_json.py +++ b/content/test/gpu/generate_buildbot_json.py
@@ -920,17 +920,12 @@ # http://crbug.com/599451: this test is currently too slow # to run on x64 in Debug mode. Need to shard the tests. 'Win7 x64 Debug (NVIDIA)', - # http://crbug.com/540543: Linux Intel driver is GL 3.0 and - # doesn't support features needed for ES3 - 'Linux Release (New Intel)', - 'Linux Debug (New Intel)', ], }, ], 'target_name': 'webgl_conformance', 'args': [ '--webgl-conformance-version=2.0.0', - '--webgl2-only=true', # The current working directory when run via isolate is # out/Debug or out/Release. Reference this file relatively to # it. @@ -938,9 +933,9 @@ '../../content/test/data/gpu/webgl2_conformance_tests_output.json', ], 'swarming': { - # These tests currently take about an hour to run. Split them - # into roughly 5-minute shards. - 'shards': 12, + # These tests currently take about an hour and fifteen minutes + # to run. Split them into roughly 5-minute shards. + 'shards': 15, }, }, 'webgl2_conformance_angle_tests': { @@ -970,7 +965,6 @@ ], 'args': [ '--webgl-conformance-version=2.0.0', - '--webgl2-only=true', # The current working directory when run via isolate is # out/Debug or out/Release. Reference this file relatively to # it. @@ -978,9 +972,9 @@ '../../content/test/data/gpu/webgl2_conformance_tests_output.json', ], 'swarming': { - # These tests currently take about an hour to run. Split them - # into roughly 5-minute shards. - 'shards': 12, + # These tests currently take about an hour and fifteen minutes + # to run. Split them into roughly 5-minute shards. + 'shards': 15, }, }, }
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index 2745c1c..43f1545 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -31,26 +31,41 @@ # All platforms. + self.Fail('conformance/misc/invalid-passed-params.html', bug=483282) + self.Fail('conformance/textures/image_bitmap_from_canvas/' + + 'tex-2d-rgba-rgba-unsigned_byte.html', bug=483282) + self.Fail('conformance/textures/image_bitmap_from_canvas/' + + 'tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html', bug=483282) + self.Fail('conformance/textures/image_bitmap_from_canvas/' + + 'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html', bug=483282) + self.Fail('conformance/textures/image_bitmap_from_canvas/' + + 'tex-2d-rgb-rgb-unsigned_byte.html', bug=483282) + self.Fail('conformance/textures/image_bitmap_from_canvas/' + + 'tex-2d-rgb-rgb-unsigned_short_5_6_5.html', bug=483282) + + # Too slow (take about one hour to run) self.Skip('deqp/functional/gles3/builtinprecision/*.html', bug=619403) - self.Fail('deqp/functional/gles3/framebufferblit/depth_stencil.html', - bug=483282) self.Fail('deqp/data/gles3/shaders/linkage.html', bug=601821) - self.Flaky('deqp/functional/gles3/negativefragmentapi.html', bug=604794) - - self.Fail('deqp/data/gles3/shaders/preprocessor.html', bug=483282) - self.Fail('conformance2/glsl3/forbidden-operators.html', bug=483282) - self.Flaky('conformance2/query/occlusion-query.html', bug=603168) + # Mark this test Flaky on all platforms but Intel Linux that is failing + # reliably. + self.Flaky('conformance2/query/occlusion-query.html', + ['win', 'mac'], bug=603168) + self.Flaky('conformance2/query/occlusion-query.html', + ['linux', 'nvidia', 'amd'], bug=603168) self.Fail('conformance2/rendering/attrib-type-match.html', bug=627193) self.Fail('conformance2/transform_feedback/' + 'unwritten-output-defaults-to-zero.html', bug=1441) # ANGLE bug + # Likely move this to WebGL 2.0.1. + self.Fail('conformance2/glsl3/tricky-loop-conditions.html', bug=483282) + # Avoid a conflict with a Mac expectation by setting self.Fail('conformance2/textures/misc/tex-input-validation.html', ['d3d9', 'd3d11', 'opengl'], bug=483282) @@ -60,6 +75,33 @@ ['amd'], bug=617290) # Windows only. + self.Fail('conformance/glsl/bugs/' + + 'pow-of-small-constant-in-user-defined-function.html', + ['win'], bug=485641) + self.Fail('conformance/misc/uninitialized-test.html', + ['win'], bug=483282) + self.Fail('conformance/rendering/point-specific-shader-variables.html', + ['win'], bug=616335) + self.Fail('conformance/textures/canvas/' + + 'tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html', + ['win'], bug=483282) + self.Fail('conformance/textures/canvas/' + + 'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html', + ['win'], bug=483282) + self.Fail('conformance/textures/canvas/' + + 'tex-2d-rgb-rgb-unsigned_short_5_6_5.html', + ['win'], bug=483282) + self.Fail('conformance/textures/webgl_canvas/' + + 'tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html', + ['win'], bug=483282) + self.Fail('conformance/textures/webgl_canvas/' + + 'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html', + ['win'], bug=483282) + self.Fail('conformance/textures/webgl_canvas/' + + 'tex-2d-rgb-rgb-unsigned_short_5_6_5.html', + ['win'], bug=483282) + self.Fail('deqp/data/gles2/shaders/functions.html', + ['win'], bug=478572) self.Fail('deqp/functional/gles3/shaderloop_for.html', ['win'], bug=617817) self.Fail('deqp/functional/gles3/shaderloop_while.html', @@ -67,29 +109,6 @@ self.Fail('deqp/functional/gles3/shaderloop_do_while.html', ['win'], bug=617817) - self.Fail('deqp/functional/gles3/shadertexturefunction/texturelod.html', - ['win'], bug=483282) - self.Fail('deqp/functional/gles3/shadertexturefunction/' + - 'texturelodoffset.html', - ['win'], bug=483282) - self.Fail('deqp/functional/gles3/shadertexturefunction/' + - 'textureprojlod.html', - ['win'], bug=483282) - self.Fail('deqp/functional/gles3/shadertexturefunction/' + - 'textureprojlodoffset.html', - ['win'], bug=483282) - self.Fail('deqp/functional/gles3/shadertexturefunction/texturegrad.html', - ['win'], bug=483282) - self.Fail('deqp/functional/gles3/shadertexturefunction/' + - 'texturegradoffset.html', - ['win'], bug=483282) - self.Fail('deqp/functional/gles3/shadertexturefunction/' + - 'textureprojgrad.html', - ['win'], bug=483282) - self.Fail('deqp/functional/gles3/shadertexturefunction/' + - 'textureprojgradoffset.html', - ['win'], bug=483282) - self.Fail('conformance2/glsl3/array-in-complex-expression.html', ['win'], bug=483282) self.Skip('conformance2/reading/read-pixels-pack-parameters.html', @@ -103,13 +122,14 @@ self.Fail('deqp/functional/gles3/fboinvalidate/whole.html', ['win'], bug=624506) + self.Fail('deqp/functional/gles3/textureformat/compressed_cube.html', + ['win'], bug=614573) + # Windows 8 only. self.Flaky('deqp/functional/gles3/buffercopy.html', ['win8'], bug=587601) # Win / NVidia - self.Fail('deqp/functional/gles3/textureformat/compressed_cube.html', - ['win', 'nvidia'], bug=614573) self.Fail('deqp/functional/gles3/framebufferblit/rect_02.html', ['win', 'nvidia'], bug=483282) self.Fail('deqp/functional/gles3/framebufferblit/rect_05.html', @@ -124,8 +144,6 @@ self.Fail('deqp/functional/gles3/texturespecification/' + 'texstorage3d_format_depth_stencil.html', ['win', ('amd', 0x6779)], bug=614178) - self.Fail('deqp/functional/gles3/textureformat/compressed_cube.html', - ['win', ('amd', 0x6779)], bug=614573) self.Fail('deqp/functional/gles3/shadertexturefunction/texture.html', ['win', ('amd', 0x6779)], bug=483282) self.Fail('deqp/functional/gles3/shadertexturefunction/' + @@ -147,6 +165,7 @@ # It's unfortunate that this suppression needs to be so broad, but # basically any test that uses readPixels is potentially flaky, and # it's infeasible to suppress individual failures one by one. + self.Flaky('conformance/*', ['win', ('amd', 0x6779)], bug=491419) self.Flaky('conformance2/*', ['win', ('amd', 0x6779)], bug=491419) self.Flaky('deqp/*', ['win', ('amd', 0x6779)], bug=491419) @@ -183,8 +202,6 @@ ['win', 'intel'], bug=614418) self.Fail('deqp/functional/gles3/textureformat/sized_depth_stencil.html', ['win', 'intel'], bug=614418) - self.Fail('deqp/functional/gles3/textureformat/compressed_cube.html', - ['win', 'intel'], bug=614418) self.Flaky('deqp/functional/gles3/textureformat/unsized_3d.html', ['win', 'intel'], bug=614418) self.Fail('deqp/functional/gles3/shadertexturefunction/texture.html', @@ -204,6 +221,10 @@ ['win', 'intel'], bug=626068) # Mac only. + self.Fail('conformance/glsl/misc/shaders-with-invariance.html', + ['mac'], bug=483282) + self.Fail('deqp/data/gles2/shaders/scoping.html', + ['mac'], bug=483282) self.Flaky('deqp/functional/gles3/shaderindexing/varying.html', ['mac'], bug=619264) self.Fail('deqp/functional/gles3/shaderloop_do_while.html', @@ -215,12 +236,8 @@ self.Fail('deqp/functional/gles3/uniformbuffers/random.html', ['mac'], bug=618464) - self.Fail('deqp/functional/gles3/textureformat/compressed_2d.html', - ['mac'], bug=612205) self.Fail('deqp/functional/gles3/textureformat/compressed_cube.html', ['mac'], bug=612205) - self.Fail('deqp/functional/gles3/texturewrap/e*', - ['mac'], bug=612205) self.Fail('deqp/data/gles3/shaders/qualification_order.html', ['mac'], bug=483282) @@ -229,10 +246,6 @@ self.Fail('deqp/functional/gles3/pixelbufferobject.html', ['mac'], bug=483282) - self.Fail('conformance2/textures/misc/compressed-tex-image.html', - ['mac'], bug=565438) - self.Fail('conformance2/textures/misc/tex-storage-compressed-formats.html', - ['mac'], bug=295792) self.Fail('conformance2/renderbuffers/framebuffer-test.html', ['mac'], bug=483282) self.Fail('conformance2/rendering/framebuffer-completeness-unaffected.html', @@ -284,6 +297,16 @@ ['mac'], bug=483282) # Mac Retina NVIDIA + self.Fail('conformance/attribs/gl-disabled-vertex-attrib.html', + ['mac', ('nvidia', 0xfe9)], bug=483282) + self.Fail( + 'conformance/glsl/bugs/array-of-struct-with-int-first-position.html', + ['mac', ('nvidia', 0xfd5), ('nvidia', 0xfe9)], bug=368912) + self.Fail('conformance/programs/' + + 'gl-bind-attrib-location-long-names-test.html', + ['mac', ('nvidia', 0xfe9)], bug=483282) + self.Fail('conformance/programs/gl-bind-attrib-location-test.html', + ['mac', ('nvidia', 0xfe9)], bug=483282) self.Fail('conformance2/textures/misc/tex-input-validation.html', ['mac', ('nvidia', 0xfe9), 'no_angle'], bug=483282) self.Fail('conformance2/textures/misc/tex-mipmap-levels.html', @@ -499,6 +522,22 @@ ['mac', 'intel'], bug=483282) # Linux only. + self.Flaky('conformance/textures/video/' + + 'tex-2d-rgba-rgba-unsigned_byte.html', + ['linux'], bug=627525) + self.Flaky('conformance/textures/video/' + + 'tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html', + ['linux'], bug=627525) + self.Flaky('conformance/textures/video/' + + 'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html', + ['linux'], bug=627525) + self.Flaky('conformance/textures/video/' + + 'tex-2d-rgb-rgb-unsigned_byte.html', + ['linux'], bug=627525) + self.Flaky('conformance/textures/video/' + + 'tex-2d-rgb-rgb-unsigned_short_5_6_5.html', + ['linux'], bug=627525) + self.Fail('conformance2/glsl3/vector-dynamic-indexing.html', ['linux'], bug=483282) @@ -529,6 +568,21 @@ ['linux', 'nvidia'], bug=621178) # Linux NVIDIA with ANGLE only + self.Fail('conformance/attribs/gl-disabled-vertex-attrib.html', + ['linux', 'nvidia', 'opengl'], bug=483282) + self.Fail('conformance/misc/uninitialized-test.html', + ['linux', 'nvidia', 'opengl'], bug=483282) + self.Fail('conformance/state/state-uneffected-after-compositing.html', + ['linux', 'nvidia', 'opengl'], bug=483282) + self.Fail('conformance/textures/webgl_canvas/' + + 'tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html', + ['linux', 'nvidia', 'opengl'], bug=483282) + self.Fail('conformance/textures/webgl_canvas/' + + 'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html', + ['linux', 'nvidia', 'opengl'], bug=483282) + self.Fail('conformance/textures/webgl_canvas/' + + 'tex-2d-rgb-rgb-unsigned_short_5_6_5.html', + ['linux', 'nvidia', 'opengl'], bug=483282) self.Fail('deqp/functional/gles3/buffercopy.html', ['linux', 'nvidia', 'opengl'], bug=483282) self.Fail('deqp/functional/gles3/bufferobjectquery.html', @@ -550,57 +604,83 @@ self.Fail('conformance2/textures/misc/tex-unpack-params.html', ['linux', 'nvidia', 'opengl'], bug=483282) - # Linux Intel with ANGLE only + # Linux Intel self.Fail('deqp/functional/gles3/pixelbufferobject.html', - ['linux', 'intel', 'opengl'], bug=483282) - self.Fail('deqp/functional/gles3/shaderderivate_*', - ['linux', 'intel', 'opengl'], bug=618408) - - self.Fail('deqp/functional/gles3/fragmentoutput/*.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) + self.Fail('deqp/functional/gles3/shaderderivate_dfdx.html', + ['linux', 'intel'], bug=618408) # The Mesa Intel driver has a scoping bug, see # https://bugs.freedesktop.org/show_bug.cgi?id=95184 + # It has been fixed in Mesa 12.0 self.Fail('deqp/data/gles3/shaders/scoping.html', ['linux', 'intel'], bug=610800) self.Fail('deqp/functional/gles3/framebufferblit/conversion_04.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) self.Fail('deqp/functional/gles3/framebufferblit/conversion_07.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) self.Fail('deqp/functional/gles3/framebufferblit/conversion_08.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) self.Fail('deqp/functional/gles3/framebufferblit/conversion_10.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) self.Fail('deqp/functional/gles3/framebufferblit/conversion_11.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) self.Fail('deqp/functional/gles3/framebufferblit/conversion_12.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) self.Fail('deqp/functional/gles3/framebufferblit/conversion_13.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) self.Fail('deqp/functional/gles3/framebufferblit/conversion_18.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) self.Fail('deqp/functional/gles3/framebufferblit/conversion_25.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) self.Fail('deqp/functional/gles3/framebufferblit/conversion_28.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) self.Fail('deqp/functional/gles3/framebufferblit/conversion_29.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) self.Fail('deqp/functional/gles3/framebufferblit/conversion_30.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) self.Fail('deqp/functional/gles3/framebufferblit/conversion_31.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) self.Fail('deqp/functional/gles3/framebufferblit/conversion_32.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) self.Fail('deqp/functional/gles3/framebufferblit/conversion_33.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) self.Fail('deqp/functional/gles3/framebufferblit/conversion_34.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) self.Fail('deqp/functional/gles3/framebufferblit/' + 'default_framebuffer_00.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) self.Fail('deqp/functional/gles3/framebufferblit/rect_02.html', - ['linux', 'intel', 'opengl'], bug=483282) + ['linux', 'intel'], bug=598902) + + # Linux Intel with ANGLE only + self.Fail('deqp/functional/gles3/fragmentoutput/*.html', + ['linux', 'intel', 'opengl'], bug=598902) + + # Linux Intel without ANGLE only + self.Fail('conformance2/query/occlusion-query.html', + ['linux', 'intel', 'no_angle'], bug=598902) + self.Fail('conformance2/query/query.html', + ['linux', 'intel', 'no_angle'], bug=598902) + self.Fail('conformance2/reading/read-pixels-from-fbo-test.html', + ['linux', 'intel', 'no_angle'], bug=598902) + self.Fail('conformance2/renderbuffers/framebuffer-object-attachment.html', + ['linux', 'intel', 'no_angle'], bug=598902) + self.Fail('deqp/functional/gles3/fbocompleteness.html', + ['linux', 'intel', 'no_angle'], bug=598902) + self.Fail('deqp/functional/gles3/instancedrendering.html', + ['linux', 'intel', 'no_angle'], bug=598902) + self.Fail('deqp/functional/gles3/lifetime.html', + ['linux', 'intel', 'no_angle'], bug=598902) + self.Fail('deqp/functional/gles3/negativefragmentapi.html', + ['linux', 'intel', 'no_angle'], bug=598902) + self.Fail('deqp/functional/gles3/negativestateapi.html', + ['linux', 'intel', 'no_angle'], bug=598902) + self.Fail('deqp/functional/gles3/occlusionquery_conservative.html', + ['linux', 'intel', 'no_angle'], bug=598902) + self.Fail('deqp/functional/gles3/occlusionquery_strict.html', + ['linux', 'intel', 'no_angle'], bug=598902) # Linux AMD only. # It looks like AMD shader compiler rejects many valid ES3 semantics.
diff --git a/content/test/gpu/gpu_tests/webgl_conformance.py b/content/test/gpu/gpu_tests/webgl_conformance.py index dffc795..73af5df 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance.py +++ b/content/test/gpu/gpu_tests/webgl_conformance.py
@@ -329,11 +329,15 @@ i = 0 min_version = None + max_version = None while i < len(line_tokens): token = line_tokens[i] if token == '--min-version': i += 1 min_version = line_tokens[i] + elif token == '--max-version': + i += 1 + max_version = line_tokens[i] i += 1 min_version_to_compare = min_version or folder_min_version @@ -342,6 +346,9 @@ _CompareVersion(version, min_version_to_compare) < 0): continue + if max_version and _CompareVersion(version, max_version) > 0: + continue + if (webgl2_only and not '.txt' in test_name and (not min_version_to_compare or not min_version_to_compare.startswith('2'))):
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index aac19a8..8d26b5fd 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -402,7 +402,7 @@ # This is because webview already has this expectation below self.Fail('conformance/textures/video/' + 'tex-2d-rgb-rgb-unsigned_byte.html', - ['android-content-shell', 'android-chromium', + ['android', 'android-content-shell', 'android-chromium', ('qualcomm', 'Adreno (TM) 430')], bug=611945) self.Fail('conformance/textures/video/' + 'tex-2d-rgb-rgb-unsigned_short_5_6_5.html', @@ -410,15 +410,15 @@ ('qualcomm', 'Adreno (TM) 430')], bug=611945) self.Fail('conformance/textures/video/' + 'tex-2d-rgba-rgba-unsigned_byte.html', - ['android-content-shell', 'android-chromium', + ['android', 'android-content-shell', 'android-chromium', ('qualcomm', 'Adreno (TM) 430')], bug=611945) self.Fail('conformance/textures/video/' + 'tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html', - ['android-content-shell', 'android-chromium', + ['android', 'android-content-shell', 'android-chromium', ('qualcomm', 'Adreno (TM) 430')], bug=611945) self.Fail('conformance/textures/video/' + 'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html', - ['android-content-shell', 'android-chromium', + ['android', 'android-content-shell', 'android-chromium', ('qualcomm', 'Adreno (TM) 430')], bug=611945) self.Fail('conformance/textures/webgl_canvas/' + 'tex-2d-rgb-rgb-unsigned_byte.html', @@ -638,6 +638,22 @@ ['mac', ('amd', 0x6821)], bug=599272) # Linux failures + self.Flaky('conformance/textures/video/' + + 'tex-2d-rgba-rgba-unsigned_byte.html', + ['linux'], bug=627525) + self.Flaky('conformance/textures/video/' + + 'tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html', + ['linux'], bug=627525) + self.Flaky('conformance/textures/video/' + + 'tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html', + ['linux'], bug=627525) + self.Flaky('conformance/textures/video/' + + 'tex-2d-rgb-rgb-unsigned_byte.html', + ['linux'], bug=627525) + self.Flaky('conformance/textures/video/' + + 'tex-2d-rgb-rgb-unsigned_short_5_6_5.html', + ['linux'], bug=627525) + # OpenGL self.Fail('conformance/extensions/oes-texture-half-float.html', ['linux', 'opengl'], bug=607283)
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations_unittest.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations_unittest.py index 43b6f30e..c6f5e5e0 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations_unittest.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations_unittest.py
@@ -143,5 +143,10 @@ conflicts = non_gpu_conflicts and gpu_conflicts if conflicts: - print "WARNING: Found a conflict for", pattern + print "WARNING: Found a conflict for", pattern, " :" + print " ", c1 + print " ", c2 + + print " Type:" + (" (non-gpu)" if non_gpu_conflicts else "") + \ + (" (gpu)" if gpu_conflicts else "") self.assertEquals(conflicts, False)
diff --git a/content/test/test_render_view_host.cc b/content/test/test_render_view_host.cc index 8f9c990..29fc6f7 100644 --- a/content/test/test_render_view_host.cc +++ b/content/test/test_render_view_host.cc
@@ -205,11 +205,11 @@ void TestRenderWidgetHostView::UnlockMouse() { } -uint32_t TestRenderWidgetHostView::GetSurfaceIdNamespace() { +uint32_t TestRenderWidgetHostView::GetSurfaceClientId() { // See constructor. If a test needs this, its harness needs to construct an // ImageTransportFactory. DCHECK(surface_id_allocator_); - return surface_id_allocator_->id_namespace(); + return surface_id_allocator_->client_id(); } TestRenderViewHost::TestRenderViewHost(
diff --git a/content/test/test_render_view_host.h b/content/test/test_render_view_host.h index a21fc48f..082d369 100644 --- a/content/test/test_render_view_host.h +++ b/content/test/test_render_view_host.h
@@ -122,7 +122,7 @@ gfx::Rect GetBoundsInRootWindow() override; bool LockMouse() override; void UnlockMouse() override; - uint32_t GetSurfaceIdNamespace() override; + uint32_t GetSurfaceClientId() override; bool is_showing() const { return is_showing_; } bool is_occluded() const { return is_occluded_; }
diff --git a/courgette/courgette_tool.cc b/courgette/courgette_tool.cc index 83a6834..d0fdb4e 100644 --- a/courgette/courgette_tool.cc +++ b/courgette/courgette_tool.cc
@@ -13,6 +13,7 @@ #include "base/command_line.h" #include "base/files/file_path.h" #include "base/files/file_util.h" +#include "base/files/memory_mapped_file.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -52,16 +53,25 @@ exit(1); } -std::string ReadOrFail(const base::FilePath& file_name, const char* kind) { - int64_t file_size = 0; - if (!base::GetFileSize(file_name, &file_size)) - Problem("Can't read %s file.", kind); - std::string buffer; - buffer.reserve(static_cast<size_t>(file_size)); - if (!base::ReadFileToString(file_name, &buffer)) - Problem("Can't read %s file.", kind); - return buffer; -} +// A file reader that calls Problem() on failure. +class BufferedFileReader { + public: + BufferedFileReader(const base::FilePath& file_name, const char* kind) { + int64_t file_size = 0; + if (!base::GetFileSize(file_name, &file_size)) + Problem("Can't read %s file.", kind); + buffer_.reserve(static_cast<size_t>(file_size)); + if (!base::ReadFileToString(file_name, &buffer_)) + Problem("Can't read %s file.", kind); + } + const uint8_t* data() { + return reinterpret_cast<const uint8_t*>(buffer_.data()); + } + size_t length() { return buffer_.length(); } + + private: + std::string buffer_; +}; void WriteSinkToFile(const courgette::SinkStream *sink, const base::FilePath& output_file) { @@ -77,12 +87,11 @@ void Disassemble(const base::FilePath& input_file, const base::FilePath& output_file) { - std::string buffer = ReadOrFail(input_file, "input"); + BufferedFileReader buffer(input_file, "input"); std::unique_ptr<courgette::AssemblyProgram> program; - const courgette::Status parse_status = - courgette::ParseDetectedExecutable(buffer.c_str(), buffer.length(), - &program); + const courgette::Status parse_status = courgette::ParseDetectedExecutable( + buffer.data(), buffer.length(), &program); if (parse_status != courgette::C_OK) Problem("Can't parse input (code = %d).", parse_status); @@ -111,14 +120,12 @@ bool Supported(const base::FilePath& input_file) { bool result = false; - std::string buffer = ReadOrFail(input_file, "input"); + BufferedFileReader buffer(input_file, "input"); courgette::ExecutableType type; size_t detected_length; - DetectExecutableType(buffer.c_str(), buffer.length(), - &type, - &detected_length); + DetectExecutableType(buffer.data(), buffer.length(), &type, &detected_length); // If the detection fails, we just fall back on UNKNOWN std::string format = "Unsupported"; @@ -156,22 +163,20 @@ void DisassembleAndAdjust(const base::FilePath& program_file, const base::FilePath& model_file, const base::FilePath& output_file) { - std::string program_buffer = ReadOrFail(program_file, "program"); - std::string model_buffer = ReadOrFail(model_file, "reference"); + BufferedFileReader program_buffer(program_file, "program"); + BufferedFileReader model_buffer(model_file, "model"); std::unique_ptr<courgette::AssemblyProgram> program; const courgette::Status parse_program_status = - courgette::ParseDetectedExecutable(program_buffer.c_str(), - program_buffer.length(), - &program); + courgette::ParseDetectedExecutable(program_buffer.data(), + program_buffer.length(), &program); if (parse_program_status != courgette::C_OK) Problem("Can't parse program input (code = %d).", parse_program_status); std::unique_ptr<courgette::AssemblyProgram> model; const courgette::Status parse_model_status = - courgette::ParseDetectedExecutable(model_buffer.c_str(), - model_buffer.length(), - &model); + courgette::ParseDetectedExecutable(model_buffer.data(), + model_buffer.length(), &model); if (parse_model_status != courgette::C_OK) Problem("Can't parse model input (code = %d).", parse_model_status); @@ -212,22 +217,20 @@ const base::FilePath& program_file, const base::FilePath& output_file_root, bool adjust) { - std::string model_buffer = ReadOrFail(model_file, "'old'"); - std::string program_buffer = ReadOrFail(program_file, "'new'"); + BufferedFileReader model_buffer(model_file, "old"); + BufferedFileReader program_buffer(program_file, "new"); std::unique_ptr<courgette::AssemblyProgram> model; const courgette::Status parse_model_status = - courgette::ParseDetectedExecutable(model_buffer.c_str(), - model_buffer.length(), - &model); + courgette::ParseDetectedExecutable(model_buffer.data(), + model_buffer.length(), &model); if (parse_model_status != courgette::C_OK) Problem("Can't parse model input (code = %d).", parse_model_status); std::unique_ptr<courgette::AssemblyProgram> program; const courgette::Status parse_program_status = - courgette::ParseDetectedExecutable(program_buffer.c_str(), - program_buffer.length(), - &program); + courgette::ParseDetectedExecutable(program_buffer.data(), + program_buffer.length(), &program); if (parse_program_status != courgette::C_OK) Problem("Can't parse program input (code = %d).", parse_program_status); @@ -293,10 +296,10 @@ void Assemble(const base::FilePath& input_file, const base::FilePath& output_file) { - std::string buffer = ReadOrFail(input_file, "input"); + BufferedFileReader buffer(input_file, "input"); courgette::SourceStreamSet sources; - if (!sources.Init(buffer.c_str(), buffer.length())) + if (!sources.Init(buffer.data(), buffer.length())) Problem("Bad input file."); std::unique_ptr<courgette::EncodedProgram> encoded; @@ -318,13 +321,13 @@ void GenerateEnsemblePatch(const base::FilePath& old_file, const base::FilePath& new_file, const base::FilePath& patch_file) { - std::string old_buffer = ReadOrFail(old_file, "'old' input"); - std::string new_buffer = ReadOrFail(new_file, "'new' input"); + BufferedFileReader old_buffer(old_file, "'old' input"); + BufferedFileReader new_buffer(new_file, "'new' input"); courgette::SourceStream old_stream; courgette::SourceStream new_stream; - old_stream.Init(old_buffer); - new_stream.Init(new_buffer); + old_stream.Init(old_buffer.data(), old_buffer.length()); + new_stream.Init(new_buffer.data(), new_buffer.length()); courgette::SinkStream patch_stream; courgette::Status status = @@ -376,12 +379,9 @@ break; } - // If we failed due to a missing input file, this will - // print the message. - std::string old_buffer = ReadOrFail(old_file, "'old' input"); - old_buffer.clear(); - std::string patch_buffer = ReadOrFail(patch_file, "'patch' input"); - patch_buffer.clear(); + // If we failed due to a missing input file, this will print the message. + { BufferedFileReader old_buffer(old_file, "'old' input"); } + { BufferedFileReader patch_buffer(patch_file, "'patch' input"); } // Non-input related errors: if (status == courgette::C_WRITE_OPEN_ERROR) @@ -395,13 +395,13 @@ void GenerateBSDiffPatch(const base::FilePath& old_file, const base::FilePath& new_file, const base::FilePath& patch_file) { - std::string old_buffer = ReadOrFail(old_file, "'old' input"); - std::string new_buffer = ReadOrFail(new_file, "'new' input"); + BufferedFileReader old_buffer(old_file, "'old' input"); + BufferedFileReader new_buffer(new_file, "'new' input"); courgette::SourceStream old_stream; courgette::SourceStream new_stream; - old_stream.Init(old_buffer); - new_stream.Init(new_buffer); + old_stream.Init(old_buffer.data(), old_buffer.length()); + new_stream.Init(new_buffer.data(), new_buffer.length()); courgette::SinkStream patch_stream; courgette::BSDiffStatus status = @@ -415,13 +415,13 @@ void ApplyBSDiffPatch(const base::FilePath& old_file, const base::FilePath& patch_file, const base::FilePath& new_file) { - std::string old_buffer = ReadOrFail(old_file, "'old' input"); - std::string patch_buffer = ReadOrFail(patch_file, "'patch' input"); + BufferedFileReader old_buffer(old_file, "'old' input"); + BufferedFileReader patch_buffer(patch_file, "'patch' input"); courgette::SourceStream old_stream; courgette::SourceStream patch_stream; - old_stream.Init(old_buffer); - patch_stream.Init(patch_buffer); + old_stream.Init(old_buffer.data(), old_buffer.length()); + patch_stream.Init(patch_buffer.data(), patch_buffer.length()); courgette::SinkStream new_stream; courgette::BSDiffStatus status =
diff --git a/courgette/encode_decode_unittest.cc b/courgette/encode_decode_unittest.cc index cec0bfa9..6e88ee3 100644 --- a/courgette/encode_decode_unittest.cc +++ b/courgette/encode_decode_unittest.cc
@@ -15,21 +15,20 @@ class EncodeDecodeTest : public BaseTest { public: - void TestAssembleToStreamDisassemble(std::string file, + void TestAssembleToStreamDisassemble(const std::string& file, size_t expected_encoded_length) const; }; void EncodeDecodeTest::TestAssembleToStreamDisassemble( - std::string file, + const std::string& file, size_t expected_encoded_length) const { - const void* original_buffer = file.c_str(); + const uint8_t* original_buffer = + reinterpret_cast<const uint8_t*>(file.data()); size_t original_length = file.length(); std::unique_ptr<courgette::AssemblyProgram> program; - const courgette::Status parse_status = - courgette::ParseDetectedExecutable(original_buffer, - original_length, - &program); + const courgette::Status parse_status = courgette::ParseDetectedExecutable( + original_buffer, original_length, &program); EXPECT_EQ(courgette::C_OK, parse_status); std::unique_ptr<courgette::EncodedProgram> encoded;
diff --git a/courgette/encoded_program_fuzz_unittest.cc b/courgette/encoded_program_fuzz_unittest.cc index 1bf7ff2..be32adf 100644 --- a/courgette/encoded_program_fuzz_unittest.cc +++ b/courgette/encoded_program_fuzz_unittest.cc
@@ -41,7 +41,8 @@ void DecodeFuzzTest::FuzzExe(const char* file_name) const { std::string file1 = FileContents(file_name); - const void* original_buffer = file1.c_str(); + const uint8_t* original_buffer = + reinterpret_cast<const uint8_t*>(file1.data()); size_t original_length = file1.length(); std::unique_ptr<courgette::AssemblyProgram> program;
diff --git a/courgette/program_detector.h b/courgette/program_detector.h index 62f4dc9..75e81a9 100644 --- a/courgette/program_detector.h +++ b/courgette/program_detector.h
@@ -29,16 +29,6 @@ ExecutableType* type, size_t* detected_length); -// Same as above, takes void* instead. -// TODO(etiennep): Propagate "const uint8_t*" upwards. -inline Status DetectExecutableType(const void* buffer, - size_t length, - ExecutableType* type, - size_t* detected_length) { - return DetectExecutableType(reinterpret_cast<const uint8_t*>(buffer), length, - type, detected_length); -} - // Attempts to detect the type of executable, and parse it with the appropriate // tools. // On success: @@ -50,16 +40,6 @@ size_t length, std::unique_ptr<AssemblyProgram>* output); -// Same as above, takes void* instead. -// TODO(etiennep): Propagate "const uint8_t*" upwards. -inline Status ParseDetectedExecutable( - const void* buffer, - size_t length, - std::unique_ptr<AssemblyProgram>* output) { - return ParseDetectedExecutable(reinterpret_cast<const uint8_t*>(buffer), - length, output); -} - } // namespace courgette #endif // COURGETTE_PROGRAM_DETECTOR_H_
diff --git a/courgette/program_detector_unittest.cc b/courgette/program_detector_unittest.cc index d78f72ec..82c6fdb 100644 --- a/courgette/program_detector_unittest.cc +++ b/courgette/program_detector_unittest.cc
@@ -52,8 +52,8 @@ ExecutableType expected_type) const { ExecutableType detected_type = EXE_UNKNOWN; size_t detected_length = 0; - DetectExecutableType(test_data.data(), test_data.size(), &detected_type, - &detected_length); + DetectExecutableType(reinterpret_cast<const uint8_t*>(test_data.data()), + test_data.size(), &detected_type, &detected_length); EXPECT_EQ(expected_type, detected_type); EXPECT_EQ(test_data.size(), detected_length); }
diff --git a/crypto/ec_private_key.cc b/crypto/ec_private_key.cc index 8f3c411..a8005bc 100644 --- a/crypto/ec_private_key.cc +++ b/crypto/ec_private_key.cc
@@ -146,8 +146,10 @@ std::unique_ptr<ECPrivateKey> ECPrivateKey::Copy() const { std::unique_ptr<ECPrivateKey> copy(new ECPrivateKey()); - if (key_) - copy->key_ = EVP_PKEY_up_ref(key_); + if (key_) { + EVP_PKEY_up_ref(key_); + copy->key_ = key_; + } return copy; }
diff --git a/crypto/rsa_private_key.cc b/crypto/rsa_private_key.cc index 746bf28..3c00f48 100644 --- a/crypto/rsa_private_key.cc +++ b/crypto/rsa_private_key.cc
@@ -62,7 +62,8 @@ if (EVP_PKEY_type(key->type) != EVP_PKEY_RSA) return nullptr; std::unique_ptr<RSAPrivateKey> copy(new RSAPrivateKey); - copy->key_ = EVP_PKEY_up_ref(key); + EVP_PKEY_up_ref(key); + copy->key_ = key; return copy; }
diff --git a/device/bluetooth/bluetooth_uuid.cc b/device/bluetooth/bluetooth_uuid.cc index 071493a..b35094d 100644 --- a/device/bluetooth/bluetooth_uuid.cc +++ b/device/bluetooth/bluetooth_uuid.cc
@@ -13,8 +13,8 @@ namespace { -const char* kCommonUuidPostfix = "-0000-1000-8000-00805f9b34fb"; -const char* kCommonUuidPrefix = "0000"; +const char kCommonUuidPostfix[] = "-0000-1000-8000-00805f9b34fb"; +const char kCommonUuidPrefix[] = "0000"; // Returns the canonical, 128-bit canonical, and the format of the UUID // in |canonical|, |canonical_128|, and |format| based on |uuid|. @@ -30,8 +30,10 @@ if (uuid.empty()) return; - if (uuid.size() < 11 && uuid.find("0x") == 0) + if (uuid.size() < 11 && + base::StartsWith(uuid, "0x", base::CompareCase::SENSITIVE)) { uuid = uuid.substr(2); + } if (!(uuid.size() == 4 || uuid.size() == 8 || uuid.size() == 36)) return;
diff --git a/device/bluetooth/public/interfaces/bluetooth_uuid_struct_traits.h b/device/bluetooth/public/interfaces/bluetooth_uuid_struct_traits.h index 371a840..439f127 100644 --- a/device/bluetooth/public/interfaces/bluetooth_uuid_struct_traits.h +++ b/device/bluetooth/public/interfaces/bluetooth_uuid_struct_traits.h
@@ -7,42 +7,30 @@ #include <string> -#include "base/optional.h" -#include "base/strings/string_piece.h" #include "device/bluetooth/bluetooth_uuid.h" #include "device/bluetooth/public/interfaces/bluetooth_uuid.mojom.h" namespace mojo { template <> -struct StructTraits<device::mojom::BluetoothUUID, - base::Optional<device::BluetoothUUID>> { - static bool IsNull(const base::Optional<device::BluetoothUUID>& uuid) { - return !uuid; - } - - static void SetToNull(base::Optional<device::BluetoothUUID>* output) { - *output = base::nullopt; - } - - static std::string uuid(const base::Optional<device::BluetoothUUID>& uuid) { - DCHECK(uuid); - return uuid->canonical_value(); +struct StructTraits<device::mojom::BluetoothUUID, device::BluetoothUUID> { + static const std::string& uuid(const device::BluetoothUUID& uuid) { + return uuid.canonical_value(); } static bool Read(device::mojom::BluetoothUUIDDataView input, - base::Optional<device::BluetoothUUID>* output) { + device::BluetoothUUID* output) { std::string result; if (!input.ReadUuid(&result)) return false; - *output = base::make_optional(device::BluetoothUUID(result)); + *output = device::BluetoothUUID(result); // If the format isn't 128-bit, .value() would return a different answer // than .canonical_value(). Then if browser-side code accidentally checks // .value() against a 128-bit string literal, a hostile renderer could use // the 16- or 32-bit format and evade the check. - return output->value().IsValid() && - output->value().format() == device::BluetoothUUID::kFormat128Bit; + return output->IsValid() && + output->format() == device::BluetoothUUID::kFormat128Bit; } };
diff --git a/device/gamepad/gamepad_data_fetcher.h b/device/gamepad/gamepad_data_fetcher.h index 28b3949a..d071a25 100644 --- a/device/gamepad/gamepad_data_fetcher.h +++ b/device/gamepad/gamepad_data_fetcher.h
@@ -10,6 +10,7 @@ #include <limits> #include "build/build_config.h" +#include "device/gamepad/gamepad_export.h" #include "device/gamepad/gamepad_standard_mappings.h" #include "third_party/WebKit/public/platform/WebGamepads.h" @@ -17,7 +18,7 @@ // Abstract interface for imlementing platform- (and test-) specific behaviro // for getting the gamepad data. -class GamepadDataFetcher { +class DEVICE_GAMEPAD_EXPORT GamepadDataFetcher { public: virtual ~GamepadDataFetcher() {} virtual void GetGamepadData(blink::WebGamepads* pads,
diff --git a/device/gamepad/gamepad_platform_data_fetcher_linux.h b/device/gamepad/gamepad_platform_data_fetcher_linux.h index 39907c9..a3160f0b2 100644 --- a/device/gamepad/gamepad_platform_data_fetcher_linux.h +++ b/device/gamepad/gamepad_platform_data_fetcher_linux.h
@@ -24,7 +24,8 @@ namespace device { -class GamepadPlatformDataFetcherLinux : public GamepadDataFetcher { +class DEVICE_GAMEPAD_EXPORT GamepadPlatformDataFetcherLinux + : public GamepadDataFetcher { public: GamepadPlatformDataFetcherLinux(); ~GamepadPlatformDataFetcherLinux() override;
diff --git a/extensions/DEPS b/extensions/DEPS index 52dbb3f..0765359a 100644 --- a/extensions/DEPS +++ b/extensions/DEPS
@@ -5,6 +5,7 @@ "+components/guest_view", "+components/prefs", "+components/url_matcher", + "+components/version_info", "-content", "+content/grit/content_resources.h", "+content/public/common",
diff --git a/extensions/browser/api/alarms/alarm_manager.cc b/extensions/browser/api/alarms/alarm_manager.cc index 9d1493abd..626c4ce6 100644 --- a/extensions/browser/api/alarms/alarm_manager.cc +++ b/extensions/browser/api/alarms/alarm_manager.cc
@@ -258,7 +258,7 @@ void AlarmManager::OnAlarm(AlarmIterator it) { CHECK(it.first != alarms_.end()); - Alarm& alarm = *it.second->get(); + Alarm& alarm = **it.second; std::string extension_id_copy(it.first->first); delegate_->OnAlarm(extension_id_copy, alarm);
diff --git a/extensions/browser/api/app_window/app_window_api.cc b/extensions/browser/api/app_window/app_window_api.cc index 05650e92..096f050 100644 --- a/extensions/browser/api/app_window/app_window_api.cc +++ b/extensions/browser/api/app_window/app_window_api.cc
@@ -187,8 +187,8 @@ frame_id = existing_frame->GetRoutingID(); } - if (!options->hidden.get() || !*options->hidden.get()) { - if (options->focused.get() && !*options->focused.get()) + if (!options->hidden.get() || !*options->hidden) { + if (options->focused.get() && !*options->focused) existing_window->Show(AppWindow::SHOW_INACTIVE); else existing_window->Show(AppWindow::SHOW_ACTIVE); @@ -297,13 +297,13 @@ } if (options->hidden.get()) - create_params.hidden = *options->hidden.get(); + create_params.hidden = *options->hidden; if (options->resizable.get()) - create_params.resizable = *options->resizable.get(); + create_params.resizable = *options->resizable; if (options->always_on_top.get()) { - create_params.always_on_top = *options->always_on_top.get(); + create_params.always_on_top = *options->always_on_top; if (create_params.always_on_top && !extension()->permissions_data()->HasAPIPermission( @@ -314,11 +314,11 @@ } if (options->focused.get()) - create_params.focused = *options->focused.get(); + create_params.focused = *options->focused; if (options->visible_on_all_workspaces.get()) { create_params.visible_on_all_workspaces = - *options->visible_on_all_workspaces.get(); + *options->visible_on_all_workspaces; } if (options->type != app_window::WINDOW_TYPE_PANEL) { @@ -455,33 +455,33 @@ // This will be preserved as apps may be relying on this behavior. if (options.default_width.get()) - params->content_spec.bounds.set_width(*options.default_width.get()); + params->content_spec.bounds.set_width(*options.default_width); if (options.default_height.get()) - params->content_spec.bounds.set_height(*options.default_height.get()); + params->content_spec.bounds.set_height(*options.default_height); if (options.default_left.get()) - params->window_spec.bounds.set_x(*options.default_left.get()); + params->window_spec.bounds.set_x(*options.default_left); if (options.default_top.get()) - params->window_spec.bounds.set_y(*options.default_top.get()); + params->window_spec.bounds.set_y(*options.default_top); if (options.width.get()) - params->content_spec.bounds.set_width(*options.width.get()); + params->content_spec.bounds.set_width(*options.width); if (options.height.get()) - params->content_spec.bounds.set_height(*options.height.get()); + params->content_spec.bounds.set_height(*options.height); if (options.left.get()) - params->window_spec.bounds.set_x(*options.left.get()); + params->window_spec.bounds.set_x(*options.left); if (options.top.get()) - params->window_spec.bounds.set_y(*options.top.get()); + params->window_spec.bounds.set_y(*options.top); if (options.bounds.get()) { app_window::ContentBounds* bounds = options.bounds.get(); if (bounds->width.get()) - params->content_spec.bounds.set_width(*bounds->width.get()); + params->content_spec.bounds.set_width(*bounds->width); if (bounds->height.get()) - params->content_spec.bounds.set_height(*bounds->height.get()); + params->content_spec.bounds.set_height(*bounds->height); if (bounds->left.get()) - params->window_spec.bounds.set_x(*bounds->left.get()); + params->window_spec.bounds.set_x(*bounds->left); if (bounds->top.get()) - params->window_spec.bounds.set_y(*bounds->top.get()); + params->window_spec.bounds.set_y(*bounds->top); } gfx::Size& minimum_size = params->content_spec.minimum_size;
diff --git a/extensions/browser/api/app_window/app_window_apitest.cc b/extensions/browser/api/app_window/app_window_apitest.cc index d8215a8..63ac734 100644 --- a/extensions/browser/api/app_window/app_window_apitest.cc +++ b/extensions/browser/api/app_window/app_window_apitest.cc
@@ -9,12 +9,12 @@ #include "chrome/browser/apps/app_browsertest_util.h" #include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/extensions/features/feature_channel.h" #include "chrome/test/base/testing_profile.h" #include "components/version_info/version_info.h" #include "extensions/browser/app_window/app_window.h" #include "extensions/browser/app_window/app_window_registry.h" #include "extensions/browser/app_window/native_app_window.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/test/extension_test_message_listener.h" #include "ui/base/base_window.h" #include "ui/gfx/geometry/rect.h"
diff --git a/extensions/browser/api/bluetooth/bluetooth_api.cc b/extensions/browser/api/bluetooth/bluetooth_api.cc index 3580c88..35fc145 100644 --- a/extensions/browser/api/bluetooth/bluetooth_api.cc +++ b/extensions/browser/api/bluetooth/bluetooth_api.cc
@@ -105,7 +105,7 @@ bool BluetoothGetAdapterStateFunction::DoWork( scoped_refptr<BluetoothAdapter> adapter) { bluetooth::AdapterState state; - PopulateAdapterState(*adapter.get(), &state); + PopulateAdapterState(*adapter, &state); results_ = bluetooth::GetAdapterState::Results::Create(state); SendResponse(true); return true;
diff --git a/extensions/browser/api/bluetooth/bluetooth_apitest.cc b/extensions/browser/api/bluetooth/bluetooth_apitest.cc index ff93bdf..43ffddb4 100644 --- a/extensions/browser/api/bluetooth/bluetooth_apitest.cc +++ b/extensions/browser/api/bluetooth/bluetooth_apitest.cc
@@ -155,9 +155,9 @@ event_router()->DeviceAdded(mock_adapter_, device1_.get()); event_router()->DeviceAdded(mock_adapter_, device2_.get()); - EXPECT_CALL(*device2_.get(), GetDeviceName()) - .WillRepeatedly(testing::Return("the real d2")); - EXPECT_CALL(*device2_.get(), GetNameForDisplay()) + EXPECT_CALL(*device2_, GetDeviceName()) + .WillRepeatedly(testing::Return("the real d2")); + EXPECT_CALL(*device2_, GetNameForDisplay()) .WillRepeatedly(testing::Return(base::UTF8ToUTF16("the real d2"))); event_router()->DeviceChanged(mock_adapter_, device2_.get()); @@ -410,31 +410,28 @@ // Set up the first device object to reflect a real-world device. BluetoothAdapter::ConstDeviceList devices; - EXPECT_CALL(*device1_.get(), GetAddress()) - .WillRepeatedly(testing::Return("A4:17:31:00:00:00")); - EXPECT_CALL(*device1_.get(), GetDeviceName()) - .WillRepeatedly(testing::Return("Chromebook Pixel")); - EXPECT_CALL(*device1_.get(), GetNameForDisplay()) + EXPECT_CALL(*device1_, GetAddress()) + .WillRepeatedly(testing::Return("A4:17:31:00:00:00")); + EXPECT_CALL(*device1_, GetDeviceName()) + .WillRepeatedly(testing::Return("Chromebook Pixel")); + EXPECT_CALL(*device1_, GetNameForDisplay()) .WillRepeatedly(testing::Return(base::UTF8ToUTF16("Chromebook Pixel"))); - EXPECT_CALL(*device1_.get(), GetBluetoothClass()) - .WillRepeatedly(testing::Return(0x080104)); - EXPECT_CALL(*device1_.get(), GetDeviceType()) - .WillRepeatedly(testing::Return(BluetoothDevice::DEVICE_COMPUTER)); - EXPECT_CALL(*device1_.get(), GetVendorIDSource()) - .WillRepeatedly(testing::Return(BluetoothDevice::VENDOR_ID_BLUETOOTH)); - EXPECT_CALL(*device1_.get(), GetVendorID()) - .WillRepeatedly(testing::Return(0x00E0)); - EXPECT_CALL(*device1_.get(), GetProductID()) - .WillRepeatedly(testing::Return(0x240A)); - EXPECT_CALL(*device1_.get(), GetDeviceID()) - .WillRepeatedly(testing::Return(0x0400)); + EXPECT_CALL(*device1_, GetBluetoothClass()) + .WillRepeatedly(testing::Return(0x080104)); + EXPECT_CALL(*device1_, GetDeviceType()) + .WillRepeatedly(testing::Return(BluetoothDevice::DEVICE_COMPUTER)); + EXPECT_CALL(*device1_, GetVendorIDSource()) + .WillRepeatedly(testing::Return(BluetoothDevice::VENDOR_ID_BLUETOOTH)); + EXPECT_CALL(*device1_, GetVendorID()).WillRepeatedly(testing::Return(0x00E0)); + EXPECT_CALL(*device1_, GetProductID()) + .WillRepeatedly(testing::Return(0x240A)); + EXPECT_CALL(*device1_, GetDeviceID()).WillRepeatedly(testing::Return(0x0400)); BluetoothDevice::UUIDList uuids; uuids.push_back(BluetoothUUID("1105")); uuids.push_back(BluetoothUUID("1106")); - EXPECT_CALL(*device1_.get(), GetUUIDs()) - .WillOnce(testing::Return(uuids)); + EXPECT_CALL(*device1_, GetUUIDs()).WillOnce(testing::Return(uuids)); devices.push_back(device1_.get());
diff --git a/extensions/browser/api/bluetooth/bluetooth_event_router.cc b/extensions/browser/api/bluetooth/bluetooth_event_router.cc index bd73e79..39300a7 100644 --- a/extensions/browser/api/bluetooth/bluetooth_event_router.cc +++ b/extensions/browser/api/bluetooth/bluetooth_event_router.cc
@@ -375,7 +375,7 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); api::bluetooth::AdapterState state; CHECK(adapter_.get()); - PopulateAdapterState(*adapter_.get(), &state); + PopulateAdapterState(*adapter_, &state); std::unique_ptr<base::ListValue> args = bluetooth::OnAdapterStateChanged::Create(state);
diff --git a/extensions/browser/api/bluetooth/bluetooth_private_api.cc b/extensions/browser/api/bluetooth/bluetooth_private_api.cc index 0ba6c01e..86fc88c 100644 --- a/extensions/browser/api/bluetooth/bluetooth_private_api.cc +++ b/extensions/browser/api/bluetooth/bluetooth_private_api.cc
@@ -102,8 +102,8 @@ const device::BluetoothDevice* device, const bt_private::SetPairingResponseOptions& options) { bool response = options.response != bt_private::PAIRING_RESPONSE_NONE; - bool pincode = options.pincode.get() != nullptr; - bool passkey = options.passkey.get() != nullptr; + bool pincode = options.pincode != nullptr; + bool passkey = options.passkey != nullptr; if (!response && !pincode && !passkey) return false; @@ -280,9 +280,9 @@ } if (options.pincode.get()) { - device->SetPinCode(*options.pincode.get()); + device->SetPinCode(*options.pincode); } else if (options.passkey.get()) { - device->SetPasskey(*options.passkey.get()); + device->SetPasskey(*options.passkey); } else { switch (options.response) { case bt_private::PAIRING_RESPONSE_CONFIRM:
diff --git a/extensions/browser/api/bluetooth/bluetooth_private_apitest.cc b/extensions/browser/api/bluetooth/bluetooth_private_apitest.cc index f0bab09..9264e836 100644 --- a/extensions/browser/api/bluetooth/bluetooth_private_apitest.cc +++ b/extensions/browser/api/bluetooth/bluetooth_private_apitest.cc
@@ -67,9 +67,9 @@ event_router()->SetAdapterForTest(mock_adapter_.get()); mock_device_.reset(new NiceMock<MockBluetoothDevice>( mock_adapter_.get(), 0, kDeviceName, kDeviceAddress, false, false)); - ON_CALL(*mock_adapter_.get(), GetDevice(kDeviceAddress)) + ON_CALL(*mock_adapter_, GetDevice(kDeviceAddress)) .WillByDefault(Return(mock_device_.get())); - ON_CALL(*mock_adapter_.get(), IsPresent()).WillByDefault(Return(true)); + ON_CALL(*mock_adapter_, IsPresent()).WillByDefault(Return(true)); } void TearDownOnMainThread() override {} @@ -160,33 +160,36 @@ } IN_PROC_BROWSER_TEST_F(BluetoothPrivateApiTest, SetAdapterState) { - ON_CALL(*mock_adapter_.get(), GetName()) + ON_CALL(*mock_adapter_, GetName()) .WillByDefault(ReturnPointee(&adapter_name_)); - ON_CALL(*mock_adapter_.get(), IsPowered()) + ON_CALL(*mock_adapter_, IsPowered()) .WillByDefault(ReturnPointee(&adapter_powered_)); - ON_CALL(*mock_adapter_.get(), IsDiscoverable()) + ON_CALL(*mock_adapter_, IsDiscoverable()) .WillByDefault(ReturnPointee(&adapter_discoverable_)); - EXPECT_CALL(*mock_adapter_.get(), SetName("Dome", _, _)).WillOnce( - WithArgs<0, 1>(Invoke(this, &BluetoothPrivateApiTest::SetName))); - EXPECT_CALL(*mock_adapter_.get(), SetPowered(true, _, _)).WillOnce( - WithArgs<0, 1>(Invoke(this, &BluetoothPrivateApiTest::SetPowered))); - EXPECT_CALL(*mock_adapter_.get(), SetDiscoverable(true, _, _)).WillOnce( - WithArgs<0, 1>(Invoke(this, &BluetoothPrivateApiTest::SetDiscoverable))); + EXPECT_CALL(*mock_adapter_, SetName("Dome", _, _)) + .WillOnce( + WithArgs<0, 1>(Invoke(this, &BluetoothPrivateApiTest::SetName))); + EXPECT_CALL(*mock_adapter_, SetPowered(true, _, _)) + .WillOnce( + WithArgs<0, 1>(Invoke(this, &BluetoothPrivateApiTest::SetPowered))); + EXPECT_CALL(*mock_adapter_, SetDiscoverable(true, _, _)) + .WillOnce(WithArgs<0, 1>( + Invoke(this, &BluetoothPrivateApiTest::SetDiscoverable))); ASSERT_TRUE(RunComponentExtensionTest("bluetooth_private/adapter_state")) << message_; } IN_PROC_BROWSER_TEST_F(BluetoothPrivateApiTest, NoBluetoothAdapter) { - ON_CALL(*mock_adapter_.get(), IsPresent()).WillByDefault(Return(false)); + ON_CALL(*mock_adapter_, IsPresent()).WillByDefault(Return(false)); ASSERT_TRUE(RunComponentExtensionTest("bluetooth_private/no_adapter")) << message_; } IN_PROC_BROWSER_TEST_F(BluetoothPrivateApiTest, CancelPairing) { InSequence s; - EXPECT_CALL(*mock_adapter_.get(), + EXPECT_CALL(*mock_adapter_, AddPairingDelegate( _, device::BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH)) .WillOnce(WithoutArgs(Invoke( @@ -199,7 +202,7 @@ } IN_PROC_BROWSER_TEST_F(BluetoothPrivateApiTest, PincodePairing) { - EXPECT_CALL(*mock_adapter_.get(), + EXPECT_CALL(*mock_adapter_, AddPairingDelegate( _, device::BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH)) .WillOnce(WithoutArgs( @@ -211,7 +214,7 @@ } IN_PROC_BROWSER_TEST_F(BluetoothPrivateApiTest, PasskeyPairing) { - EXPECT_CALL(*mock_adapter_.get(), + EXPECT_CALL(*mock_adapter_, AddPairingDelegate( _, device::BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH)) .WillOnce(WithoutArgs( @@ -241,7 +244,7 @@ // Device::Forget not implemented on OSX. #if !defined(OS_MACOSX) IN_PROC_BROWSER_TEST_F(BluetoothPrivateApiTest, ForgetDevice) { - EXPECT_CALL(*mock_device_.get(), Forget(_, _)) + EXPECT_CALL(*mock_device_, Forget(_, _)) .WillOnce( WithArgs<0>(Invoke(this, &BluetoothPrivateApiTest::ForgetDevice))); ASSERT_TRUE(RunComponentExtensionTest("bluetooth_private/forget_device")) @@ -258,8 +261,8 @@ discovery_filter.AddUUID( BluetoothUUID("0000bebe-0000-1000-8000-00805f9b34fb")); - EXPECT_CALL(*mock_adapter_.get(), StartDiscoverySessionWithFilterRaw( - IsFilterEqual(&discovery_filter), _, _)) + EXPECT_CALL(*mock_adapter_, StartDiscoverySessionWithFilterRaw( + IsFilterEqual(&discovery_filter), _, _)) .Times(1) .WillOnce(WithArgs<1>(Invoke( this, &BluetoothPrivateApiTest::CallSetDiscoveryFilterCallback))); @@ -275,23 +278,23 @@ } IN_PROC_BROWSER_TEST_F(BluetoothPrivateApiTest, Connect) { - EXPECT_CALL(*mock_device_.get(), IsConnected()) + EXPECT_CALL(*mock_device_, IsConnected()) .Times(2) .WillOnce(Return(false)) .WillOnce(Return(true)); - EXPECT_CALL(*mock_device_.get(), Connect(_, _, _)) + EXPECT_CALL(*mock_device_, Connect(_, _, _)) .WillOnce(InvokeCallbackArgument<1>()); ASSERT_TRUE(RunComponentExtensionTest("bluetooth_private/connect")) << message_; } IN_PROC_BROWSER_TEST_F(BluetoothPrivateApiTest, Pair) { - EXPECT_CALL(*mock_adapter_.get(), + EXPECT_CALL(*mock_adapter_, AddPairingDelegate( _, device::BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH)); EXPECT_CALL(*mock_device_, ExpectingConfirmation()) .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_device_.get(), Pair(_, _, _)) + EXPECT_CALL(*mock_device_, Pair(_, _, _)) .WillOnce(DoAll( WithoutArgs(Invoke( this,
diff --git a/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc b/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc index cd3bd1c4..1aa75322 100644 --- a/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc +++ b/extensions/browser/api/bluetooth_socket/bluetooth_socket_api.cc
@@ -62,15 +62,15 @@ void SetSocketProperties(BluetoothApiSocket* socket, SocketProperties* properties) { if (properties->name.get()) { - socket->set_name(*properties->name.get()); + socket->set_name(*properties->name); } if (properties->persistent.get()) { - socket->set_persistent(*properties->persistent.get()); + socket->set_persistent(*properties->persistent); } if (properties->buffer_size.get()) { // buffer size is validated when issuing the actual Recv operation // on the socket. - socket->set_buffer_size(*properties->buffer_size.get()); + socket->set_buffer_size(*properties->buffer_size); } } @@ -195,8 +195,7 @@ BluetoothApiSocket* socket = new BluetoothApiSocket(extension_id()); - bluetooth_socket::SocketProperties* properties = - params_.get()->properties.get(); + bluetooth_socket::SocketProperties* properties = params_->properties.get(); if (properties) { SetSocketProperties(socket, properties); } @@ -224,7 +223,7 @@ return; } - SetSocketProperties(socket, ¶ms_.get()->properties); + SetSocketProperties(socket, ¶ms_->properties); results_ = bluetooth_socket::Update::Results::Create(); }
diff --git a/extensions/browser/api/bluetooth_socket/bluetooth_socket_apitest.cc b/extensions/browser/api/bluetooth_socket/bluetooth_socket_apitest.cc index 1462ed4..1793113a 100644 --- a/extensions/browser/api/bluetooth_socket/bluetooth_socket_apitest.cc +++ b/extensions/browser/api/bluetooth_socket/bluetooth_socket_apitest.cc
@@ -103,9 +103,9 @@ // Return the right mock device object for the address used by the test, // return NULL for the "Device not found" test. - EXPECT_CALL(*mock_adapter_.get(), GetDevice(mock_device1_->GetAddress())) + EXPECT_CALL(*mock_adapter_, GetDevice(mock_device1_->GetAddress())) .WillRepeatedly(testing::Return(mock_device1_.get())); - EXPECT_CALL(*mock_adapter_.get(), GetDevice(std::string("aa:aa:aa:aa:aa:aa"))) + EXPECT_CALL(*mock_adapter_, GetDevice(std::string("aa:aa:aa:aa:aa:aa"))) .WillOnce(testing::Return(static_cast<BluetoothDevice*>(NULL))); // Return a mock socket object as a successful result to the connect() call. @@ -118,12 +118,12 @@ // Since the socket is unpaused, expect a call to Receive() from the socket // dispatcher. Since there is no data, this will not call its callback. - EXPECT_CALL(*mock_socket.get(), Receive(testing::_, testing::_, testing::_)); + EXPECT_CALL(*mock_socket, Receive(testing::_, testing::_, testing::_)); // The test also cleans up by calling Disconnect and Close. - EXPECT_CALL(*mock_socket.get(), Disconnect(testing::_)) + EXPECT_CALL(*mock_socket, Disconnect(testing::_)) .WillOnce(InvokeCallbackArgument<0>()); - EXPECT_CALL(*mock_socket.get(), Close()); + EXPECT_CALL(*mock_socket, Close()); // Run the test. ExtensionTestMessageListener listener("ready", true); @@ -154,13 +154,13 @@ BluetoothAdapter::ServiceOptions service_options; service_options.name.reset(new std::string("MyServiceName")); EXPECT_CALL( - *mock_adapter_.get(), + *mock_adapter_, CreateRfcommService( service_uuid, testing::Field(&BluetoothAdapter::ServiceOptions::name, testing::Pointee(testing::Eq("MyServiceName"))), - testing::_, - testing::_)).WillOnce(InvokeCallbackArgument<2>(mock_server_socket)); + testing::_, testing::_)) + .WillOnce(InvokeCallbackArgument<2>(mock_server_socket)); // Since the socket is unpaused, expect a call to Accept() from the socket // dispatcher. We'll immediately send back another mock socket to represent @@ -168,10 +168,10 @@ // pending. scoped_refptr<testing::StrictMock<MockBluetoothSocket> > mock_client_socket = new testing::StrictMock<MockBluetoothSocket>(); - EXPECT_CALL(*mock_server_socket.get(), Accept(testing::_, testing::_)) + EXPECT_CALL(*mock_server_socket, Accept(testing::_, testing::_)) .Times(2) .WillOnce( - InvokeCallbackArgument<0>(mock_device1_.get(), mock_client_socket)) + InvokeCallbackArgument<0>(mock_device1_.get(), mock_client_socket)) .WillOnce(testing::Return()); // Run the test, it sends a ready signal once it's ready for us to dispatch @@ -191,13 +191,13 @@ // Second stage of tests checks for error conditions, and will clean up // the existing server and client sockets. - EXPECT_CALL(*mock_server_socket.get(), Disconnect(testing::_)) + EXPECT_CALL(*mock_server_socket, Disconnect(testing::_)) .WillOnce(InvokeCallbackArgument<0>()); - EXPECT_CALL(*mock_server_socket.get(), Close()); + EXPECT_CALL(*mock_server_socket, Close()); - EXPECT_CALL(*mock_client_socket.get(), Disconnect(testing::_)) + EXPECT_CALL(*mock_client_socket, Disconnect(testing::_)) .WillOnce(InvokeCallbackArgument<0>()); - EXPECT_CALL(*mock_client_socket.get(), Close()); + EXPECT_CALL(*mock_client_socket, Close()); EXPECT_TRUE(listener.WaitUntilSatisfied()); listener.Reply("go");
diff --git a/extensions/browser/api/cast_channel/cast_channel_api.cc b/extensions/browser/api/cast_channel/cast_channel_api.cc index c016fbf..15e44f19 100644 --- a/extensions/browser/api/cast_channel/cast_channel_api.cc +++ b/extensions/browser/api/cast_channel/cast_channel_api.cc
@@ -271,12 +271,12 @@ } else { // Parse timeout parameters if they are set. if (connect_info.liveness_timeout.get()) { - liveness_timeout_ = base::TimeDelta::FromMilliseconds( - *connect_info.liveness_timeout.get()); + liveness_timeout_ = + base::TimeDelta::FromMilliseconds(*connect_info.liveness_timeout); } if (connect_info.ping_interval.get()) { ping_interval_ = - base::TimeDelta::FromMilliseconds(*connect_info.ping_interval.get()); + base::TimeDelta::FromMilliseconds(*connect_info.ping_interval); } // Validate timeout parameters. @@ -313,10 +313,10 @@ extension_->id(), *ip_endpoint_, channel_auth_, ExtensionsBrowserClient::Get()->GetNetLog(), base::TimeDelta::FromMilliseconds(connect_info.timeout.get() - ? *connect_info.timeout.get() + ? *connect_info.timeout : kDefaultConnectTimeoutMillis), liveness_timeout_ > base::TimeDelta(), api_->GetLogger(), - connect_info.capabilities.get() ? *connect_info.capabilities.get() + connect_info.capabilities.get() ? *connect_info.capabilities : CastDeviceCapability::NONE); } new_channel_id_ = AddSocket(socket);
diff --git a/extensions/browser/api/cast_channel/cast_framer.cc b/extensions/browser/api/cast_channel/cast_framer.cc index c0dec495..e453415 100644 --- a/extensions/browser/api/cast_channel/cast_framer.cc +++ b/extensions/browser/api/cast_channel/cast_framer.cc
@@ -133,8 +133,7 @@ case HEADER: if (BytesRequested() == 0) { MessageHeader header; - MessageHeader::Deserialize(input_buffer_.get()->StartOfBuffer(), - &header); + MessageHeader::Deserialize(input_buffer_->StartOfBuffer(), &header); if (header.message_size > MessageHeader::max_message_size()) { VLOG(1) << "Error parsing header (message size too large)."; *error = CHANNEL_ERROR_INVALID_MESSAGE;
diff --git a/extensions/browser/api/device_permissions_manager.cc b/extensions/browser/api/device_permissions_manager.cc index 9320b330..7a6dac2 100644 --- a/extensions/browser/api/device_permissions_manager.cc +++ b/extensions/browser/api/device_permissions_manager.cc
@@ -101,7 +101,7 @@ } std::unique_ptr<base::Value> device_entry(entry->ToValue()); - DCHECK(devices->Find(*device_entry.get()) == devices->end()); + DCHECK(devices->Find(*device_entry) == devices->end()); devices->Append(std::move(device_entry)); }
diff --git a/extensions/browser/api/document_scan/document_scan_api.cc b/extensions/browser/api/document_scan/document_scan_api.cc index 6cdaf1d..a89dbb7 100644 --- a/extensions/browser/api/document_scan/document_scan_api.cc +++ b/extensions/browser/api/document_scan/document_scan_api.cc
@@ -65,7 +65,7 @@ // types are specified, the first scanner that supports one of these // MIME types is selected. if (params_->options.mime_types) { - std::vector<std::string>& mime_types = *params_->options.mime_types.get(); + std::vector<std::string>& mime_types = *params_->options.mime_types; for (; scanner_i != scanner_descriptions.end(); ++scanner_i) { if (std::find(mime_types.begin(), mime_types.end(), scanner_i->image_mime_type) != mime_types.end()) {
diff --git a/extensions/browser/api/management/management_api.cc b/extensions/browser/api/management/management_api.cc index 7c69010..dff828b 100644 --- a/extensions/browser/api/management/management_api.cc +++ b/extensions/browser/api/management/management_api.cc
@@ -257,7 +257,7 @@ content::BrowserContext* context) { for (ExtensionSet::const_iterator iter = extensions.begin(); iter != extensions.end(); ++iter) { - const Extension& extension = *iter->get(); + const Extension& extension = **iter; if (extension.ShouldNotBeVisible()) continue; // Skip built-in extensions/apps.
diff --git a/extensions/browser/api/printer_provider/printer_provider_apitest.cc b/extensions/browser/api/printer_provider/printer_provider_apitest.cc index ca949ec..f2e5b1a 100644 --- a/extensions/browser/api/printer_provider/printer_provider_apitest.cc +++ b/extensions/browser/api/printer_provider/printer_provider_apitest.cc
@@ -331,11 +331,11 @@ // in |expoected_printers| are unique. void ValidatePrinterListValue( const base::ListValue& printers, - const std::vector<std::unique_ptr<base::Value>> expected_printers) { + const std::vector<std::unique_ptr<base::Value>>& expected_printers) { ASSERT_EQ(expected_printers.size(), printers.GetSize()); for (const auto& printer_value : expected_printers) { - EXPECT_TRUE(printers.Find(*printer_value.get()) != printers.end()) - << "Unable to find " << *printer_value.get() << " in " << printers; + EXPECT_TRUE(printers.Find(*printer_value) != printers.end()) + << "Unable to find " << *printer_value << " in " << printers; } } @@ -508,7 +508,7 @@ .Set("name", "Printer 2") .Build()); - ValidatePrinterListValue(printers, std::move(expected_printers)); + ValidatePrinterListValue(printers, expected_printers); } IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest, GetPrintersAsyncSuccess) { @@ -539,7 +539,7 @@ .Set("name", "Printer 1") .Build()); - ValidatePrinterListValue(printers, std::move(expected_printers)); + ValidatePrinterListValue(printers, expected_printers); } IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest, GetPrintersTwoExtensions) { @@ -601,7 +601,7 @@ .Set("name", "Printer 2") .Build()); - ValidatePrinterListValue(printers, std::move(expected_printers)); + ValidatePrinterListValue(printers, expected_printers); } IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest, @@ -680,7 +680,7 @@ .Set("name", "Printer 2") .Build()); - ValidatePrinterListValue(printers, std::move(expected_printers)); + ValidatePrinterListValue(printers, expected_printers); } IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest, @@ -727,7 +727,7 @@ .Set("name", "Printer 2") .Build()); - ValidatePrinterListValue(printers, std::move(expected_printers)); + ValidatePrinterListValue(printers, expected_printers); } IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest, GetPrintersNoListener) {
diff --git a/extensions/browser/api/serial/serial_api.cc b/extensions/browser/api/serial/serial_api.cc index 3f126a8..2dfc1b66 100644 --- a/extensions/browser/api/serial/serial_api.cc +++ b/extensions/browser/api/serial/serial_api.cc
@@ -131,7 +131,7 @@ void SerialConnectFunction::AsyncWorkStart() { DCHECK_CURRENTLY_ON(BrowserThread::IO); connection_ = CreateSerialConnection(params_->path, extension_->id()); - connection_->Open(*params_->options.get(), + connection_->Open(*params_->options, base::Bind(&SerialConnectFunction::OnConnected, this)); }
diff --git a/extensions/browser/api/socket/socket_api.cc b/extensions/browser/api/socket/socket_api.cc index 714766b..6534342c 100644 --- a/extensions/browser/api/socket/socket_api.cc +++ b/extensions/browser/api/socket/socket_api.cc
@@ -446,9 +446,9 @@ return; } - int result = socket->Listen( - params_->address, params_->port, - params_->backlog.get() ? *params_->backlog.get() : 5, &error_); + int result = + socket->Listen(params_->address, params_->port, + params_->backlog.get() ? *params_->backlog : 5, &error_); SetResult(base::MakeUnique<base::FundamentalValue>(result)); if (result != net::OK) { AsyncWorkCompleted(); @@ -511,7 +511,7 @@ return; } - socket->Read(params_->buffer_size.get() ? *params_->buffer_size.get() : 4096, + socket->Read(params_->buffer_size.get() ? *params_->buffer_size : 4096, base::Bind(&SocketReadFunction::OnCompleted, this)); }
diff --git a/extensions/browser/api/socket/tls_socket.cc b/extensions/browser/api/socket/tls_socket.cc index f9df610..2f531634 100644 --- a/extensions/browser/api/socket/tls_socket.cc +++ b/extensions/browser/api/socket/tls_socket.cc
@@ -253,10 +253,10 @@ uint16_t version_min = 0, version_max = 0; api::socket::TLSVersionConstraints* versions = options->tls_version.get(); if (versions->min.get()) { - version_min = SSLProtocolVersionFromString(*versions->min.get()); + version_min = SSLProtocolVersionFromString(*versions->min); } if (versions->max.get()) { - version_max = SSLProtocolVersionFromString(*versions->max.get()); + version_max = SSLProtocolVersionFromString(*versions->max); } if (version_min) { ssl_config.version_min = version_min;
diff --git a/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc b/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc index be8e45d1..a9f9368 100644 --- a/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc +++ b/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc
@@ -68,15 +68,15 @@ void SetSocketProperties(ResumableTCPSocket* socket, SocketProperties* properties) { if (properties->name.get()) { - socket->set_name(*properties->name.get()); + socket->set_name(*properties->name); } if (properties->persistent.get()) { - socket->set_persistent(*properties->persistent.get()); + socket->set_persistent(*properties->persistent); } if (properties->buffer_size.get()) { // buffer size is validated when issuing the actual Recv operation // on the socket. - socket->set_buffer_size(*properties->buffer_size.get()); + socket->set_buffer_size(*properties->buffer_size); } } @@ -126,7 +126,7 @@ void SocketsTcpCreateFunction::Work() { ResumableTCPSocket* socket = new ResumableTCPSocket(extension_->id()); - sockets_tcp::SocketProperties* properties = params_.get()->properties.get(); + sockets_tcp::SocketProperties* properties = params_->properties.get(); if (properties) { SetSocketProperties(socket, properties); } @@ -153,7 +153,7 @@ return; } - SetSocketProperties(socket, ¶ms_.get()->properties); + SetSocketProperties(socket, ¶ms_->properties); results_ = sockets_tcp::Update::Results::Create(); } @@ -210,7 +210,7 @@ return; } - int delay = params_->delay ? *params_->delay.get() : 0; + int delay = params_->delay ? *params_->delay : 0; bool success = socket->SetKeepAlive(params_->enable, delay); int net_result = (success ? net::OK : net::ERR_FAILED); @@ -508,11 +508,11 @@ legacy_params.tls_version.reset(new api::socket::TLSVersionConstraints); if (params_->options->tls_version->min.get()) { legacy_params.tls_version->min.reset( - new std::string(*params_->options->tls_version->min.get())); + new std::string(*params_->options->tls_version->min)); } if (params_->options->tls_version->max.get()) { legacy_params.tls_version->max.reset( - new std::string(*params_->options->tls_version->max.get())); + new std::string(*params_->options->tls_version->max)); } }
diff --git a/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc b/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc index 87b332a..31d3565 100644 --- a/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc +++ b/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc
@@ -48,10 +48,10 @@ void SetSocketProperties(ResumableTCPServerSocket* socket, SocketProperties* properties) { if (properties->name.get()) { - socket->set_name(*properties->name.get()); + socket->set_name(*properties->name); } if (properties->persistent.get()) { - socket->set_persistent(*properties->persistent.get()); + socket->set_persistent(*properties->persistent); } } @@ -87,8 +87,7 @@ ResumableTCPServerSocket* socket = new ResumableTCPServerSocket(extension_->id()); - sockets_tcp_server::SocketProperties* properties = - params_.get()->properties.get(); + sockets_tcp_server::SocketProperties* properties = params_->properties.get(); if (properties) { SetSocketProperties(socket, properties); } @@ -115,7 +114,7 @@ return; } - SetSocketProperties(socket, ¶ms_.get()->properties); + SetSocketProperties(socket, ¶ms_->properties); results_ = sockets_tcp_server::Update::Results::Create(); } @@ -192,9 +191,8 @@ } int net_result = socket->Listen( - params_->address, - params_->port, - params_->backlog.get() ? *params_->backlog.get() : kDefaultListenBacklog, + params_->address, params_->port, + params_->backlog.get() ? *params_->backlog : kDefaultListenBacklog, &error_); results_ = sockets_tcp_server::Listen::Results::Create(net_result); if (net_result == net::OK) {
diff --git a/extensions/browser/api/sockets_udp/sockets_udp_api.cc b/extensions/browser/api/sockets_udp/sockets_udp_api.cc index 9e2e607..05ef6620 100644 --- a/extensions/browser/api/sockets_udp/sockets_udp_api.cc +++ b/extensions/browser/api/sockets_udp/sockets_udp_api.cc
@@ -75,13 +75,13 @@ void SetSocketProperties(ResumableUDPSocket* socket, sockets_udp::SocketProperties* properties) { if (properties->name.get()) { - socket->set_name(*properties->name.get()); + socket->set_name(*properties->name); } if (properties->persistent.get()) { - socket->set_persistent(*properties->persistent.get()); + socket->set_persistent(*properties->persistent); } if (properties->buffer_size.get()) { - socket->set_buffer_size(*properties->buffer_size.get()); + socket->set_buffer_size(*properties->buffer_size); } } @@ -98,7 +98,7 @@ void SocketsUdpCreateFunction::Work() { ResumableUDPSocket* socket = new ResumableUDPSocket(extension_->id()); - sockets_udp::SocketProperties* properties = params_.get()->properties.get(); + sockets_udp::SocketProperties* properties = params_->properties.get(); if (properties) { SetSocketProperties(socket, properties); } @@ -125,7 +125,7 @@ return; } - SetSocketProperties(socket, ¶ms_.get()->properties); + SetSocketProperties(socket, ¶ms_->properties); results_ = sockets_udp::Update::Results::Create(); }
diff --git a/extensions/browser/api/system_network/system_network_api.cc b/extensions/browser/api/system_network/system_network_api.cc index ece1ebb..38b5a251 100644 --- a/extensions/browser/api/system_network/system_network_api.cc +++ b/extensions/browser/api/system_network/system_network_api.cc
@@ -62,7 +62,7 @@ std::vector<api::system_network::NetworkInterface> create_arg; create_arg.reserve(interface_list.size()); - for (const net::NetworkInterface interface : interface_list) { + for (const net::NetworkInterface& interface : interface_list) { api::system_network::NetworkInterface info; info.name = interface.name; info.address = interface.address.ToString();
diff --git a/extensions/browser/api/usb/usb_api.cc b/extensions/browser/api/usb/usb_api.cc index 14de39b..62e4c5ad 100644 --- a/extensions/browser/api/usb/usb_api.cc +++ b/extensions/browser/api/usb/usb_api.cc
@@ -503,7 +503,7 @@ vendor_id_ = parameters->options.vendor_id; product_id_ = parameters->options.product_id; int interface_id = parameters->options.interface_id.get() - ? *parameters->options.interface_id.get() + ? *parameters->options.interface_id : UsbDevicePermissionData::ANY_INTERFACE; UsbDevicePermission::CheckParam param(vendor_id_, product_id_, interface_id); if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
diff --git a/extensions/browser/api/usb/usb_apitest.cc b/extensions/browser/api/usb/usb_apitest.cc index d17a9d73..ff28276 100644 --- a/extensions/browser/api/usb/usb_apitest.cc +++ b/extensions/browser/api/usb/usb_apitest.cc
@@ -144,7 +144,7 @@ mock_device_ = new MockUsbDevice(0, 0, "Test Manufacturer", "Test Device", "ABC123", configs); mock_device_handle_ = new MockUsbDeviceHandle(mock_device_.get()); - EXPECT_CALL(*mock_device_.get(), Open(_)) + EXPECT_CALL(*mock_device_, Open(_)) .WillRepeatedly(InvokeCallback<0>(mock_device_handle_)); device_client_->usb_service()->AddDevice(mock_device_); } @@ -159,86 +159,79 @@ IN_PROC_BROWSER_TEST_F(UsbApiTest, DeviceHandling) { mock_device_->ActiveConfigurationChanged(1); - EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(2); + EXPECT_CALL(*mock_device_handle_, Close()).Times(2); ASSERT_TRUE(RunAppTest("api_test/usb/device_handling")); } IN_PROC_BROWSER_TEST_F(UsbApiTest, ResetDevice) { - EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(2); - EXPECT_CALL(*mock_device_handle_.get(), ResetDevice(_)) + EXPECT_CALL(*mock_device_handle_, Close()).Times(2); + EXPECT_CALL(*mock_device_handle_, ResetDevice(_)) .WillOnce(InvokeCallback<0>(true)) .WillOnce(InvokeCallback<0>(false)); - EXPECT_CALL(*mock_device_handle_.get(), + EXPECT_CALL(*mock_device_handle_, GenericTransfer(device::USB_DIRECTION_OUTBOUND, 2, _, 1, _, _)) .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED)); ASSERT_TRUE(RunAppTest("api_test/usb/reset_device")); } IN_PROC_BROWSER_TEST_F(UsbApiTest, SetConfiguration) { - EXPECT_CALL(*mock_device_handle_.get(), SetConfiguration(1, _)) + EXPECT_CALL(*mock_device_handle_, SetConfiguration(1, _)) .WillOnce(SetConfiguration(mock_device_.get())); - EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(1); + EXPECT_CALL(*mock_device_handle_, Close()).Times(1); ASSERT_TRUE(RunAppTest("api_test/usb/set_configuration")); } IN_PROC_BROWSER_TEST_F(UsbApiTest, ListInterfaces) { mock_device_->ActiveConfigurationChanged(1); - EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(1); + EXPECT_CALL(*mock_device_handle_, Close()).Times(1); ASSERT_TRUE(RunAppTest("api_test/usb/list_interfaces")); } IN_PROC_BROWSER_TEST_F(UsbApiTest, TransferEvent) { - EXPECT_CALL(*mock_device_handle_.get(), - ControlTransfer(device::USB_DIRECTION_OUTBOUND, - UsbDeviceHandle::STANDARD, - UsbDeviceHandle::DEVICE, - 1, - 2, - 3, - _, - 1, - _, - _)) + EXPECT_CALL( + *mock_device_handle_, + ControlTransfer(device::USB_DIRECTION_OUTBOUND, UsbDeviceHandle::STANDARD, + UsbDeviceHandle::DEVICE, 1, 2, 3, _, 1, _, _)) .WillOnce(InvokeUsbTransferCallback<9>(device::USB_TRANSFER_COMPLETED)); - EXPECT_CALL(*mock_device_handle_.get(), + EXPECT_CALL(*mock_device_handle_, GenericTransfer(device::USB_DIRECTION_OUTBOUND, 1, _, 1, _, _)) .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED)); - EXPECT_CALL(*mock_device_handle_.get(), + EXPECT_CALL(*mock_device_handle_, GenericTransfer(device::USB_DIRECTION_OUTBOUND, 2, _, 1, _, _)) .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED)); - EXPECT_CALL(*mock_device_handle_.get(), IsochronousTransferOut(3, _, _, _, _)) + EXPECT_CALL(*mock_device_handle_, IsochronousTransferOut(3, _, _, _, _)) .WillOnce(InvokeUsbIsochronousTransferOutCallback(1, 1u)); - EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber()); + EXPECT_CALL(*mock_device_handle_, Close()).Times(AnyNumber()); ASSERT_TRUE(RunAppTest("api_test/usb/transfer_event")); } IN_PROC_BROWSER_TEST_F(UsbApiTest, ZeroLengthTransfer) { - EXPECT_CALL(*mock_device_handle_.get(), GenericTransfer(_, _, _, 0, _, _)) + EXPECT_CALL(*mock_device_handle_, GenericTransfer(_, _, _, 0, _, _)) .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED)); - EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber()); + EXPECT_CALL(*mock_device_handle_, Close()).Times(AnyNumber()); ASSERT_TRUE(RunAppTest("api_test/usb/zero_length_transfer")); } IN_PROC_BROWSER_TEST_F(UsbApiTest, TransferFailure) { - EXPECT_CALL(*mock_device_handle_.get(), + EXPECT_CALL(*mock_device_handle_, GenericTransfer(device::USB_DIRECTION_OUTBOUND, 1, _, _, _, _)) .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_COMPLETED)) .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_ERROR)) .WillOnce(InvokeUsbTransferCallback<5>(device::USB_TRANSFER_TIMEOUT)); - EXPECT_CALL(*mock_device_handle_.get(), IsochronousTransferIn(2, _, _, _)) + EXPECT_CALL(*mock_device_handle_, IsochronousTransferIn(2, _, _, _)) .WillOnce(InvokeUsbIsochronousTransferInCallback(8, 10u)) .WillOnce(InvokeUsbIsochronousTransferInCallback(8, 5u)); - EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber()); + EXPECT_CALL(*mock_device_handle_, Close()).Times(AnyNumber()); ASSERT_TRUE(RunAppTest("api_test/usb/transfer_failure")); } IN_PROC_BROWSER_TEST_F(UsbApiTest, InvalidLengthTransfer) { - EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber()); + EXPECT_CALL(*mock_device_handle_, Close()).Times(AnyNumber()); ASSERT_TRUE(RunAppTest("api_test/usb/invalid_length_transfer")); } IN_PROC_BROWSER_TEST_F(UsbApiTest, InvalidTimeout) { - EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber()); + EXPECT_CALL(*mock_device_handle_, Close()).Times(AnyNumber()); ASSERT_TRUE(RunAppTest("api_test/usb/invalid_timeout")); } @@ -276,7 +269,7 @@ ExtensionTestMessageListener result_listener("success", false); result_listener.set_failure_message("failure"); - EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(1); + EXPECT_CALL(*mock_device_handle_, Close()).Times(1); TestExtensionsAPIClient test_api_client; ASSERT_TRUE(LoadApp("api_test/usb/get_user_selected_devices"));
diff --git a/extensions/browser/api_test_utils.cc b/extensions/browser/api_test_utils.cc index 84d39de..0a0efeb 100644 --- a/extensions/browser/api_test_utils.cc +++ b/extensions/browser/api_test_utils.cc
@@ -44,7 +44,7 @@ bool GetResponse() { EXPECT_TRUE(HasResponse()); - return *response_.get(); + return *response_; } void OnSendResponse(UIThreadExtensionFunction* function,
diff --git a/extensions/browser/extension_throttle_simulation_unittest.cc b/extensions/browser/extension_throttle_simulation_unittest.cc index 9b415e23..6fb3e49 100644 --- a/extensions/browser/extension_throttle_simulation_unittest.cc +++ b/extensions/browser/extension_throttle_simulation_unittest.cc
@@ -193,7 +193,7 @@ return max_experienced_queries_per_tick_; } - const URLRequest& mock_request() const { return *mock_request_.get(); } + const URLRequest& mock_request() const { return *mock_request_; } std::string VisualizeASCII(int terminal_width) { // Account for | characters we place at left of graph.
diff --git a/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc b/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc index d15d1c0..31404c50 100644 --- a/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc +++ b/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc
@@ -71,7 +71,7 @@ std::unique_ptr<base::DictionaryValue> create_params, const WebContentsCreatedCallback& callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - MimeHandlerViewGuest::CreateWebContents(*create_params.get(), callback); + MimeHandlerViewGuest::CreateWebContents(*create_params, callback); } // static
diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc index a5fec8a..571d06e 100644 --- a/extensions/browser/process_manager.cc +++ b/extensions/browser/process_manager.cc
@@ -107,7 +107,7 @@ static void CreateBackgroundHostForExtensionLoad( ProcessManager* manager, const Extension* extension) { - DVLOG(1) << "CreateBackgroundHostForExtensionLoad"; + DVLOG(1) << "CreateBackgroundHostForExtensionLoad " << extension->id(); if (BackgroundInfo::HasPersistentBackgroundPage(extension)) manager->CreateBackgroundHost(extension, BackgroundInfo::GetBackgroundURL(extension));
diff --git a/extensions/browser/value_store/value_store_frontend.cc b/extensions/browser/value_store/value_store_frontend.cc index ccd50403..964fdbe 100644 --- a/extensions/browser/value_store/value_store_frontend.cc +++ b/extensions/browser/value_store/value_store_frontend.cc
@@ -50,9 +50,8 @@ LazyInit(); // We don't need the old value, so skip generating changes. ValueStore::WriteResult result = storage_->Set( - ValueStore::IGNORE_QUOTA | ValueStore::NO_GENERATE_CHANGES, - key, - *value.get()); + ValueStore::IGNORE_QUOTA | ValueStore::NO_GENERATE_CHANGES, key, + *value); LOG_IF(ERROR, !result->status().ok()) << "Error while writing " << key << " to " << db_path_.value(); }
diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json index ac12ff9..faf3636d 100644 --- a/extensions/common/api/_api_features.json +++ b/extensions/common/api/_api_features.json
@@ -293,6 +293,7 @@ "matches": [ "chrome://md-settings/*", "chrome://network/*", + "chrome://oobe/*", "chrome://settings/*", "chrome://settings-frame/*" ]
diff --git a/extensions/common/extension_l10n_util.cc b/extensions/common/extension_l10n_util.cc index 492f283..9701ea43 100644 --- a/extensions/common/extension_l10n_util.cc +++ b/extensions/common/extension_l10n_util.cc
@@ -16,6 +16,7 @@ #include "base/json/json_file_value_serializer.h" #include "base/logging.h" #include "base/memory/linked_ptr.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" @@ -270,11 +271,10 @@ extensions::file_util::LoadMessageBundle(extension_path, default_locale, error)); - if (!message_bundle.get() && !error->empty()) + if (!message_bundle && !error->empty()) return false; - if (message_bundle.get() && - !LocalizeManifest(*message_bundle, manifest, error)) + if (message_bundle && !LocalizeManifest(*message_bundle, manifest, error)) return false; return true; @@ -287,7 +287,7 @@ std::string* error) { // Accept name that starts with a . but don't add it to the list of supported // locales. - if (locale_name.find(".") == 0) + if (base::StartsWith(locale_name, ".", base::CompareCase::SENSITIVE)) return true; if (chrome_locales.find(locale_name) == chrome_locales.end()) { // Warn if there is an extension locale that's not in the Chrome list, @@ -297,14 +297,13 @@ return true; } // Check if messages file is actually present (but don't check content). - if (base::PathExists(locale_folder.Append(extensions::kMessagesFilename))) { - valid_locales->insert(locale_name); - } else { + if (!base::PathExists(locale_folder.Append(extensions::kMessagesFilename))) { *error = base::StringPrintf("Catalog file is missing for locale %s.", locale_name.c_str()); return false; } + valid_locales->insert(locale_name); return true; }
diff --git a/extensions/common/features/base_feature_provider.cc b/extensions/common/features/base_feature_provider.cc index 40065ff0..99b8bb4 100644 --- a/extensions/common/features/base_feature_provider.cc +++ b/extensions/common/features/base_feature_provider.cc
@@ -4,148 +4,14 @@ #include "extensions/common/features/base_feature_provider.h" -#include <stddef.h> - -#include <stack> -#include <utility> - #include "base/strings/string_split.h" #include "base/strings/string_util.h" -#include "base/values.h" -#include "extensions/common/extensions_client.h" -#include "extensions/common/features/complex_feature.h" -#include "extensions/common/features/simple_feature.h" +#include "extensions/common/features/feature.h" namespace extensions { -namespace { - -bool IsNocompile(const base::Value& value) { - bool nocompile = false; - const base::DictionaryValue* as_dict = nullptr; - if (value.GetAsDictionary(&as_dict)) { - as_dict->GetBoolean("nocompile", &nocompile); - } else { - // "nocompile" is not supported for any other feature type. - } - return nocompile; -} - -bool ParseFeature(const base::DictionaryValue* value, - const std::string& name, - SimpleFeature* feature) { - feature->set_name(name); - std::string error = feature->Parse(value); - if (!error.empty()) - LOG(ERROR) << error; - return error.empty(); -} - -} // namespace - -BaseFeatureProvider::BaseFeatureProvider(const base::DictionaryValue& root, - FeatureFactory factory) - : factory_(factory) { - for (base::DictionaryValue::Iterator iter(root); !iter.IsAtEnd(); - iter.Advance()) { - if (IsNocompile(iter.value())) { - continue; - } - - if (iter.value().GetType() == base::Value::TYPE_DICTIONARY) { - std::unique_ptr<SimpleFeature> feature((*factory_)()); - - std::vector<std::string> split = base::SplitString( - iter.key(), ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - - // Push parent features on the stack, starting with the current feature. - // If one of the features has "noparent" set, stop pushing features on - // the stack. The features will then be parsed in order, starting with - // the farthest parent that is either top level or has "noparent" set. - std::stack<std::pair<std::string, const base::DictionaryValue*> > - parse_stack; - while (!split.empty()) { - std::string parent_name = base::JoinString(split, "."); - split.pop_back(); - if (root.HasKey(parent_name)) { - const base::DictionaryValue* parent = nullptr; - if (!root.GetDictionaryWithoutPathExpansion(parent_name, &parent)) { - // If the parent is a complex feature, find the parent with the - // 'default_parent' flag. - const base::ListValue* parent_list = nullptr; - CHECK(root.GetListWithoutPathExpansion(parent_name, &parent_list)); - for (size_t i = 0; i < parent_list->GetSize(); ++i) { - CHECK(parent_list->GetDictionary(i, &parent)); - if (parent->HasKey("default_parent")) - break; - parent = nullptr; - } - CHECK(parent) << parent_name << " must declare one of its features" - << " the default parent, with {\"default_parent\": true}."; - } - parse_stack.push(std::make_pair(parent_name, parent)); - bool no_parent = false; - parent->GetBoolean("noparent", &no_parent); - if (no_parent) - break; - } - } - - CHECK(!parse_stack.empty()); - // Parse all parent features. - bool parse_error = false; - while (!parse_stack.empty()) { - if (!ParseFeature(parse_stack.top().second, - parse_stack.top().first, - feature.get())) { - parse_error = true; - break; - } - parse_stack.pop(); - } - - if (parse_error) - continue; - - features_[iter.key()] = std::move(feature); - } else if (iter.value().GetType() == base::Value::TYPE_LIST) { - // This is a complex feature. - const base::ListValue* list = - static_cast<const base::ListValue*>(&iter.value()); - CHECK_GT(list->GetSize(), 0UL); - - std::unique_ptr<ComplexFeature::FeatureList> features( - new ComplexFeature::FeatureList()); - - // Parse and add all SimpleFeatures from the list. - for (const auto& entry : *list) { - base::DictionaryValue* dict; - if (!entry->GetAsDictionary(&dict)) { - LOG(ERROR) << iter.key() << ": Feature rules must be dictionaries."; - continue; - } - - std::unique_ptr<SimpleFeature> feature((*factory_)()); - if (!ParseFeature(dict, iter.key(), feature.get())) - continue; - - features->push_back(std::move(feature)); - } - - std::unique_ptr<ComplexFeature> feature( - new ComplexFeature(std::move(features))); - feature->set_name(iter.key()); - - features_[iter.key()] = std::move(feature); - } else { - LOG(ERROR) << iter.key() << ": Feature description must be dictionary or" - << " list of dictionaries."; - } - } -} - -BaseFeatureProvider::~BaseFeatureProvider() { -} +BaseFeatureProvider::BaseFeatureProvider() {} +BaseFeatureProvider::~BaseFeatureProvider() {} const FeatureMap& BaseFeatureProvider::GetAllFeatures() const { return features_;
diff --git a/extensions/common/features/base_feature_provider.h b/extensions/common/features/base_feature_provider.h index 503371e..59c1669 100644 --- a/extensions/common/features/base_feature_provider.h +++ b/extensions/common/features/base_feature_provider.h
@@ -10,24 +10,22 @@ #include <string> #include <vector> +#include "base/macros.h" #include "extensions/common/features/feature_provider.h" -#include "extensions/common/features/simple_feature.h" - -namespace Base { -class DictionaryValue; -} namespace extensions { +class Feature; -// Reads Features out of a simple JSON file description. +// A FeatureProvider contains the mapping of all feature names specified in the +// _*_features.json files to the Feature classes. Look up a Feature by its name +// to determine whether or not it is available in a certain context. +// Subclasses implement the specific logic for how the features are populated; +// this class handles vending the features given the query. +// TODO(devlin): We could probably combine this and FeatureProvider, since both +// contain common functionality and neither are designed to be full +// implementations. class BaseFeatureProvider : public FeatureProvider { public: - typedef SimpleFeature*(*FeatureFactory)(); - - // Creates a new BaseFeatureProvider. Pass null to |factory| to have the - // provider create plain old Feature instances. - BaseFeatureProvider(const base::DictionaryValue& root, - FeatureFactory factory); ~BaseFeatureProvider() override; // Gets the feature |feature_name|, if it exists. @@ -37,13 +35,12 @@ const FeatureMap& GetAllFeatures() const override; - private: + protected: + BaseFeatureProvider(); std::map<std::string, std::unique_ptr<Feature>> features_; - // Populated on first use. - mutable std::vector<std::string> feature_names_; - - FeatureFactory factory_; + private: + DISALLOW_COPY_AND_ASSIGN(BaseFeatureProvider); }; } // namespace extensions
diff --git a/extensions/common/features/complex_feature.cc b/extensions/common/features/complex_feature.cc index 9a330c1..5f041dbb 100644 --- a/extensions/common/features/complex_feature.cc +++ b/extensions/common/features/complex_feature.cc
@@ -102,16 +102,4 @@ return features_[0]->IsInternal(); } -std::string ComplexFeature::GetAvailabilityMessage(AvailabilityResult result, - Manifest::Type type, - const GURL& url, - Context context) const { - if (result == IS_AVAILABLE) - return std::string(); - - // TODO(justinlin): Form some kind of combined availabilities/messages from - // SimpleFeatures. - return features_[0]->GetAvailabilityMessage(result, type, url, context); -} - } // namespace extensions
diff --git a/extensions/common/features/complex_feature.h b/extensions/common/features/complex_feature.h index 9019838..44668c0 100644 --- a/extensions/common/features/complex_feature.h +++ b/extensions/common/features/complex_feature.h
@@ -43,12 +43,7 @@ bool IsIdInWhitelist(const std::string& extension_id) const override; protected: - // extensions::Feature: - std::string GetAvailabilityMessage(AvailabilityResult result, - Manifest::Type type, - const GURL& url, - Context context) const override; - + // Feature: bool IsInternal() const override; private:
diff --git a/extensions/common/features/feature.cc b/extensions/common/features/feature.cc index dc28d6dff..94125e0 100644 --- a/extensions/common/features/feature.cc +++ b/extensions/common/features/feature.cc
@@ -46,7 +46,7 @@ -1); // manifest_version } -Feature::Feature() : no_parent_(false) {} +Feature::Feature() : no_parent_(false), check_channel_(false) {} Feature::~Feature() {}
diff --git a/extensions/common/features/feature.h b/extensions/common/features/feature.h index b9f8073a..5b85bb2 100644 --- a/extensions/common/features/feature.h +++ b/extensions/common/features/feature.h
@@ -141,11 +141,6 @@ const GURL& url, Platform platform) const = 0; - virtual std::string GetAvailabilityMessage(AvailabilityResult result, - Manifest::Type type, - const GURL& url, - Context context) const = 0; - // Returns true if the feature is available to the current environment, // without needing to know information about an Extension or any other // contextual information. Typically used when the Feature is purely @@ -160,9 +155,13 @@ virtual bool IsIdInBlacklist(const std::string& extension_id) const = 0; virtual bool IsIdInWhitelist(const std::string& extension_id) const = 0; + void set_check_channel(bool check_channel) { check_channel_ = check_channel; } + protected: std::string name_; bool no_parent_; + // TODO(devlin): Remove this once we set the feature channel for tests. + bool check_channel_; }; } // namespace extensions
diff --git a/extensions/common/features/feature_channel.cc b/extensions/common/features/feature_channel.cc new file mode 100644 index 0000000..13bd6e1d --- /dev/null +++ b/extensions/common/features/feature_channel.cc
@@ -0,0 +1,40 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/common/features/feature_channel.h" + +#include "components/version_info/version_info.h" + +namespace { + +const version_info::Channel kDefaultChannel = version_info::Channel::STABLE; +version_info::Channel g_current_channel = kDefaultChannel; + +} // namespace + +namespace extensions { + +version_info::Channel GetCurrentChannel() { + return g_current_channel; +} + +void SetCurrentChannel(version_info::Channel channel) { + g_current_channel = channel; +} + +version_info::Channel GetDefaultChannel() { + return kDefaultChannel; +} + +ScopedCurrentChannel::ScopedCurrentChannel(version_info::Channel channel) + : original_channel_(version_info::Channel::UNKNOWN) { + original_channel_ = GetCurrentChannel(); + SetCurrentChannel(channel); +} + +ScopedCurrentChannel::~ScopedCurrentChannel() { + SetCurrentChannel(original_channel_); +} + +} // namespace extensions
diff --git a/extensions/common/features/feature_channel.h b/extensions/common/features/feature_channel.h new file mode 100644 index 0000000..5533e5d --- /dev/null +++ b/extensions/common/features/feature_channel.h
@@ -0,0 +1,41 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef EXTENSIONS_COMMON_FEATURES_FEATURE_CHANNEL_H_ +#define EXTENSIONS_COMMON_FEATURES_FEATURE_CHANNEL_H_ + +#include "base/macros.h" + +namespace version_info { +enum class Channel; +} + +namespace extensions { + +// Gets the current channel as seen by the Feature system. +version_info::Channel GetCurrentChannel(); + +// Sets the current channel as seen by the Feature system. In the browser +// process this should be chrome::GetChannel(), and in the renderer this will +// need to come from an IPC. +void SetCurrentChannel(version_info::Channel channel); + +// Gets the default channel as seen by the Feature system. +version_info::Channel GetDefaultChannel(); + +// Scoped channel setter. Use for tests. +class ScopedCurrentChannel { + public: + explicit ScopedCurrentChannel(version_info::Channel channel); + ~ScopedCurrentChannel(); + + private: + version_info::Channel original_channel_; + + DISALLOW_COPY_AND_ASSIGN(ScopedCurrentChannel); +}; + +} // namespace extensions + +#endif // EXTENSIONS_COMMON_FEATURES_FEATURE_CHANNEL_H_
diff --git a/extensions/common/features/json_feature_provider.cc b/extensions/common/features/json_feature_provider.cc new file mode 100644 index 0000000..15eba689 --- /dev/null +++ b/extensions/common/features/json_feature_provider.cc
@@ -0,0 +1,149 @@ +// 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. + +#include "extensions/common/features/json_feature_provider.h" + +#include <stddef.h> + +#include <stack> +#include <utility> + +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "base/values.h" +#include "extensions/common/extensions_client.h" +#include "extensions/common/features/complex_feature.h" +#include "extensions/common/features/simple_feature.h" + +namespace extensions { + +namespace { + +bool IsNocompile(const base::Value& value) { + bool nocompile = false; + const base::DictionaryValue* as_dict = nullptr; + if (value.GetAsDictionary(&as_dict)) { + as_dict->GetBoolean("nocompile", &nocompile); + } else { + // "nocompile" is not supported for any other feature type. + } + return nocompile; +} + +bool ParseFeature(const base::DictionaryValue* value, + const std::string& name, + SimpleFeature* feature) { + feature->set_name(name); + std::string error = feature->Parse(value); + if (!error.empty()) + LOG(ERROR) << error; + return error.empty(); +} + +} // namespace + +JSONFeatureProvider::JSONFeatureProvider(const base::DictionaryValue& root, + FeatureFactory factory) + : factory_(factory) { + for (base::DictionaryValue::Iterator iter(root); !iter.IsAtEnd(); + iter.Advance()) { + if (IsNocompile(iter.value())) { + continue; + } + + if (iter.value().GetType() == base::Value::TYPE_DICTIONARY) { + std::unique_ptr<SimpleFeature> feature((*factory_)()); + + std::vector<std::string> split = base::SplitString( + iter.key(), ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + + // Push parent features on the stack, starting with the current feature. + // If one of the features has "noparent" set, stop pushing features on + // the stack. The features will then be parsed in order, starting with + // the farthest parent that is either top level or has "noparent" set. + std::stack<std::pair<std::string, const base::DictionaryValue*>> + parse_stack; + while (!split.empty()) { + std::string parent_name = base::JoinString(split, "."); + split.pop_back(); + if (root.HasKey(parent_name)) { + const base::DictionaryValue* parent = nullptr; + if (!root.GetDictionaryWithoutPathExpansion(parent_name, &parent)) { + // If the parent is a complex feature, find the parent with the + // 'default_parent' flag. + const base::ListValue* parent_list = nullptr; + CHECK(root.GetListWithoutPathExpansion(parent_name, &parent_list)); + for (size_t i = 0; i < parent_list->GetSize(); ++i) { + CHECK(parent_list->GetDictionary(i, &parent)); + if (parent->HasKey("default_parent")) + break; + parent = nullptr; + } + CHECK(parent) + << parent_name << " must declare one of its features" + << " the default parent, with {\"default_parent\": true}."; + } + parse_stack.push(std::make_pair(parent_name, parent)); + bool no_parent = false; + parent->GetBoolean("noparent", &no_parent); + if (no_parent) + break; + } + } + + CHECK(!parse_stack.empty()); + // Parse all parent features. + bool parse_error = false; + while (!parse_stack.empty()) { + if (!ParseFeature(parse_stack.top().second, parse_stack.top().first, + feature.get())) { + parse_error = true; + break; + } + parse_stack.pop(); + } + + if (parse_error) + continue; + + features_[iter.key()] = std::move(feature); + } else if (iter.value().GetType() == base::Value::TYPE_LIST) { + // This is a complex feature. + const base::ListValue* list = + static_cast<const base::ListValue*>(&iter.value()); + CHECK_GT(list->GetSize(), 0UL); + + std::unique_ptr<ComplexFeature::FeatureList> features( + new ComplexFeature::FeatureList()); + + // Parse and add all SimpleFeatures from the list. + for (const auto& entry : *list) { + base::DictionaryValue* dict; + if (!entry->GetAsDictionary(&dict)) { + LOG(ERROR) << iter.key() << ": Feature rules must be dictionaries."; + continue; + } + + std::unique_ptr<SimpleFeature> feature((*factory_)()); + if (!ParseFeature(dict, iter.key(), feature.get())) + continue; + + features->push_back(std::move(feature)); + } + + std::unique_ptr<ComplexFeature> feature( + new ComplexFeature(std::move(features))); + feature->set_name(iter.key()); + + features_[iter.key()] = std::move(feature); + } else { + LOG(ERROR) << iter.key() << ": Feature description must be dictionary or" + << " list of dictionaries."; + } + } +} + +JSONFeatureProvider::~JSONFeatureProvider() {} + +} // namespace extensions
diff --git a/extensions/common/features/json_feature_provider.h b/extensions/common/features/json_feature_provider.h new file mode 100644 index 0000000..37a571a --- /dev/null +++ b/extensions/common/features/json_feature_provider.h
@@ -0,0 +1,36 @@ +// 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 EXTENSIONS_COMMON_FEATURES_JSON_FEATURE_PROVIDER_H_ +#define EXTENSIONS_COMMON_FEATURES_JSON_FEATURE_PROVIDER_H_ + +#include "extensions/common/features/base_feature_provider.h" + +namespace base { +class DictionaryValue; +} + +namespace extensions { +class SimpleFeature; + +// Reads Features out of a simple JSON file description. +class JSONFeatureProvider : public BaseFeatureProvider { + public: + typedef SimpleFeature* (*FeatureFactory)(); + + // Creates a new JSONFeatureProvider. Pass null to |factory| to have the + // provider create plain old Feature instances. + JSONFeatureProvider(const base::DictionaryValue& root, + FeatureFactory factory); + ~JSONFeatureProvider() override; + + private: + FeatureFactory factory_; + + DISALLOW_COPY_AND_ASSIGN(JSONFeatureProvider); +}; + +} // namespace extensions + +#endif // EXTENSIONS_COMMON_FEATURES_JSON_FEATURE_PROVIDER_H_
diff --git a/extensions/common/features/simple_feature.cc b/extensions/common/features/simple_feature.cc index 8833fb23..b4a3919 100644 --- a/extensions/common/features/simple_feature.cc +++ b/extensions/common/features/simple_feature.cc
@@ -19,6 +19,7 @@ #include "base/strings/stringprintf.h" #include "components/crx_file/id_util.h" #include "extensions/common/extension_api.h" +#include "extensions/common/features/feature_channel.h" #include "extensions/common/features/feature_provider.h" #include "extensions/common/features/feature_util.h" #include "extensions/common/switches.h" @@ -81,13 +82,12 @@ *enum_value = iter->second; } -template<typename T> -void ParseEnum(const base::DictionaryValue* value, - const std::string& property, +template <typename T> +void ParseEnum(const base::Value* value, T* enum_value, const std::map<std::string, T>& mapping) { std::string string_value; - if (!value->GetString(property, &string_value)) + if (!value->GetAsString(&string_value)) return; ParseEnum(string_value, enum_value, mapping); @@ -190,6 +190,23 @@ return ""; } +std::string GetDisplayName(version_info::Channel channel) { + switch (channel) { + case version_info::Channel::UNKNOWN: + return "trunk"; + case version_info::Channel::CANARY: + return "canary"; + case version_info::Channel::DEV: + return "dev"; + case version_info::Channel::BETA: + return "beta"; + case version_info::Channel::STABLE: + return "stable"; + } + NOTREACHED(); + return ""; +} + // Gets a human-readable list of the display names (pluralized, comma separated // with the "and" in the correct place) for each of |enum_types|. template <typename EnumType> @@ -274,12 +291,19 @@ platforms["linux"] = Feature::LINUX_PLATFORM; platforms["mac"] = Feature::MACOSX_PLATFORM; platforms["win"] = Feature::WIN_PLATFORM; + + channels["trunk"] = version_info::Channel::UNKNOWN; + channels["canary"] = version_info::Channel::CANARY; + channels["dev"] = version_info::Channel::DEV; + channels["beta"] = version_info::Channel::BETA; + channels["stable"] = version_info::Channel::STABLE; } std::map<std::string, Manifest::Type> extension_types; std::map<std::string, Feature::Context> contexts; std::map<std::string, SimpleFeature::Location> locations; std::map<std::string, Feature::Platform> platforms; + std::map<std::string, version_info::Channel> channels; }; SimpleFeature::SimpleFeature() @@ -290,14 +314,6 @@ SimpleFeature::~SimpleFeature() {} -bool SimpleFeature::HasDependencies() const { - return !dependencies_.empty(); -} - -void SimpleFeature::AddFilter(std::unique_ptr<SimpleFeatureFilter> filter) { - filters_.push_back(std::move(filter)); -} - std::string SimpleFeature::Parse(const base::DictionaryValue* dictionary) { static base::LazyInstance<SimpleFeature::Mappings> mappings = LAZY_INSTANCE_INITIALIZER; @@ -323,8 +339,7 @@ ParseEnumVector<Context>(value, &contexts_, mappings.Get().contexts); } else if (key == "location") { - ParseEnum<Location>(dictionary, "location", &location_, - mappings.Get().locations); + ParseEnum<Location>(value, &location_, mappings.Get().locations); } else if (key == "platforms") { ParseEnumVector<Platform>(value, &platforms_, mappings.Get().platforms); @@ -339,6 +354,10 @@ &component_extensions_auto_granted_); } else if (key == "command_line_switch") { dictionary->GetString("command_line_switch", &command_line_switch_); + } else if (key == "channel") { + channel_.reset(new version_info::Channel(version_info::Channel::UNKNOWN)); + ParseEnum<version_info::Channel>(value, channel_.get(), + mappings.Get().channels); } } @@ -351,14 +370,12 @@ // "matches" to be chromium.org/*. That sub-feature doesn't need to specify // "web_page" context because it's inherited, but we don't know that here. - std::string result; - for (const auto& filter : filters_) { - result = filter->Parse(dictionary); - if (!result.empty()) - break; - } + // All features must be channel-restricted, either directly or through + // dependents. + if (!channel_ && dependencies_.empty()) + return name() + ": Must supply a value for channel or dependencies."; - return result; + return std::string(); } Feature::Availability SimpleFeature::IsAvailableToManifest( @@ -410,12 +427,8 @@ return CreateAvailability(MISSING_COMMAND_LINE_SWITCH, type); } - for (const auto& filter : filters_) { - Availability availability = filter->IsAvailableToManifest( - extension_id, type, location, manifest_version, platform); - if (!availability.is_available()) - return availability; - } + if (channel_ && check_channel_ && *channel_ < GetCurrentChannel()) + return CreateAvailability(UNSUPPORTED_CHANNEL, *channel_); return CheckDependencies(base::Bind(&IsAvailableToManifestForBind, extension_id, @@ -455,13 +468,6 @@ return CreateAvailability(INVALID_URL, url); } - for (const auto& filter : filters_) { - Availability availability = - filter->IsAvailableToContext(extension, context, url, platform); - if (!availability.is_available()) - return availability; - } - // TODO(kalman): Assert that if the context was a webpage or WebUI context // then at some point a "matches" restriction was checked. return CheckDependencies(base::Bind( @@ -472,7 +478,8 @@ AvailabilityResult result, Manifest::Type type, const GURL& url, - Context context) const { + Context context, + version_info::Channel channel) const { switch (result) { case IS_AVAILABLE: return std::string(); @@ -522,8 +529,9 @@ name().c_str()); case UNSUPPORTED_CHANNEL: return base::StringPrintf( - "'%s' is unsupported in this version of the platform.", - name().c_str()); + "'%s' requires %s channel or newer, but this is the %s channel.", + name().c_str(), GetDisplayName(channel).c_str(), + GetDisplayName(GetCurrentChannel()).c_str()); case MISSING_COMMAND_LINE_SWITCH: return base::StringPrintf( "'%s' requires the '%s' command line switch to be enabled.", @@ -538,13 +546,15 @@ AvailabilityResult result) const { return Availability( result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, GURL(), - UNSPECIFIED_CONTEXT)); + UNSPECIFIED_CONTEXT, + version_info::Channel::UNKNOWN)); } Feature::Availability SimpleFeature::CreateAvailability( AvailabilityResult result, Manifest::Type type) const { - return Availability(result, GetAvailabilityMessage(result, type, GURL(), - UNSPECIFIED_CONTEXT)); + return Availability( + result, GetAvailabilityMessage(result, type, GURL(), UNSPECIFIED_CONTEXT, + version_info::Channel::UNKNOWN)); } Feature::Availability SimpleFeature::CreateAvailability( @@ -552,7 +562,8 @@ const GURL& url) const { return Availability( result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, url, - UNSPECIFIED_CONTEXT)); + UNSPECIFIED_CONTEXT, + version_info::Channel::UNKNOWN)); } Feature::Availability SimpleFeature::CreateAvailability( @@ -560,7 +571,15 @@ Context context) const { return Availability( result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, GURL(), - context)); + context, version_info::Channel::UNKNOWN)); +} + +Feature::Availability SimpleFeature::CreateAvailability( + AvailabilityResult result, + version_info::Channel channel) const { + return Availability( + result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, GURL(), + UNSPECIFIED_CONTEXT, channel)); } bool SimpleFeature::IsInternal() const {
diff --git a/extensions/common/features/simple_feature.h b/extensions/common/features/simple_feature.h index cefd730..373f6e5 100644 --- a/extensions/common/features/simple_feature.h +++ b/extensions/common/features/simple_feature.h
@@ -17,9 +17,9 @@ #include "base/lazy_instance.h" #include "base/macros.h" #include "base/values.h" +#include "components/version_info/version_info.h" #include "extensions/common/extension.h" #include "extensions/common/features/feature.h" -#include "extensions/common/features/simple_feature_filter.h" #include "extensions/common/manifest.h" namespace extensions { @@ -46,14 +46,6 @@ SimpleFeature(); ~SimpleFeature() override; - // Dependency resolution is a property of Features that is preferrably - // handled internally to avoid temptation, but FeatureFilters may need - // to know if there are any at all. - bool HasDependencies() const; - - // Adds a filter to this feature. The feature takes ownership of the filter. - void AddFilter(std::unique_ptr<SimpleFeatureFilter> filter); - // Parses the JSON representation of a feature into the fields of this object. // Unspecified values in the JSON are not modified in the object. This allows // us to implement inheritance by parsing one value after another. Returns @@ -87,11 +79,6 @@ const GURL& url, Platform platform) const override; - std::string GetAvailabilityMessage(AvailabilityResult result, - Manifest::Type type, - const GURL& url, - Context context) const override; - bool IsInternal() const override; bool IsIdInBlacklist(const std::string& extension_id) const override; @@ -141,6 +128,12 @@ command_line_switch_ = command_line_switch; } + std::string GetAvailabilityMessage(AvailabilityResult result, + Manifest::Type type, + const GURL& url, + Context context, + version_info::Channel channel) const; + // Handy utilities which construct the correct availability message. Availability CreateAvailability(AvailabilityResult result) const; Availability CreateAvailability(AvailabilityResult result, @@ -149,6 +142,8 @@ const GURL& url) const; Availability CreateAvailability(AvailabilityResult result, Context context) const; + Availability CreateAvailability(AvailabilityResult result, + version_info::Channel channel) const; private: friend class SimpleFeatureTest; @@ -204,8 +199,7 @@ int max_manifest_version_; bool component_extensions_auto_granted_; std::string command_line_switch_; - - std::vector<std::unique_ptr<SimpleFeatureFilter>> filters_; + std::unique_ptr<version_info::Channel> channel_; DISALLOW_COPY_AND_ASSIGN(SimpleFeature); };
diff --git a/extensions/common/features/simple_feature_filter.cc b/extensions/common/features/simple_feature_filter.cc deleted file mode 100644 index 623c49cc..0000000 --- a/extensions/common/features/simple_feature_filter.cc +++ /dev/null
@@ -1,37 +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. - -#include "extensions/common/features/simple_feature_filter.h" - -#include "extensions/common/features/simple_feature.h" - -namespace extensions { - -SimpleFeatureFilter::SimpleFeatureFilter(SimpleFeature* feature) - : feature_(feature) {} - -SimpleFeatureFilter::~SimpleFeatureFilter() {} - -std::string SimpleFeatureFilter::Parse(const base::DictionaryValue* value) { - return std::string(); -} - -Feature::Availability SimpleFeatureFilter::IsAvailableToContext( - const Extension* extension, - Feature::Context context, - const GURL& url, - Feature::Platform platform) const { - return Feature::Availability(Feature::IS_AVAILABLE, std::string()); -} - -Feature::Availability SimpleFeatureFilter::IsAvailableToManifest( - const std::string& extension_id, - Manifest::Type type, - Manifest::Location location, - int manifest_version, - Feature::Platform platform) const { - return Feature::Availability(Feature::IS_AVAILABLE, std::string()); -} - -} // namespace extensions
diff --git a/extensions/common/features/simple_feature_filter.h b/extensions/common/features/simple_feature_filter.h deleted file mode 100644 index 4f8a8c2..0000000 --- a/extensions/common/features/simple_feature_filter.h +++ /dev/null
@@ -1,64 +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 EXTENSIONS_COMMON_FEATURES_SIMPLE_FEATURE_FILTER_H_ -#define EXTENSIONS_COMMON_FEATURES_SIMPLE_FEATURE_FILTER_H_ - -#include <string> - -#include "base/macros.h" -#include "extensions/common/features/feature.h" -#include "extensions/common/manifest.h" - -class GURL; - -namespace base { -class DictionaryValue; -} - -namespace extensions { - -class SimpleFeature; - -// A SimpleFeatureFilter can be attached to SimpleFeature objects to provide -// additional parsing and availability filtering behavior. -class SimpleFeatureFilter { - public: - explicit SimpleFeatureFilter(SimpleFeature* feature); - virtual ~SimpleFeatureFilter(); - - SimpleFeature* feature() const { return feature_; } - - // Parses any additional feature data that may be used by this filter. - // Returns an error string on failure or the empty string on success. - // The default implementation simply returns the empty string. - virtual std::string Parse(const base::DictionaryValue* value); - - // Indicates whether or not the owning feature is available within a given - // extensions context. The default implementation only affirms availability. - virtual Feature::Availability IsAvailableToContext( - const Extension* extension, - Feature::Context context, - const GURL& url, - Feature::Platform platform) const; - - // Indicates whether or not the owning feature is available to a given - // extension manifest. The default implementation only affirms availability. - virtual Feature::Availability IsAvailableToManifest( - const std::string& extension_id, - Manifest::Type type, - Manifest::Location location, - int manifest_version, - Feature::Platform platform) const; - - private: - // The feature which owns this filter. - SimpleFeature* feature_; - - DISALLOW_COPY_AND_ASSIGN(SimpleFeatureFilter); -}; - -} // namespace extensions - -#endif // EXTENSIONS_COMMON_FEATURES_SIMPLE_FEATURE_FILTER_H_
diff --git a/extensions/common/features/simple_feature_unittest.cc b/extensions/common/features/simple_feature_unittest.cc index f24c0fb..50e3bbc 100644 --- a/extensions/common/features/simple_feature_unittest.cc +++ b/extensions/common/features/simple_feature_unittest.cc
@@ -13,6 +13,10 @@ #include "base/stl_util.h" #include "base/test/scoped_command_line.h" #include "base/values.h" +#include "extensions/common/features/complex_feature.h" +#include "extensions/common/features/feature_channel.h" +#include "extensions/common/features/json_feature_provider.h" +#include "extensions/common/features/permission_feature.h" #include "extensions/common/manifest.h" #include "extensions/common/value_builder.h" #include "testing/gtest/include/gtest/gtest.h" @@ -30,10 +34,37 @@ Feature::AvailabilityResult expected_result; }; +template <class FeatureClass> +SimpleFeature* CreateFeature() { + SimpleFeature* feature = new FeatureClass(); + feature->set_check_channel(true); + return feature; +} + +Feature::AvailabilityResult IsAvailableInChannel( + const std::string& channel, + version_info::Channel channel_for_testing) { + ScopedCurrentChannel current_channel(channel_for_testing); + + SimpleFeature feature; + + base::DictionaryValue feature_value; + feature_value.SetString("channel", channel); + feature.set_check_channel(true); + feature.Parse(&feature_value); + + return feature + .IsAvailableToManifest("random-extension", Manifest::TYPE_UNKNOWN, + Manifest::INVALID_LOCATION, -1, + Feature::GetCurrentPlatform()) + .result(); +} + } // namespace class SimpleFeatureTest : public testing::Test { protected: + SimpleFeatureTest() : current_channel_(version_info::Channel::UNKNOWN) {} bool LocationIsAvailable(SimpleFeature::Location feature_location, Manifest::Location manifest_location) { SimpleFeature feature; @@ -46,6 +77,10 @@ Feature::UNSPECIFIED_PLATFORM).result(); return availability_result == Feature::IS_AVAILABLE; } + + private: + ScopedCurrentChannel current_channel_; + DISALLOW_COPY_AND_ASSIGN(SimpleFeatureTest); }; TEST_F(SimpleFeatureTest, IsAvailableNullCase) { @@ -743,4 +778,239 @@ "aaaabbbbccccddddeeeeffffgggghhhh", kIdArray, arraysize(kIdArray))); } +// Tests that all combinations of feature channel and Chrome channel correctly +// compute feature availability. +TEST_F(SimpleFeatureTest, SupportedChannel) { + // stable supported. + EXPECT_EQ(Feature::IS_AVAILABLE, + IsAvailableInChannel("stable", version_info::Channel::UNKNOWN)); + EXPECT_EQ(Feature::IS_AVAILABLE, + IsAvailableInChannel("stable", version_info::Channel::CANARY)); + EXPECT_EQ(Feature::IS_AVAILABLE, + IsAvailableInChannel("stable", version_info::Channel::DEV)); + EXPECT_EQ(Feature::IS_AVAILABLE, + IsAvailableInChannel("stable", version_info::Channel::BETA)); + EXPECT_EQ(Feature::IS_AVAILABLE, + IsAvailableInChannel("stable", version_info::Channel::STABLE)); + + // beta supported. + EXPECT_EQ(Feature::IS_AVAILABLE, + IsAvailableInChannel("beta", version_info::Channel::UNKNOWN)); + EXPECT_EQ(Feature::IS_AVAILABLE, + IsAvailableInChannel("beta", version_info::Channel::CANARY)); + EXPECT_EQ(Feature::IS_AVAILABLE, + IsAvailableInChannel("beta", version_info::Channel::DEV)); + EXPECT_EQ(Feature::IS_AVAILABLE, + IsAvailableInChannel("beta", version_info::Channel::BETA)); + EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, + IsAvailableInChannel("beta", version_info::Channel::STABLE)); + + // dev supported. + EXPECT_EQ(Feature::IS_AVAILABLE, + IsAvailableInChannel("dev", version_info::Channel::UNKNOWN)); + EXPECT_EQ(Feature::IS_AVAILABLE, + IsAvailableInChannel("dev", version_info::Channel::CANARY)); + EXPECT_EQ(Feature::IS_AVAILABLE, + IsAvailableInChannel("dev", version_info::Channel::DEV)); + EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, + IsAvailableInChannel("dev", version_info::Channel::BETA)); + EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, + IsAvailableInChannel("dev", version_info::Channel::STABLE)); + + // canary supported. + EXPECT_EQ(Feature::IS_AVAILABLE, + IsAvailableInChannel("canary", version_info::Channel::UNKNOWN)); + EXPECT_EQ(Feature::IS_AVAILABLE, + IsAvailableInChannel("canary", version_info::Channel::CANARY)); + EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, + IsAvailableInChannel("canary", version_info::Channel::DEV)); + EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, + IsAvailableInChannel("canary", version_info::Channel::BETA)); + EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, + IsAvailableInChannel("canary", version_info::Channel::STABLE)); + + // trunk supported. + EXPECT_EQ(Feature::IS_AVAILABLE, + IsAvailableInChannel("trunk", version_info::Channel::UNKNOWN)); + EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, + IsAvailableInChannel("trunk", version_info::Channel::CANARY)); + EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, + IsAvailableInChannel("trunk", version_info::Channel::DEV)); + EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, + IsAvailableInChannel("trunk", version_info::Channel::BETA)); + EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, + IsAvailableInChannel("trunk", version_info::Channel::STABLE)); +} + +// Tests the validation of features with channel entries. +TEST_F(SimpleFeatureTest, FeatureValidation) { + std::unique_ptr<base::DictionaryValue> value(new base::DictionaryValue()); + + base::DictionaryValue* feature1 = new base::DictionaryValue(); + feature1->SetString("channel", "trunk"); + value->Set("feature1", feature1); + + base::DictionaryValue* feature2 = new base::DictionaryValue(); + feature2->SetString("channel", "trunk"); + base::ListValue* extension_types = new base::ListValue(); + extension_types->AppendString("extension"); + feature2->Set("extension_types", extension_types); + base::ListValue* contexts = new base::ListValue(); + contexts->AppendString("blessed_extension"); + feature2->Set("contexts", contexts); + value->Set("feature2", feature2); + + std::unique_ptr<JSONFeatureProvider> provider( + new JSONFeatureProvider(*value, CreateFeature<PermissionFeature>)); + + // feature1 won't validate because it lacks an extension type. + EXPECT_FALSE(provider->GetFeature("feature1")); + + // If we add one, it works. + feature1->Set("extension_types", extension_types->DeepCopy()); + provider.reset( + new JSONFeatureProvider(*value, CreateFeature<PermissionFeature>)); + EXPECT_TRUE(provider->GetFeature("feature1")); + + // Remove the channel, and feature1 won't validate. + feature1->Remove("channel", NULL); + provider.reset( + new JSONFeatureProvider(*value, CreateFeature<PermissionFeature>)); + EXPECT_FALSE(provider->GetFeature("feature1")); + + // feature2 won't validate because of the presence of "contexts". + EXPECT_FALSE(provider->GetFeature("feature2")); + + // If we remove it, it works. + feature2->Remove("contexts", NULL); + provider.reset( + new JSONFeatureProvider(*value, CreateFeature<PermissionFeature>)); + EXPECT_TRUE(provider->GetFeature("feature2")); +} + +// Tests simple feature availability across channels. +TEST_F(SimpleFeatureTest, SimpleFeatureAvailability) { + std::unique_ptr<base::DictionaryValue> rule( + DictionaryBuilder() + .Set("feature1", + ListBuilder() + .Append(DictionaryBuilder() + .Set("channel", "beta") + .Set("extension_types", + ListBuilder().Append("extension").Build()) + .Build()) + .Append(DictionaryBuilder() + .Set("channel", "beta") + .Set("extension_types", + ListBuilder() + .Append("legacy_packaged_app") + .Build()) + .Build()) + .Build()) + .Build()); + + std::unique_ptr<JSONFeatureProvider> provider( + new JSONFeatureProvider(*rule, CreateFeature<SimpleFeature>)); + + Feature* feature = provider->GetFeature("feature1"); + EXPECT_TRUE(feature); + + // Make sure both rules are applied correctly. + { + ScopedCurrentChannel current_channel(version_info::Channel::BETA); + EXPECT_EQ( + Feature::IS_AVAILABLE, + feature->IsAvailableToManifest("1", + Manifest::TYPE_EXTENSION, + Manifest::INVALID_LOCATION, + Feature::UNSPECIFIED_PLATFORM).result()); + EXPECT_EQ( + Feature::IS_AVAILABLE, + feature->IsAvailableToManifest("2", + Manifest::TYPE_LEGACY_PACKAGED_APP, + Manifest::INVALID_LOCATION, + Feature::UNSPECIFIED_PLATFORM).result()); + } + { + ScopedCurrentChannel current_channel(version_info::Channel::STABLE); + EXPECT_NE( + Feature::IS_AVAILABLE, + feature->IsAvailableToManifest("1", + Manifest::TYPE_EXTENSION, + Manifest::INVALID_LOCATION, + Feature::UNSPECIFIED_PLATFORM).result()); + EXPECT_NE( + Feature::IS_AVAILABLE, + feature->IsAvailableToManifest("2", + Manifest::TYPE_LEGACY_PACKAGED_APP, + Manifest::INVALID_LOCATION, + Feature::UNSPECIFIED_PLATFORM).result()); + } +} + +// Tests complex feature availability across channels. +TEST_F(SimpleFeatureTest, ComplexFeatureAvailability) { + std::unique_ptr<ComplexFeature::FeatureList> features( + new ComplexFeature::FeatureList()); + + // Rule: "extension", channel trunk. + std::unique_ptr<SimpleFeature> simple_feature(CreateFeature<SimpleFeature>()); + std::unique_ptr<base::DictionaryValue> rule( + DictionaryBuilder() + .Set("channel", "trunk") + .Set("extension_types", ListBuilder().Append("extension").Build()) + .Build()); + simple_feature->Parse(rule.get()); + features->push_back(std::move(simple_feature)); + + // Rule: "legacy_packaged_app", channel stable. + simple_feature.reset(CreateFeature<SimpleFeature>()); + rule = DictionaryBuilder() + .Set("channel", "stable") + .Set("extension_types", + ListBuilder().Append("legacy_packaged_app").Build()) + .Build(); + simple_feature->Parse(rule.get()); + features->push_back(std::move(simple_feature)); + + std::unique_ptr<ComplexFeature> feature( + new ComplexFeature(std::move(features))); + + // Test match 1st rule. + { + ScopedCurrentChannel current_channel(version_info::Channel::UNKNOWN); + EXPECT_EQ( + Feature::IS_AVAILABLE, + feature->IsAvailableToManifest("1", + Manifest::TYPE_EXTENSION, + Manifest::INVALID_LOCATION, + Feature::UNSPECIFIED_PLATFORM, + Feature::GetCurrentPlatform()).result()); + } + + // Test match 2nd rule. + { + ScopedCurrentChannel current_channel(version_info::Channel::BETA); + EXPECT_EQ( + Feature::IS_AVAILABLE, + feature->IsAvailableToManifest("2", + Manifest::TYPE_LEGACY_PACKAGED_APP, + Manifest::INVALID_LOCATION, + Feature::UNSPECIFIED_PLATFORM, + Feature::GetCurrentPlatform()).result()); + } + + // Test feature not available to extensions above channel unknown. + { + ScopedCurrentChannel current_channel(version_info::Channel::BETA); + EXPECT_NE( + Feature::IS_AVAILABLE, + feature->IsAvailableToManifest("1", + Manifest::TYPE_EXTENSION, + Manifest::INVALID_LOCATION, + Feature::UNSPECIFIED_PLATFORM, + Feature::GetCurrentPlatform()).result()); + } +} + } // namespace extensions
diff --git a/extensions/extensions.gypi b/extensions/extensions.gypi index 8f95c4c..4d4dc93f 100644 --- a/extensions/extensions.gypi +++ b/extensions/extensions.gypi
@@ -82,6 +82,8 @@ 'common/features/api_feature.h', 'common/features/base_feature_provider.cc', 'common/features/base_feature_provider.h', + 'common/features/json_feature_provider.cc', + 'common/features/json_feature_provider.h', 'common/features/behavior_feature.cc', 'common/features/behavior_feature.h', 'common/features/complex_feature.cc', @@ -90,6 +92,8 @@ 'common/features/feature.h', 'common/features/feature_provider.cc', 'common/features/feature_provider.h', + 'common/features/feature_channel.cc', + 'common/features/feature_channel.h', 'common/features/feature_util.h', 'common/features/json_feature_provider_source.cc', 'common/features/json_feature_provider_source.h', @@ -99,8 +103,6 @@ 'common/features/permission_feature.h', 'common/features/simple_feature.cc', 'common/features/simple_feature.h', - 'common/features/simple_feature_filter.cc', - 'common/features/simple_feature_filter.h', 'common/file_util.cc', 'common/file_util.h', 'common/guest_view/extensions_guest_view_messages.h',
diff --git a/extensions/renderer/api/display_source/wifi_display/DEPS b/extensions/renderer/api/display_source/wifi_display/DEPS index 4e30f49a..6dd95bf 100644 --- a/extensions/renderer/api/display_source/wifi_display/DEPS +++ b/extensions/renderer/api/display_source/wifi_display/DEPS
@@ -2,6 +2,7 @@ # TODO(Mikhail): Consider removing when https://crbug.com/432381 is fixed. "+media/base", "+media/video", + "+services/shell/public/cpp", "+third_party/openh264/src/codec/api", "+third_party/wds/src/libwds/public", ]
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.cc b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.cc index 7358146..02bf1381 100644 --- a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.cc +++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.cc
@@ -7,7 +7,6 @@ #include "base/logging.h" #include "base/rand_util.h" #include "base/task_runner_util.h" -#include "content/public/common/service_registry.h" #include "content/public/renderer/media_stream_utils.h" #include "content/public/renderer/media_stream_video_sink.h" #include "content/public/renderer/render_thread.h" @@ -16,6 +15,7 @@ #include "extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_info.h" #include "extensions/renderer/api/display_source/wifi_display/wifi_display_media_pipeline.h" #include "media/base/bind_to_current_loop.h" +#include "services/shell/public/cpp/interface_provider.h" namespace extensions { @@ -86,11 +86,11 @@ const blink::WebMediaStreamTrack& video_track, const blink::WebMediaStreamTrack& audio_track, const std::string& sink_ip_address, - content::ServiceRegistry* service_registry, + shell::InterfaceProvider* interface_provider, const ErrorCallback& error_callback) : video_track_(video_track), audio_track_(audio_track), - service_registry_(service_registry), + interface_provider_(interface_provider), sink_ip_address_(sink_ip_address), player_(nullptr), io_task_runner_(content::RenderThread::Get()->GetIOTaskRunner()), @@ -99,7 +99,7 @@ is_initialized_(false), weak_factory_(this) { DCHECK(!video_track.isNull() || !audio_track.isNull()); - DCHECK(service_registry_); + DCHECK(interface_provider_); DCHECK(!error_callback_.is_null()); } @@ -488,7 +488,7 @@ void WiFiDisplayMediaManager::ConnectToRemoteService( WiFiDisplayMediaServiceRequest request) { DCHECK(content::RenderThread::Get()); - service_registry_->ConnectToRemoteService(std::move(request)); + interface_provider_->GetInterface(std::move(request)); } } // namespace extensions
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.h b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.h index 4506ff7..9f69f2c 100644 --- a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.h +++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.h
@@ -18,9 +18,9 @@ #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" #include "third_party/wds/src/libwds/public/media_manager.h" -namespace content { -class ServiceRegistry; -} // namespace content +namespace shell { +class InterfaceProvider; +} // namespace shell namespace extensions { class WiFiDisplayAudioSink; @@ -36,7 +36,7 @@ const blink::WebMediaStreamTrack& video_track, const blink::WebMediaStreamTrack& audio_track, const std::string& sink_ip_address, - content::ServiceRegistry* service_registry, + shell::InterfaceProvider* interface_provider, const ErrorCallback& error_callback); ~WiFiDisplayMediaManager() override; @@ -79,7 +79,7 @@ std::unique_ptr<WiFiDisplayAudioSink> audio_sink_; std::unique_ptr<WiFiDisplayVideoSink> video_sink_; - content::ServiceRegistry* service_registry_; + shell::InterfaceProvider* interface_provider_; std::string sink_ip_address_; std::pair<int, int> sink_rtp_ports_; wds::H264VideoFormat optimal_video_format_;
diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_session.cc b/extensions/renderer/api/display_source/wifi_display/wifi_display_session.cc index 93e9c4d..eefbb1a 100644 --- a/extensions/renderer/api/display_source/wifi_display/wifi_display_session.cc +++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_session.cc
@@ -8,9 +8,9 @@ #include "base/logging.h" #include "base/timer/timer.h" -#include "content/public/common/service_registry.h" #include "content/public/renderer/render_frame.h" #include "extensions/renderer/api/display_source/wifi_display/wifi_display_media_manager.h" +#include "services/shell/public/cpp/interface_provider.h" #include "third_party/wds/src/libwds/public/logging.h" #include "third_party/wds/src/libwds/public/media_manager.h" @@ -42,8 +42,7 @@ weak_factory_(this) { DCHECK(params_.render_frame); wds::LogSystem::set_error_func(&LogWDSError); - params.render_frame->GetServiceRegistry()->ConnectToRemoteService( - mojo::GetProxy(&service_)); + params.render_frame->GetRemoteInterfaces()->GetInterface(&service_); service_.set_connection_error_handler(base::Bind( &WiFiDisplaySession::OnIPCConnectionError, weak_factory_.GetWeakPtr())); @@ -84,7 +83,7 @@ params_.video_track, params_.audio_track, sink_ip_address, - params_.render_frame->GetServiceRegistry(), + params_.render_frame->GetRemoteInterfaces(), base::Bind( &WiFiDisplaySession::OnMediaError, weak_factory_.GetWeakPtr())));
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc index df6e9cd4..30883e4 100644 --- a/extensions/renderer/dispatcher.cc +++ b/extensions/renderer/dispatcher.cc
@@ -1406,7 +1406,7 @@ continue; } - if (context->IsAnyFeatureAvailableToContext(*map_entry.second.get())) { + if (context->IsAnyFeatureAvailableToContext(*map_entry.second)) { // TODO(lazyboy): RegisterBinding() uses |source_map_|, any thread // safety issue? RegisterBinding(map_entry.first, context);
diff --git a/extensions/shell/common/shell_extensions_client.cc b/extensions/shell/common/shell_extensions_client.cc index 76f5a5835..338f312 100644 --- a/extensions/shell/common/shell_extensions_client.cc +++ b/extensions/shell/common/shell_extensions_client.cc
@@ -11,8 +11,8 @@ #include "extensions/common/common_manifest_handlers.h" #include "extensions/common/extension_urls.h" #include "extensions/common/features/api_feature.h" -#include "extensions/common/features/base_feature_provider.h" #include "extensions/common/features/behavior_feature.h" +#include "extensions/common/features/json_feature_provider.h" #include "extensions/common/features/json_feature_provider_source.h" #include "extensions/common/features/manifest_feature.h" #include "extensions/common/features/permission_feature.h" @@ -102,16 +102,16 @@ std::unique_ptr<JSONFeatureProviderSource> source( CreateFeatureProviderSource(name)); if (name == "api") { - provider.reset(new BaseFeatureProvider(source->dictionary(), + provider.reset(new JSONFeatureProvider(source->dictionary(), CreateFeature<APIFeature>)); } else if (name == "manifest") { - provider.reset(new BaseFeatureProvider(source->dictionary(), + provider.reset(new JSONFeatureProvider(source->dictionary(), CreateFeature<ManifestFeature>)); } else if (name == "permission") { - provider.reset(new BaseFeatureProvider(source->dictionary(), + provider.reset(new JSONFeatureProvider(source->dictionary(), CreateFeature<PermissionFeature>)); } else if (name == "behavior") { - provider.reset(new BaseFeatureProvider(source->dictionary(), + provider.reset(new JSONFeatureProvider(source->dictionary(), CreateFeature<BehaviorFeature>)); } else { NOTREACHED();
diff --git a/extensions/test/test_extensions_client.cc b/extensions/test/test_extensions_client.cc index 7ec31ad..025e1cd 100644 --- a/extensions/test/test_extensions_client.cc +++ b/extensions/test/test_extensions_client.cc
@@ -9,9 +9,9 @@ #include "extensions/common/common_manifest_handlers.h" #include "extensions/common/extension_urls.h" #include "extensions/common/features/api_feature.h" -#include "extensions/common/features/base_feature_provider.h" #include "extensions/common/features/behavior_feature.h" #include "extensions/common/features/feature_provider.h" +#include "extensions/common/features/json_feature_provider.h" #include "extensions/common/features/json_feature_provider_source.h" #include "extensions/common/features/manifest_feature.h" #include "extensions/common/features/permission_feature.h" @@ -78,16 +78,16 @@ std::unique_ptr<JSONFeatureProviderSource> source( CreateFeatureProviderSource(name)); if (name == "api") { - provider.reset(new BaseFeatureProvider(source->dictionary(), + provider.reset(new JSONFeatureProvider(source->dictionary(), CreateFeature<APIFeature>)); } else if (name == "manifest") { - provider.reset(new BaseFeatureProvider(source->dictionary(), + provider.reset(new JSONFeatureProvider(source->dictionary(), CreateFeature<ManifestFeature>)); } else if (name == "permission") { - provider.reset(new BaseFeatureProvider(source->dictionary(), + provider.reset(new JSONFeatureProvider(source->dictionary(), CreateFeature<PermissionFeature>)); } else if (name == "behavior") { - provider.reset(new BaseFeatureProvider(source->dictionary(), + provider.reset(new JSONFeatureProvider(source->dictionary(), CreateFeature<BehaviorFeature>)); } else { NOTREACHED();
diff --git a/gin/BUILD.gn b/gin/BUILD.gn index 88fa40a..4da0428 100644 --- a/gin/BUILD.gn +++ b/gin/BUILD.gn
@@ -86,6 +86,11 @@ "//base/third_party/dynamic_annotations", "//crypto", ] + if (v8_use_external_startup_data && is_win) { + public_deps += [ ":gin_v8_snapshot_fingerprint" ] + sources += [ "$target_gen_dir/v8_snapshot_fingerprint.cc" ] + defines += [ "V8_VERIFY_EXTERNAL_STARTUP_DATA" ] + } if (is_mac) { libs = [ "CoreFoundation.framework" ] @@ -94,6 +99,36 @@ configs += [ "//v8:external_startup_data" ] } +if (v8_use_external_startup_data) { + action("gin_v8_snapshot_fingerprint") { + script = "//gin/fingerprint/fingerprint_v8_snapshot.py" + + snapshot_file = "$root_out_dir/snapshot_blob.bin" + natives_file = "$root_out_dir/natives_blob.bin" + output_file = "$target_gen_dir/v8_snapshot_fingerprint.cc" + + args = [ + "--snapshot_file", + rebase_path(snapshot_file, root_build_dir), + "--natives_file", + rebase_path(natives_file, root_build_dir), + "--output_file", + rebase_path(output_file, root_build_dir), + ] + inputs = [ + snapshot_file, + natives_file, + ] + outputs = [ + output_file, + ] + + deps = [ + "//v8", + ] + } +} + executable("gin_shell") { sources = [ "shell/gin_main.cc",
diff --git a/gin/fingerprint/fingerprint_v8_snapshot.gypi b/gin/fingerprint/fingerprint_v8_snapshot.gypi new file mode 100644 index 0000000..ede0de3 --- /dev/null +++ b/gin/fingerprint/fingerprint_v8_snapshot.gypi
@@ -0,0 +1,47 @@ +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This file is meant to be included into a target to provide a rule that +# fingerprints the v8 snapshot and generates a .cc file which includes this +# fingerprint. +# +# To use this, create a gyp target with the following form: +# { +# 'target_name': 'gin_v8_snapshot_fingerprint', +# 'type': 'none', +# 'variables': { +# 'snapshot_file': 'snapshot blob file to be fingerprinted', +# 'natives_file': 'natives blob file to be fingerprinted', +# 'output_file': 'output .cc file to generate with fingerprints', +# }, +# 'includes': [ '../gin/fingerprint/fingerprint_v8_snapshot.gypi' ], +# }, +# + +{ + 'conditions': [ + ['v8_use_external_startup_data==1', { + 'actions': [ + { + 'action_name': 'Generate V8 snapshot fingerprint', + 'message': 'Generating V8 snapshot fingerprint', + 'inputs': [ + '<(DEPTH)/gin/fingerprint/fingerprint_v8_snapshot.py', + '<(snapshot_file)', + '<(natives_file)', + ], + 'outputs': [ + '<(output_file)', + ], + 'action': [ + 'python', '<(DEPTH)/gin/fingerprint/fingerprint_v8_snapshot.py', + '--snapshot_file=<(snapshot_file)', + '--natives_file=<(natives_file)', + '--output_file=<(output_file)', + ], + } + ], + }], + ], +} \ No newline at end of file
diff --git a/gin/fingerprint/fingerprint_v8_snapshot.py b/gin/fingerprint/fingerprint_v8_snapshot.py new file mode 100755 index 0000000..d1f70923 --- /dev/null +++ b/gin/fingerprint/fingerprint_v8_snapshot.py
@@ -0,0 +1,86 @@ +#!/usr/bin/env python +# +# Copyright 2015 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Fingerprints the V8 snapshot blob files. + +Constructs a SHA256 fingerprint of the V8 natives and snapshot blob files and +creates a .cc file which includes these fingerprint as variables. +""" + +import hashlib +import optparse +import os +import sys + +_HEADER = """// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file was generated by fingerprint_v8_snapshot.py. + +namespace gin { +""" + +_FOOTER = """ +} // namespace gin +""" + + +def FingerprintFile(file_path): + input_file = open(file_path, 'rb') + sha256 = hashlib.sha256() + while True: + block = input_file.read(sha256.block_size) + if not block: + break + sha256.update(block) + return sha256.digest() + + +def WriteFingerprint(output_file, variable_name, fingerprint): + output_file.write('\nextern const unsigned char %s[] = { ' % variable_name) + for byte in fingerprint: + output_file.write(str(ord(byte)) + ', ') + output_file.write('};\n') + + +def WriteOutputFile(natives_fingerprint, + snapshot_fingerprint, + output_file_path): + output_dir_path = os.path.dirname(output_file_path) + if not os.path.exists(output_dir_path): + os.makedirs(output_dir_path) + output_file = open(output_file_path, 'w') + + output_file.write(_HEADER) + WriteFingerprint(output_file, 'g_natives_fingerprint', natives_fingerprint) + output_file.write('\n') + WriteFingerprint(output_file, 'g_snapshot_fingerprint', snapshot_fingerprint) + output_file.write(_FOOTER) + + +def main(): + parser = optparse.OptionParser() + + parser.add_option('--snapshot_file', + help='The input V8 snapshot blob file path.') + parser.add_option('--natives_file', + help='The input V8 natives blob file path.') + parser.add_option('--output_file', + help='The path for the output cc file which will be write.') + + options, _ = parser.parse_args() + + natives_fingerprint = FingerprintFile(options.natives_file) + snapshot_fingerprint = FingerprintFile(options.snapshot_file) + WriteOutputFile( + natives_fingerprint, snapshot_fingerprint, options.output_file) + + return 0 + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/gin/gin.gyp b/gin/gin.gyp index aeecb22e..0ea039fe 100644 --- a/gin/gin.gyp +++ b/gin/gin.gyp
@@ -84,6 +84,30 @@ 'wrappable.h', 'wrapper_info.cc', ], + 'conditions': [ + ['v8_use_external_startup_data==1 and OS=="win"', { + 'dependencies': [ + 'gin_v8_snapshot_fingerprint', + '../crypto/crypto.gyp:crypto', + ], + 'sources': [ + '<(gin_gen_path)/v8_snapshot_fingerprint.cc', + ], + 'defines': [ + 'V8_VERIFY_EXTERNAL_STARTUP_DATA', + ] + }], + ], + }, + { + 'target_name': 'gin_v8_snapshot_fingerprint', + 'type': 'none', + 'variables': { + 'snapshot_file': '<(PRODUCT_DIR)/snapshot_blob.bin', + 'natives_file': '<(PRODUCT_DIR)/natives_blob.bin', + 'output_file': '<(gin_gen_path)/v8_snapshot_fingerprint.cc', + }, + 'includes': [ '../gin/fingerprint/fingerprint_v8_snapshot.gypi' ], }, { 'target_name': 'gin_shell',
diff --git a/gin/v8_initializer.cc b/gin/v8_initializer.cc index 4b0630d..c5cf128 100644 --- a/gin/v8_initializer.cc +++ b/gin/v8_initializer.cc
@@ -191,6 +191,36 @@ return opened; } +#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) +bool VerifyV8StartupFile(base::MemoryMappedFile** file, + const unsigned char* fingerprint) { + unsigned char output[crypto::kSHA256Length]; + crypto::SHA256HashString( + base::StringPiece(reinterpret_cast<const char*>((*file)->data()), + (*file)->length()), + output, sizeof(output)); + if (!memcmp(fingerprint, output, sizeof(output))) { + return true; + } + + // TODO(oth): Remove this temporary diagnostics for http://crbug.com/501799 + uint64_t input[sizeof(output)]; + memcpy(input, fingerprint, sizeof(input)); + + base::debug::Alias(output); + base::debug::Alias(input); + + const uint64_t* o64 = reinterpret_cast<const uint64_t*>(output); + const uint64_t* f64 = reinterpret_cast<const uint64_t*>(fingerprint); + LOG(FATAL) << "Natives length " << (*file)->length() + << " H(computed) " << o64[0] << o64[1] << o64[2] << o64[3] + << " H(expected) " << f64[0] << f64[1] << f64[2] << f64[3]; + + delete *file; + *file = NULL; + return false; +} +#endif // V8_VERIFY_EXTERNAL_STARTUP_DATA #endif // V8_USE_EXTERNAL_STARTUP_DATA bool GenerateEntropy(unsigned char* buffer, size_t amount) { @@ -213,37 +243,47 @@ } // namespace #if defined(V8_USE_EXTERNAL_STARTUP_DATA) - -namespace { +#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) +// Defined in gen/gin/v8_snapshot_fingerprint.cc +extern const unsigned char g_natives_fingerprint[]; +extern const unsigned char g_snapshot_fingerprint[]; +#endif // V8_VERIFY_EXTERNAL_STARTUP_DATA enum LoadV8FileResult { V8_LOAD_SUCCESS = 0, V8_LOAD_FAILED_OPEN, V8_LOAD_FAILED_MAP, - V8_LOAD_FAILED_VERIFY, // Deprecated. + V8_LOAD_FAILED_VERIFY, V8_LOAD_MAX_VALUE }; -LoadV8FileResult MapOpenedFile( - const OpenedFileMap::mapped_type& file_region, - base::MemoryMappedFile** mmapped_file_out) { +static LoadV8FileResult MapVerify(const OpenedFileMap::mapped_type& file_region, +#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) + const unsigned char* fingerprint, +#endif + base::MemoryMappedFile** mmapped_file_out) { if (file_region.first == base::kInvalidPlatformFile) return V8_LOAD_FAILED_OPEN; if (!MapV8File(file_region.first, file_region.second, mmapped_file_out)) return V8_LOAD_FAILED_MAP; +#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) + if (!VerifyV8StartupFile(mmapped_file_out, fingerprint)) + return V8_LOAD_FAILED_VERIFY; +#endif // V8_VERIFY_EXTERNAL_STARTUP_DATA return V8_LOAD_SUCCESS; } -} // namespace - // static void V8Initializer::LoadV8Snapshot() { if (g_mapped_snapshot) return; OpenFileIfNecessary(kSnapshotFileName); - LoadV8FileResult result = MapOpenedFile(GetOpenedFile(kSnapshotFileName), - &g_mapped_snapshot); + LoadV8FileResult result = MapVerify(GetOpenedFile(kSnapshotFileName), +#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) + g_snapshot_fingerprint, +#endif + &g_mapped_snapshot); // V8 can't start up without the source of the natives, but it can // start up (slower) without the snapshot. UMA_HISTOGRAM_ENUMERATION("V8.Initializer.LoadV8Snapshot.Result", result, @@ -255,7 +295,10 @@ return; OpenFileIfNecessary(kNativesFileName); - LoadV8FileResult result = MapOpenedFile(GetOpenedFile(kNativesFileName), + LoadV8FileResult result = MapVerify(GetOpenedFile(kNativesFileName), +#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) + g_natives_fingerprint, +#endif &g_mapped_natives); if (result != V8_LOAD_SUCCESS) { LOG(FATAL) << "Couldn't mmap v8 natives data file, status code is " @@ -283,6 +326,10 @@ LoadV8FileResult result = V8_LOAD_SUCCESS; if (!MapV8File(snapshot_pf, snapshot_region, &g_mapped_snapshot)) result = V8_LOAD_FAILED_MAP; +#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) + if (!VerifyV8StartupFile(&g_mapped_snapshot, g_snapshot_fingerprint)) + result = V8_LOAD_FAILED_VERIFY; +#endif // V8_VERIFY_EXTERNAL_STARTUP_DATA if (result == V8_LOAD_SUCCESS) { g_opened_files.Get()[kSnapshotFileName] = std::make_pair(snapshot_pf, snapshot_region); @@ -310,6 +357,11 @@ if (!MapV8File(natives_pf, natives_region, &g_mapped_natives)) { LOG(FATAL) << "Couldn't mmap v8 natives data file"; } +#if defined(V8_VERIFY_EXTERNAL_STARTUP_DATA) + if (!VerifyV8StartupFile(&g_mapped_natives, g_natives_fingerprint)) { + LOG(FATAL) << "Couldn't verify contents of v8 natives data file"; + } +#endif // V8_VERIFY_EXTERNAL_STARTUP_DATA g_opened_files.Get()[kNativesFileName] = std::make_pair(natives_pf, natives_region); }
diff --git a/google_apis/drive/drive_api_requests.cc b/google_apis/drive/drive_api_requests.cc index 307e541..eefaa35 100644 --- a/google_apis/drive/drive_api_requests.cc +++ b/google_apis/drive/drive_api_requests.cc
@@ -15,6 +15,8 @@ #include "base/sequenced_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/task_runner_util.h" #include "base/values.h" @@ -144,37 +146,6 @@ return json_string; } -// Splits |string| into lines by |kHttpBr|. -// Each line does not include |kHttpBr|. -void SplitIntoLines(const std::string& string, - std::vector<base::StringPiece>* output) { - const size_t br_size = std::string(kHttpBr).size(); - std::string::const_iterator it = string.begin(); - std::vector<base::StringPiece> lines; - while (true) { - const std::string::const_iterator next_pos = - std::search(it, string.end(), kHttpBr, kHttpBr + br_size); - lines.push_back(base::StringPiece(it, next_pos)); - if (next_pos == string.end()) - break; - it = next_pos + br_size; - } - output->swap(lines); -} - -// Remove transport padding (spaces and tabs at the end of line) from |piece|. -base::StringPiece TrimTransportPadding(const base::StringPiece& piece) { - size_t trim_size = 0; - while (trim_size < piece.size() && - (piece[piece.size() - 1 - trim_size] == ' ' || - piece[piece.size() - 1 - trim_size] == '\t')) { - ++trim_size; - } - return piece.substr(0, piece.size() - trim_size); -} - -void EmptyClosure(std::unique_ptr<BatchableDelegate>) {} - } // namespace MultipartHttpResponse::MultipartHttpResponse() : code(HTTP_SUCCESS) { @@ -231,8 +202,8 @@ const std::string header = "--" + boundary; const std::string terminator = "--" + boundary + "--"; - std::vector<base::StringPiece> lines; - SplitIntoLines(response, &lines); + std::vector<base::StringPiece> lines = base::SplitStringPieceUsingSubstr( + response, kHttpBr, base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); enum { STATE_START, @@ -274,7 +245,8 @@ body.clear(); continue; } - const base::StringPiece chopped_line = TrimTransportPadding(line); + const base::StringPiece chopped_line = + base::TrimString(line, " \t", base::TRIM_TRAILING); const bool is_new_part = chopped_line == header; const bool was_last_part = chopped_line == terminator; if (is_new_part || was_last_part) { @@ -1346,10 +1318,7 @@ child->data_size = data.size(); total_size += data.size(); - parts.push_back(ContentTypeAndData()); - parts.back().type = kHttpContentType; - parts.back().data = header; - parts.back().data.append(data); + parts.push_back(ContentTypeAndData({kHttpContentType, header + data})); } UMA_HISTOGRAM_COUNTS_100(kUMADriveTotalFileCountInBatchUpload, parts.size()); @@ -1420,12 +1389,12 @@ } for (size_t i = 0; i < parts.size(); ++i) { - BatchableDelegate* const delegate = child_requests_[i]->request.get(); - // Pass onwership of |delegate| so that child_requests_.clear() won't + BatchableDelegate* delegate = child_requests_[i]->request.get(); + // Pass ownership of |delegate| so that child_requests_.clear() won't // kill the delegate. It has to be deleted after the notification. - delegate->NotifyResult( - parts[i].code, parts[i].body, - base::Bind(&EmptyClosure, base::Passed(&child_requests_[i]->request))); + delegate->NotifyResult(parts[i].code, parts[i].body, + base::Bind(&base::DeletePointer<BatchableDelegate>, + child_requests_[i]->request.release())); } child_requests_.clear(); @@ -1433,16 +1402,15 @@ } void BatchUploadRequest::RunCallbackOnPrematureFailure(DriveApiErrorCode code) { - for (auto child : child_requests_) { + for (auto& child : child_requests_) child->request->NotifyError(code); - } child_requests_.clear(); } void BatchUploadRequest::OnURLFetchUploadProgress(const net::URLFetcher* source, int64_t current, int64_t total) { - for (auto child : child_requests_) { + for (auto& child : child_requests_) { if (child->data_offset <= current && current <= child->data_offset + child->data_size) { child->request->NotifyUploadProgress(source, current - child->data_offset,
diff --git a/google_apis/gcm/engine/gservices_settings.cc b/google_apis/gcm/engine/gservices_settings.cc index cde4d7fb..65f4453f 100644 --- a/google_apis/gcm/engine/gservices_settings.cc +++ b/google_apis/gcm/engine/gservices_settings.cc
@@ -227,7 +227,8 @@ return false; } - if (settings_diff && name.find(kDeleteSettingPrefix) == 0) { + if (settings_diff && base::StartsWith(name, kDeleteSettingPrefix, + base::CompareCase::SENSITIVE)) { std::string setting_to_delete = name.substr(arraysize(kDeleteSettingPrefix) - 1); new_settings.erase(setting_to_delete);
diff --git a/gpu/PRESUBMIT.py b/gpu/PRESUBMIT.py index 034a9d8..d993bd90 100644 --- a/gpu/PRESUBMIT.py +++ b/gpu/PRESUBMIT.py
@@ -23,9 +23,9 @@ return [] bots = [ - 'tryserver.chromium.linux:linux_optional_gpu_tests_rel', - 'tryserver.chromium.mac:mac_optional_gpu_tests_rel', - 'tryserver.chromium.win:win_optional_gpu_tests_rel', + 'master.tryserver.chromium.linux:linux_optional_gpu_tests_rel', + 'master.tryserver.chromium.mac:mac_optional_gpu_tests_rel', + 'master.tryserver.chromium.win:win_optional_gpu_tests_rel', ] results = []
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 8ec4d1f..d441c1b 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -10831,7 +10831,7 @@ } void GLES2DecoderTestBase::SetupInitStateExpectations(bool es3_capable) { - const auto& feature_info_ = group_->feature_info(); + auto* feature_info_ = group_->feature_info(); """) # We need to sort the keys so the expectations match for state_name in sorted(_STATES.keys()):
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc b/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc index d1f731f..459e39e 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc +++ b/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc
@@ -492,7 +492,7 @@ const char* kNotArrayNames[] = { "u_name", "u_name[]", "u_name]", "u_name[0a]", "u_name[a0]", "u_name[0a0]", "[3]", ""}; - for (auto name : kNotArrayNames) { + for (auto* name : kNotArrayNames) { GLSLArrayName parsed_name(name); EXPECT_FALSE(parsed_name.IsArrayName()); }
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn index 0dbf9d0..14f25b66 100644 --- a/gpu/command_buffer/service/BUILD.gn +++ b/gpu/command_buffer/service/BUILD.gn
@@ -157,6 +157,7 @@ "//gpu/command_buffer/client:client_sources", "//gpu/command_buffer/common:gles2_utils", "//gpu/config:config_sources", + "//third_party/angle:angle_image_util", "//third_party/angle:commit_id", "//third_party/angle:translator", "//third_party/protobuf:protobuf_lite",
diff --git a/gpu/command_buffer/service/buffer_manager.cc b/gpu/command_buffer/service/buffer_manager.cc index 1407ec8c..41833591 100644 --- a/gpu/command_buffer/service/buffer_manager.cc +++ b/gpu/command_buffer/service/buffer_manager.cc
@@ -8,6 +8,7 @@ #include <limits> +#include "base/format_macros.h" #include "base/logging.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" @@ -638,21 +639,23 @@ bool BufferManager::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, base::trace_event::ProcessMemoryDump* pmd) { - const int client_id = memory_tracker_->ClientId(); + const uint64_t share_group_tracing_guid = + memory_tracker_->ShareGroupTracingGUID(); for (const auto& buffer_entry : buffers_) { const auto& client_buffer_id = buffer_entry.first; const auto& buffer = buffer_entry.second; - std::string dump_name = base::StringPrintf( - "gpu/gl/buffers/client_%d/buffer_%d", client_id, client_buffer_id); + std::string dump_name = + base::StringPrintf("gpu/gl/buffers/share_group_%" PRIu64 "/buffer_%d", + share_group_tracing_guid, client_buffer_id); base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name); dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, base::trace_event::MemoryAllocatorDump::kUnitsBytes, static_cast<uint64_t>(buffer->size())); - auto guid = gl::GetGLBufferGUIDForTracing( - memory_tracker_->ShareGroupTracingGUID(), client_buffer_id); + auto guid = gl::GetGLBufferGUIDForTracing(share_group_tracing_guid, + client_buffer_id); pmd->CreateSharedGlobalAllocatorDump(guid); pmd->AddOwnershipEdge(dump->guid(), guid); }
diff --git a/gpu/command_buffer/service/context_state.cc b/gpu/command_buffer/service/context_state.cc index b717c04..5440b893 100644 --- a/gpu/command_buffer/service/context_state.cc +++ b/gpu/command_buffer/service/context_state.cc
@@ -265,6 +265,26 @@ } } +void ContextState::PushTextureDecompressionUnpackState() const { + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + if (bound_pixel_unpack_buffer.get()) { + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0); + } +} + +void ContextState::RestoreUnpackState() const { + glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment); + if (bound_pixel_unpack_buffer.get()) { + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, + GetBufferId(bound_pixel_unpack_buffer.get())); + glPixelStorei(GL_UNPACK_ROW_LENGTH, unpack_row_length); + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, unpack_image_height); + } +} + void ContextState::RestoreBufferBindings() const { if (vertex_attrib_manager.get()) { Buffer* element_array_buffer =
diff --git a/gpu/command_buffer/service/context_state.h b/gpu/command_buffer/service/context_state.h index 8447ee3..6478704 100644 --- a/gpu/command_buffer/service/context_state.h +++ b/gpu/command_buffer/service/context_state.h
@@ -195,6 +195,9 @@ void RestoreTextureUnitBindings( GLuint unit, const ContextState* prev_state) const; + void PushTextureDecompressionUnpackState() const; + void RestoreUnpackState() const; + // Helper for getting cached state. bool GetStateAsGLint( GLenum pname, GLint* params, GLsizei* num_written) const;
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index 413e11d..4be125a 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc
@@ -137,7 +137,8 @@ ext_multisample_compatibility(false), ext_blend_func_extended(false), ext_read_format_bgra(false), - desktop_srgb_support(false) {} + desktop_srgb_support(false), + arb_es3_compatibility(false) {} FeatureInfo::FeatureInfo() { InitializeBasicState(base::CommandLine::InitializedForCurrentProcess() @@ -644,6 +645,12 @@ validators_.read_pixel_format.AddValue(GL_BGRA_EXT); } + // GL_ARB_ES3_compatibility adds support for some ES3 texture formats that are + // not supported in desktop GL + feature_flags_.arb_es3_compatibility = + extensions.Contains("GL_ARB_ES3_compatibility") && + !gl_version_info_->is_es; + // glGetInteger64v for timestamps is implemented on the client side in a way // that it does not depend on a driver-level implementation of // glGetInteger64v. The GPUTimer class which implements timer queries can also
diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h index ff2222fb..a34fff1 100644 --- a/gpu/command_buffer/service/feature_info.h +++ b/gpu/command_buffer/service/feature_info.h
@@ -91,6 +91,7 @@ bool ext_blend_func_extended; bool ext_read_format_bgra; bool desktop_srgb_support; + bool arb_es3_compatibility; }; FeatureInfo();
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 6df7f6a2..3ccb1c4 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -64,6 +64,7 @@ #include "gpu/command_buffer/service/transform_feedback_manager.h" #include "gpu/command_buffer/service/vertex_array_manager.h" #include "gpu/command_buffer/service/vertex_attrib_manager.h" +#include "third_party/angle/src/image_util/loadimage.h" #include "third_party/smhasher/src/City.h" #include "ui/gfx/buffer_types.h" #include "ui/gfx/geometry/point.h" @@ -402,7 +403,7 @@ bool AllocateStorage(const gfx::Size& size, GLenum format, bool zero); // Copy the contents of the currently bound frame buffer. - void Copy(const gfx::Size& size, GLenum format); + void Copy(); // Destroy the render texture. This must be explicitly called before // destroying this object. @@ -1900,9 +1901,13 @@ bool ValidateCompressedTexDimensions( const char* function_name, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum format); - bool ValidateCompressedTexFuncData( - const char* function_name, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLsizei size); + bool ValidateCompressedTexFuncData(const char* function_name, + GLsizei width, + GLsizei height, + GLsizei depth, + GLenum format, + GLsizei size, + const GLvoid* data); bool ValidateCompressedTexSubDimensions( const char* function_name, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, @@ -2592,15 +2597,14 @@ return success; } -void BackTexture::Copy(const gfx::Size& size, GLenum format) { +void BackTexture::Copy() { DCHECK_NE(id(), 0u); ScopedGLErrorSuppressor suppressor("BackTexture::Copy", decoder_->state_.GetErrorState()); ScopedTextureBinder binder(&decoder_->state_, id(), Target()); - glCopyTexImage2D(Target(), - 0, // level - format, 0, 0, size.width(), size.height(), - 0); // border + glCopyTexSubImage2D(Target(), + 0, // level + 0, 0, 0, 0, size_.width(), size_.height()); } void BackTexture::Destroy() { @@ -11482,6 +11486,146 @@ {12, 10}, {12, 12}}; +bool CheckETCFormatSupport(const FeatureInfo& featureInfo) { + const gl::GLVersionInfo& versionInfo = featureInfo.gl_version_info(); + return versionInfo.IsAtLeastGL(4, 3) || versionInfo.IsAtLeastGLES(3, 0) || + featureInfo.feature_flags().arb_es3_compatibility; +} + +using CompressedFormatSupportCheck = bool (*)(const FeatureInfo&); +using CompressedFormatDecompressionFunction = void (*)(size_t width, + size_t height, + size_t depth, + const uint8_t* input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t* output, + size_t outputRowPitch, + size_t outputDepthPitch); + +struct CompressedFormatInfo { + GLenum format; + uint32_t block_size; + uint32_t bytes_per_block; + CompressedFormatSupportCheck support_check; + CompressedFormatDecompressionFunction decompression_function; + GLenum decompressed_internal_format; + GLenum decompressed_format; + GLenum decompressed_type; +}; + +const CompressedFormatInfo kCompressedFormatInfoArray[] = { + { + GL_COMPRESSED_R11_EAC, 4, 8, CheckETCFormatSupport, + angle::LoadEACR11ToR8, GL_R8, GL_RED, GL_UNSIGNED_BYTE, + }, + { + GL_COMPRESSED_SIGNED_R11_EAC, 4, 8, CheckETCFormatSupport, + angle::LoadEACR11SToR8, GL_R8_SNORM, GL_RED, GL_BYTE, + }, + { + GL_COMPRESSED_RG11_EAC, 4, 16, CheckETCFormatSupport, + angle::LoadEACRG11ToRG8, GL_RG8, GL_RG, GL_UNSIGNED_BYTE, + }, + { + GL_COMPRESSED_SIGNED_RG11_EAC, 4, 16, CheckETCFormatSupport, + angle::LoadEACRG11SToRG8, GL_RG8_SNORM, GL_RG, GL_BYTE, + }, + { + GL_COMPRESSED_RGB8_ETC2, 4, 8, CheckETCFormatSupport, + angle::LoadETC2RGB8ToRGBA8, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, + }, + { + GL_COMPRESSED_SRGB8_ETC2, 4, 8, CheckETCFormatSupport, + angle::LoadETC2SRGB8ToRGBA8, GL_SRGB8_ALPHA8, GL_SRGB_ALPHA, + GL_UNSIGNED_BYTE, + }, + { + GL_COMPRESSED_RGBA8_ETC2_EAC, 4, 16, CheckETCFormatSupport, + angle::LoadETC2RGBA8ToRGBA8, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, + }, + { + GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 8, + CheckETCFormatSupport, angle::LoadETC2RGB8A1ToRGBA8, GL_RGBA8, GL_RGBA, + GL_UNSIGNED_BYTE, + }, + { + GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, 4, 16, CheckETCFormatSupport, + angle::LoadETC2SRGBA8ToSRGBA8, GL_SRGB8_ALPHA8, GL_SRGB_ALPHA, + GL_UNSIGNED_BYTE, + }, + { + GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 8, + CheckETCFormatSupport, angle::LoadETC2SRGB8A1ToRGBA8, GL_SRGB8_ALPHA8, + GL_SRGB_ALPHA, GL_UNSIGNED_BYTE, + }, +}; + +const CompressedFormatInfo* GetCompressedFormatInfo(GLenum format) { + for (size_t i = 0; i < arraysize(kCompressedFormatInfoArray); i++) { + if (kCompressedFormatInfoArray[i].format == format) { + return &kCompressedFormatInfoArray[i]; + } + } + return nullptr; +} + +uint32_t GetCompressedFormatRowPitch(const CompressedFormatInfo& info, + uint32_t width) { + uint32_t num_blocks_wide = (width + info.block_size - 1) / info.block_size; + return num_blocks_wide * info.bytes_per_block; +} + +uint32_t GetCompressedFormatDepthPitch(const CompressedFormatInfo& info, + uint32_t width, + uint32_t height) { + uint32_t num_blocks_high = (height + info.block_size - 1) / info.block_size; + return num_blocks_high * GetCompressedFormatRowPitch(info, width); +} + +std::unique_ptr<uint8_t[]> DecompressTextureData( + const ContextState& state, + const CompressedFormatInfo& info, + uint32_t width, + uint32_t height, + uint32_t depth, + GLsizei image_size, + const void* data) { + uint32_t output_pixel_size = GLES2Util::ComputeImageGroupSize( + info.decompressed_format, info.decompressed_type); + std::unique_ptr<uint8_t[]> decompressed_data( + new uint8_t[output_pixel_size * width * height]); + + // If a PBO is bound, map it to decompress the data. + const void* input_data = data; + if (state.bound_pixel_unpack_buffer) { + input_data = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, + reinterpret_cast<GLintptr>(data), image_size, + GL_MAP_READ_BIT); + if (input_data == nullptr) { + LOG(ERROR) << "Failed to map pixel unpack buffer."; + return nullptr; + } + } + + DCHECK_NE(input_data, nullptr); + info.decompression_function( + width, height, depth, static_cast<const uint8_t*>(input_data), + GetCompressedFormatRowPitch(info, width), + GetCompressedFormatDepthPitch(info, width, height), + decompressed_data.get(), output_pixel_size * width, + output_pixel_size * width * height); + + if (state.bound_pixel_unpack_buffer) { + if (glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER) != GL_TRUE) { + LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE"; + return nullptr; + } + } + + return decompressed_data; +} + bool IsValidDXTSize(GLint level, GLsizei size) { // TODO(zmo): Linux NVIDIA driver does allow size of 1 and 2 on level 0. // However, the WebGL conformance test and blink side code forbid it. @@ -11623,9 +11767,13 @@ return true; } -bool GLES2DecoderImpl::ValidateCompressedTexFuncData( - const char* function_name, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLsizei size) { +bool GLES2DecoderImpl::ValidateCompressedTexFuncData(const char* function_name, + GLsizei width, + GLsizei height, + GLsizei depth, + GLenum format, + GLsizei size, + const GLvoid* data) { GLsizei bytes_required = 0; if (!GetCompressedTexSizeInBytes( function_name, width, height, depth, format, &bytes_required)) { @@ -11638,6 +11786,25 @@ return false; } + if (state_.bound_pixel_unpack_buffer.get()) { + if (state_.bound_pixel_unpack_buffer->GetMappedRange() != nullptr) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, + "pixel unpack buffer is mapped"); + return false; + } + + base::CheckedNumeric<GLintptr> pbo_bytes_required( + reinterpret_cast<GLintptr>(data)); + pbo_bytes_required += bytes_required; + if (!pbo_bytes_required.IsValid() || + pbo_bytes_required.ValueOrDie() > + state_.bound_pixel_unpack_buffer->size()) { + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, + "pixel unpack buffer is not large enough"); + return false; + } + } + return true; } @@ -11889,8 +12056,8 @@ } if (!ValidateCompressedTexDimensions("glCompressedTexImage2D", target, level, width, height, 1, internal_format) || - !ValidateCompressedTexFuncData("glCompressedTexImage2D", width, height, - 1, internal_format, image_size)) { + !ValidateCompressedTexFuncData("glCompressedTexImage2D", width, height, 1, + internal_format, image_size, data)) { return error::kNoError; } @@ -11905,14 +12072,32 @@ } std::unique_ptr<int8_t[]> zero; - if (!data) { + if (!state_.bound_pixel_unpack_buffer && !data) { zero.reset(new int8_t[image_size]); memset(zero.get(), 0, image_size); data = zero.get(); } LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage2D"); - glCompressedTexImage2D( - target, level, internal_format, width, height, border, image_size, data); + + const CompressedFormatInfo* format_info = + GetCompressedFormatInfo(internal_format); + if (format_info != nullptr && !format_info->support_check(*feature_info_)) { + std::unique_ptr<uint8_t[]> decompressed_data = DecompressTextureData( + state_, *format_info, width, height, 1, image_size, data); + if (!decompressed_data) { + MarkContextLost(error::kGuilty); + group_->LoseContexts(error::kInnocent); + return error::kLostContext; + } + state_.PushTextureDecompressionUnpackState(); + glTexImage2D(target, level, format_info->decompressed_internal_format, + width, height, border, format_info->decompressed_format, + format_info->decompressed_type, decompressed_data.get()); + state_.RestoreUnpackState(); + } else { + glCompressedTexImage2D(target, level, internal_format, width, height, + border, image_size, data); + } GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage2D"); if (error == GL_NO_ERROR) { texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format, @@ -11962,7 +12147,8 @@ if (!ValidateCompressedTexDimensions("glCompressedTexImage3D", target, level, width, height, depth, internal_format) || !ValidateCompressedTexFuncData("glCompressedTexImage3D", width, height, - depth, internal_format, image_size)) { + depth, internal_format, image_size, + data)) { return error::kNoError; } @@ -11977,14 +12163,31 @@ } std::unique_ptr<int8_t[]> zero; - if (!data) { + if (!state_.bound_pixel_unpack_buffer && !data) { zero.reset(new int8_t[image_size]); memset(zero.get(), 0, image_size); data = zero.get(); } LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCompressedTexImage3D"); - glCompressedTexImage3D(target, level, internal_format, width, height, depth, - border, image_size, data); + const CompressedFormatInfo* format_info = + GetCompressedFormatInfo(internal_format); + if (format_info != nullptr && !format_info->support_check(*feature_info_)) { + std::unique_ptr<uint8_t[]> decompressed_data = DecompressTextureData( + state_, *format_info, width, height, depth, image_size, data); + if (!decompressed_data) { + MarkContextLost(error::kGuilty); + group_->LoseContexts(error::kInnocent); + return error::kLostContext; + } + state_.PushTextureDecompressionUnpackState(); + glTexImage3D(target, level, format_info->decompressed_internal_format, + width, height, depth, border, format_info->decompressed_format, + format_info->decompressed_type, decompressed_data.get()); + state_.RestoreUnpackState(); + } else { + glCompressedTexImage3D(target, level, internal_format, width, height, depth, + border, image_size, data); + } GLenum error = LOCAL_PEEK_GL_ERROR("glCompressedTexImage3D"); if (error == GL_NO_ERROR) { texture_manager()->SetLevelInfo(texture_ref, target, level, internal_format, @@ -12035,13 +12238,11 @@ "bad dimensions"); return; } - if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D", - width, height, depth, format, - image_size) || - !ValidateCompressedTexSubDimensions("glCompressedTexSubImage3D", - target, level, xoffset, yoffset, - zoffset, width, height, depth, - format, texture)) { + if (!ValidateCompressedTexFuncData("glCompressedTexSubImage3D", width, height, + depth, format, image_size, data) || + !ValidateCompressedTexSubDimensions( + "glCompressedTexSubImage3D", target, level, xoffset, yoffset, zoffset, + width, height, depth, format, texture)) { return; } @@ -12049,9 +12250,26 @@ // because the validation above means you can only get here if the level // is already a matching compressed format and in that case // CompressedTexImage3D already cleared the texture. - glCompressedTexSubImage3D( - target, level, xoffset, yoffset, zoffset, width, height, depth, format, - image_size, data); + + const CompressedFormatInfo* format_info = + GetCompressedFormatInfo(internal_format); + if (format_info != nullptr && !format_info->support_check(*feature_info_)) { + std::unique_ptr<uint8_t[]> decompressed_data = DecompressTextureData( + state_, *format_info, width, height, depth, image_size, data); + if (!decompressed_data) { + MarkContextLost(error::kGuilty); + group_->LoseContexts(error::kInnocent); + return; + } + state_.PushTextureDecompressionUnpackState(); + glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, + depth, format_info->decompressed_format, + format_info->decompressed_type, decompressed_data.get()); + state_.RestoreUnpackState(); + } else { + glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, + height, depth, format, image_size, data); + } // This may be a slow command. Exit command processing to allow for // context preemption and GPU watchdog checks. @@ -12274,11 +12492,11 @@ return; } - if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D", - width, height, 1, format, image_size) || - !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D", - target, level, xoffset, yoffset, 0, - width, height, 1, format, texture)) { + if (!ValidateCompressedTexFuncData("glCompressedTexSubImage2D", width, height, + 1, format, image_size, data) || + !ValidateCompressedTexSubDimensions("glCompressedTexSubImage2D", target, + level, xoffset, yoffset, 0, width, + height, 1, format, texture)) { return; } @@ -12300,8 +12518,25 @@ DCHECK(texture->IsLevelCleared(target, level)); } - glCompressedTexSubImage2D( - target, level, xoffset, yoffset, width, height, format, image_size, data); + const CompressedFormatInfo* format_info = + GetCompressedFormatInfo(internal_format); + if (format_info != nullptr && !format_info->support_check(*feature_info_)) { + std::unique_ptr<uint8_t[]> decompressed_data = DecompressTextureData( + state_, *format_info, width, height, 1, image_size, data); + if (!decompressed_data) { + MarkContextLost(error::kGuilty); + group_->LoseContexts(error::kInnocent); + return; + } + state_.PushTextureDecompressionUnpackState(); + glTexSubImage2D(target, level, xoffset, yoffset, width, height, + format_info->decompressed_format, + format_info->decompressed_type, decompressed_data.get()); + state_.RestoreUnpackState(); + } else { + glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, + format, image_size, data); + } // This may be a slow command. Exit command processing to allow for // context preemption and GPU watchdog checks. @@ -13479,9 +13714,7 @@ if (offscreen_target_buffer_preserved_) { // Copy the target frame buffer to the saved offscreen texture. - offscreen_saved_color_texture_->Copy( - offscreen_saved_color_texture_->size(), - offscreen_saved_color_format_); + offscreen_saved_color_texture_->Copy(); } else { offscreen_saved_color_texture_.swap(offscreen_target_color_texture_); offscreen_target_frame_buffer_->AttachRenderTexture( @@ -15098,13 +15331,22 @@ } } + GLenum compatibility_internal_format = internal_format; + const CompressedFormatInfo* format_info = + GetCompressedFormatInfo(internal_format); + if (format_info != nullptr && !format_info->support_check(*feature_info_)) { + compatibility_internal_format = format_info->decompressed_internal_format; + } + // TODO(zmo): We might need to emulate TexStorage using TexImage or // CompressedTexImage on Mac OSX where we expose ES3 APIs when the underlying // driver is lower than 4.2 and ARB_texture_storage extension doesn't exist. if (dimension == ContextState::k2D) { - glTexStorage2DEXT(target, levels, internal_format, width, height); + glTexStorage2DEXT(target, levels, compatibility_internal_format, width, + height); } else { - glTexStorage3D(target, levels, internal_format, width, height, depth); + glTexStorage3D(target, levels, compatibility_internal_format, width, height, + depth); } {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h index 9868745..e0dd006 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h
@@ -35,7 +35,7 @@ } void GLES2DecoderTestBase::SetupInitStateExpectations(bool es3_capable) { - const auto& feature_info_ = group_->feature_info(); + auto* feature_info_ = group_->feature_info(); EXPECT_CALL(*gl_, BlendColor(0.0f, 0.0f, 0.0f, 0.0f)) .Times(1) .RetiresOnSaturation();
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc index fa72a021..0e53ba25 100644 --- a/gpu/command_buffer/service/program_manager.cc +++ b/gpu/command_buffer/service/program_manager.cc
@@ -1073,6 +1073,14 @@ set_log_info("glBindUniformLocationCHROMIUM() conflicts"); return false; } + if (DetectInterfaceBlocksMismatch(&conflicting_name)) { + std::string info_log = + "Interface blocks with the same name but different" + " fields/layout: " + + conflicting_name; + set_log_info(ProcessLogInfo(info_log).c_str()); + return false; + } if (DetectVaryingsMismatch(&conflicting_name)) { std::string info_log = "Varyings with the same name but different type, " "or statically used varyings in fragment shader " @@ -1620,6 +1628,29 @@ return false; } +bool Program::DetectInterfaceBlocksMismatch( + std::string* conflicting_name) const { + std::map<std::string, const sh::InterfaceBlock*> interface_pointer_map; + for (auto shader : attached_shaders_) { + const InterfaceBlockMap& shader_interfaces = shader->interface_block_map(); + for (const auto& it : shader_interfaces) { + const auto& name = it.first; + auto hit = interface_pointer_map.find(name); + if (hit == interface_pointer_map.end()) { + interface_pointer_map[name] = &(it.second); + } else { + // If an interface is in the map, i.e., it has already been declared by + // another shader, then the layout must match. + if (hit->second->isSameInterfaceBlockAtLinkTime(it.second)) + continue; + *conflicting_name = name; + return true; + } + } + } + return false; +} + bool Program::DetectVaryingsMismatch(std::string* conflicting_name) const { DCHECK(attached_shaders_[0].get() && attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER && @@ -1654,7 +1685,7 @@ } bool Program::DetectFragmentInputLocationBindingConflicts() const { - auto shader = attached_shaders_[ShaderTypeToIndex(GL_FRAGMENT_SHADER)].get(); + auto* shader = attached_shaders_[ShaderTypeToIndex(GL_FRAGMENT_SHADER)].get(); if (!shader || !shader->valid()) return false;
diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h index 734e50f..a735023 100644 --- a/gpu/command_buffer/service/program_manager.h +++ b/gpu/command_buffer/service/program_manager.h
@@ -345,6 +345,10 @@ // conflicting_name if such cases are detected. bool DetectUniformsMismatch(std::string* conflicting_name) const; + // Detects if there are interface blocks of the same name but different + // layouts. + bool DetectInterfaceBlocksMismatch(std::string* conflicting_name) const; + // Return true if a varying is statically used in fragment shader, but it // is not declared in vertex shader. bool DetectVaryingsMismatch(std::string* conflicting_name) const;
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index f6a75dd..07b587b 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc
@@ -12,6 +12,7 @@ #include <utility> #include "base/bits.h" +#include "base/format_macros.h" #include "base/lazy_instance.h" #include "base/metrics/histogram_macros.h" #include "base/strings/stringprintf.h" @@ -3068,9 +3069,9 @@ if (size == 0) return; - std::string dump_name = - base::StringPrintf("gpu/gl/textures/client_%d/texture_%d", - memory_tracker_->ClientId(), ref->client_id()); + std::string dump_name = base::StringPrintf( + "gpu/gl/textures/share_group_%" PRIu64 "/texture_%d", + memory_tracker_->ShareGroupTracingGUID(), ref->client_id()); base::trace_event::MemoryAllocatorDump* dump = pmd->CreateAllocatorDump(dump_name); @@ -3355,7 +3356,7 @@ } void Texture::IncrementManagerServiceIdGeneration() { - for (auto ref : refs_) { + for (auto* ref : refs_) { TextureManager* manager = ref->manager(); manager->IncrementServiceIdGeneration(); }
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc index aad304c..6d6658cb 100644 --- a/gpu/command_buffer/tests/gl_manager.cc +++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -188,7 +188,8 @@ force_shader_name_hashing(false), multisampled(false), backbuffer_alpha(true), - image_factory(nullptr) {} + image_factory(nullptr), + preserve_backbuffer(false) {} GLManager::GLManager() : sync_point_manager_(nullptr), @@ -293,6 +294,7 @@ attribs.should_use_native_gmb_for_backbuffer = options.image_factory != nullptr; attribs.offscreen_framebuffer_size = options.size; + attribs.buffer_preserved = options.preserve_backbuffer; if (!context_group) { GpuDriverBugWorkarounds gpu_driver_bug_workaround(&command_line);
diff --git a/gpu/command_buffer/tests/gl_manager.h b/gpu/command_buffer/tests/gl_manager.h index 4dff34d7..aa8a49a 100644 --- a/gpu/command_buffer/tests/gl_manager.h +++ b/gpu/command_buffer/tests/gl_manager.h
@@ -82,6 +82,8 @@ bool backbuffer_alpha; // The ImageFactory to use to generate images for the backbuffer. gpu::ImageFactory* image_factory; + // Whether to preserve the backbuffer after a call to SwapBuffers(). + bool preserve_backbuffer; }; GLManager(); ~GLManager() override;
diff --git a/gpu/command_buffer/tests/gl_native_gmb_backbuffer_unittest.cc b/gpu/command_buffer/tests/gl_native_gmb_backbuffer_unittest.cc index 2bb44e4..cafe0c6 100644 --- a/gpu/command_buffer/tests/gl_native_gmb_backbuffer_unittest.cc +++ b/gpu/command_buffer/tests/gl_native_gmb_backbuffer_unittest.cc
@@ -15,21 +15,68 @@ #include "ui/gl/gl_context.h" #include "ui/gl/gl_image.h" +#if defined(OS_MACOSX) +#include "gpu/ipc/service/gpu_memory_buffer_factory_io_surface.h" +#endif + namespace gpu { class GLNativeGMBTest : public testing::Test { protected: void SetUp() override { gl_.Initialize(GLManager::Options()); - image_factory_.SetRequiredTextureType(GL_TEXTURE_RECTANGLE_ARB); } void TearDown() override { gl_.Destroy(); } + // Runs a simple battery of tests. + void RunBackbufferTestWithOptions(const GLManager::Options& options) { + GLManager gl; + gl.Initialize(options); + gl.MakeCurrent(); + + // Clear the back buffer and check that it has the right values. + glClearColor(0.0f, 0.25f, 0.5f, 0.7f); + glClear(GL_COLOR_BUFFER_BIT); + uint8_t pixel[4]; + memset(pixel, 0, 4); + glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel); + EXPECT_NEAR(0u, pixel[0], 2); + EXPECT_NEAR(64u, pixel[1], 2); + EXPECT_NEAR(127u, pixel[2], 2); + uint8_t alpha = options.backbuffer_alpha ? 178 : 255; + EXPECT_NEAR(alpha, pixel[3], 2); + + // Resize, then clear the back buffer and check its contents. + glResizeCHROMIUM(10, 10, 1, true); + glClearColor(0.5f, 0.6f, 0.7f, 0.8f); + glClear(GL_COLOR_BUFFER_BIT); + memset(pixel, 0, 4); + glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel); + EXPECT_NEAR(128u, pixel[0], 2); + EXPECT_NEAR(153u, pixel[1], 2); + EXPECT_NEAR(178u, pixel[2], 2); + uint8_t alpha2 = options.backbuffer_alpha ? 204 : 255; + EXPECT_NEAR(alpha2, pixel[3], 2); + + // Swap buffers, then clear the back buffer and check its contents. + ::gles2::GetGLContext()->SwapBuffers(); + glClearColor(0.1f, 0.2f, 0.3f, 0.4f); + glClear(GL_COLOR_BUFFER_BIT); + memset(pixel, 0, 4); + glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel); + EXPECT_NEAR(25u, pixel[0], 2); + EXPECT_NEAR(51u, pixel[1], 2); + EXPECT_NEAR(76u, pixel[2], 2); + uint8_t alpha3 = options.backbuffer_alpha ? 102 : 255; + EXPECT_NEAR(alpha3, pixel[3], 2); + + gl.Destroy(); + } + GLManager gl_; - TextureImageFactory image_factory_; }; TEST_F(GLNativeGMBTest, TestNativeGMBBackbufferWithDifferentConfigurations) { @@ -37,55 +84,25 @@ LOG(INFO) << "GL_ARB_texture_rectangle not supported. Skipping test..."; return; } +#if defined(OS_MACOSX) + GpuMemoryBufferFactoryIOSurface image_factory; +#else + TextureImageFactory image_factory; + image_factory.SetRequiredTextureType(GL_TEXTURE_RECTANGLE_ARB); +#endif for (int has_alpha = 0; has_alpha <= 1; ++has_alpha) { for (int msaa = 0; msaa <= 1; ++msaa) { - GLManager::Options options; - options.image_factory = &image_factory_; - options.multisampled = msaa == 1; - options.backbuffer_alpha = has_alpha == 1; + for (int preserve_backbuffer = 0; preserve_backbuffer <= 1; + ++preserve_backbuffer) { + GLManager::Options options; + options.image_factory = &image_factory; + options.multisampled = msaa == 1; + options.backbuffer_alpha = has_alpha == 1; + options.preserve_backbuffer = preserve_backbuffer; - GLManager gl; - gl.Initialize(options); - gl.MakeCurrent(); - - // Clear the back buffer and check that it has the right values. - glClearColor(0.0f, 0.25f, 0.5f, 0.7f); - glClear(GL_COLOR_BUFFER_BIT); - uint8_t pixel[4]; - memset(pixel, 0, 4); - glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel); - EXPECT_NEAR(0u, pixel[0], 2); - EXPECT_NEAR(64u, pixel[1], 2); - EXPECT_NEAR(127u, pixel[2], 2); - uint8_t alpha = has_alpha ? 178 : 255; - EXPECT_NEAR(alpha, pixel[3], 2); - - // Resize, then clear the back buffer and check its contents. - glResizeCHROMIUM(10, 10, 1, true); - glClearColor(0.5f, 0.6f, 0.7f, 0.8f); - glClear(GL_COLOR_BUFFER_BIT); - memset(pixel, 0, 4); - glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel); - EXPECT_NEAR(128u, pixel[0], 2); - EXPECT_NEAR(153u, pixel[1], 2); - EXPECT_NEAR(178u, pixel[2], 2); - uint8_t alpha2 = has_alpha ? 204 : 255; - EXPECT_NEAR(alpha2, pixel[3], 2); - - // Swap buffers, then clear the back buffer and check its contents. - ::gles2::GetGLContext()->SwapBuffers(); - glClearColor(0.1f, 0.2f, 0.3f, 0.4f); - glClear(GL_COLOR_BUFFER_BIT); - memset(pixel, 0, 4); - glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel); - EXPECT_NEAR(25u, pixel[0], 2); - EXPECT_NEAR(51u, pixel[1], 2); - EXPECT_NEAR(76u, pixel[2], 2); - uint8_t alpha3 = has_alpha ? 102 : 255; - EXPECT_NEAR(alpha3, pixel[3], 2); - - gl.Destroy(); + RunBackbufferTestWithOptions(options); + } } } }
diff --git a/gpu/config/gpu_control_list.cc b/gpu/config/gpu_control_list.cc index 752003fe..a1e1ae5 100644 --- a/gpu/config/gpu_control_list.cc +++ b/gpu/config/gpu_control_list.cc
@@ -1394,14 +1394,11 @@ bool GpuControlList::LoadList( const std::string& json_context, GpuControlList::OsFilter os_filter) { - std::unique_ptr<base::Value> root = base::JSONReader::Read(json_context); - if (root.get() == NULL || !root->IsType(base::Value::TYPE_DICTIONARY)) + std::unique_ptr<base::DictionaryValue> root = + base::DictionaryValue::From(base::JSONReader::Read(json_context)); + if (!root) return false; - - base::DictionaryValue* root_dictionary = - static_cast<base::DictionaryValue*>(root.get()); - DCHECK(root_dictionary); - return LoadList(*root_dictionary, os_filter); + return LoadList(*root, os_filter); } bool GpuControlList::LoadList(const base::DictionaryValue& parsed_json,
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp index 45a6bac0..da5f917 100644 --- a/gpu/gpu.gyp +++ b/gpu/gpu.gyp
@@ -699,6 +699,7 @@ '../build/android/disable_gcc_lto.gypi', ], 'dependencies': [ + '../third_party/angle/src/angle.gyp:angle_image_util', 'command_buffer_common', 'disk_cache_proto', 'gpu_config', @@ -793,6 +794,7 @@ ], 'dependencies': [ '../base/base.gyp:base', + '../third_party/angle/src/angle.gyp:angle_image_util', 'command_buffer/command_buffer.gyp:gles2_utils', 'disk_cache_proto', ],
diff --git a/gpu/ipc/common/BUILD.gn b/gpu/ipc/common/BUILD.gn index a22105f8..67ca2e7 100644 --- a/gpu/ipc/common/BUILD.gn +++ b/gpu/ipc/common/BUILD.gn
@@ -121,6 +121,7 @@ sources = [ "capabilities.mojom", "command_buffer.mojom", + "gpu_info.mojom", "mailbox.mojom", "mailbox_holder.mojom", "sync_token.mojom",
diff --git a/gpu/ipc/common/OWNERS b/gpu/ipc/common/OWNERS index a1ff686..93c2189 100644 --- a/gpu/ipc/common/OWNERS +++ b/gpu/ipc/common/OWNERS
@@ -6,5 +6,9 @@ # The following lines are redundant, they're just to silence the presubmit per-file *_messages*.h=set noparent per-file *_messages*.h=file://ipc/SECURITY_OWNERS +per-file *.mojom=set noparent +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
diff --git a/gpu/ipc/common/gpu_info.mojom b/gpu/ipc/common/gpu_info.mojom new file mode 100644 index 0000000..26b83872 --- /dev/null +++ b/gpu/ipc/common/gpu_info.mojom
@@ -0,0 +1,21 @@ +// 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. + +module gpu.mojom; + +// gpu::GPUInfo::GPUDevice +struct GpuDevice { + uint32 vendor_id; + uint32 device_id; + bool active; + string vendor_string; + string device_string; +}; + +enum CollectInfoResult { + kCollectInfoNone = 0, + kCollectInfoSuccess = 1, + kCollectInfoNonFatalFailure = 2, + kCollectInfoFatalFailure = 3 +};
diff --git a/gpu/ipc/common/gpu_info.typemap b/gpu/ipc/common/gpu_info.typemap new file mode 100644 index 0000000..3282fde --- /dev/null +++ b/gpu/ipc/common/gpu_info.typemap
@@ -0,0 +1,17 @@ +# 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. + +mojom = "//gpu/ipc/common/gpu_info.mojom" +public_headers = [ "//gpu/config/gpu_info.h" ] +traits_headers = [ "//gpu/ipc/common/gpu_info_struct_traits.h" ] +sources = [ + "//gpu/ipc/common/gpu_info_struct_traits.cc", +] +deps = [ + "//gpu/config", +] +type_mappings = [ + "gpu.mojom.GpuDevice=::gpu::GPUInfo::GPUDevice", + "gpu.mojom.CollectInfoResult=::gpu::CollectInfoResult", +]
diff --git a/gpu/ipc/common/gpu_info_struct_traits.cc b/gpu/ipc/common/gpu_info_struct_traits.cc new file mode 100644 index 0000000..6bcea5ce --- /dev/null +++ b/gpu/ipc/common/gpu_info_struct_traits.cc
@@ -0,0 +1,60 @@ +// 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 "gpu/ipc/common/gpu_info_struct_traits.h" + +namespace mojo { + +// static +bool StructTraits<gpu::mojom::GpuDevice, gpu::GPUInfo::GPUDevice>::Read( + gpu::mojom::GpuDeviceDataView data, + gpu::GPUInfo::GPUDevice* out) { + out->vendor_id = data.vendor_id(); + out->device_id = data.device_id(); + out->active = data.active(); + return data.ReadVendorString(&out->vendor_string) && + data.ReadDeviceString(&out->device_string); +} + +// static +gpu::mojom::CollectInfoResult +EnumTraits<gpu::mojom::CollectInfoResult, gpu::CollectInfoResult>::ToMojom( + gpu::CollectInfoResult collect_info_result) { + switch (collect_info_result) { + case gpu::CollectInfoResult::kCollectInfoNone: + return gpu::mojom::CollectInfoResult::kCollectInfoNone; + case gpu::CollectInfoResult::kCollectInfoSuccess: + return gpu::mojom::CollectInfoResult::kCollectInfoSuccess; + case gpu::CollectInfoResult::kCollectInfoNonFatalFailure: + return gpu::mojom::CollectInfoResult::kCollectInfoNonFatalFailure; + case gpu::CollectInfoResult::kCollectInfoFatalFailure: + return gpu::mojom::CollectInfoResult::kCollectInfoFatalFailure; + } + NOTREACHED() << "Invalid CollectInfoResult value:" << collect_info_result; + return gpu::mojom::CollectInfoResult::kCollectInfoNone; +} + +// static +bool EnumTraits<gpu::mojom::CollectInfoResult, gpu::CollectInfoResult>:: + FromMojom(gpu::mojom::CollectInfoResult input, + gpu::CollectInfoResult* out) { + switch (input) { + case gpu::mojom::CollectInfoResult::kCollectInfoNone: + *out = gpu::CollectInfoResult::kCollectInfoNone; + return true; + case gpu::mojom::CollectInfoResult::kCollectInfoSuccess: + *out = gpu::CollectInfoResult::kCollectInfoSuccess; + return true; + case gpu::mojom::CollectInfoResult::kCollectInfoNonFatalFailure: + *out = gpu::CollectInfoResult::kCollectInfoNonFatalFailure; + return true; + case gpu::mojom::CollectInfoResult::kCollectInfoFatalFailure: + *out = gpu::CollectInfoResult::kCollectInfoFatalFailure; + return true; + } + NOTREACHED() << "Invalid CollectInfoResult value:" << input; + return false; +} + +} // namespace mojo
diff --git a/gpu/ipc/common/gpu_info_struct_traits.h b/gpu/ipc/common/gpu_info_struct_traits.h new file mode 100644 index 0000000..ca14216 --- /dev/null +++ b/gpu/ipc/common/gpu_info_struct_traits.h
@@ -0,0 +1,51 @@ +// 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 CC_IPC_GPU_STRUCT_TRAITS_H_ +#define CC_IPC_GPU_STRUCT_TRAITS_H_ + +#include "gpu/config/gpu_info.h" +#include "gpu/ipc/common/gpu_info.mojom.h" + +namespace mojo { + +template <> +struct StructTraits<gpu::mojom::GpuDevice, gpu::GPUInfo::GPUDevice> { + static bool Read(gpu::mojom::GpuDeviceDataView data, + gpu::GPUInfo::GPUDevice* out); + + static uint32_t vendor_id(const gpu::GPUInfo::GPUDevice& input) { + return input.vendor_id; + } + + static uint32_t device_id(const gpu::GPUInfo::GPUDevice& input) { + return input.device_id; + } + + static bool active(const gpu::GPUInfo::GPUDevice& input) { + return input.active; + } + + static const std::string& vendor_string( + const gpu::GPUInfo::GPUDevice& input) { + return input.vendor_string; + } + + static const std::string& device_string( + const gpu::GPUInfo::GPUDevice& input) { + return input.device_string; + } +}; + +template <> +struct EnumTraits<gpu::mojom::CollectInfoResult, gpu::CollectInfoResult> { + static gpu::mojom::CollectInfoResult ToMojom( + gpu::CollectInfoResult collect_info_result); + + static bool FromMojom(gpu::mojom::CollectInfoResult input, + gpu::CollectInfoResult* out); +}; + +} // namespace mojo +#endif // CC_IPC_GPU_STRUCT_TRAITS_H_
diff --git a/gpu/ipc/common/mailbox.typemap b/gpu/ipc/common/mailbox.typemap index 9436df9..ed80a1c1 100644 --- a/gpu/ipc/common/mailbox.typemap +++ b/gpu/ipc/common/mailbox.typemap
@@ -5,7 +5,9 @@ mojom = "//gpu/ipc/common/mailbox.mojom" public_headers = [ "//gpu/command_buffer/common/mailbox.h" ] traits_headers = [ "//gpu/ipc/common/mailbox_struct_traits.h" ] -sources = [ "//gpu/ipc/common/mailbox_struct_traits.cc" ] +sources = [ + "//gpu/ipc/common/mailbox_struct_traits.cc", +] deps = [ "//mojo/public/cpp/bindings", ]
diff --git a/gpu/ipc/common/struct_traits_unittest.cc b/gpu/ipc/common/struct_traits_unittest.cc index a56bab21..a589c05 100644 --- a/gpu/ipc/common/struct_traits_unittest.cc +++ b/gpu/ipc/common/struct_traits_unittest.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <string> + #include "base/message_loop/message_loop.h" #include "gpu/ipc/common/traits_test_service.mojom.h" #include "mojo/public/cpp/bindings/binding_set.h" @@ -22,6 +24,11 @@ private: // TraitsTestService: + void EchoGpuDevice(const GPUInfo::GPUDevice& g, + const EchoGpuDeviceCallback& callback) override { + callback.Run(g); + } + void EchoMailbox(const Mailbox& m, const EchoMailboxCallback& callback) override { callback.Run(m); @@ -45,6 +52,30 @@ } // namespace +TEST_F(StructTraitsTest, GPUDevice) { + gpu::GPUInfo::GPUDevice input; + // Using the values from gpu/config/gpu_info_collector_unittest.cc::nvidia_gpu + const uint32_t vendor_id = 0x10de; + const uint32_t device_id = 0x0df8; + const std::string vendor_string = "vendor_string"; + const std::string device_string = "device_string"; + + input.vendor_id = vendor_id; + input.device_id = device_id; + input.vendor_string = vendor_string; + input.device_string = device_string; + input.active = false; + mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy(); + gpu::GPUInfo::GPUDevice output; + proxy->EchoGpuDevice(input, &output); + + EXPECT_EQ(vendor_id, output.vendor_id); + EXPECT_EQ(device_id, output.device_id); + EXPECT_FALSE(output.active); + EXPECT_TRUE(vendor_string.compare(output.vendor_string) == 0); + EXPECT_TRUE(device_string.compare(output.device_string) == 0); +} + TEST_F(StructTraitsTest, Mailbox) { const int8_t mailbox_name[GL_MAILBOX_SIZE_CHROMIUM] = { 0, 9, 8, 7, 6, 5, 4, 3, 2, 1, 9, 7, 5, 3, 1, 2, 4, 6, 8, 0, 0, 9,
diff --git a/gpu/ipc/common/traits_test_service.mojom b/gpu/ipc/common/traits_test_service.mojom index f19bf949..196b3f8 100644 --- a/gpu/ipc/common/traits_test_service.mojom +++ b/gpu/ipc/common/traits_test_service.mojom
@@ -4,6 +4,7 @@ module gpu.mojom; +import "gpu/ipc/common/gpu_info.mojom"; import "gpu/ipc/common/mailbox.mojom"; import "gpu/ipc/common/mailbox_holder.mojom"; import "gpu/ipc/common/sync_token.mojom"; @@ -11,6 +12,10 @@ // All functions on this interface echo their arguments to test StructTraits // serialization and deserialization. interface TraitsTestService { + + [Sync] + EchoGpuDevice(GpuDevice g) => (GpuDevice pass); + [Sync] EchoMailbox(Mailbox m) => (Mailbox pass);
diff --git a/gpu/ipc/common/typemaps.gni b/gpu/ipc/common/typemaps.gni index 1eac9c78..6339167 100644 --- a/gpu/ipc/common/typemaps.gni +++ b/gpu/ipc/common/typemaps.gni
@@ -5,6 +5,7 @@ typemaps = [ "//gpu/ipc/common/capabilities.typemap", "//gpu/ipc/common/command_buffer.typemap", + "//gpu/ipc/common/gpu_info.typemap", "//gpu/ipc/common/mailbox.typemap", "//gpu/ipc/common/mailbox_holder.typemap", "//gpu/ipc/common/sync_token.typemap",
diff --git a/gpu/ipc/service/gpu_channel_unittest.cc b/gpu/ipc/service/gpu_channel_unittest.cc index e41df434..b48b7ae 100644 --- a/gpu/ipc/service/gpu_channel_unittest.cc +++ b/gpu/ipc/service/gpu_channel_unittest.cc
@@ -12,15 +12,13 @@ #include "gpu/ipc/service/gpu_channel_test_common.h" #include "ipc/ipc_test_sink.h" #include "ui/gl/gl_context_stub_with_extensions.h" -#include "ui/gl/gl_mock.h" +#include "ui/gl/gl_stub_api.h" #include "ui/gl/gl_surface_stub.h" #include "ui/gl/init/gl_factory.h" #include "ui/gl/test/gl_surface_test_support.h" namespace gpu { -static constexpr int kFakeTextureIds[] = {1, 2}; - class GpuChannelTest : public GpuChannelTestCommon { public: GpuChannelTest() : GpuChannelTestCommon() {} @@ -28,95 +26,8 @@ void SetUp() override { // We need GL bindings to actually initialize command buffers. - gl::SetGLGetProcAddressProc(gl::MockGLInterface::GetGLProcAddress); gl::GLSurfaceTestSupport::InitializeOneOffWithMockBindings(); - - // This GLInterface is a stub for the gl driver. - gl_interface_.reset(new testing::NiceMock<gl::MockGLInterface>); - gl::MockGLInterface::SetGLInterface(gl_interface_.get()); - - using testing::AnyNumber; - using testing::NotNull; - using testing::Return; - using testing::SetArgPointee; - using testing::SetArrayArgument; - // We need it to return non-null strings in order for things to not crash. - EXPECT_CALL(*gl_interface_, GetString(GL_RENDERER)) - .Times(AnyNumber()) - .WillRepeatedly(Return(reinterpret_cast<const GLubyte*>(""))); - EXPECT_CALL(*gl_interface_, GetString(GL_VERSION)) - .Times(AnyNumber()) - .WillRepeatedly(Return(reinterpret_cast<const GLubyte*>("2.0"))); - EXPECT_CALL(*gl_interface_, GetString(GL_EXTENSIONS)) - .Times(AnyNumber()) - .WillRepeatedly(Return( - reinterpret_cast<const GLubyte*>("GL_EXT_framebuffer_object "))); - // And we need some values to be large enough to initialize ContextGroup. - EXPECT_CALL(*gl_interface_, - GetIntegerv(GL_MAX_RENDERBUFFER_SIZE, NotNull())) - .Times(AnyNumber()) - .WillRepeatedly(SetArgPointee<1>(512)); - EXPECT_CALL(*gl_interface_, GetIntegerv(GL_MAX_VERTEX_ATTRIBS, NotNull())) - .Times(AnyNumber()) - .WillRepeatedly(SetArgPointee<1>(8)); - EXPECT_CALL(*gl_interface_, - GetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, NotNull())) - .Times(AnyNumber()) - .WillRepeatedly(SetArgPointee<1>(8)); - EXPECT_CALL(*gl_interface_, - GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, NotNull())) - .Times(AnyNumber()) - .WillRepeatedly(SetArgPointee<1>(8)); - EXPECT_CALL(*gl_interface_, GetIntegerv(GL_MAX_TEXTURE_SIZE, NotNull())) - .Times(AnyNumber()) - .WillRepeatedly(SetArgPointee<1>(2048)); - EXPECT_CALL(*gl_interface_, - GetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, NotNull())) - .Times(AnyNumber()) - .WillRepeatedly(SetArgPointee<1>(2048)); - EXPECT_CALL(*gl_interface_, GetIntegerv(GL_MAX_VARYING_FLOATS, NotNull())) - .Times(AnyNumber()) - .WillRepeatedly(SetArgPointee<1>(8 * 4)); - EXPECT_CALL(*gl_interface_, - GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, NotNull())) - .Times(AnyNumber()) - .WillRepeatedly(SetArgPointee<1>(128 * 4)); - EXPECT_CALL(*gl_interface_, - GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, NotNull())) - .Times(AnyNumber()) - .WillRepeatedly(SetArgPointee<1>(16 * 4)); - EXPECT_CALL(*gl_interface_, - GetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, NotNull())) - .Times(AnyNumber()) - .WillRepeatedly(SetArgPointee<1>(32)); - EXPECT_CALL(*gl_interface_, GetIntegerv(GL_MAX_VIEWPORT_DIMS, NotNull())) - .Times(AnyNumber()) - .WillRepeatedly(SetArgPointee<1>(1024 << 8)); - EXPECT_CALL(*gl_interface_, GetIntegerv(GL_ALPHA_BITS, NotNull())) - .Times(AnyNumber()) - .WillRepeatedly(SetArgPointee<1>(8)); - EXPECT_CALL(*gl_interface_, GetIntegerv(GL_DEPTH_BITS, NotNull())) - .Times(AnyNumber()) - .WillRepeatedly(SetArgPointee<1>(24)); - EXPECT_CALL(*gl_interface_, GetIntegerv(GL_STENCIL_BITS, NotNull())) - .Times(AnyNumber()) - .WillRepeatedly(SetArgPointee<1>(8)); - // Allow generating non-0 resources so code does not DCHECK. - EXPECT_CALL(*gl_interface_, GenFramebuffersEXT(1, NotNull())) - .Times(AnyNumber()) - .WillRepeatedly(SetArgPointee<1>(1)); - EXPECT_CALL(*gl_interface_, GenTextures(1, NotNull())) - .Times(AnyNumber()) - .WillRepeatedly( - SetArrayArgument<1>(kFakeTextureIds, kFakeTextureIds + 1)); - EXPECT_CALL(*gl_interface_, GenTextures(2, NotNull())) - .Times(AnyNumber()) - .WillRepeatedly( - SetArrayArgument<1>(kFakeTextureIds, kFakeTextureIds + 2)); - // And errors should be squashed. - EXPECT_CALL(*gl_interface_, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) - .Times(AnyNumber()) - .WillRepeatedly(Return(GL_FRAMEBUFFER_COMPLETE)); + gl::SetStubGLApi(&api_); GpuChannelTestCommon::SetUp(); } @@ -124,9 +35,7 @@ void TearDown() override { GpuChannelTestCommon::TearDown(); - gl::MockGLInterface::SetGLInterface(nullptr); gl::init::ClearGLBindings(); - gl_interface_ = nullptr; } GpuChannel* CreateChannel(int32_t client_id, @@ -180,7 +89,7 @@ private: base::TestMessageLoop message_loop_; - std::unique_ptr<gl::MockGLInterface> gl_interface_; + gl::GLStubApi api_; }; #if defined(OS_WIN)
diff --git a/gpu/tools/compositor_model_bench/compositor_model_bench.cc b/gpu/tools/compositor_model_bench/compositor_model_bench.cc index 2cf79d0..4b7042a 100644 --- a/gpu/tools/compositor_model_bench/compositor_model_bench.cc +++ b/gpu/tools/compositor_model_bench/compositor_model_bench.cc
@@ -19,6 +19,7 @@ #include <queue> #include <string> +#include <utility> #include <vector> #include "base/at_exit.h" @@ -59,20 +60,18 @@ class Simulator { public: Simulator(int seconds_per_test, const base::FilePath& output_path) - : current_sim_(NULL), - output_path_(output_path), - seconds_per_test_(seconds_per_test), - display_(NULL), - window_(0), - gl_context_(NULL), - window_width_(WINDOW_WIDTH), - window_height_(WINDOW_HEIGHT), - weak_factory_(this) { - } + : output_path_(output_path), + seconds_per_test_(seconds_per_test), + display_(nullptr), + window_(0), + gl_context_(nullptr), + window_width_(WINDOW_WIDTH), + window_height_(WINDOW_HEIGHT), + weak_factory_(this) {} ~Simulator() { // Cleanup GL. - glXMakeCurrent(display_, 0, NULL); + glXMakeCurrent(display_, 0, nullptr); glXDestroyContext(display_, gl_context_); // Destroy window and display. @@ -153,7 +152,7 @@ // Initialize X11. Returns true if successful. This method creates the // X11 window. Further initialization is done in X11VideoRenderer. bool InitX11() { - display_ = XOpenDisplay(NULL); + display_ = XOpenDisplay(nullptr); if (!display_) { LOG(FATAL) << "Cannot open display"; return false; @@ -212,7 +211,7 @@ if (!glXMakeCurrent(display_, window_, gl_context_)) { glXDestroyContext(display_, gl_context_); - gl_context_ = NULL; + gl_context_ = nullptr; return false; } @@ -221,32 +220,26 @@ bool InitializeNextTest() { SimulationSpecification& spec = sims_remaining_.front(); - LOG(INFO) << "Initializing test for " << spec.simulation_name << - "(" << ModelToString(spec.model_under_test) << ")"; + LOG(INFO) << "Initializing test for " << spec.simulation_name << "(" + << ModelToString(spec.model_under_test) << ")"; const base::FilePath& path = spec.input_path; - RenderNode* root = NULL; - if (!(root = BuildRenderTreeFromFile(path))) { - LOG(ERROR) << "Couldn't parse test configuration file " << - path.LossyDisplayName(); + std::unique_ptr<RenderNode> root = BuildRenderTreeFromFile(path); + if (!root) { + LOG(ERROR) << "Couldn't parse test configuration file " + << path.LossyDisplayName(); return false; } - current_sim_ = ConstructSimulationModel(spec.model_under_test, - root, - window_width_, - window_height_); - if (!current_sim_) - return false; - - return true; + current_sim_ = ConstructSimulationModel( + spec.model_under_test, std::move(root), window_width_, window_height_); + return !!current_sim_; } void CleanupCurrentTest() { LOG(INFO) << "Finished test " << sims_remaining_.front().simulation_name; - delete current_sim_; - current_sim_ = NULL; + current_sim_.reset(); } void UpdateCurrentTest() { @@ -276,8 +269,8 @@ FILE* f = base::OpenFile(output_path_, "w"); if (!f) { - LOG(ERROR) << "Failed to open output file " << - output_path_.LossyDisplayName(); + LOG(ERROR) << "Failed to open output file " + << output_path_.LossyDisplayName(); exit(-1); } @@ -338,7 +331,7 @@ } // Simulation task list for this execution - RenderModelSimulator* current_sim_; + std::unique_ptr<RenderModelSimulator> current_sim_; queue<SimulationSpecification> sims_remaining_; queue<SimulationSpecification> sims_completed_; base::FilePath output_path_;
diff --git a/gpu/tools/compositor_model_bench/forward_render_model.cc b/gpu/tools/compositor_model_bench/forward_render_model.cc index ec7248f4..d8d1dfc0 100644 --- a/gpu/tools/compositor_model_bench/forward_render_model.cc +++ b/gpu/tools/compositor_model_bench/forward_render_model.cc
@@ -39,11 +39,11 @@ } }; -ForwardRenderSimulator::ForwardRenderSimulator(RenderNode* root, +ForwardRenderSimulator::ForwardRenderSimulator(std::unique_ptr<RenderNode> root, int window_width, int window_height) - : RenderModelSimulator(root) { - textures_.reset(new TextureGenerator(root)); + : RenderModelSimulator(std::move(root)) { + textures_.reset(new TextureGenerator(root_.get())); visitor_.reset(new ForwardRenderNodeVisitor()); glViewport(0, 0, window_width, window_height); glDisable(GL_DEPTH_TEST);
diff --git a/gpu/tools/compositor_model_bench/forward_render_model.h b/gpu/tools/compositor_model_bench/forward_render_model.h index cceddd9..a1da865 100644 --- a/gpu/tools/compositor_model_bench/forward_render_model.h +++ b/gpu/tools/compositor_model_bench/forward_render_model.h
@@ -17,9 +17,9 @@ class ForwardRenderSimulator : public RenderModelSimulator { public: - explicit ForwardRenderSimulator(RenderNode* root, - int window_width, - int window_height); + ForwardRenderSimulator(std::unique_ptr<RenderNode> root, + int window_width, + int window_height); ~ForwardRenderSimulator() override; void Update() override; void Resize(int width, int height) override;
diff --git a/gpu/tools/compositor_model_bench/render_models.cc b/gpu/tools/compositor_model_bench/render_models.cc index bbbfac6c..a784706 100644 --- a/gpu/tools/compositor_model_bench/render_models.cc +++ b/gpu/tools/compositor_model_bench/render_models.cc
@@ -5,7 +5,9 @@ #include "gpu/tools/compositor_model_bench/render_models.h" #include <string> +#include <utility> +#include "base/memory/ptr_util.h" #include "gpu/tools/compositor_model_bench/forward_render_model.h" const char* ModelToString(RenderModel m) { @@ -17,25 +19,24 @@ } } -RenderModelSimulator::RenderModelSimulator(RenderNode* root) : root_(root) { -} +RenderModelSimulator::RenderModelSimulator(std::unique_ptr<RenderNode> root) + : root_(std::move(root)) {} RenderModelSimulator::~RenderModelSimulator() { } -RenderModelSimulator* ConstructSimulationModel(RenderModel model, - RenderNode* render_tree_root, - int window_width, - int window_height) { +std::unique_ptr<RenderModelSimulator> ConstructSimulationModel( + RenderModel model, + std::unique_ptr<RenderNode> render_tree_root, + int window_width, + int window_height) { switch (model) { case ForwardRenderModel: - return new ForwardRenderSimulator(render_tree_root, - window_width, - window_height); + return base::WrapUnique(new ForwardRenderSimulator( + std::move(render_tree_root), window_width, window_height)); default: LOG(ERROR) << "Unrecognized render model. " "If we know its name, then it's..." << ModelToString(model); - return 0; + return nullptr; } } -
diff --git a/gpu/tools/compositor_model_bench/render_models.h b/gpu/tools/compositor_model_bench/render_models.h index cc17dcb..c68d5c6 100644 --- a/gpu/tools/compositor_model_bench/render_models.h +++ b/gpu/tools/compositor_model_bench/render_models.h
@@ -26,17 +26,19 @@ virtual void Resize(int width, int height) = 0; protected: - explicit RenderModelSimulator(RenderNode* root); + explicit RenderModelSimulator(std::unique_ptr<RenderNode> root); + std::unique_ptr<RenderNode> root_; private: DISALLOW_IMPLICIT_CONSTRUCTORS(RenderModelSimulator); }; -RenderModelSimulator* ConstructSimulationModel(RenderModel model, - RenderNode* render_tree_root, - int window_width, - int window_height); +std::unique_ptr<RenderModelSimulator> ConstructSimulationModel( + RenderModel model, + std::unique_ptr<RenderNode> render_tree_root, + int window_width, + int window_height); #endif // GPU_TOOLS_COMPOSITOR_MODEL_BENCH_RENDER_MODELS_H_
diff --git a/gpu/tools/compositor_model_bench/render_tree.cc b/gpu/tools/compositor_model_bench/render_tree.cc index 7c495e27..642c5fe 100644 --- a/gpu/tools/compositor_model_bench/render_tree.cc +++ b/gpu/tools/compositor_model_bench/render_tree.cc
@@ -19,8 +19,7 @@ using base::JSONReader; using base::JSONWriter; using base::ReadFileToString; -using std::string; -using std::vector; +using base::Value; GLenum TextureFormatFromString(const std::string& format) { if (format == "RGBA") @@ -116,25 +115,25 @@ this->EndVisitRenderNode(v); } -RenderNode* InterpretNode(base::DictionaryValue* node); +std::unique_ptr<RenderNode> InterpretNode(const base::DictionaryValue& node); -std::string ValueTypeAsString(base::Value::Type type) { +std::string ValueTypeAsString(Value::Type type) { switch (type) { - case base::Value::TYPE_NULL: + case Value::TYPE_NULL: return "NULL"; - case base::Value::TYPE_BOOLEAN: + case Value::TYPE_BOOLEAN: return "BOOLEAN"; - case base::Value::TYPE_INTEGER: + case Value::TYPE_INTEGER: return "INTEGER"; - case base::Value::TYPE_DOUBLE: + case Value::TYPE_DOUBLE: return "DOUBLE"; - case base::Value::TYPE_STRING: + case Value::TYPE_STRING: return "STRING"; - case base::Value::TYPE_BINARY: + case Value::TYPE_BINARY: return "BINARY"; - case base::Value::TYPE_DICTIONARY: + case Value::TYPE_DICTIONARY: return "DICTIONARY"; - case base::Value::TYPE_LIST: + case Value::TYPE_LIST: return "LIST"; default: return "(UNKNOWN TYPE)"; @@ -142,16 +141,16 @@ } // Makes sure that the key exists and has the type we expect. -bool VerifyDictionaryEntry(base::DictionaryValue* node, +bool VerifyDictionaryEntry(const base::DictionaryValue& node, const std::string& key, - base::Value::Type type) { - if (!node->HasKey(key)) { + Value::Type type) { + if (!node.HasKey(key)) { LOG(ERROR) << "Missing value for key: " << key; return false; } - base::Value* child; - node->Get(key, &child); + const Value* child; + node.Get(key, &child); if (!child->IsType(type)) { LOG(ERROR) << key << " did not have the expected type " "(expected " << ValueTypeAsString(type) << ")"; @@ -162,61 +161,59 @@ } // Makes sure that the list entry has the type we expect. -bool VerifyListEntry(base::ListValue* l, +bool VerifyListEntry(const base::ListValue& l, int idx, - base::Value::Type type, - const char* listName = 0) { + Value::Type type, + const char* listName = nullptr) { // Assume the idx is valid (since we'll be able to generate a better // error message for this elsewhere.) - base::Value* el; - l->Get(idx, &el); + const Value* el; + l.Get(idx, &el); if (!el->IsType(type)) { - LOG(ERROR) << (listName ? listName : "List") << "element " << idx << - " did not have the expected type (expected " << - ValueTypeAsString(type) << ")\n"; + LOG(ERROR) << (listName ? listName : "List") << "element " << idx + << " did not have the expected type (expected " + << ValueTypeAsString(type) << ")\n"; return false; } return true; } -bool InterpretCommonContents(base::DictionaryValue* node, RenderNode* c) { - if (!VerifyDictionaryEntry(node, "layerID", base::Value::TYPE_INTEGER) || - !VerifyDictionaryEntry(node, "width", base::Value::TYPE_INTEGER) || - !VerifyDictionaryEntry(node, "height", base::Value::TYPE_INTEGER) || - !VerifyDictionaryEntry(node, "drawsContent", base::Value::TYPE_BOOLEAN) || - !VerifyDictionaryEntry(node, "targetSurfaceID", - base::Value::TYPE_INTEGER) || - !VerifyDictionaryEntry(node, "transform", base::Value::TYPE_LIST) - ) { +bool InterpretCommonContents(const base::DictionaryValue& node, RenderNode* c) { + if (!VerifyDictionaryEntry(node, "layerID", Value::TYPE_INTEGER) || + !VerifyDictionaryEntry(node, "width", Value::TYPE_INTEGER) || + !VerifyDictionaryEntry(node, "height", Value::TYPE_INTEGER) || + !VerifyDictionaryEntry(node, "drawsContent", Value::TYPE_BOOLEAN) || + !VerifyDictionaryEntry(node, "targetSurfaceID", Value::TYPE_INTEGER) || + !VerifyDictionaryEntry(node, "transform", Value::TYPE_LIST)) { return false; } int layerID; - node->GetInteger("layerID", &layerID); + node.GetInteger("layerID", &layerID); c->set_layerID(layerID); int width; - node->GetInteger("width", &width); + node.GetInteger("width", &width); c->set_width(width); int height; - node->GetInteger("height", &height); + node.GetInteger("height", &height); c->set_height(height); bool drawsContent; - node->GetBoolean("drawsContent", &drawsContent); + node.GetBoolean("drawsContent", &drawsContent); c->set_drawsContent(drawsContent); int targetSurface; - node->GetInteger("targetSurfaceID", &targetSurface); + node.GetInteger("targetSurfaceID", &targetSurface); c->set_targetSurface(targetSurface); - base::ListValue* transform; - node->GetList("transform", &transform); + const base::ListValue* transform; + node.GetList("transform", &transform); if (transform->GetSize() != 16) { LOG(ERROR) << "4x4 transform matrix did not have 16 elements"; return false; } float transform_mat[16]; for (int i = 0; i < 16; ++i) { - if (!VerifyListEntry(transform, i, base::Value::TYPE_DOUBLE, "Transform")) + if (!VerifyListEntry(*transform, i, Value::TYPE_DOUBLE, "Transform")) return false; double el; transform->GetDouble(i, &el); @@ -224,81 +221,81 @@ } c->set_transform(transform_mat); - if (node->HasKey("tiles")) { - if (!VerifyDictionaryEntry(node, "tiles", base::Value::TYPE_DICTIONARY)) + if (!node.HasKey("tiles")) + return true; + + if (!VerifyDictionaryEntry(node, "tiles", Value::TYPE_DICTIONARY)) + return false; + const base::DictionaryValue* tiles_dict; + node.GetDictionary("tiles", &tiles_dict); + if (!VerifyDictionaryEntry(*tiles_dict, "dim", Value::TYPE_LIST)) + return false; + const base::ListValue* dim; + tiles_dict->GetList("dim", &dim); + if (!VerifyListEntry(*dim, 0, Value::TYPE_INTEGER, "Tile dimension") || + !VerifyListEntry(*dim, 1, Value::TYPE_INTEGER, "Tile dimension")) { + return false; + } + int tile_width; + dim->GetInteger(0, &tile_width); + c->set_tile_width(tile_width); + int tile_height; + dim->GetInteger(1, &tile_height); + c->set_tile_height(tile_height); + + if (!VerifyDictionaryEntry(*tiles_dict, "info", Value::TYPE_LIST)) + return false; + const base::ListValue* tiles; + tiles_dict->GetList("info", &tiles); + for (unsigned int i = 0; i < tiles->GetSize(); ++i) { + if (!VerifyListEntry(*tiles, i, Value::TYPE_DICTIONARY, "Tile info")) return false; - base::DictionaryValue* tiles_dict; - node->GetDictionary("tiles", &tiles_dict); - if (!VerifyDictionaryEntry(tiles_dict, "dim", base::Value::TYPE_LIST)) - return false; - base::ListValue* dim; - tiles_dict->GetList("dim", &dim); - if (!VerifyListEntry(dim, 0, base::Value::TYPE_INTEGER, "Tile dimension") || - !VerifyListEntry(dim, 1, base::Value::TYPE_INTEGER, "Tile dimension")) { + const base::DictionaryValue* tdict; + tiles->GetDictionary(i, &tdict); + + if (!VerifyDictionaryEntry(*tdict, "x", Value::TYPE_INTEGER) || + !VerifyDictionaryEntry(*tdict, "y", Value::TYPE_INTEGER)) { return false; } - int tile_width; - dim->GetInteger(0, &tile_width); - c->set_tile_width(tile_width); - int tile_height; - dim->GetInteger(1, &tile_height); - c->set_tile_height(tile_height); - - if (!VerifyDictionaryEntry(tiles_dict, "info", base::Value::TYPE_LIST)) - return false; - base::ListValue* tiles; - tiles_dict->GetList("info", &tiles); - for (unsigned int i = 0; i < tiles->GetSize(); ++i) { - if (!VerifyListEntry(tiles, i, base::Value::TYPE_DICTIONARY, "Tile info")) + Tile t; + tdict->GetInteger("x", &t.x); + tdict->GetInteger("y", &t.y); + if (tdict->HasKey("texID")) { + if (!VerifyDictionaryEntry(*tdict, "texID", Value::TYPE_INTEGER)) return false; - base::DictionaryValue* tdict; - tiles->GetDictionary(i, &tdict); - - if (!VerifyDictionaryEntry(tdict, "x", base::Value::TYPE_INTEGER) || - !VerifyDictionaryEntry(tdict, "y", base::Value::TYPE_INTEGER)) { - return false; - } - Tile t; - tdict->GetInteger("x", &t.x); - tdict->GetInteger("y", &t.y); - if (tdict->HasKey("texID")) { - if (!VerifyDictionaryEntry(tdict, "texID", base::Value::TYPE_INTEGER)) - return false; - tdict->GetInteger("texID", &t.texID); - } else { - t.texID = -1; - } - c->add_tile(t); + tdict->GetInteger("texID", &t.texID); + } else { + t.texID = -1; } + c->add_tile(t); } return true; } -bool InterpretCCData(base::DictionaryValue* node, CCNode* c) { - if (!VerifyDictionaryEntry(node, "vertex_shader", base::Value::TYPE_STRING) || - !VerifyDictionaryEntry(node, "fragment_shader", - base::Value::TYPE_STRING) || - !VerifyDictionaryEntry(node, "textures", base::Value::TYPE_LIST)) { +bool InterpretCCData(const base::DictionaryValue& node, CCNode* c) { + if (!VerifyDictionaryEntry(node, "vertex_shader", Value::TYPE_STRING) || + !VerifyDictionaryEntry(node, "fragment_shader", Value::TYPE_STRING) || + !VerifyDictionaryEntry(node, "textures", Value::TYPE_LIST)) { return false; } - string vertex_shader_name, fragment_shader_name; - node->GetString("vertex_shader", &vertex_shader_name); - node->GetString("fragment_shader", &fragment_shader_name); + std::string vertex_shader_name, fragment_shader_name; + node.GetString("vertex_shader", &vertex_shader_name); + node.GetString("fragment_shader", &fragment_shader_name); c->set_vertex_shader(ShaderIDFromString(vertex_shader_name)); c->set_fragment_shader(ShaderIDFromString(fragment_shader_name)); - base::ListValue* textures; - node->GetList("textures", &textures); + const base::ListValue* textures; + node.GetList("textures", &textures); for (unsigned int i = 0; i < textures->GetSize(); ++i) { - if (!VerifyListEntry(textures, i, base::Value::TYPE_DICTIONARY, "Tex list")) + if (!VerifyListEntry(*textures, i, Value::TYPE_DICTIONARY, "Tex list")) return false; - base::DictionaryValue* tex; + const base::DictionaryValue* tex; textures->GetDictionary(i, &tex); - if (!VerifyDictionaryEntry(tex, "texID", base::Value::TYPE_INTEGER) || - !VerifyDictionaryEntry(tex, "height", base::Value::TYPE_INTEGER) || - !VerifyDictionaryEntry(tex, "width", base::Value::TYPE_INTEGER) || - !VerifyDictionaryEntry(tex, "format", base::Value::TYPE_STRING)) { + if (!VerifyDictionaryEntry(*tex, "texID", Value::TYPE_INTEGER) || + !VerifyDictionaryEntry(*tex, "height", Value::TYPE_INTEGER) || + !VerifyDictionaryEntry(*tex, "width", Value::TYPE_INTEGER) || + !VerifyDictionaryEntry(*tex, "format", Value::TYPE_STRING)) { return false; } Texture t; @@ -306,13 +303,14 @@ tex->GetInteger("height", &t.height); tex->GetInteger("width", &t.width); - string formatName; + std::string formatName; tex->GetString("format", &formatName); t.format = TextureFormatFromString(formatName); if (t.format == GL_INVALID_ENUM) { - LOG(ERROR) << "Unrecognized texture format in layer " << c->layerID() << - " (format: " << formatName << ")\n" - "The layer had " << textures->GetSize() << " children."; + LOG(ERROR) << "Unrecognized texture format in layer " << c->layerID() + << " (format: " << formatName << ")\n" + "The layer had " + << textures->GetSize() << " children."; return false; } @@ -320,115 +318,116 @@ } if (c->vertex_shader() == SHADER_UNRECOGNIZED) { - LOG(ERROR) << "Unrecognized vertex shader name, layer " << c->layerID() << - " (shader: " << vertex_shader_name << ")"; + LOG(ERROR) << "Unrecognized vertex shader name, layer " << c->layerID() + << " (shader: " << vertex_shader_name << ")"; return false; } if (c->fragment_shader() == SHADER_UNRECOGNIZED) { - LOG(ERROR) << "Unrecognized fragment shader name, layer " << c->layerID() << - " (shader: " << fragment_shader_name << ")"; + LOG(ERROR) << "Unrecognized fragment shader name, layer " << c->layerID() + << " (shader: " << fragment_shader_name << ")"; return false; } return true; } -RenderNode* InterpretContentLayer(base::DictionaryValue* node) { - ContentLayerNode* n = new ContentLayerNode; - if (!InterpretCommonContents(node, n)) - return NULL; +std::unique_ptr<RenderNode> InterpretContentLayer( + const base::DictionaryValue& node) { + auto n = base::MakeUnique<ContentLayerNode>(); + if (!InterpretCommonContents(node, n.get())) + return nullptr; - if (!VerifyDictionaryEntry(node, "type", base::Value::TYPE_STRING) || - !VerifyDictionaryEntry(node, "skipsDraw", base::Value::TYPE_BOOLEAN) || - !VerifyDictionaryEntry(node, "children", base::Value::TYPE_LIST)) { - return NULL; + if (!VerifyDictionaryEntry(node, "type", Value::TYPE_STRING) || + !VerifyDictionaryEntry(node, "skipsDraw", Value::TYPE_BOOLEAN) || + !VerifyDictionaryEntry(node, "children", Value::TYPE_LIST)) { + return nullptr; } - string type; - node->GetString("type", &type); + std::string type; + node.GetString("type", &type); DCHECK_EQ(type, "ContentLayer"); bool skipsDraw; - node->GetBoolean("skipsDraw", &skipsDraw); + node.GetBoolean("skipsDraw", &skipsDraw); n->set_skipsDraw(skipsDraw); - base::ListValue* children; - node->GetList("children", &children); + const base::ListValue* children; + node.GetList("children", &children); for (unsigned int i = 0; i < children->GetSize(); ++i) { - base::DictionaryValue* childNode; - children->GetDictionary(i, &childNode); - RenderNode* child = InterpretNode(childNode); + const base::DictionaryValue* childNode; + if (!children->GetDictionary(i, &childNode)) + continue; + std::unique_ptr<RenderNode> child = InterpretNode(*childNode); if (child) - n->add_child(child); + n->add_child(child.release()); } return n; } -RenderNode* InterpretCanvasLayer(base::DictionaryValue* node) { - CCNode* n = new CCNode; - if (!InterpretCommonContents(node, n)) - return NULL; +std::unique_ptr<RenderNode> InterpretCanvasLayer( + const base::DictionaryValue& node) { + auto n = base::MakeUnique<CCNode>(); + if (!InterpretCommonContents(node, n.get())) + return nullptr; - if (!VerifyDictionaryEntry(node, "type", base::Value::TYPE_STRING)) { - return NULL; - } + if (!VerifyDictionaryEntry(node, "type", Value::TYPE_STRING)) + return nullptr; - string type; - node->GetString("type", &type); + std::string type; + node.GetString("type", &type); assert(type == "CanvasLayer"); - if (!InterpretCCData(node, n)) - return NULL; + if (!InterpretCCData(node, n.get())) + return nullptr; return n; } -RenderNode* InterpretVideoLayer(base::DictionaryValue* node) { - CCNode* n = new CCNode; - if (!InterpretCommonContents(node, n)) - return NULL; +std::unique_ptr<RenderNode> InterpretVideoLayer( + const base::DictionaryValue& node) { + auto n = base::MakeUnique<CCNode>(); + if (!InterpretCommonContents(node, n.get())) + return nullptr; - if (!VerifyDictionaryEntry(node, "type", base::Value::TYPE_STRING)) { - return NULL; - } + if (!VerifyDictionaryEntry(node, "type", Value::TYPE_STRING)) + return nullptr; - string type; - node->GetString("type", &type); + std::string type; + node.GetString("type", &type); assert(type == "VideoLayer"); - if (!InterpretCCData(node, n)) - return NULL; + if (!InterpretCCData(node, n.get())) + return nullptr; return n; } -RenderNode* InterpretImageLayer(base::DictionaryValue* node) { - CCNode* n = new CCNode; - if (!InterpretCommonContents(node, n)) - return NULL; +std::unique_ptr<RenderNode> InterpretImageLayer( + const base::DictionaryValue& node) { + auto n = base::MakeUnique<CCNode>(); + if (!InterpretCommonContents(node, n.get())) + return nullptr; - if (!VerifyDictionaryEntry(node, "type", base::Value::TYPE_STRING)) { - return NULL; - } + if (!VerifyDictionaryEntry(node, "type", Value::TYPE_STRING)) + return nullptr; - string type; - node->GetString("type", &type); + std::string type; + node.GetString("type", &type); assert(type == "ImageLayer"); - if (!InterpretCCData(node, n)) - return NULL; + if (!InterpretCCData(node, n.get())) + return nullptr; return n; } -RenderNode* InterpretNode(base::DictionaryValue* node) { - if (!VerifyDictionaryEntry(node, "type", base::Value::TYPE_STRING)) { - return NULL; - } +std::unique_ptr<RenderNode> InterpretNode(const base::DictionaryValue& node) { + if (!VerifyDictionaryEntry(node, "type", Value::TYPE_STRING)) + return nullptr; - string type; - node->GetString("type", &type); + std::string type; + node.GetString("type", &type); if (type == "ContentLayer") return InterpretContentLayer(node); if (type == "CanvasLayer") @@ -438,42 +437,39 @@ if (type == "ImageLayer") return InterpretImageLayer(node); - - string outjson; - JSONWriter::WriteWithOptions(*node, base::JSONWriter::OPTIONS_PRETTY_PRINT, + std::string outjson; + JSONWriter::WriteWithOptions(node, base::JSONWriter::OPTIONS_PRETTY_PRINT, &outjson); LOG(ERROR) << "Unrecognized node type! JSON:\n\n" - "-----------------------\n" << - outjson << - "-----------------------"; + "-----------------------\n" + << outjson << "-----------------------"; - return NULL; + return nullptr; } -RenderNode* BuildRenderTreeFromFile(const base::FilePath& path) { +std::unique_ptr<RenderNode> BuildRenderTreeFromFile( + const base::FilePath& path) { LOG(INFO) << "Reading " << path.LossyDisplayName(); - string contents; + std::string contents; if (!ReadFileToString(path, &contents)) - return NULL; + return nullptr; int error_code = 0; - string error_message; - std::unique_ptr<base::Value> root = JSONReader::ReadAndReturnError( - contents, base::JSON_ALLOW_TRAILING_COMMAS, &error_code, &error_message); + std::string error_message; + std::unique_ptr<base::DictionaryValue> root = base::DictionaryValue::From( + JSONReader::ReadAndReturnError(contents, base::JSON_ALLOW_TRAILING_COMMAS, + &error_code, &error_message)); if (!root) { - LOG(ERROR) << "Failed to parse JSON file " << path.LossyDisplayName() << - "\n(" << error_message << ")"; - return NULL; + if (error_code) { + LOG(ERROR) << "Failed to parse JSON file " << path.LossyDisplayName() + << "\n(" << error_message << ")"; + } else { + LOG(ERROR) << path.LossyDisplayName() + << " doesn not encode a JSON dictionary."; + } + return nullptr; } - if (root->IsType(base::Value::TYPE_DICTIONARY)) { - base::DictionaryValue* v = static_cast<base::DictionaryValue*>(root.get()); - RenderNode* tree = InterpretContentLayer(v); - return tree; - } else { - LOG(ERROR) << path.LossyDisplayName() << - " doesn not encode a JSON dictionary."; - return NULL; - } + return InterpretContentLayer(*root); }
diff --git a/gpu/tools/compositor_model_bench/render_tree.h b/gpu/tools/compositor_model_bench/render_tree.h index 01f50ac..996a2d1 100644 --- a/gpu/tools/compositor_model_bench/render_tree.h +++ b/gpu/tools/compositor_model_bench/render_tree.h
@@ -208,7 +208,7 @@ virtual void EndVisitCCNode(CCNode* v); }; -RenderNode* BuildRenderTreeFromFile(const base::FilePath& path); +std::unique_ptr<RenderNode> BuildRenderTreeFromFile(const base::FilePath& path); #endif // GPU_TOOLS_COMPOSITOR_MODEL_BENCH_RENDER_TREE_H_
diff --git a/ios/chrome/BUILD.gn b/ios/chrome/BUILD.gn index 0d2daa33..01a2f17 100644 --- a/ios/chrome/BUILD.gn +++ b/ios/chrome/BUILD.gn
@@ -43,7 +43,12 @@ "browser/net/image_fetcher_unittest.mm", "browser/net/metrics_network_client_unittest.mm", "browser/net/retryable_url_fetcher_unittest.mm", + "browser/passwords/credential_manager_js_unittest.mm", + "browser/passwords/credential_manager_unittest.mm", + "browser/passwords/password_controller_js_unittest.mm", + "browser/passwords/password_controller_off_the_record_unittest.mm", "browser/passwords/password_controller_unittest.mm", + "browser/passwords/password_generation_agent_unittest.mm", "browser/reading_list/reading_list_entry_unittest.cc", "browser/reading_list/reading_list_model_unittest.cc", "browser/signin/chrome_identity_service_observer_bridge_unittest.mm", @@ -72,6 +77,8 @@ ":native_content_controller_test_xib", "//base", "//base/test:test_support", + "//components/autofill/core/common:common", + "//components/autofill/ios/browser:browser", "//components/bookmarks/test", "//components/favicon_base", "//components/metrics", @@ -95,6 +102,7 @@ "//ios/chrome/test:run_all_unittests", "//ios/public/provider/chrome/browser", "//ios/public/provider/chrome/browser:test_support", + "//ios/testing:ocmock_support", "//ios/web", "//ios/web:test_support", "//net:test_support",
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS index e334443..3ce842d 100644 --- a/ios/chrome/browser/DEPS +++ b/ios/chrome/browser/DEPS
@@ -96,6 +96,7 @@ # For tests. "+ios/chrome/test", "+ios/public/test", + "+ios/testing", # Only parts of skia are compiled on iOS, so we explicitly list the # files that can be included to avoid bringing in more code.
diff --git a/ios/chrome/browser/about_flags.mm b/ios/chrome/browser/about_flags.mm index 9f19234..79a4628 100644 --- a/ios/chrome/browser/about_flags.mm +++ b/ios/chrome/browser/about_flags.mm
@@ -19,7 +19,6 @@ #include "base/strings/stringprintf.h" #include "base/strings/sys_string_conversions.h" #include "base/sys_info.h" -#include "components/autofill/core/common/autofill_switches.h" #include "components/dom_distiller/core/dom_distiller_switches.h" #include "components/flags_ui/feature_entry.h" #include "components/flags_ui/feature_entry_macros.h" @@ -144,14 +143,6 @@ if ([defaults boolForKey:@"EnableCredentialManagement"]) command_line->AppendSwitch(switches::kEnableCredentialManagerAPI); - // Populate command line flags from FullFormAutofill. - NSString* fullFormAutofillValue = [defaults stringForKey:@"FullFormAutofill"]; - if ([fullFormAutofillValue isEqualToString:@"Enabled"]) { - command_line->AppendSwitch(autofill::switches::kEnableFullFormAutofillIOS); - } else if ([fullFormAutofillValue isEqualToString:@"Disabled"]) { - command_line->AppendSwitch(autofill::switches::kDisableFullFormAutofillIOS); - } - NSString* autoReloadEnabledValue = [defaults stringForKey:@"AutoReloadEnabled"]; if ([autoReloadEnabledValue isEqualToString:@"Enabled"]) {
diff --git a/ios/chrome/browser/autofill/form_suggestion_controller.mm b/ios/chrome/browser/autofill/form_suggestion_controller.mm index 71a5d78..2499d40 100644 --- a/ios/chrome/browser/autofill/form_suggestion_controller.mm +++ b/ios/chrome/browser/autofill/form_suggestion_controller.mm
@@ -13,7 +13,6 @@ #include "base/mac/scoped_nsobject.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" -#include "components/autofill/core/browser/autofill_field_trial_ios.h" #include "components/autofill/core/browser/autofill_popup_delegate.h" #import "components/autofill/ios/browser/form_suggestion.h" #import "ios/chrome/browser/autofill/form_input_accessory_view_controller.h" @@ -304,12 +303,7 @@ forField:base::SysUTF8ToNSString(_suggestionState->field_name) form:base::SysUTF8ToNSString(_suggestionState->form_name) completionHandler:^{ - if (autofill::AutofillFieldTrialIOS::IsFullFormAutofillEnabled()) { - [[weakSelf accessoryViewDelegate] closeKeyboardWithoutButtonPress]; - } else { - [[weakSelf accessoryViewDelegate] - selectNextElementWithoutButtonPress]; - } + [[weakSelf accessoryViewDelegate] closeKeyboardWithoutButtonPress]; }]; _provider = nil; }
diff --git a/ios/chrome/browser/passwords/credential_manager_js_unittest.mm b/ios/chrome/browser/passwords/credential_manager_js_unittest.mm new file mode 100644 index 0000000..42382ba8 --- /dev/null +++ b/ios/chrome/browser/passwords/credential_manager_js_unittest.mm
@@ -0,0 +1,510 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <memory> + +#include "base/mac/foundation_util.h" +#import "base/mac/scoped_nsobject.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#import "ios/chrome/browser/passwords/js_credential_manager.h" +#include "ios/web/public/web_state/credential.h" +#import "ios/web/public/web_state/js/crw_js_injection_receiver.h" +#import "ios/web/public/web_state/web_state.h" +#include "ios/web/public/web_state/web_state_observer.h" +#import "ios/web/public/test/web_test_with_web_state.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gtest_mac.h" +#include "url/gurl.h" + +namespace { + +using ::testing::_; + +// Matcher to match web::Credential. +MATCHER_P(IsEqualTo, value, "") { + return arg.type == value.type && arg.id == value.id && + arg.name == value.name && arg.avatar_url == value.avatar_url && + arg.password == value.password && + arg.federation_origin.Serialize() == + value.federation_origin.Serialize(); +} + +// A mock WebStateObserver for testing the Credential Manager API. +class MockWebStateObserver : public web::WebStateObserver { + public: + explicit MockWebStateObserver(web::WebState* web_state) + : web::WebStateObserver(web_state) {} + ~MockWebStateObserver() override {} + + MOCK_METHOD5( + CredentialsRequested, + void(int, const GURL&, bool, const std::vector<std::string>&, bool)); + MOCK_METHOD3(SignedIn, void(int, const GURL&, const web::Credential&)); + MOCK_METHOD2(SignedIn, void(int, const GURL&)); + MOCK_METHOD2(SignedOut, void(int, const GURL&)); + MOCK_METHOD3(SignInFailed, void(int, const GURL&, const web::Credential&)); + MOCK_METHOD2(SignInFailed, void(int, const GURL&)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockWebStateObserver); +}; + +// Unit tests for the Credential Manager JavaScript and associated plumbing. +class CredentialManagerJsTest : public web::WebTestWithWebState { + public: + CredentialManagerJsTest() {} + + void SetUp() override { + web::WebTestWithWebState::SetUp(); + js_credential_manager_.reset(base::mac::ObjCCastStrict<JSCredentialManager>( + [[web_state()->GetJSInjectionReceiver() + instanceOfClass:[JSCredentialManager class]] retain])); + observer_.reset(new MockWebStateObserver(web_state())); + } + + // Sets up a web page and injects the JSCredentialManager. Must be called + // before any interaction with the page. + void Inject() { + LoadHtml(@""); + [js_credential_manager_ inject]; + } + + // Returns the mock observer. + MockWebStateObserver& observer() { return *observer_; } + + // Returns a string that creates a Credential object for JavaScript testing. + NSString* test_credential_js() { + return @"new PasswordCredential('bob', 'bobiscool', 'Bob Boblaw'," + @"'https://bobboblawslawblog.com/bob.jpg')"; + } + + // Returns a Credential to match the one returned by |test_credential_js()|. + web::Credential test_credential() { + web::Credential test_credential; + test_credential.type = web::CredentialType::CREDENTIAL_TYPE_PASSWORD; + test_credential.id = base::ASCIIToUTF16("bob"); + test_credential.password = base::ASCIIToUTF16("bobiscool"); + test_credential.name = base::ASCIIToUTF16("Bob Boblaw"); + test_credential.avatar_url = GURL("https://bobboblawslawblog.com/bob.jpg"); + return test_credential; + } + + // Adds handlers for resolving and rejecting the promise returned by + // executing the code in |promise|. + void PrepareResolverAndRejecter(NSString* promise) { + EvaluateJavaScriptAsString( + [NSString stringWithFormat:@"var resolved = false; " + @"var rejected = false; " + @"var resolvedCredential = null; " + @"var rejectedError = null; " + @"function resolve(credential) { " + @" resolved = true; " + @" resolvedCredential = credential;" + @"} " + @"function reject(error) { " + @" rejected = true; " + @" rejectedError = error; " + @"} " + @"%@.then(resolve, reject); ", + promise]); + // Wait until the promise executor has executed. + WaitForCondition(^bool { + return [EvaluateJavaScriptAsString( + @"Object.keys(__gCrWeb.credentialManager.resolvers_).length > 0") + isEqualToString:@"true"]; + }); + } + + // Checks that the Credential returned to the resolve handler in JavaScript + // matches the structure of |test_credential()|. + void CheckResolvedCredentialMatchesTestCredential() { + EXPECT_NSEQ(@"true", EvaluateJavaScriptAsString(@"resolved")); + EXPECT_NSEQ( + @"PasswordCredential", + EvaluateJavaScriptAsString(@"resolvedCredential.constructor.name")); + EXPECT_NSEQ(@"bob", EvaluateJavaScriptAsString(@"resolvedCredential.id")); + EXPECT_NSEQ(@"bobiscool", + EvaluateJavaScriptAsString(@"resolvedCredential.password_")); + EXPECT_NSEQ(@"Bob Boblaw", + EvaluateJavaScriptAsString(@"resolvedCredential.name")); + EXPECT_NSEQ(@"https://bobboblawslawblog.com/bob.jpg", + EvaluateJavaScriptAsString(@"resolvedCredential.avatarURL")); + } + + // Checks that the promise set up by |PrepareResolverAndRejecter| was resolved + // without a credential. + void CheckResolvedWithoutCredential() { + EXPECT_NSEQ(@"true", EvaluateJavaScriptAsString(@"resolved")); + EXPECT_NSEQ(@"false", EvaluateJavaScriptAsString(@"!!resolvedCredential")); + } + + // Checks that the promise set up by |PrepareResolverAndRejecter| was rejected + // with an error with name |error_name| and |message|. + void CheckRejected(NSString* error_name, NSString* message) { + EXPECT_NSEQ(@"true", EvaluateJavaScriptAsString(@"rejected")); + EXPECT_NSEQ(error_name, EvaluateJavaScriptAsString(@"rejectedError.name")); + EXPECT_NSEQ(message, EvaluateJavaScriptAsString(@"rejectedError.message")); + } + + // Waits until the promise set up by |PrepareResolverAndRejecter| has been + // either resolved or rejected. + void WaitUntilPromiseResolvedOrRejected() { + WaitForCondition(^bool { + return [EvaluateJavaScriptAsString(@"resolved || rejected") + isEqualToString:@"true"]; + }); + } + + // Resolves the promise set up by |PrepareResolverAndRejecter| and associated + // with |request_id| with |test_credential()|. + void ResolvePromiseWithTestCredential(int request_id) { + __block bool finished = false; + [js_credential_manager() resolvePromiseWithRequestID:request_id + credential:test_credential() + completionHandler:^(BOOL success) { + EXPECT_TRUE(success); + finished = true; + }]; + WaitForCondition(^bool { + return finished; + }); + WaitUntilPromiseResolvedOrRejected(); + } + + // Resolves the promise set up by |PrepareResolverAndRejecter| and associated + // with |request_id| without a credential. + void ResolvePromiseWithoutCredential(int request_id) { + __block bool finished = false; + [js_credential_manager() resolvePromiseWithRequestID:request_id + completionHandler:^(BOOL success) { + EXPECT_TRUE(success); + finished = true; + }]; + WaitForCondition(^bool { + return finished; + }); + WaitUntilPromiseResolvedOrRejected(); + } + + // Rejects the promise set up by |PrepareResolverAndRejecter| and associated + // with |request_id| with an error of type |error_type| and |message|. + void RejectPromise(int request_id, NSString* error_type, NSString* message) { + __block bool finished = false; + [js_credential_manager() rejectPromiseWithRequestID:request_id + errorType:error_type + message:message + completionHandler:^(BOOL success) { + EXPECT_TRUE(success); + finished = true; + }]; + WaitForCondition(^bool { + return finished; + }); + WaitUntilPromiseResolvedOrRejected(); + } + + // Tests that the promise set up by |PrepareResolverAndRejecter| wasn't + // rejected. + void CheckNeverRejected() { + EXPECT_NSEQ(@"false", EvaluateJavaScriptAsString(@"rejected")); + } + + // Tests that the promise set up by |PrepareResolverAndRejecter| wasn't + // resolved. + void CheckNeverResolved() { + EXPECT_NSEQ(@"false", EvaluateJavaScriptAsString(@"resolved")); + } + + // Returns the JSCredentialManager for testing. + JSCredentialManager* js_credential_manager() { + return js_credential_manager_; + } + + // Tests that resolving the promise returned by |promise| and associated with + // |request_id| with |test_credential()| correctly forwards that credential + // to the client. + void TestPromiseResolutionWithCredential(int request_id, NSString* promise) { + PrepareResolverAndRejecter(promise); + ResolvePromiseWithTestCredential(request_id); + CheckResolvedCredentialMatchesTestCredential(); + CheckNeverRejected(); + } + + // Tests that resolving the promise returned by |promise| and associated with + // |request_id| without a credential correctly invokes the client. + void TestPromiseResolutionWithoutCredential(int request_id, + NSString* promise) { + PrepareResolverAndRejecter(promise); + ResolvePromiseWithoutCredential(request_id); + CheckResolvedWithoutCredential(); + CheckNeverRejected(); + } + + // Tests that rejecting the promise returned by |promise| and associated with + // |request_id| with an error of type |error| and message |message| correctly + // forwards that error to the client. + void TestPromiseRejection(int request_id, + NSString* error, + NSString* message, + NSString* promise) { + PrepareResolverAndRejecter(promise); + RejectPromise(request_id, error, message); + CheckRejected(error, message); + CheckNeverResolved(); + } + + private: + // Manager for injected credential manager JavaScript. + base::scoped_nsobject<JSCredentialManager> js_credential_manager_; + + // Mock observer for testing. + std::unique_ptr<MockWebStateObserver> observer_; + + DISALLOW_COPY_AND_ASSIGN(CredentialManagerJsTest); +}; + +// Tests that navigator.credentials calls use distinct request identifiers. +TEST_F(CredentialManagerJsTest, RequestIdentifiersDiffer) { + Inject(); + EXPECT_CALL(observer(), CredentialsRequested(0, _, _, _, _)); + EvaluateJavaScriptAsString(@"navigator.credentials.request()"); + EXPECT_CALL(observer(), SignInFailed(1, _)); + EvaluateJavaScriptAsString(@"navigator.credentials.notifyFailedSignIn()"); + EXPECT_CALL(observer(), SignInFailed(2, _)); + EvaluateJavaScriptAsString(@"navigator.credentials.notifyFailedSignIn()"); + EXPECT_CALL(observer(), SignedIn(3, _)); + EvaluateJavaScriptAsString(@"navigator.credentials.notifySignedIn()"); + EXPECT_CALL(observer(), SignedOut(4, _)); + EvaluateJavaScriptAsString(@"navigator.credentials.notifySignedOut()"); + EXPECT_CALL(observer(), CredentialsRequested(5, _, _, _, _)); + EvaluateJavaScriptAsString(@"navigator.credentials.request()"); +} + +// Tests that navigator.credentials.request() creates and forwards the right +// arguments to the app side. +// TODO(rohitrao): Fails after merge r376674. https://crbug.com/588706. +TEST_F(CredentialManagerJsTest, DISABLED_RequestToApp) { + Inject(); + std::vector<std::string> empty_federations; + std::vector<std::string> nonempty_federations; + nonempty_federations.push_back("foo"); + nonempty_federations.push_back("bar"); + + EXPECT_CALL(observer(), + CredentialsRequested(0, _, false, empty_federations, _)); + EvaluateJavaScriptAsString(@"navigator.credentials.request()"); + + EXPECT_CALL(observer(), + CredentialsRequested(1, _, false, empty_federations, _)); + EvaluateJavaScriptAsString(@"navigator.credentials.request({})"); + + EXPECT_CALL(observer(), + CredentialsRequested(2, _, true, empty_federations, _)); + EvaluateJavaScriptAsString( + @"navigator.credentials.request({suppressUI: true})"); + + EXPECT_CALL(observer(), + CredentialsRequested(3, _, false, nonempty_federations, _)); + EvaluateJavaScriptAsString( + @"navigator.credentials.request({federations: ['foo', 'bar']})"); + + EXPECT_CALL(observer(), + CredentialsRequested(4, _, true, nonempty_federations, _)); + EvaluateJavaScriptAsString( + @"navigator.credentials.request(" + @" { suppressUI: true, federations: ['foo', 'bar'] })"); + + EXPECT_CALL(observer(), + CredentialsRequested(5, _, false, empty_federations, _)); + EvaluateJavaScriptAsString(@"navigator.credentials.request(" + @" { suppressUI: false, federations: [] })"); +} + +// Tests that navigator.credentials.notifySignedIn() creates and forwards the +// right arguments to the app side. +TEST_F(CredentialManagerJsTest, NotifySignedInToApp) { + Inject(); + EXPECT_CALL(observer(), SignedIn(0, _)); + EvaluateJavaScriptAsString(@"navigator.credentials.notifySignedIn()"); + + EXPECT_CALL(observer(), SignedIn(1, _, IsEqualTo(test_credential()))); + EvaluateJavaScriptAsString( + [NSString stringWithFormat:@"navigator.credentials.notifySignedIn(%@)", + test_credential_js()]); +} + +// Tests that navigator.credentials.notifySignedOut() creates and forwards the +// right arguments to the app side. +TEST_F(CredentialManagerJsTest, NotifySignedOutToApp) { + Inject(); + EXPECT_CALL(observer(), SignedOut(0, _)); + EvaluateJavaScriptAsString(@"navigator.credentials.notifySignedOut()"); +} + +// Tests that navigator.credentials.notifyFailedSignIn() creates and forwards +// the right arguments to the app side. +TEST_F(CredentialManagerJsTest, NotifyFailedSignInToApp) { + Inject(); + EXPECT_CALL(observer(), SignInFailed(0, _)); + EvaluateJavaScriptAsString(@"navigator.credentials.notifyFailedSignIn()"); + + EXPECT_CALL(observer(), SignInFailed(1, _, IsEqualTo(test_credential()))); + EvaluateJavaScriptAsString([NSString + stringWithFormat:@"navigator.credentials.notifyFailedSignIn(%@)", + test_credential_js()]); +} + +// Tests that resolving the promise returned by a call to +// navigator.credentials.request() with a credential correctly forwards that +// credential to the client. +TEST_F(CredentialManagerJsTest, ResolveRequestPromiseWithCredential) { + Inject(); + const int request_id = 0; + EXPECT_CALL(observer(), CredentialsRequested(request_id, _, _, _, _)); + TestPromiseResolutionWithCredential(request_id, + @"navigator.credentials.request()"); +} + +// Tests that resolving the promise returned by a call to +// navigator.credentials.request() without a credential correctly invokes the +// client handler. +TEST_F(CredentialManagerJsTest, ResolveRequestPromiseWithoutCredential) { + Inject(); + const int request_id = 0; + EXPECT_CALL(observer(), CredentialsRequested(request_id, _, _, _, _)); + TestPromiseResolutionWithoutCredential(request_id, + @"navigator.credentials.request()"); +} + +// Tests that resolving the promise returned by a call to +// navigator.credentials.notifySignedIn() without a credential correctly invokes +// the client handler. +TEST_F(CredentialManagerJsTest, ResolveNotifySignedInPromiseWithoutCredential) { + Inject(); + const int request_id = 0; + EXPECT_CALL(observer(), SignedIn(request_id, _)); + TestPromiseResolutionWithoutCredential( + request_id, @"navigator.credentials.notifySignedIn()"); +} + +// Tests that resolving the promise returned by a call to +// navigator.credentials.notifyFailedSignIn() without a credential correctly +// invokes the client handler. +TEST_F(CredentialManagerJsTest, + ResolveNotifyFailedSignInPromiseWithoutCredential) { + Inject(); + const int request_id = 0; + EXPECT_CALL(observer(), SignInFailed(request_id, _)); + TestPromiseResolutionWithoutCredential( + request_id, @"navigator.credentials.notifyFailedSignIn()"); +} + +// Tests that resolving the promise returned by a call to +// navigator.credentials.notifyFailedSignIn() without a credential correctly +// invokes the client handler. +TEST_F(CredentialManagerJsTest, + ResolveNotifySignedOutPromiseWithoutCredential) { + Inject(); + const int request_id = 0; + EXPECT_CALL(observer(), SignedOut(request_id, _)); + TestPromiseResolutionWithoutCredential( + request_id, @"navigator.credentials.notifySignedOut()"); +} + +// Tests that rejecting the promise returned by a call to +// navigator.credentials.request() with a InvalidStateError correctly forwards +// that error to the client. +TEST_F(CredentialManagerJsTest, RejectRequestPromiseWithInvalidStateError) { + Inject(); + const int request_id = 0; + EXPECT_CALL(observer(), CredentialsRequested(request_id, _, _, _, _)); + TestPromiseRejection(request_id, @"InvalidStateError", @"foo", + @"navigator.credentials.request()"); +} + +// Tests that rejecting the promise returned by a call to +// navigator.credentials.notifySignedIn() with a InvalidStateError correctly +// forwards that error to the client. +TEST_F(CredentialManagerJsTest, + RejectNotifySignedInPromiseWithInvalidStateError) { + Inject(); + const int request_id = 0; + EXPECT_CALL(observer(), SignedIn(request_id, _)); + TestPromiseRejection(request_id, @"InvalidStateError", @"foo", + @"navigator.credentials.notifySignedIn()"); +} + +// Tests that rejecting the promise returned by a call to +// navigator.credentials.notifyFailedSignIn() with a InvalidStateError correctly +// forwards that error to the client. +TEST_F(CredentialManagerJsTest, + RejectNotifyFailedSignInPromiseWithInvalidStateError) { + Inject(); + const int request_id = 0; + EXPECT_CALL(observer(), SignInFailed(request_id, _)); + TestPromiseRejection(request_id, @"InvalidStateError", @"foo", + @"navigator.credentials.notifyFailedSignIn()"); +} + +// Tests that rejecting the promise returned by a call to +// navigator.credentials.notifySignedOut() with a InvalidStateError correctly +// forwards that error to the client. +TEST_F(CredentialManagerJsTest, + RejectNotifySignedOutPromiseWithInvalidStateError) { + Inject(); + const int request_id = 0; + EXPECT_CALL(observer(), SignedOut(request_id, _)); + TestPromiseRejection(request_id, @"InvalidStateError", @"foo", + @"navigator.credentials.notifySignedOut()"); +} + +// Tests that rejecting the promise returned by a call to +// navigator.credentials.request() with a SecurityError correctly forwards that +// error to the client. +TEST_F(CredentialManagerJsTest, RejectRequestPromiseWithSecurityError) { + Inject(); + const int request_id = 0; + EXPECT_CALL(observer(), CredentialsRequested(request_id, _, _, _, _)); + TestPromiseRejection(request_id, @"SecurityError", @"foo", + @"navigator.credentials.request()"); +} + +// Tests that rejecting the promise returned by a call to +// navigator.credentials.notifySignedIn() with a SecurityError correctly +// forwards that error to the client. +TEST_F(CredentialManagerJsTest, RejectNotifySignedInPromiseWithSecurityError) { + Inject(); + const int request_id = 0; + EXPECT_CALL(observer(), SignedIn(request_id, _)); + TestPromiseRejection(request_id, @"SecurityError", @"foo", + @"navigator.credentials.notifySignedIn()"); +} + +// Tests that rejecting the promise returned by a call to +// navigator.credentials.notifyFailedSignIn() with a SecurityError correctly +// forwards that error to the client. +TEST_F(CredentialManagerJsTest, + RejectPromiseWithSecurityError_notifyFailedSignIn) { + Inject(); + const int request_id = 0; + EXPECT_CALL(observer(), SignInFailed(request_id, _)); + TestPromiseRejection(request_id, @"SecurityError", @"foo", + @"navigator.credentials.notifyFailedSignIn()"); +} + +// Tests that rejecting the promise returned by a call to +// navigator.credentials.notifySignedOut() with a SecurityError correctly +// forwards that error to the client. +TEST_F(CredentialManagerJsTest, + RejectPromiseWithSecurityError_notifySignedOut) { + Inject(); + const int request_id = 0; + EXPECT_CALL(observer(), SignedOut(request_id, _)); + TestPromiseRejection(request_id, @"SecurityError", @"foo", + @"navigator.credentials.notifySignedOut()"); +} + +} // namespace
diff --git a/ios/chrome/browser/passwords/credential_manager_unittest.mm b/ios/chrome/browser/passwords/credential_manager_unittest.mm new file mode 100644 index 0000000..4b7e97b79 --- /dev/null +++ b/ios/chrome/browser/passwords/credential_manager_unittest.mm
@@ -0,0 +1,610 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/passwords/credential_manager.h" + +#include <memory> +#include <utility> + +#include "base/mac/bind_objc_block.h" +#include "base/memory/ref_counted.h" +#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "components/password_manager/core/browser/password_bubble_experiment.h" +#include "components/password_manager/core/browser/stub_password_manager_client.h" +#include "components/password_manager/core/browser/stub_password_manager_driver.h" +#include "components/password_manager/core/browser/test_password_store.h" +#include "components/password_manager/core/common/credential_manager_types.h" +#include "components/password_manager/core/common/password_manager_pref_names.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/testing_pref_service.h" +#import "ios/web/public/web_state/web_state.h" +#import "ios/chrome/browser/passwords/js_credential_manager.h" +#import "ios/testing/ocmock_complex_type_helper.h" +#import "ios/web/public/test/web_test_with_web_state.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gtest_mac.h" +#include "third_party/ocmock/OCMock/OCMock.h" +#include "third_party/ocmock/gtest_support.h" +#include "url/gurl.h" + +using testing::Return; + +namespace { +// Type of a function invoked when a promise is resolved. +typedef void (^ResolvePromiseBlock)(NSInteger request_id, + const web::Credential& credential); +} // namespace + +// A helper to mock methods that have C++ object parameters. +@interface MockJSCredentialManager : OCMockComplexTypeHelper +@end + +@implementation MockJSCredentialManager +- (void)resolvePromiseWithRequestID:(NSInteger)requestID + credential:(const web::Credential&)credential + completionHandler:(void (^)(BOOL))completionHandler { + static_cast<ResolvePromiseBlock>([self blockForSelector:_cmd])(requestID, + credential); + completionHandler(YES); +} +@end + +namespace { + +// Returns a test credential. +autofill::PasswordForm GetTestPasswordForm1(bool zero_click_allowed) { + autofill::PasswordForm form; + form.username_value = base::ASCIIToUTF16("foo"); + form.password_value = base::ASCIIToUTF16("bar"); + form.skip_zero_click = !zero_click_allowed; + form.ssl_valid = true; + form.type = autofill::PasswordForm::Type::TYPE_API; + return form; +} + +// Returns a test credential matching |GetTestPasswordForm1()|. +web::Credential GetTestWebCredential1(bool zero_click_allowed) { + web::Credential credential; + autofill::PasswordForm form(GetTestPasswordForm1(zero_click_allowed)); + credential.type = web::CredentialType::CREDENTIAL_TYPE_PASSWORD; + credential.id = form.username_value; + credential.password = form.password_value; + return credential; +} + +// Returns a different test credential. +autofill::PasswordForm GetTestPasswordForm2(bool zero_click_allowed) { + autofill::PasswordForm form; + form.username_value = base::ASCIIToUTF16("baz"); + form.password_value = base::ASCIIToUTF16("bah"); + form.skip_zero_click = !zero_click_allowed; + form.ssl_valid = true; + return form; +} + +// Returns a test credential matching |GetTestPasswordForm2()|. +web::Credential GetTestWebCredential2(bool zero_click_allowed) { + web::Credential credential; + autofill::PasswordForm form(GetTestPasswordForm2(zero_click_allowed)); + credential.type = web::CredentialType::CREDENTIAL_TYPE_PASSWORD; + credential.id = form.username_value; + credential.password = form.password_value; + return credential; +} + +typedef BOOL (^StringPredicate)(NSString*); + +// Returns a block that takes a string argument and returns whether it is equal +// to |string|. +StringPredicate EqualsString(const char* string) { + return [[^BOOL(NSString* other) { + return [base::SysUTF8ToNSString(string) isEqualToString:other]; + } copy] autorelease]; +} + +// A stub PasswordManagerClient for testing. +class StubPasswordManagerClient + : public password_manager::StubPasswordManagerClient { + public: + StubPasswordManagerClient() + : password_manager::StubPasswordManagerClient(), + password_store_(nullptr) { + prefs_.registry()->RegisterBooleanPref( + password_manager::prefs::kCredentialsEnableAutosignin, false); + password_bubble_experiment::RegisterPrefs(prefs_.registry()); + } + + ~StubPasswordManagerClient() override { + if (password_store_) + password_store_->ShutdownOnUIThread(); + } + + MOCK_CONST_METHOD0(IsSavingAndFillingEnabledForCurrentPage, bool()); + + void SetPasswordStore( + scoped_refptr<password_manager::PasswordStore> password_store) { + password_store_ = password_store; + } + + password_manager::PasswordStore* GetPasswordStore() const override { + return password_store_.get(); + } + + void SetUserChosenCredential( + const password_manager::CredentialInfo& credential) { + user_chosen_credential_ = credential; + } + + bool PromptUserToChooseCredentials( + ScopedVector<autofill::PasswordForm> local_forms, + ScopedVector<autofill::PasswordForm> federated_forms, + const GURL& origin, + const CredentialsCallback& callback) override { + return false; + } + + bool PromptUserToSaveOrUpdatePassword( + std::unique_ptr<password_manager::PasswordFormManager> form_to_save, + password_manager::CredentialSourceType type, + bool update_password) override { + if (!update_password) + saved_form_ = std::move(form_to_save); + return true; + } + + PrefService* GetPrefs() override { return &prefs_; } + + password_manager::PasswordFormManager* saved_form() { + return saved_form_.get(); + } + + private: + // PrefService for testing. + TestingPrefServiceSimple prefs_; + + // PasswordStore for testing. + scoped_refptr<password_manager::PasswordStore> password_store_; + + // The password form shown to the user for saving. + std::unique_ptr<password_manager::PasswordFormManager> saved_form_; + + // The credential to be returned to callers of PromptUserToChooseCredentials. + password_manager::CredentialInfo user_chosen_credential_; + + DISALLOW_COPY_AND_ASSIGN(StubPasswordManagerClient); +}; + +// Tests for CredentialManager. +class CredentialManagerTest : public web::WebTestWithWebState { + public: + CredentialManagerTest() {} + ~CredentialManagerTest() override {} + + void SetUp() override { + web::WebTestWithWebState::SetUp(); + id originalMock = + [OCMockObject niceMockForClass:[JSCredentialManager class]]; + mock_js_credential_manager_.reset([[MockJSCredentialManager alloc] + initWithRepresentedObject:originalMock]); + credential_manager_.reset(new CredentialManager( + web_state(), &stub_client_, &stub_driver_, + static_cast<id>(mock_js_credential_manager_.get()))); + } + + // Sets up an expectation that the promise identified by |request_id| will be + // resolved with |credential|. |verified| must point to a variable that will + // be checked by the caller to ensure that the expectations were run. (This + // is necessary because OCMock doesn't handle methods with C++ object + // parameters.) + void ExpectPromiseResolved(bool* verified, + int request_id, + const web::Credential& credential) { + SEL selector = + @selector(resolvePromiseWithRequestID:credential:completionHandler:); + web::Credential strong_credential(credential); + [mock_js_credential_manager_ + onSelector:selector + callBlockExpectation:^(NSInteger block_request_id, + const web::Credential& block_credential) { + EXPECT_EQ(request_id, block_request_id); + EXPECT_TRUE(CredentialsEqual(strong_credential, block_credential)); + *verified = true; + }]; + } + + // Same as |ExpectPromiseResolved(bool*, int, const web::Credential&)| but + // does not expect a credential to be passed. + void ExpectPromiseResolved(int request_id) { + [[[mock_js_credential_manager_ representedObject] expect] + resolvePromiseWithRequestID:request_id + completionHandler:nil]; + } + + // Clears the expectations set up by |ExpectPromiseResolved()|. + void ClearPromiseResolutionExpectations() { + SEL selector = + @selector(resolvePromiseWithRequestID:credential:completionHandler:); + [mock_js_credential_manager_ removeBlockExpectationOnSelector:selector]; + } + + // Sets up an expectation that the promise identified by |request_id| will be + // rejected with the given |error_type| and |message|. The caller should use + // EXPECT_OCMOCK_VERIFY to verify that the expectations were run. + void ExpectPromiseRejected(int request_id, + const char* error_type, + const char* message) { + [[[mock_js_credential_manager_ representedObject] expect] + rejectPromiseWithRequestID:request_id + errorType:[OCMArg + checkWithBlock:EqualsString(error_type)] + message:[OCMArg checkWithBlock:EqualsString(message)] + completionHandler:[OCMArg any]]; + } + + protected: + // Mock for PasswordManagerClient. + StubPasswordManagerClient stub_client_; + + // Stub for PasswordManagerDriver. + password_manager::StubPasswordManagerDriver stub_driver_; + + // Mock for JSCredentialManager. + base::scoped_nsobject<MockJSCredentialManager> mock_js_credential_manager_; + + // CredentialManager for testing. + std::unique_ptr<CredentialManager> credential_manager_; + + private: + explicit CredentialManagerTest(const CredentialManagerTest&) = delete; + CredentialManagerTest& operator=(const CredentialManagerTest&) = delete; +}; + +// Tests that a credential request is rejected properly when the PasswordStore +// is unavailable. +TEST_F(CredentialManagerTest, RequestRejectedWhenPasswordStoreUnavailable) { + // Clear the password store. + stub_client_.SetPasswordStore(nullptr); + + // Requesting a credential should reject the request with an error. + const int request_id = 0; + ExpectPromiseRejected(request_id, + kCredentialsPasswordStoreUnavailableErrorType, + kCredentialsPasswordStoreUnavailableErrorMessage); + credential_manager_->CredentialsRequested(request_id, + GURL("http://foo.com/login"), false, + std::vector<std::string>(), true); + + // Pump the message loop and verify. + WaitForBackgroundTasks(); + EXPECT_OCMOCK_VERIFY([mock_js_credential_manager_ representedObject]); +} + +// Tests that a credential request is rejected when another request is pending. +TEST_F(CredentialManagerTest, RequestRejectedWhenExistingRequestIsPending) { + // Set a password store, but prevent requests from completing. + stub_client_.SetPasswordStore(new password_manager::TestPasswordStore); + + // Make an initial request. Don't pump the message loop, so that the task + // doesn't complete. Expect the request to resolve with an empty credential + // after the message loop is pumped. + const int first_request_id = 0; + bool first_verified = false; + ExpectPromiseResolved(&first_verified, first_request_id, web::Credential()); + credential_manager_->CredentialsRequested(first_request_id, + GURL("http://foo.com/login"), false, + std::vector<std::string>(), true); + + // Making a second request and then pumping the message loop should reject the + // request with an error. + const int second_request_id = 0; + ExpectPromiseRejected(second_request_id, kCredentialsPendingRequestErrorType, + kCredentialsPendingRequestErrorMessage); + credential_manager_->CredentialsRequested(second_request_id, + GURL("http://foo.com/login"), false, + std::vector<std::string>(), true); + + // Pump the message loop and verify. + WaitForBackgroundTasks(); + EXPECT_TRUE(first_verified); + EXPECT_OCMOCK_VERIFY([mock_js_credential_manager_ representedObject]); +} + +// Tests that a zero-click credential request is resolved properly with an empty +// credential when zero-click sign-in is disabled. +TEST_F(CredentialManagerTest, + ZeroClickRequestResolvedWithEmptyCredentialWhenZeroClickSignInDisabled) { + // Set a password store, but request a zero-click credential with zero-click + // disabled. + stub_client_.SetPasswordStore(new password_manager::TestPasswordStore); + const bool zero_click = true; + static_cast<TestingPrefServiceSimple*>(stub_client_.GetPrefs()) + ->SetUserPref(password_manager::prefs::kCredentialsEnableAutosignin, + new base::FundamentalValue(!zero_click)); + + // Requesting a zero-click credential should immediately resolve the request + // with an empty credential. + const int request_id = 0; + bool verified = false; + ExpectPromiseResolved(&verified, request_id, web::Credential()); + credential_manager_->CredentialsRequested( + request_id, GURL("http://foo.com/login"), zero_click, + std::vector<std::string>(), true); + + // Pump the message loop and verify. + WaitForBackgroundTasks(); + EXPECT_TRUE(verified); +} + +// Tests that a credential request is properly resolved with an empty credential +// when no credentials are available. +TEST_F(CredentialManagerTest, + RequestResolvedWithEmptyCredentialWhenNoneAvailable) { + // Set a password store with no credentials, enable zero-click, and request a + // zero-click credential. + stub_client_.SetPasswordStore(new password_manager::TestPasswordStore); + const bool zero_click = true; + static_cast<TestingPrefServiceSimple*>(stub_client_.GetPrefs()) + ->SetUserPref(password_manager::prefs::kCredentialsEnableAutosignin, + new base::FundamentalValue(zero_click)); + + // Requesting a zero-click credential should try to retrieve PasswordForms + // from the PasswordStore and resolve the request with an empty Credential + // when none are found. + const int request_id = 0; + bool verified = false; + ExpectPromiseResolved(&verified, request_id, web::Credential()); + credential_manager_->CredentialsRequested( + request_id, GURL("http://foo.com/login"), zero_click, + std::vector<std::string>(), true); + + // Pump the message loop and verify. + WaitForBackgroundTasks(); + EXPECT_TRUE(verified); +} + +// Tests that a zero-click credential request properly resolves. +TEST_F(CredentialManagerTest, ZeroClickRequestResolved) { + // Set a password store with a credential, enable zero-click, and request a + // zero-click credential. + scoped_refptr<password_manager::TestPasswordStore> store( + new password_manager::TestPasswordStore); + const bool zero_click = true; + store->AddLogin(GetTestPasswordForm1(zero_click)); + stub_client_.SetPasswordStore(store); + static_cast<TestingPrefServiceSimple*>(stub_client_.GetPrefs()) + ->SetUserPref(password_manager::prefs::kCredentialsEnableAutosignin, + new base::FundamentalValue(zero_click)); + // Without the first run experience, the zero-click credentials won't be + // passed to the site. + static_cast<TestingPrefServiceSimple*>(stub_client_.GetPrefs()) + ->SetUserPref( + password_manager::prefs::kWasAutoSignInFirstRunExperienceShown, + new base::FundamentalValue(true)); + WaitForBackgroundTasks(); + + // Requesting a zero-click credential should retrieve a PasswordForm from the + // PasswordStore and resolve the request with a corresponding Credential. + const int request_id = 0; + bool verified = false; + ExpectPromiseResolved(&verified, request_id, + GetTestWebCredential1(zero_click)); + credential_manager_->CredentialsRequested( + request_id, GURL("http://foo.com/login"), zero_click, + std::vector<std::string>(), true); + + // Pump the message loop and verify. + WaitForBackgroundTasks(); + EXPECT_TRUE(verified); +} + +// Tests that a credential request properly resolves. +// TODO(crbug.com/598851): Reenabled this test. +TEST_F(CredentialManagerTest, DISABLED_RequestResolved) { + // Set a password store with two credentials and set a credential to be + // returned by the PasswordManagerClient as if chosen by the user. + scoped_refptr<password_manager::TestPasswordStore> store( + new password_manager::TestPasswordStore); + const bool zero_click = false; + store->AddLogin(GetTestPasswordForm1(zero_click)); + store->AddLogin(GetTestPasswordForm2(zero_click)); + stub_client_.SetPasswordStore(store); + stub_client_.SetUserChosenCredential(password_manager::CredentialInfo( + GetTestPasswordForm2(zero_click), + password_manager::CredentialType::CREDENTIAL_TYPE_PASSWORD)); + WaitForBackgroundTasks(); + + // Request a credential. The request should be resolved with the credential + // set on the stub client. + const int request_id = 0; + bool verified = false; + ExpectPromiseResolved(&verified, request_id, + GetTestWebCredential2(zero_click)); + credential_manager_->CredentialsRequested( + request_id, GURL("http://foo.com/login"), zero_click, + std::vector<std::string>(), true); + + // Pump the message loop and verify. + WaitForBackgroundTasks(); + EXPECT_TRUE(verified); +} + +// Tests that two requests back-to-back succeed when they wait to be resolved. +// TODO(crbug.com/598851): Reenable this test. +TEST_F(CredentialManagerTest, DISABLED_ConsecutiveRequestsResolve) { + // Set a password store with two credentials and set a credential to be + // returned by the PasswordManagerClient as if chosen by the user. + scoped_refptr<password_manager::TestPasswordStore> store( + new password_manager::TestPasswordStore); + const bool zero_click = false; + store->AddLogin(GetTestPasswordForm1(zero_click)); + stub_client_.SetPasswordStore(store); + stub_client_.SetUserChosenCredential(password_manager::CredentialInfo( + GetTestPasswordForm1(zero_click), + password_manager::CredentialType::CREDENTIAL_TYPE_PASSWORD)); + WaitForBackgroundTasks(); + + // Request a credential. The request should be resolved with the credential + // set on the stub client. + const int first_request_id = 0; + bool first_verified = false; + ExpectPromiseResolved(&first_verified, first_request_id, + GetTestWebCredential1(zero_click)); + credential_manager_->CredentialsRequested( + first_request_id, GURL("http://foo.com/login"), zero_click, + std::vector<std::string>(), true); + + // Pump the message loop and verify. + WaitForBackgroundTasks(); + EXPECT_TRUE(first_verified); + + ClearPromiseResolutionExpectations(); + + // Make a second request. It should be resolved again. + const int second_request_id = 1; + bool second_verified = false; + ExpectPromiseResolved(&second_verified, second_request_id, + GetTestWebCredential1(zero_click)); + credential_manager_->CredentialsRequested( + second_request_id, GURL("http://foo.com/login"), zero_click, + std::vector<std::string>(), true); + + // Pump the message loop and verify. + WaitForBackgroundTasks(); + EXPECT_TRUE(second_verified); +} + +// Tests that notifySignedIn prompts the user to save a password. +TEST_F(CredentialManagerTest, + SignInResolvesAndPromptsUserWhenSavingEnabledAndNotBlacklisted) { + // Set a password store so the PasswordFormManager can retrieve credentials. + scoped_refptr<password_manager::TestPasswordStore> store( + new password_manager::TestPasswordStore); + stub_client_.SetPasswordStore(store); + const bool saving_enabled = true; + EXPECT_CALL(stub_client_, IsSavingAndFillingEnabledForCurrentPage()) + .WillOnce(Return(saving_enabled)) + .WillOnce(Return(saving_enabled)); + + // Notify the browser that the user signed in. + const int request_id = 0; + ExpectPromiseResolved(request_id); + const bool zero_click = false; + credential_manager_->SignedIn(request_id, GURL("http://foo.com/login"), + GetTestWebCredential1(zero_click)); + + // Pump the message loop and verify. + WaitForBackgroundTasks(); + autofill::PasswordForm expected_observed_form( + GetTestPasswordForm1(zero_click)); + expected_observed_form.username_value.clear(); + expected_observed_form.password_value.clear(); + EXPECT_EQ(expected_observed_form, stub_client_.saved_form()->observed_form()); +} + +// Tests that notifySignedIn doesn't prompt the user to save a password when the +// password manager is disabled for the current page. +TEST_F(CredentialManagerTest, + SignInResolvesAndDoesNotPromptsUserWhenSavingDisabledAndNotBlacklisted) { + // Disable saving. + scoped_refptr<password_manager::TestPasswordStore> store( + new password_manager::TestPasswordStore); + stub_client_.SetPasswordStore(store); + const bool saving_enabled = false; + EXPECT_CALL(stub_client_, IsSavingAndFillingEnabledForCurrentPage()) + .WillOnce(Return(saving_enabled)); + + // Notify the browser that the user signed in. + const int request_id = 0; + ExpectPromiseResolved(request_id); + const bool zero_click = false; + credential_manager_->SignedIn(request_id, GURL("http://foo.com/login"), + GetTestWebCredential1(zero_click)); + + // Pump the message loop and verify that no form was saved. + WaitForBackgroundTasks(); + EXPECT_FALSE(stub_client_.saved_form()); +} + +// Tests that notifySignedIn doesn't prompt the user to save a password when the +// submitted form is blacklisted by the password manager. +TEST_F(CredentialManagerTest, + SignInResolvesAndDoesNotPromptUserWhenSavingEnabledAndBlacklisted) { + // Disable saving. + scoped_refptr<password_manager::TestPasswordStore> store( + new password_manager::TestPasswordStore); + stub_client_.SetPasswordStore(store); + const bool saving_enabled = true; + EXPECT_CALL(stub_client_, IsSavingAndFillingEnabledForCurrentPage()) + .WillOnce(Return(saving_enabled)) + .WillOnce(Return(saving_enabled)); + + // Save the credential that will be signed in and mark it blacklisted. + const bool zero_click = false; + autofill::PasswordForm blacklisted_form(GetTestPasswordForm1(zero_click)); + blacklisted_form.blacklisted_by_user = true; + store->AddLogin(blacklisted_form); + WaitForBackgroundTasks(); + + // Notify the browser that the user signed in. + const int request_id = 0; + ExpectPromiseResolved(request_id); + credential_manager_->SignedIn(request_id, GURL("http://foo.com/login"), + GetTestWebCredential1(zero_click)); + + // Pump the message loop and verify that no form was saved. + WaitForBackgroundTasks(); + EXPECT_FALSE(stub_client_.saved_form()); +} + +// Tests that notifySignedOut marks credentials as non-zero-click. +TEST_F(CredentialManagerTest, SignOutResolvesAndMarksFormsNonZeroClick) { + // Create two zero-click credentials for the current page. + std::string current_origin(credential_manager_->GetOrigin().spec()); + autofill::PasswordForm form1(GetTestPasswordForm1(true)); + form1.signon_realm = current_origin; + autofill::PasswordForm form2(GetTestPasswordForm2(true)); + form2.signon_realm = current_origin; + + // Add both credentials to the store. + scoped_refptr<password_manager::TestPasswordStore> store( + new password_manager::TestPasswordStore); + stub_client_.SetPasswordStore(store); + store->AddLogin(form1); + store->AddLogin(form2); + WaitForBackgroundTasks(); + + // Check that both credentials in the store are zero-click. + EXPECT_EQ(1U, store->stored_passwords().size()); + const std::vector<autofill::PasswordForm>& passwords_before_signout = + store->stored_passwords().find(current_origin)->second; + EXPECT_EQ(2U, passwords_before_signout.size()); + for (const autofill::PasswordForm& form : passwords_before_signout) + EXPECT_FALSE(form.skip_zero_click); + + // Sign out the current origin, which has credentials, and a second origin, + // which doesnt. + const int first_request_id = 0; + ExpectPromiseResolved(first_request_id); + credential_manager_->SignedOut(first_request_id, + credential_manager_->GetOrigin()); + const int second_request_id = 1; + ExpectPromiseResolved(second_request_id); + credential_manager_->SignedOut(second_request_id, GURL("https://foo.com")); + + // Pump the message loop to let the promises resolve. Check that the + // credentials in the store are now non-zero-click and that signing out an + // origin with no credentials had no effect. + WaitForBackgroundTasks(); + EXPECT_EQ(1U, store->stored_passwords().size()); + const std::vector<autofill::PasswordForm>& passwords_after_signout = + store->stored_passwords().find(current_origin)->second; + EXPECT_EQ(2U, passwords_after_signout.size()); + for (const autofill::PasswordForm& form : passwords_after_signout) + EXPECT_TRUE(form.skip_zero_click); +} + +} // namespace
diff --git a/ios/chrome/browser/passwords/password_controller_js_unittest.mm b/ios/chrome/browser/passwords/password_controller_js_unittest.mm new file mode 100644 index 0000000..966edc5e --- /dev/null +++ b/ios/chrome/browser/passwords/password_controller_js_unittest.mm
@@ -0,0 +1,300 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <Foundation/Foundation.h> + +#import "ios/chrome/browser/passwords/js_password_manager.h" +#import "ios/web/public/test/web_js_test.h" +#import "ios/web/public/test/web_test_with_web_state.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gtest_mac.h" + +// Unit tests for ios/chrome/browser/web/resources/password_controller.js +namespace { + +// Text fixture to test password controller. +class PasswordControllerJsTest + : public web::WebJsTest<web::WebTestWithWebState> { + public: + PasswordControllerJsTest() + : web::WebJsTest<web::WebTestWithWebState>(@[ @"password_controller" ]) {} +}; + +// IDs used in the Username and Password <input> elements. +NSString* const kEmailInputID = @"Email"; +NSString* const kPasswordInputID = @"Passwd"; + +// Returns an autoreleased string of an HTML form that is similar to the +// Google Accounts sign in form. |email| may be nil if the form does not +// need to be pre-filled with the username. Use |isReadOnly| flag to indicate +// if the email field should be read-only. +NSString* GAIASignInForm(NSString* formAction, + NSString* email, + BOOL isReadOnly) { + return [NSString + stringWithFormat: + @"<html><body>" + "<form novalidate method=\"post\" action=\"%@\" " + "id=\"gaia_loginform\">" + " <input name=\"GALX\" type=\"hidden\" value=\"abcdefghij\">" + " <input name=\"service\" type=\"hidden\" value=\"mail\">" + " <input id=\"%@\" name=\"Email\" type=\"email\" value=\"%@\" %@>" + " <input id=\"%@\" name=\"Passwd\" type=\"password\" " + " placeholder=\"Password\">" + "</form></body></html>", + formAction, kEmailInputID, email ? email : @"", + isReadOnly ? @"readonly" : @"", kPasswordInputID]; +} + +// Returns an autoreleased string of JSON for a parsed form. +NSString* GAIASignInFormData(NSString* formAction) { + return [NSString stringWithFormat:@"{" + " \"action\":\"%@\"," + " \"origin\":\"%@\"," + " \"fields\":[" + " {\"name\":\"%@\", \"value\":\"\"}," + " {\"name\":\"%@\",\"value\":\"\"}" + " ]" + "}", + formAction, formAction, kEmailInputID, + kPasswordInputID]; +} + +// Loads a page with a password form containing a username value already. +// Checks that an attempt to fill in credentials with the same username +// succeeds. +TEST_F(PasswordControllerJsTest, + FillPasswordFormWithPrefilledUsername_SucceedsWhenUsernameMatches) { + NSString* const formAction = @"https://accounts.google.com/ServiceLoginAuth"; + NSString* const username = @"john.doe@gmail.com"; + NSString* const password = @"super!secret"; + LoadHtmlAndInject(GAIASignInForm(formAction, username, YES)); + EXPECT_NSEQ(@"true", EvaluateJavaScriptWithFormat( + @"__gCrWeb.fillPasswordForm(%@, '%@', '%@', '%@')", + GAIASignInFormData(formAction), username, password, + formAction)); + // Verifies that the sign-in form has been filled with username/password. + EvaluateJavaScriptOnElementsAndCheck(@"document.getElementById('%@').value", + @[ kEmailInputID, kPasswordInputID ], + @[ username, password ]); +} + +// Loads a page with a password form containing a username value already. +// Checks that an attempt to fill in credentials with a different username +// fails, as long as the field is read-only. +TEST_F(PasswordControllerJsTest, + FillPasswordFormWithPrefilledUsername_FailsWhenUsernameMismatched) { + NSString* const formAction = @"https://accounts.google.com/ServiceLoginAuth"; + NSString* const username1 = @"john.doe@gmail.com"; + NSString* const username2 = @"jean.dubois@gmail.com"; + NSString* const password = @"super!secret"; + LoadHtmlAndInject(GAIASignInForm(formAction, username1, YES)); + EXPECT_NSEQ(@"false", EvaluateJavaScriptWithFormat( + @"__gCrWeb.fillPasswordForm(%@, '%@', '%@', '%@')", + GAIASignInFormData(formAction), username2, password, + formAction)); + // Verifies that the sign-in form has not been filled. + EvaluateJavaScriptOnElementsAndCheck(@"document.getElementById('%@').value", + @[ kEmailInputID, kPasswordInputID ], + @[ username1, @"" ]); +} + +// Loads a page with a password form containing a username value already. +// Checks that an attempt to fill in credentials with a different username +// succeeds, as long as the field is writeable. +TEST_F(PasswordControllerJsTest, + FillPasswordFormWithPrefilledUsername_SucceedsByOverridingUsername) { + NSString* const formAction = @"https://accounts.google.com/ServiceLoginAuth"; + NSString* const username1 = @"john.doe@gmail.com"; + NSString* const username2 = @"jane.doe@gmail.com"; + NSString* const password = @"super!secret"; + LoadHtmlAndInject(GAIASignInForm(formAction, username1, NO)); + EXPECT_NSEQ(@"true", EvaluateJavaScriptWithFormat( + @"__gCrWeb.fillPasswordForm(%@, '%@', '%@', '%@')", + GAIASignInFormData(formAction), username2, password, + formAction)); + // Verifies that the sign-in form has been filled with the new username + // and password. + EvaluateJavaScriptOnElementsAndCheck(@"document.getElementById('%@').value", + @[ kEmailInputID, kPasswordInputID ], + @[ username2, password ]); +} + +// Check that when instructed to fill a form named "bar", a form named "foo" +// is not filled with generated password. +TEST_F(PasswordControllerJsTest, + FillPasswordFormWithGeneratedPassword_FailsWhenFormNotFound) { + LoadHtmlAndInject(@"<html>" + " <body>" + " <form name=\"foo\">" + " <input type=\"password\" name=\"ps\">" + " </form>" + " </body" + "</html>"); + NSString* const formName = @"bar"; + NSString* const password = @"abc"; + EXPECT_NSEQ(@"false", + EvaluateJavaScriptWithFormat( + @"__gCrWeb.fillPasswordFormWithGeneratedPassword('%@', '%@')", + formName, password)); +} + +// Check that filling a form without password fields fails. +TEST_F(PasswordControllerJsTest, + FillPasswordFormWithGeneratedPassword_FailsWhenNoFieldsFilled) { + LoadHtmlAndInject(@"<html>" + " <body>" + " <form name=\"foo\">" + " <input type=\"text\" name=\"user\">" + " <input type=\"submit\" name=\"go\">" + " </form>" + " </body" + "</html>"); + NSString* const formName = @"foo"; + NSString* const password = @"abc"; + EXPECT_NSEQ(@"false", + EvaluateJavaScriptWithFormat( + @"__gCrWeb.fillPasswordFormWithGeneratedPassword('%@', '%@')", + formName, password)); +} + +// Check that a matching and complete password form is successfully filled +// with the generated password. +TEST_F(PasswordControllerJsTest, + FillPasswordFormWithGeneratedPassword_SucceedsWhenFieldsFilled) { + LoadHtmlAndInject(@"<html>" + " <body>" + " <form name=\"foo\">" + " <input type=\"text\" id=\"user\" name=\"user\">" + " <input type=\"password\" id=\"ps1\" name=\"ps1\">" + " <input type=\"password\" id=\"ps2\" name=\"ps2\">" + " <input type=\"submit\" name=\"go\">" + " </form>" + " </body" + "</html>"); + NSString* const formName = @"foo"; + NSString* const password = @"abc"; + EXPECT_NSEQ(@"true", + EvaluateJavaScriptWithFormat( + @"__gCrWeb.fillPasswordFormWithGeneratedPassword('%@', '%@')", + formName, password)); + EXPECT_NSEQ(@"true", + EvaluateJavaScriptWithFormat( + @"document.getElementById('ps1').value == '%@'", password)); + EXPECT_NSEQ(@"true", + EvaluateJavaScriptWithFormat( + @"document.getElementById('ps2').value == '%@'", password)); + EXPECT_NSEQ(@"false", + EvaluateJavaScriptWithFormat( + @"document.getElementById('user').value == '%@'", password)); +} + +// Check that one password form is identified and serialized correctly. +TEST_F(PasswordControllerJsTest, + FindAndPreparePasswordFormsSingleFrameSingleForm) { + LoadHtmlAndInject( + @"<html><body>" + "<form action='/generic_submit' method='post' name='login_form'>" + " Name: <input type='text' name='name'>" + " Password: <input type='password' name='password'>" + " <input type='submit' value='Submit'>" + "</form>" + "</body></html>"); + + const std::string base_url = BaseUrl(); + NSString* result = [NSString + stringWithFormat: + @"[{\"action\":\"/generic_submit\"," + "\"method\":\"post\"," + "\"name\":\"login_form\"," + "\"origin\":\"%s\"," + "\"fields\":[{\"element\":\"name\",\"type\":\"text\"}," + "{\"element\":\"password\",\"type\":\"password\"}," + "{\"element\":\"\",\"type\":\"submit\"}]," + "\"usernameElement\":\"name\"," + "\"usernameValue\":\"\"," + "\"passwords\":[{\"element\":\"password\",\"value\":\"\"}]}]", + base_url.c_str()]; + EXPECT_NSEQ(result, + EvaluateJavaScriptWithFormat(@"__gCrWeb.findPasswordForms()")); +}; + +// Check that multiple password forms are identified and serialized correctly. +TEST_F(PasswordControllerJsTest, + FindAndPreparePasswordFormsSingleFrameMultipleForms) { + LoadHtmlAndInject( + @"<html><body>" + "<form action='/generic_submit' method='post' id='login_form1'>" + " Name: <input type='text' name='name'>" + " Password: <input type='password' name='password'>" + " <input type='submit' value='Submit'>" + "</form>" + "<form action='/generic_s2' method='post' name='login_form2'>" + " Name: <input type='text' name='name2'>" + " Password: <input type='password' name='password2'>" + " <input type='submit' value='Submit'>" + "</form>" + "</body></html>"); + + const std::string base_url = BaseUrl(); + NSString* result = [NSString + stringWithFormat: + @"[{\"action\":\"/generic_submit\"," + "\"method\":\"post\"," + "\"name\":\"login_form1\"," + "\"origin\":\"%s\"," + "\"fields\":[{\"element\":\"name\",\"type\":\"text\"}," + "{\"element\":\"password\",\"type\":\"password\"}," + "{\"element\":\"\",\"type\":\"submit\"}]," + "\"usernameElement\":\"name\"," + "\"usernameValue\":\"\"," + "\"passwords\":[{\"element\":\"password\",\"value\":\"\"}]}," + "{\"action\":\"/generic_s2\"," + "\"method\":\"post\"," + "\"name\":\"login_form2\"," + "\"origin\":\"%s\"," + "\"fields\":[{\"element\":\"name2\",\"type\":\"text\"}," + "{\"element\":\"password2\",\"type\":\"password\"}," + "{\"element\":\"\",\"type\":\"submit\"}]," + "\"usernameElement\":\"name2\"," + "\"usernameValue\":\"\"," + "\"passwords\":[{\"element\":\"password2\",\"value\":\"\"}]}]", + base_url.c_str(), base_url.c_str()]; + EXPECT_NSEQ(result, + EvaluateJavaScriptWithFormat(@"__gCrWeb.findPasswordForms()")); +}; + +// Test serializing of password forms. +TEST_F(PasswordControllerJsTest, GetPasswordFormData) { + LoadHtmlAndInject( + @"<html><body>" + "<form name='np' id='np1' action='/generic_submit' method='post'>" + " Name: <input type='text' name='name'>" + " Password: <input type='password' name='password'>" + " <input type='submit' value='Submit'>" + "</form>" + "</body></html>"); + + const std::string base_url = BaseUrl(); + NSString* parameter = @"window.document.getElementsByTagName('form')[0]"; + NSString* result = [NSString + stringWithFormat: + @"{\"action\":\"/generic_submit\"," + "\"method\":\"post\"," + "\"name\":\"np\"," + "\"origin\":\"%s\"," + "\"fields\":[{\"element\":\"name\",\"type\":\"text\"}," + "{\"element\":\"password\",\"type\":\"password\"}," + "{\"element\":\"\",\"type\":\"submit\"}]," + "\"usernameElement\":\"name\"," + "\"usernameValue\":\"\"," + "\"passwords\":[{\"element\":\"password\",\"value\":\"\"}]}", + base_url.c_str()]; + EXPECT_NSEQ( + result, + EvaluateJavaScriptWithFormat( + @"__gCrWeb.stringify(__gCrWeb.getPasswordFormData(%@))", parameter)); +}; + +} // namespace
diff --git a/ios/chrome/browser/passwords/password_controller_off_the_record_unittest.mm b/ios/chrome/browser/passwords/password_controller_off_the_record_unittest.mm new file mode 100644 index 0000000..2ce74f8 --- /dev/null +++ b/ios/chrome/browser/passwords/password_controller_off_the_record_unittest.mm
@@ -0,0 +1,66 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <memory> + +#import "base/mac/scoped_nsobject.h" +#include "base/memory/ptr_util.h" +#include "components/password_manager/core/browser/stub_password_manager_client.h" +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" +#import "ios/chrome/browser/passwords/password_controller.h" +#import "ios/web/public/test/test_web_state.h" +#import "ios/web/public/test/web_test_with_web_state.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +class IncognitoPasswordManagerClient + : public password_manager::StubPasswordManagerClient { + public: + bool IsOffTheRecord() const override { return true; } +}; + +} // namespace + +class OffTheRecordWebState : public web::TestWebState { + public: + OffTheRecordWebState() { + TestChromeBrowserState::Builder test_cbs_builder; + chrome_browser_state_ = test_cbs_builder.Build(); + } + + web::BrowserState* GetBrowserState() const override { + return chrome_browser_state_->GetOffTheRecordChromeBrowserState(); + } + + private: + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; +}; + +class PasswordControllerOffTheRecordTest : public web::WebTestWithWebState { + public: + void SetUp() override { + web::WebTestWithWebState::SetUp(); + password_controller_.reset([[PasswordController alloc] + initWithWebState:&off_the_record_web_state_ + passwordsUiDelegate:nil + client:base::WrapUnique( + new IncognitoPasswordManagerClient())]); + } + + void TearDown() override { + [password_controller_ detach]; + web::WebTestWithWebState::TearDown(); + } + + protected: + OffTheRecordWebState off_the_record_web_state_; + base::scoped_nsobject<PasswordController> password_controller_; +}; + +// Check that if the PasswordController is told (by the PasswordManagerClient) +// that this is Incognito, it won't enable password generation. +TEST_F(PasswordControllerOffTheRecordTest, PasswordGenerationDisabled) { + EXPECT_FALSE([this->password_controller_ passwordGenerationManager]); +}
diff --git a/ios/chrome/browser/passwords/password_controller_unittest.mm b/ios/chrome/browser/passwords/password_controller_unittest.mm index 7757fe29..56148f2 100644 --- a/ios/chrome/browser/passwords/password_controller_unittest.mm +++ b/ios/chrome/browser/passwords/password_controller_unittest.mm
@@ -1,28 +1,50 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. +// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #import "ios/chrome/browser/passwords/password_controller.h" -#include <memory> -#include <vector> +#import <Foundation/Foundation.h> -#include "base/mac/scoped_nsobject.h" +#include <memory> +#include <utility> + +#include "base/json/json_reader.h" +#include "base/mac/bind_objc_block.h" +#import "base/mac/scoped_nsobject.h" #include "base/memory/ptr_util.h" +#include "base/memory/ref_counted.h" +#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" +#import "base/test/ios/wait_util.h" +#include "base/values.h" +#include "components/autofill/core/common/password_form_fill_data.h" #include "components/password_manager/core/browser/log_manager.h" -#include "components/password_manager/core/browser/password_form_manager.h" +#include "components/password_manager/core/browser/mock_password_store.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "components/password_manager/core/common/password_manager_pref_names.h" -#include "components/syncable_prefs/testing_pref_service_syncable.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/testing_pref_service.h" +#import "ios/chrome/browser/autofill/form_input_accessory_view_controller.h" +#import "ios/chrome/browser/autofill/form_suggestion_controller.h" #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" +#import "ios/chrome/browser/passwords/js_password_manager.h" +#import "ios/web/public/web_state/web_state.h" +#import "ios/web/public/test/web_test_with_web_state.h" #import "ios/web/public/test/test_web_state.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "testing/gtest_mac.h" +#import "third_party/ocmock/OCMock/OCMock.h" +#import "third_party/ocmock/OCMock/OCPartialMockObject.h" #include "url/gurl.h" -using testing::_; +using autofill::PasswordForm; +using autofill::PasswordFormFillData; using testing::Return; +namespace { + class MockWebState : public web::TestWebState { public: MOCK_CONST_METHOD0(GetBrowserState, web::BrowserState*(void)); @@ -31,21 +53,22 @@ class MockPasswordManagerClient : public password_manager::StubPasswordManagerClient { public: - // |form_manager| stays owned by the mock. - MOCK_METHOD3(PromptUserToSaveOrUpdatePasswordPtr, - void(password_manager::PasswordFormManager* form_manager, - password_manager::CredentialSourceType type, - bool update_password)); + explicit MockPasswordManagerClient(password_manager::PasswordStore* store) + : store_(store) {} + + ~MockPasswordManagerClient() override = default; + MOCK_CONST_METHOD0(GetLogManager, password_manager::LogManager*(void)); - // Workaround for std::unique_ptr<> lacking a copy constructor. - bool PromptUserToSaveOrUpdatePassword( - std::unique_ptr<password_manager::PasswordFormManager> manager, - password_manager::CredentialSourceType type, - bool update_password) override { - PromptUserToSaveOrUpdatePasswordPtr(manager.get(), type, update_password); - return false; + PrefService* GetPrefs() override { return &prefs_; } + + password_manager::PasswordStore* GetPasswordStore() const override { + return store_; } + + private: + TestingPrefServiceSimple prefs_; + password_manager::PasswordStore* const store_; }; class MockLogManager : public password_manager::LogManager { @@ -58,24 +81,1202 @@ void SetSuspended(bool suspended) override {} }; -TEST(PasswordControllerTest, SaveOnNonHTMLLandingPage) { - // Create the PasswordController with a MockPasswordManagerClient. +// Creates PasswordController with the given |web_state| and a mock client +// using the given |store|. If not null, |weak_client| is filled with a +// non-owning pointer to the created client. The created controller is +// returned. +base::scoped_nsobject<PasswordController> CreatePasswordController( + web::WebState* web_state, + password_manager::PasswordStore* store, + MockPasswordManagerClient** weak_client) { + auto client = base::WrapUnique(new MockPasswordManagerClient(store)); + if (weak_client) + *weak_client = client.get(); + return base::scoped_nsobject<PasswordController>([[PasswordController alloc] + initWithWebState:web_state + passwordsUiDelegate:nil + client:std::move(client)]); +} + +} // namespace + +@interface PasswordController ( + Testing)<CRWWebStateObserver, FormSuggestionProvider> + +- (void)findPasswordFormsWithCompletionHandler: + (void (^)(const std::vector<PasswordForm>&))completionHandler; + +- (void)extractSubmittedPasswordForm:(const std::string&)formName + completionHandler: + (void (^)(BOOL found, + const PasswordForm& form))completionHandler; + +- (void)fillPasswordForm:(const PasswordFormFillData&)formData + completionHandler:(void (^)(BOOL))completionHandler; + +- (BOOL)getPasswordForm:(PasswordForm*)form + fromDictionary:(const base::DictionaryValue*)dictionary + pageURL:(const GURL&)pageLocation; + +// Provides access to JavaScript Manager for testing with mocks. +@property(readonly) JsPasswordManager* passwordJsManager; + +@end + +// Real FormSuggestionController is wrapped to register the addition of +// suggestions. +@interface PasswordsTestSuggestionController : FormSuggestionController + +@property(nonatomic, copy) NSArray* suggestions; + +- (void)dealloc; + +@end + +@implementation PasswordsTestSuggestionController + +@synthesize suggestions = _suggestions; + +- (void)updateKeyboardWithSuggestions:(NSArray*)suggestions { + self.suggestions = suggestions; +} + +- (void)dealloc { + [_suggestions release]; + [super dealloc]; +} + +@end + +class PasswordControllerTest : public web::WebTestWithWebState { + public: + PasswordControllerTest() + : store_(new testing::NiceMock<password_manager::MockPasswordStore>()) {} + + ~PasswordControllerTest() override { store_->ShutdownOnUIThread(); } + + void SetUp() override { + web::WebTestWithWebState::SetUp(); + passwordController_ = + CreatePasswordController(web_state(), store_.get(), nullptr); + @autoreleasepool { + // Make sure the temporary array is released after SetUp finishes, + // otherwise [passwordController_ suggestionProvider] will be retained + // until PlatformTest teardown, at which point all Chrome objects are + // already gone and teardown may access invalid memory. + suggestionController_.reset([[PasswordsTestSuggestionController alloc] + initWithWebState:web_state() + providers:@[ [passwordController_ suggestionProvider] ]]); + accessoryViewController_.reset([[FormInputAccessoryViewController alloc] + initWithWebState:web_state() + providers:@[ [suggestionController_ accessoryViewProvider] ]]); + } + } + + protected: + // Helper method for PasswordControllerTest.DontFillReadonly. Tries to load + // |html| and find and fill there a form with hard-coded form data. Returns + // YES on success, NO otherwise. + BOOL BasicFormFill(NSString* html); + + // Retrieve the current suggestions from suggestionController_ sorted in + // alphabetical order according to their value properties. + NSArray* GetSortedSuggestionValues() { + NSMutableArray* suggestion_values = [NSMutableArray array]; + for (FormSuggestion* suggestion in [suggestionController_ suggestions]) + [suggestion_values addObject:suggestion.value]; + return [suggestion_values + sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; + } + + // Returns an identifier for the |form_number|th form in the page. + std::string FormName(int form_number) { + NSString* kFormNamingScript = + @"__gCrWeb.common.getFormIdentifier(" + " document.querySelectorAll('form')[%d]);"; + return base::SysNSStringToUTF8(EvaluateJavaScriptAsString( + [NSString stringWithFormat:kFormNamingScript, form_number])); + } + + // Sets up a partial mock that intercepts calls to the selector + // -fillPasswordForm:withUsername:password:completionHandler: to the + // PasswordController's JavaScript manager. For the first + // |target_failure_count| calls, skips the invocation of the real JavaScript + // manager, giving the effect that password form fill failed. As soon as + // |failure_count| reaches |target_failure_count|, stop the partial mock + // and let the original JavaScript manager execute. + void SetFillPasswordFormFailureCount(int target_failure_count) { + id original_manager = [passwordController_ passwordJsManager]; + OCPartialMockObject* failing_manager = + [OCMockObject partialMockForObject:original_manager]; + __block int failure_count = 0; + void (^fail_invocation)(NSInvocation*) = ^(NSInvocation* invocation) { + if (failure_count >= target_failure_count) { + [failing_manager stop]; + [invocation invokeWithTarget:original_manager]; + } else { + ++failure_count; + // Fetches the completion handler from |invocation| and calls it with + // failure status. + void (^completionHandler)(BOOL); + const NSInteger kArgOffset = 1; + const NSInteger kCompletionHandlerArgIndex = 4; + [invocation getArgument:&completionHandler + atIndex:(kCompletionHandlerArgIndex + kArgOffset)]; + ASSERT_TRUE(completionHandler); + completionHandler(NO); + } + }; + [[[failing_manager stub] andDo:fail_invocation] + fillPasswordForm:[OCMArg any] + withUsername:[OCMArg any] + password:[OCMArg any] + completionHandler:[OCMArg any]]; + } + + // SuggestionController for testing. + base::scoped_nsobject<PasswordsTestSuggestionController> + suggestionController_; + + // FormInputAccessoryViewController for testing. + base::scoped_nsobject<FormInputAccessoryViewController> + accessoryViewController_; + + // PasswordController for testing. + base::scoped_nsobject<PasswordController> passwordController_; + + scoped_refptr<password_manager::PasswordStore> store_; +}; + +struct PasswordFormTestData { + const char* const page_location; + const char* const json_string; + const char* const expected_origin; + const char* const expected_action; + const char* const expected_username_element; + const char* const expected_username_value; + const char* const expected_new_password_element; + const char* const expected_new_password_value; + const char* const expected_old_password_element; + const char* const expected_old_password_value; +}; + +// Check that given a serialization of a PasswordForm, the controller is able +// to create the corresponding PasswordForm object. +TEST_F(PasswordControllerTest, PopulatePasswordFormWithDictionary) { + // clang-format off + PasswordFormTestData test_data[] = { + // One username element, one password element. URLs contain extra + // parts: username/password, query, reference, which are all expected + // to be stripped off. The password is recognized as an old password. + { + "http://john:doe@fakedomain.com/foo/bar?baz=quz#foobar", + "{ \"action\": \"some/action?to=be&or=not#tobe\"," + "\"usernameElement\": \"account\"," + "\"usernameValue\": \"fakeaccount\"," + "\"name\": \"signup\"," + "\"origin\": \"http://john:doe@fakedomain.com/foo/bar\"," + "\"passwords\": [" + "{ \"element\": \"secret\"," "\"value\": \"fakesecret\" }," + "]}", + "http://fakedomain.com/foo/bar", + "http://fakedomain.com/foo/some/action", + "account", + "fakeaccount", + "", + "", + "secret", + "fakesecret", + }, + // One username element, one password element. Population should fail + // due to an origin mismatch. + { + "http://john:doe@fakedomain.com/foo/bar?baz=quz#foobar", + "{ \"action\": \"some/action?to=be&or=not#tobe\"," + "\"usernameElement\": \"account\"," + "\"usernameValue\": \"fakeaccount\"," + "\"name\": \"signup\"," + "\"origin\": \"http://john:doe@realdomainipromise.com/foo/bar\"," + "\"passwords\": [" + "{ \"element\": \"secret\"," "\"value\": \"fakesecret\" }," + "]}", + "", + "", + "", + "", + "", + "", + "", + "", + }, + // One username element, two password elements. Since both password + // values are the same, we are assuming that the webpage asked the user + // to enter the password twice for confirmation. + { + "http://fakedomain.com/foo", + "{ \"action\": \"http://anotherdomain.com/some_action\"," + "\"usernameElement\": \"account\"," + "\"usernameValue\": \"fakeaccount\"," + "\"name\": \"signup\"," + "\"origin\": \"http://fakedomain.com/foo\"," + "\"passwords\": [" + "{ \"element\": \"secret\"," "\"value\": \"fakesecret\" }," + "{ \"element\": \"confirm\"," "\"value\": \"fakesecret\" }," + "]}", + "http://fakedomain.com/foo", + "http://anotherdomain.com/some_action", + "account", + "fakeaccount", + "secret", + "fakesecret", + "", + "", + }, + // One username element, two password elements. The password + // values are different, so we are assuming that the webpage asked the user + // to enter the old password and new password. + { + "http://fakedomain.com/foo", + "{ \"action\": \"\"," + "\"usernameElement\": \"account\"," + "\"usernameValue\": \"fakeaccount\"," + "\"name\": \"signup\"," + "\"origin\": \"http://fakedomain.com/foo\"," + "\"passwords\": [" + "{ \"element\": \"old\"," "\"value\": \"oldsecret\" }," + "{ \"element\": \"new\"," "\"value\": \"newsecret\" }," + "]}", + "http://fakedomain.com/foo", + "http://fakedomain.com/foo", + "account", + "fakeaccount", + "new", + "newsecret", + "old", + "oldsecret", + }, + // One username element, three password elements. All passwords + // are the same. Password population should fail because this configuration + // does not make sense. + { + "http://fakedomain.com", + "{ \"action\": \"\"," + "\"usernameElement\": \"account\"," + "\"usernameValue\": \"fakeaccount\"," + "\"name\": \"signup\"," + "\"origin\": \"http://fakedomain.com/foo\"," + "\"passwords\": [" + "{ \"element\": \"pass1\"," "\"value\": \"word\" }," + "{ \"element\": \"pass2\"," "\"value\": \"word\" }," + "{ \"element\": \"pass3\"," "\"value\": \"word\" }," + "]}", + "http://fakedomain.com/", + "http://fakedomain.com/", + "account", + "fakeaccount", + "", + "", + "", + "", + }, + // One username element, three password elements. Two passwords are + // the same followed by a different one. Assuming that the duplicated + // password is the old one. + { + "http://fakedomain.com", + "{ \"action\": \"\"," + "\"usernameElement\": \"account\"," + "\"usernameValue\": \"fakeaccount\"," + "\"name\": \"signup\"," + "\"origin\": \"http://fakedomain.com/foo\"," + "\"passwords\": [" + "{ \"element\": \"pass1\"," "\"value\": \"word1\" }," + "{ \"element\": \"pass2\"," "\"value\": \"word1\" }," + "{ \"element\": \"pass3\"," "\"value\": \"word3\" }," + "]}", + "http://fakedomain.com/", + "http://fakedomain.com/", + "account", + "fakeaccount", + "pass3", + "word3", + "pass1", + "word1", + }, + // One username element, three password elements. A password is + // follwed by two duplicate ones. Assuming that the duplicated + // password is the new one. + { + "http://fakedomain.com", + "{ \"action\": \"\"," + "\"usernameElement\": \"account\"," + "\"usernameValue\": \"fakeaccount\"," + "\"name\": \"signup\"," + "\"origin\": \"http://fakedomain.com/foo\"," + "\"passwords\": [" + "{ \"element\": \"pass1\"," "\"value\": \"word1\" }," + "{ \"element\": \"pass2\"," "\"value\": \"word2\" }," + "{ \"element\": \"pass3\"," "\"value\": \"word2\" }," + "]}", + "http://fakedomain.com/", + "http://fakedomain.com/", + "account", + "fakeaccount", + "pass2", + "word2", + "pass1", + "word1", + }, + }; + // clang-format on + + for (const PasswordFormTestData& data : test_data) { + SCOPED_TRACE(testing::Message() + << "for page_location=" << data.page_location + << " and json_string=" << data.json_string); + std::unique_ptr<base::Value> json_data( + base::JSONReader::Read(data.json_string, true)); + const base::DictionaryValue* json_dict = nullptr; + ASSERT_TRUE(json_data->GetAsDictionary(&json_dict)); + PasswordForm form; + [passwordController_ getPasswordForm:&form + fromDictionary:json_dict + pageURL:GURL(data.page_location)]; + EXPECT_STREQ(data.expected_origin, form.origin.spec().c_str()); + EXPECT_STREQ(data.expected_action, form.action.spec().c_str()); + EXPECT_EQ(base::ASCIIToUTF16(data.expected_username_element), + form.username_element); + EXPECT_EQ(base::ASCIIToUTF16(data.expected_username_value), + form.username_value); + EXPECT_EQ(base::ASCIIToUTF16(data.expected_new_password_element), + form.new_password_element); + EXPECT_EQ(base::ASCIIToUTF16(data.expected_new_password_value), + form.new_password_value); + EXPECT_EQ(base::ASCIIToUTF16(data.expected_old_password_element), + form.password_element); + EXPECT_EQ(base::ASCIIToUTF16(data.expected_old_password_value), + form.password_value); + } +}; + +struct FindPasswordFormTestData { + NSString* html_string; + const bool expected_form_found; + const char* const expected_username_element; + const char* const expected_password_element; +}; + +// TODO(crbug.com/403705) This test is flaky. +// Check that HTML forms are converted correctly into PasswordForms. +TEST_F(PasswordControllerTest, FLAKY_FindPasswordFormsInView) { + // clang-format off + FindPasswordFormTestData test_data[] = { + // Normal form: a username and a password element. + { + @"<form>" + "<input type='text' name='user0'>" + "<input type='password' name='pass0'>" + "</form>", + true, "user0", "pass0" + }, + // User name is captured as an email address (HTML5). + { + @"<form>" + "<input type='email' name='email1'>" + "<input type='password' name='pass1'>" + "</form>", + true, "email1", "pass1" + }, + // No username element. + { + @"<form>" + "<input type='password' name='user2'>" + "<input type='password' name='pass2'>" + "</form>", + true, "", "user2" + }, + // No username element before password. + { + @"<form>" + "<input type='password' name='pass3'>" + "<input type='text' name='user3'>" + "</form>", + true, "", "pass3" + }, + // Disabled username element. + { + @"<form>" + "<input type='text' name='user4' disabled='disabled'>" + "<input type='password' name='pass4'>" + "</form>", + true, "", "pass4" + }, + // Username element has autocomplete='off'. + { + @"<form>" + "<input type='text' name='user5' AUTOCOMPLETE='off'>" + "<input type='password' name='pass5'>" + "</form>", + true, "user5", "pass5" + }, + // No password element. + { + @"<form>" + "<input type='text' name='user6'>" + "<input type='text' name='pass6'>" + "</form>", + false, nullptr, nullptr + }, + // Disabled password element. + { + @"<form>" + "<input type='text' name='user7'>" + "<input type='password' name='pass7' disabled='disabled'>" + "</form>", + false, nullptr, nullptr + }, + // Password element has autocomplete='off'. + { + @"<form>" + "<input type='text' name='user8'>" + "<input type='password' name='pass8' AUTOCOMPLETE='OFF'>" + "</form>", + true, "user8", "pass8" + }, + // Form element has autocomplete='off'. + { + @"<form autocomplete='off'>" + "<input type='text' name='user9'>" + "<input type='password' name='pass9'>" + "</form>", + true, "user9", "pass9" + }, + }; + // clang-format on + + for (const FindPasswordFormTestData& data : test_data) { + SCOPED_TRACE(testing::Message() << "for html_string=" << data.html_string); + LoadHtml(data.html_string); + __block std::vector<PasswordForm> forms; + __block BOOL block_was_called = NO; + [passwordController_ findPasswordFormsWithCompletionHandler:^( + const std::vector<PasswordForm>& result) { + block_was_called = YES; + forms = result; + }]; + base::test::ios::WaitUntilCondition(^bool() { + return block_was_called; + }); + if (data.expected_form_found) { + ASSERT_EQ(1U, forms.size()); + EXPECT_EQ(base::ASCIIToUTF16(data.expected_username_element), + forms[0].username_element); + EXPECT_EQ(base::ASCIIToUTF16(data.expected_password_element), + forms[0].password_element); + } else { + ASSERT_TRUE(forms.empty()); + } + } +} + +struct GetSubmittedPasswordFormTestData { + NSString* html_string; + NSString* java_script; + const int number_of_forms_to_submit; + const bool expected_form_found; + const char* expected_username_element; +}; + +// TODO(crbug.com/403705) This test is flaky. +// Check that HTML forms are captured and converted correctly into +// PasswordForms on submission. +TEST_F(PasswordControllerTest, FLAKY_GetSubmittedPasswordForm) { + // clang-format off + GetSubmittedPasswordFormTestData test_data[] = { + // Two forms with no explicit names. + { + @"<form action='javascript:;'>" + "<input type='text' name='user1'>" + "<input type='password' name='pass1'>" + "</form>" + "<form action='javascript:;'>" + "<input type='text' name='user2'>" + "<input type='password' name='pass2'>" + "<input type='submit' id='s2'>" + "</form>", + @"document.getElementById('s2').click()", + 1, true, "user2" + }, + // Two forms with explicit names. + { + @"<form name='test2a' action='javascript:;'>" + "<input type='text' name='user1'>" + "<input type='password' name='pass1'>" + "<input type='submit' id='s1'>" + "</form>" + "<form name='test2b' action='javascript:;'>" + "<input type='text' name='user2'>" + "<input type='password' name='pass2'>" + "</form>", + @"document.getElementById('s1').click()", + 0, true, "user1" + }, + // No password forms. + { + @"<form action='javascript:;'>" + "<input type='text' name='user1'>" + "<input type='text' name='pass1'>" + "<input type='submit' id='s1'>" + "</form>", + @"document.getElementById('s1').click()", + 0, false, nullptr + }, + // Form with quotes in the form and field names. + { + @"<form name=\"foo'\" action='javascript:;'>" + "<input type='text' name=\"user1'\">" + "<input type='password' id='s1' name=\"pass1'\">" + "</form>", + @"document.getElementById('s1').click()", + 0, true, "user1'" + }, + }; + // clang-format on + + for (const GetSubmittedPasswordFormTestData& data : test_data) { + SCOPED_TRACE(testing::Message() << "for html_string=" << data.html_string + << " and java_script=" << data.java_script + << " and number_of_forms_to_submit=" + << data.number_of_forms_to_submit); + LoadHtml(data.html_string); + EvaluateJavaScriptAsString(data.java_script); + __block BOOL block_was_called = NO; + id completion_handler = ^(BOOL found, const PasswordForm& form) { + block_was_called = YES; + ASSERT_EQ(data.expected_form_found, found); + if (data.expected_form_found) { + EXPECT_EQ(base::ASCIIToUTF16(data.expected_username_element), + form.username_element); + } + }; + [passwordController_ + extractSubmittedPasswordForm:FormName(data.number_of_forms_to_submit) + completionHandler:completion_handler]; + base::test::ios::WaitUntilCondition(^bool() { + return block_was_called; + }); + } +} + +// Populates |form_data| with test values. +void SetPasswordFormFillData(PasswordFormFillData& form_data, + const std::string& origin, + const std::string& action, + const char* username_field, + const char* username_value, + const char* password_field, + const char* password_value, + const char* additional_username, + const char* additional_password, + bool wait_for_username) { + form_data.origin = GURL(origin); + form_data.action = GURL(action); + autofill::FormFieldData username; + username.name = base::UTF8ToUTF16(username_field); + username.value = base::UTF8ToUTF16(username_value); + form_data.username_field = username; + autofill::FormFieldData password; + password.name = base::UTF8ToUTF16(password_field); + password.value = base::UTF8ToUTF16(password_value); + form_data.password_field = password; + if (additional_username) { + autofill::PasswordAndRealm additional_password_data; + additional_password_data.password = base::UTF8ToUTF16(additional_password); + additional_password_data.realm.clear(); + form_data.additional_logins.insert( + std::pair<base::string16, autofill::PasswordAndRealm>( + base::UTF8ToUTF16(additional_username), additional_password_data)); + } + form_data.wait_for_username = wait_for_username; +} + +// Test HTML page. It contains several password forms. Tests autofill +// them and verify that the right ones are autofilled. +static NSString* kHtmlWithMultiplePasswordForms = + @"<form>" + "<input id='un0' type='text' name='u0'>" + "<input id='pw0' type='password' name='p0'>" + "</form>" + "<form action='action?query=yes#reference'>" + "<input id='un1' type='text' name='u1'>" + "<input id='pw1' type='password' name='p1'>" + "</form>" + "<form action='http://some_other_action'>" + "<input id='un2' type='text' name='u2'>" + "<input id='pw2' type='password' name='p2'>" + "</form>" + "<form>" + "<input id='un3' type='text' name='u3'>" + "<input id='pw3' type='password' name='p3'>" + "<input id='pw3' type='password' name='p3'>" + "</form>" + "<form>" + "<input id='un4' type='text' name='u4'>" + "<input id='pw4' type='password' name='p4'>" + "</form>" + "<form>" + "<input id='un5' type='text' name='u4'>" + "<input id='pw5' type='password' name='p4'>" + "</form>" + "<form name=\"f6'\">" + "<input id=\"un6'\" type='text' name=\"u6'\">" + "<input id=\"pw6'\" type='password' name=\"p6'\">" + "</form>"; + +// A script that resets all text fields. +static NSString* kClearInputFieldsScript = + @"var inputs = document.getElementsByTagName('input');" + "for(var i = 0; i < inputs.length; i++){" + " inputs[i].value = '';" + "}"; + +// A script that we run after autofilling forms. It returns +// ids and values of all non-empty fields. +static NSString* kInputFieldValueVerificationScript = + @"var result='';" + "var inputs = document.getElementsByTagName('input');" + "for(var i = 0; i < inputs.length; i++){" + " var input = inputs[i];" + " if (input.value) {" + " result += input.id + '=' + input.value +';';" + " }" + "}; result"; + +struct FillPasswordFormTestData { + const std::string origin; + const std::string action; + const char* username_field; + const char* username_value; + const char* password_field; + const char* password_value; + const BOOL should_succeed; + NSString* expected_result; +}; + +// Test that filling password forms works correctly. +TEST_F(PasswordControllerTest, FillPasswordForm) { + LoadHtml(kHtmlWithMultiplePasswordForms); + + EXPECT_NSEQ(@"true", + EvaluateJavaScriptAsString(@"__gCrWeb.hasPasswordField()")); + + const std::string base_url = BaseUrl(); + // clang-format off + FillPasswordFormTestData test_data[] = { + // Basic test: one-to-one match on the first password form. + { + base_url, + base_url, + "u0", + "test_user", + "p0", + "test_password", + YES, + @"un0=test_user;pw0=test_password;" + }, + // Multiple forms match: they should all be autofilled. + { + base_url, + base_url, + "u4", + "test_user", + "p4", + "test_password", + YES, + @"un4=test_user;pw4=test_password;un5=test_user;pw5=test_password;" + }, + // The form matches despite a different action: the only difference + // is a query and reference. + { + base_url, + base_url, + "u1", + "test_user", + "p1", + "test_password", + YES, + @"un1=test_user;pw1=test_password;" + }, + // No match because of a different origin. + { + "http://someotherfakedomain.com", + base_url, + "u0", + "test_user", + "p0", + "test_password", + NO, + @"" + }, + // No match because of a different action. + { + base_url, + "http://someotherfakedomain.com", + "u0", + "test_user", + "p0", + "test_password", + NO, + @"" + }, + // No match because some inputs are not in the form. + { + base_url, + base_url, + "u0", + "test_user", + "p1", + "test_password", + NO, + @"" + }, + // No match because there are duplicate inputs in the form. + { + base_url, + base_url, + "u3", + "test_user", + "p3", + "test_password", + NO, + @"" + }, + // Basic test, but with quotes in the names and IDs. + { + base_url, + base_url, + "u6'", + "test_user", + "p6'", + "test_password", + YES, + @"un6'=test_user;pw6'=test_password;" + }, + }; + // clang-format on + + for (const FillPasswordFormTestData& data : test_data) { + EvaluateJavaScriptAsString(kClearInputFieldsScript); + + PasswordFormFillData form_data; + SetPasswordFormFillData(form_data, data.origin, data.action, + data.username_field, data.username_value, + data.password_field, data.password_value, nullptr, + nullptr, false); + + __block BOOL block_was_called = NO; + [passwordController_ fillPasswordForm:form_data + completionHandler:^(BOOL success) { + block_was_called = YES; + EXPECT_EQ(data.should_succeed, success); + }]; + base::test::ios::WaitUntilCondition(^bool() { + return block_was_called; + }); + + NSString* result = + EvaluateJavaScriptAsString(kInputFieldValueVerificationScript); + EXPECT_NSEQ(data.expected_result, result); + } +} + +// Tests that a form is found and the found form is filled in with the given +// username and password. +TEST_F(PasswordControllerTest, FindAndFillOnePasswordForm) { + LoadHtml(@"<form><input id='un' type='text' name='u'>" + "<input id='pw' type='password' name='p'></form>"); + __block int call_counter = 0; + __block int success_counter = 0; + [passwordController_ findAndFillPasswordForms:@"john.doe@gmail.com" + password:@"super!secret" + completionHandler:^(BOOL complete) { + ++call_counter; + if (complete) + ++success_counter; + }]; + base::test::ios::WaitUntilCondition(^{ + return call_counter == 1; + }); + EXPECT_EQ(1, success_counter); + NSString* result = + EvaluateJavaScriptAsString(kInputFieldValueVerificationScript); + EXPECT_NSEQ(@"un=john.doe@gmail.com;pw=super!secret;", result); +} + +// Tests that multiple forms on the same page are found and filled. +// This test includes an mock injected failure on form filling to verify +// that completion handler is called with the proper values. +TEST_F(PasswordControllerTest, FindAndFillMultiplePasswordForms) { + // Fails the first call to fill password form. + SetFillPasswordFormFailureCount(1); + LoadHtml(@"<form><input id='u1' type='text' name='un1'>" + "<input id='p1' type='password' name='pw1'></form>" + "<form><input id='u2' type='text' name='un2'>" + "<input id='p2' type='password' name='pw2'></form>" + "<form><input id='u3' type='text' name='un3'>" + "<input id='p3' type='password' name='pw3'></form>"); + __block int call_counter = 0; + __block int success_counter = 0; + [passwordController_ findAndFillPasswordForms:@"john.doe@gmail.com" + password:@"super!secret" + completionHandler:^(BOOL complete) { + ++call_counter; + if (complete) + ++success_counter; + LOG(INFO) << "HANDLER call " << call_counter + << " success " << success_counter; + }]; + // There should be 3 password forms and only 2 successfully filled forms. + base::test::ios::WaitUntilCondition(^{ + return call_counter == 3; + }); + EXPECT_EQ(2, success_counter); + NSString* result = + EvaluateJavaScriptAsString(kInputFieldValueVerificationScript); + EXPECT_NSEQ(@"u2=john.doe@gmail.com;p2=super!secret;" + "u3=john.doe@gmail.com;p3=super!secret;", + result); +} + +BOOL PasswordControllerTest::BasicFormFill(NSString* html) { + LoadHtml(html); + EXPECT_NSEQ(@"true", + EvaluateJavaScriptAsString(@"__gCrWeb.hasPasswordField()")); + const std::string base_url = BaseUrl(); + PasswordFormFillData form_data; + SetPasswordFormFillData(form_data, base_url, base_url, "u0", "test_user", + "p0", "test_password", nullptr, nullptr, false); + __block BOOL block_was_called = NO; + __block BOOL return_value = NO; + [passwordController_ fillPasswordForm:form_data + completionHandler:^(BOOL success) { + block_was_called = YES; + return_value = success; + }]; + base::test::ios::WaitUntilCondition(^bool() { + return block_was_called; + }); + return return_value; +} + +// Check that |fillPasswordForm| is not filled if 'readonly' attribute is set +// on either username or password fields. +// TODO(crbug.com/503050): Test is flaky. +TEST_F(PasswordControllerTest, FLAKY_DontFillReadOnly) { + // Control check that the fill operation will succceed with well-formed form. + EXPECT_TRUE(BasicFormFill(@"<form>" + "<input id='un0' type='text' name='u0'>" + "<input id='pw0' type='password' name='p0'>" + "</form>")); + // Form fill should fail with 'readonly' attribute on username. + EXPECT_FALSE(BasicFormFill( + @"<form>" + "<input id='un0' type='text' name='u0' readonly='readonly'>" + "<input id='pw0' type='password' name='p0'>" + "</form>")); + // Form fill should fail with 'readonly' attribute on password. + EXPECT_FALSE(BasicFormFill( + @"<form>" + "<input id='un0' type='text' name='u0'>" + "<input id='pw0' type='password' name='p0' readonly='readonly'>" + "</form>")); +} + +// An HTML page containing one password form. The username input field +// also has custom event handlers. We need to verify that those event +// handlers are still triggered even though we override them with our own. +static NSString* kHtmlWithPasswordForm = + @"<form>" + "<input id='un' type='text' name=\"u'\"" + " onkeyup='window.onKeyUpCalled_=true'" + " onchange='window.onChangeCalled_=true'>" + "<input id='pw' type='password' name=\"p'\">" + "</form>"; + +// A script that resets indicators used to verify that custom event +// handlers are triggered. It also finds and the username and +// password fields and caches them for future verification. +static NSString* kUsernameAndPasswordTestPreparationScript = + @"onKeyUpCalled_ = false;" + "onChangeCalled_ = false;" + "username_ = document.getElementById('un');" + "username_.__gCrWebAutofilled = 'false';" + "password_ = document.getElementById('pw');" + "password_.__gCrWebAutofilled = 'false';"; + +// A script that we run after autofilling forms. It returns +// all values for verification as a single concatenated string. +static NSString* kUsernamePasswordVerificationScript = + @"var value = username_.value;" + "var from = username_.selectionStart;" + "var to = username_.selectionEnd;" + "value.substr(0, from) + '[' + value.substr(from, to) + ']'" + " + value.substr(to, value.length) + '=' + password_.value" + " + ', onkeyup=' + onKeyUpCalled_" + " + ', onchange=' + onChangeCalled_;"; + +struct SuggestionTestData { + std::string description; + NSArray* eval_scripts; + NSArray* expected_suggestions; + NSString* expected_result; +}; + +// Tests that form activity correctly sends suggestions to the suggestion +// controller. +TEST_F(PasswordControllerTest, SuggestionUpdateTests) { + LoadHtml(kHtmlWithPasswordForm); + const std::string base_url = BaseUrl(); + EvaluateJavaScriptAsString(kUsernameAndPasswordTestPreparationScript); + + // Initialize |form_data| with test data and an indicator that autofill + // should not be performed while the user is entering the username so that + // we can test with an initially-empty username field. Testing with a + // username field that contains input is performed by a specific test below. + PasswordFormFillData form_data; + SetPasswordFormFillData(form_data, base_url, base_url, "u'", "user0", "p'", + "password0", "abc", "def", true); + form_data.name = base::ASCIIToUTF16(FormName(0)); + + __block BOOL block_was_called = NO; + [passwordController_ fillPasswordForm:form_data + completionHandler:^(BOOL success) { + block_was_called = YES; + // Verify that the fill reports failed. + EXPECT_FALSE(success); + }]; + base::test::ios::WaitUntilCondition(^bool() { + return block_was_called; + }); + + // Verify that the form has not been autofilled. + EXPECT_NSEQ(@"[]=, onkeyup=false, onchange=false", + EvaluateJavaScriptAsString(kUsernamePasswordVerificationScript)); + + // clang-format off + SuggestionTestData test_data[] = { + { + "Should show all suggestions when focusing empty username field", + @[(@"var evt = document.createEvent('Events');" + "evt.initEvent('focus', true, true, window, 1);" + "username_.dispatchEvent(evt);"), + @""], + @[@"abc", @"user0"], + @"[]=, onkeyup=false, onchange=false" + }, + { + "Should not show suggestions when focusing password field", + @[(@"var evt = document.createEvent('Events');" + "evt.initEvent('focus', true, true, window, 1);" + "password_.dispatchEvent(evt);"), + @""], + @[], + @"[]=, onkeyup=false, onchange=false" + }, + { + "Should filter suggestions when focusing username field with input", + @[(@"username_.value='ab';" + "var evt = document.createEvent('Events');" + "evt.initEvent('focus', true, true, window, 1);" + "username_.dispatchEvent(evt);"), + @""], + @[@"abc"], + @"ab[]=, onkeyup=false, onchange=false" + }, + { + "Should filter suggestions while typing", + @[(@"var evt = document.createEvent('Events');" + "evt.initEvent('focus', true, true, window, 1);" + "username_.dispatchEvent(evt);"), + (@"username_.value='ab';" + "evt = document.createEvent('Events');" + "evt.initEvent('keyup', true, true, window, 1);" + "evt.keyCode = 98;" + "username_.dispatchEvent(evt);"), + @""], + @[@"abc"], + @"ab[]=, onkeyup=true, onchange=false" + }, + { + "Should unfilter suggestions after backspacing", + @[(@"var evt = document.createEvent('Events');" + "evt.initEvent('focus', true, true, window, 1);" + "username_.dispatchEvent(evt);"), + (@"username_.value='ab';" + "evt = document.createEvent('Events');" + "evt.initEvent('keyup', true, true, window, 1);" + "evt.keyCode = 98;" + "username_.dispatchEvent(evt);"), + (@"username_.value='';" + "evt = document.createEvent('Events');" + "evt.initEvent('keyup', true, true, window, 1);" + "evt.keyCode = 8;" + "username_.dispatchEvent(evt);"), + @""], + @[@"abc", @"user0"], + @"[]=, onkeyup=true, onchange=false" + }, + }; + // clang-format on + + for (const SuggestionTestData& data : test_data) { + SCOPED_TRACE(testing::Message() + << "for description=" << data.description + << " and eval_scripts=" << data.eval_scripts); + // Prepare the test. + EvaluateJavaScriptAsString(kUsernameAndPasswordTestPreparationScript); + + for (NSString* script in data.eval_scripts) { + // Trigger events. + EvaluateJavaScriptAsString(script); + + // Pump the run loop so that the host can respond. + WaitForBackgroundTasks(); + } + + EXPECT_NSEQ(data.expected_suggestions, GetSortedSuggestionValues()); + EXPECT_NSEQ(data.expected_result, EvaluateJavaScriptAsString( + kUsernamePasswordVerificationScript)); + // Clear all suggestions. + [suggestionController_ setSuggestions:nil]; + } +} + +// Tests that selecting a suggestion will fill the corresponding form and field. +TEST_F(PasswordControllerTest, SelectingSuggestionShouldFillPasswordForm) { + LoadHtml(kHtmlWithPasswordForm); + const std::string base_url = BaseUrl(); + EvaluateJavaScriptAsString(kUsernameAndPasswordTestPreparationScript); + + // Initialize |form_data| with test data and an indicator that autofill + // should not be performed while the user is entering the username so that + // we can test with an initially-empty username field. + PasswordFormFillData form_data; + SetPasswordFormFillData(form_data, base_url, base_url, "u'", "user0", "p'", + "password0", "abc", "def", true); + form_data.name = base::ASCIIToUTF16(FormName(0)); + + __block BOOL block_was_called = NO; + [passwordController_ fillPasswordForm:form_data + completionHandler:^(BOOL success) { + block_was_called = YES; + // Verify that the fill reports failed. + EXPECT_FALSE(success); + }]; + base::test::ios::WaitUntilCondition(^bool() { + return block_was_called; + }); + + // Verify that the form has not been autofilled. + EXPECT_NSEQ(@"[]=, onkeyup=false, onchange=false", + EvaluateJavaScriptAsString(kUsernamePasswordVerificationScript)); + + // Tell PasswordController that a suggestion was selected. It should fill + // out the password form with the corresponding credentials. + FormSuggestion* suggestion = [FormSuggestion suggestionWithValue:@"abc" + displayDescription:nil + icon:nil + identifier:0]; + + block_was_called = NO; + SuggestionHandledCompletion completion = ^{ + block_was_called = YES; + EXPECT_NSEQ(@"abc[]=def, onkeyup=false, onchange=false", + ExecuteJavaScript(kUsernamePasswordVerificationScript)); + }; + [passwordController_ didSelectSuggestion:suggestion + forField:@"u" + form:base::SysUTF8ToNSString(FormName(0)) + completionHandler:completion]; + base::test::ios::WaitUntilCondition(^bool() { + return block_was_called; + }); +} + +// Tests with invalid inputs. +TEST_F(PasswordControllerTest, CheckIncorrectData) { + // clang-format off + std::string invalid_data[] = { + "{}", + + "{ \"usernameValue\": \"fakeaccount\"," + "\"passwords\": [" + "{ \"element\": \"secret\"," "\"value\": \"fakesecret\" }," + "]}", + + "{ \"usernameElement\": \"account\"," + "\"passwords\": [" + "{ \"element\": \"secret\"," "\"value\": \"fakesecret\" }," + "]}", + + "{ \"usernameElement\": \"account\"," + "\"usernameValue\": \"fakeaccount\"," + "}", + + "{ \"usernameElement\": \"account\"," + "\"usernameValue\": \"fakeaccount\"," + "\"passwords\": {}," + "}", + + "{ \"usernameElement\": \"account\"," + "\"usernameValue\": \"fakeaccount\"," + "\"passwords\": [" + "]}", + + "{ \"usernameElement\": \"account\"," + "\"usernameValue\": \"fakeaccount\"," + "\"passwords\": [" + "{ \"value\": \"fakesecret\" }," + "]}", + + "{ \"usernameElement\": \"account\"," + "\"usernameValue\": \"fakeaccount\"," + "\"passwords\": [" + "{ \"element\": \"secret\" }," + "]}", + }; + // clang-format on + + for (const std::string& data : invalid_data) { + SCOPED_TRACE(testing::Message() << "for data=" << data); + std::unique_ptr<base::Value> json_data(base::JSONReader::Read(data, true)); + const base::DictionaryValue* json_dict = nullptr; + ASSERT_TRUE(json_data->GetAsDictionary(&json_dict)); + PasswordForm form; + BOOL res = + [passwordController_ getPasswordForm:&form + fromDictionary:json_dict + pageURL:GURL("https://www.foo.com/")]; + EXPECT_FALSE(res); + } +} + +// The test case below does not need the heavy fixture from above, but it +// needs to use MockWebState. +TEST(PasswordControllerTestSimple, SaveOnNonHTMLLandingPage) { TestChromeBrowserState::Builder builder; - auto pref_service = - base::WrapUnique(new syncable_prefs::TestingPrefServiceSyncable); - pref_service->registry()->RegisterBooleanPref( - password_manager::prefs::kPasswordManagerSavingEnabled, true); - builder.SetPrefService(std::move(pref_service)); std::unique_ptr<TestChromeBrowserState> browser_state(builder.Build()); MockWebState web_state; ON_CALL(web_state, GetBrowserState()) .WillByDefault(testing::Return(browser_state.get())); - auto client = base::WrapUnique(new MockPasswordManagerClient); - MockPasswordManagerClient* weak_client = client.get(); - base::scoped_nsobject<PasswordController> passwordController( - [[PasswordController alloc] initWithWebState:&web_state - passwordsUiDelegate:nil - client:std::move(client)]); + + MockPasswordManagerClient* weak_client = nullptr; + base::scoped_nsobject<PasswordController> passwordController = + CreatePasswordController(&web_state, nullptr, &weak_client); + static_cast<TestingPrefServiceSimple*>(weak_client->GetPrefs()) + ->registry() + ->RegisterBooleanPref( + password_manager::prefs::kPasswordManagerSavingEnabled, true); // Use a mock LogManager to detect that OnPasswordFormsRendered has been // called. TODO(crbug.com/598672): this is a hack, we should modularize the
diff --git a/ios/chrome/browser/passwords/password_generation_agent_unittest.mm b/ios/chrome/browser/passwords/password_generation_agent_unittest.mm new file mode 100644 index 0000000..744518e --- /dev/null +++ b/ios/chrome/browser/passwords/password_generation_agent_unittest.mm
@@ -0,0 +1,521 @@ +// 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. + +#import "ios/chrome/browser/passwords/password_generation_agent.h" + +#include <algorithm> +#include <memory> + +#include "base/logging.h" +#include "base/mac/foundation_util.h" +#import "base/mac/scoped_nsobject.h" +#include "base/mac/scoped_objc_class_swizzler.h" +#include "base/macros.h" +#include "base/strings/string16.h" +#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/common/form_data.h" +#include "components/autofill/core/common/form_field_data.h" +#include "components/autofill/core/common/password_form.h" +#import "components/autofill/ios/browser/js_suggestion_manager.h" +#include "google_apis/gaia/gaia_urls.h" +#import "ios/chrome/browser/autofill/form_input_accessory_view_controller.h" +#import "ios/chrome/browser/passwords/js_password_manager.h" +#import "ios/chrome/browser/passwords/password_generation_offer_view.h" +#import "ios/chrome/browser/passwords/passwords_ui_delegate.h" +#import "ios/chrome/browser/ui/commands/generic_chrome_command.h" +#include "ios/chrome/browser/ui/commands/ios_command_ids.h" +#import "ios/testing/ocmock_complex_type_helper.h" +#include "ios/web/public/test/test_web_state.h" +#include "ios/web/public/web_state/url_verification_constants.h" +#import "ios/web/public/test/web_test_with_web_state.h" +#include "testing/gtest_mac.h" +#include "third_party/ocmock/OCMock/OCMock.h" +#include "third_party/ocmock/gtest_support.h" +#include "url/gurl.h" + +namespace { + +NSString* const kAccountCreationFormName = @"create-foo-account"; +NSString* const kAccountCreationFieldName = @"password"; +NSString* const kAccountCreationOrigin = @"http://foo.com/login"; +NSString* const kEmailFieldName = @"email"; + +// Static storage to access arguments passed to swizzled method of UIWindow. +static id g_chrome_execute_command_sender = nil; + +} // namespace + +@interface MockPasswordsUiDelegate : NSObject<PasswordsUiDelegate> + +- (instancetype)init; + +@property(nonatomic, readonly) BOOL UIShown; + +@end + +@implementation MockPasswordsUiDelegate { + // YES if showGenerationAlertWithPassword was called more recently than + // hideGenerationAlert, NO otherwise. + BOOL _UIShown; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _UIShown = NO; + } + return self; +} + +@synthesize UIShown = _UIShown; + +- (void)showGenerationAlertWithPassword:(NSString*)password + andPromptDelegate: + (id<PasswordGenerationPromptDelegate>)delegate { + _UIShown = YES; +} + +- (void)hideGenerationAlert { + _UIShown = NO; +} + +@end + +// A donor class that provides a chromeExecuteCommand method that can be +// swapped with UIWindow. +@interface DonorWindow : NSObject + +- (void)chromeExecuteCommand:(id)sender; + +@end + +@implementation DonorWindow + +- (void)chromeExecuteCommand:(id)sender { + g_chrome_execute_command_sender = [sender retain]; +} + +@end + +namespace { + +// A helper to swizzle chromeExecuteCommand method on UIWindow. +class ScopedWindowSwizzler { + public: + ScopedWindowSwizzler() + : class_swizzler_([UIWindow class], + [DonorWindow class], + @selector(chromeExecuteCommand:)) { + DCHECK(!g_chrome_execute_command_sender); + } + + ~ScopedWindowSwizzler() { + [g_chrome_execute_command_sender release]; + g_chrome_execute_command_sender = nil; + } + + private: + base::mac::ScopedObjCClassSwizzler class_swizzler_; + + DISALLOW_COPY_AND_ASSIGN(ScopedWindowSwizzler); +}; + +// Returns a form that should be marked as an account creation form by local +// heuristics. +autofill::PasswordForm GetAccountCreationForm() { + autofill::FormFieldData name_field; + name_field.name = base::ASCIIToUTF16("name"); + name_field.form_control_type = "text"; + + autofill::FormFieldData email_field; + email_field.name = base::ASCIIToUTF16("email"); + email_field.form_control_type = "email"; + + autofill::FormFieldData password_field; + password_field.name = base::SysNSStringToUTF16(kAccountCreationFieldName); + password_field.form_control_type = "password"; + + autofill::FormFieldData confirmPasswordField; + confirmPasswordField.name = base::ASCIIToUTF16("confirm"); + confirmPasswordField.form_control_type = "password"; + + autofill::FormData form; + form.name = base::SysNSStringToUTF16(kAccountCreationFormName); + form.origin = GURL(base::SysNSStringToUTF8(kAccountCreationOrigin)); + form.action = GURL(base::SysNSStringToUTF8(kAccountCreationOrigin)); + + form.fields.push_back(name_field); + form.fields.push_back(email_field); + form.fields.push_back(password_field); + form.fields.push_back(confirmPasswordField); + + autofill::PasswordForm password_form; + password_form.origin = form.origin; + password_form.username_element = email_field.name; + password_form.password_element = password_field.name; + + password_form.form_data = form; + + return password_form; +} + +// Executes each block in |blocks|, where each block must have the type +// void^(void). +void ExecuteBlocks(NSArray* blocks) { + for (void (^block)(void) in blocks) + block(); +} + +// Returns a form that has the same origin as GAIA. +autofill::PasswordForm GetGAIAForm() { + autofill::PasswordForm form(GetAccountCreationForm()); + form.origin = GaiaUrls::GetInstance()->gaia_login_form_realm(); + form.signon_realm = form.origin.GetOrigin().spec(); + return form; +} + +// Returns a form with no text fields. +autofill::PasswordForm GetFormWithNoTextFields() { + autofill::PasswordForm form(GetAccountCreationForm()); + form.form_data.fields.clear(); + return form; +} + +// Returns true if |field| has type "password" and false otherwise. +bool IsPasswordField(const autofill::FormFieldData& field) { + return field.form_control_type == "password"; +} + +// Returns all password fields in |form|. +std::vector<autofill::FormFieldData> GetPasswordFields( + const autofill::PasswordForm& form) { + std::vector<autofill::FormFieldData> fields; + fields.reserve(form.form_data.fields.size()); + for (const auto& field : form.form_data.fields) { + if (IsPasswordField(field)) + fields.push_back(field); + } + return fields; +} + +// Returns a form with no password fields. +autofill::PasswordForm GetFormWithNoPasswordFields() { + autofill::PasswordForm form(GetAccountCreationForm()); + form.form_data.fields.erase( + std::remove_if(form.form_data.fields.begin(), form.form_data.fields.end(), + &IsPasswordField), + form.form_data.fields.end()); + return form; +} + +// Test fixture for testing PasswordGenerationAgent. +class PasswordGenerationAgentTest : public web::WebTestWithWebState { + public: + void SetUp() override { + web::WebTestWithWebState::SetUp(); + mock_js_suggestion_manager_.reset( + [[OCMockObject niceMockForClass:[JsSuggestionManager class]] retain]); + mock_js_password_manager_.reset( + [[OCMockObject niceMockForClass:[JsPasswordManager class]] retain]); + mock_ui_delegate_.reset([[MockPasswordsUiDelegate alloc] init]); + test_web_state_.reset(new web::TestWebState); + agent_.reset([[PasswordGenerationAgent alloc] + initWithWebState:test_web_state_.get() + passwordManager:nullptr + passwordManagerDriver:nullptr + JSPasswordManager:mock_js_password_manager_ + JSSuggestionManager:mock_js_suggestion_manager_ + passwordsUiDelegate:mock_ui_delegate_]); + @autoreleasepool { + accessory_view_controller_.reset([[FormInputAccessoryViewController alloc] + initWithWebState:test_web_state_.get() + providers:@[ agent_ ]]); + } + } + + // Sends form data, autofill data, and password manager data to the + // generation agent so that it can find an account creation form and password + // field. + void LoadAccountCreationForm() { + autofill::PasswordForm password_form(GetAccountCreationForm()); + [agent() allowPasswordGenerationForForm:password_form]; + std::vector<autofill::PasswordForm> password_forms; + password_forms.push_back(password_form); + [agent() processParsedPasswordForms:password_forms]; + SetCurrentURLAndTrustLevel( + GURL(base::SysNSStringToUTF8(kAccountCreationOrigin)), + web::URLVerificationTrustLevel::kAbsolute); + SetContentIsHTML(YES); + } + + // Sets up the web controller mock to use the specified URL and trust level. + void SetCurrentURLAndTrustLevel( + GURL url, + web::URLVerificationTrustLevel url_trust_level) { + test_web_state_->SetCurrentURL(url); + test_web_state_->SetTrustLevel(url_trust_level); + } + + // Swizzles the current web controller to set whether the content is HTML. + void SetContentIsHTML(BOOL content_is_html) { + test_web_state_->SetContentIsHTML(content_is_html); + } + + // Simulates an event on the specified form/field. + void SimulateFormActivity(NSString* form_name, + NSString* field_name, + NSString* type) { + [accessory_view_controller_ webState:test_web_state_.get() + didRegisterFormActivityWithFormNamed:base::SysNSStringToUTF8(form_name) + fieldName:base::SysNSStringToUTF8(field_name) + type:base::SysNSStringToUTF8(type) + value:"" + keyCode:web::WebStateObserver:: + kInvalidFormKeyCode + inputMissing:false]; + } + + // Returns a mock of JsSuggestionManager. + id mock_js_suggestion_manager() { return mock_js_suggestion_manager_; } + + // Returns a mock of JsPasswordManager. + id mock_js_password_manager() { return mock_js_password_manager_; } + + MockPasswordsUiDelegate* mock_ui_delegate() { return mock_ui_delegate_; } + + protected: + // Returns the current generation agent. + PasswordGenerationAgent* agent() { return agent_.get(); } + + // Returns the current accessory view controller. + FormInputAccessoryViewController* accessory_controller() { + return accessory_view_controller_.get(); + } + + private: + // Test WebState. + std::unique_ptr<web::TestWebState> test_web_state_; + + // Mock for JsSuggestionManager; + base::scoped_nsobject<id> mock_js_suggestion_manager_; + + // Mock for JsPasswordManager. + base::scoped_nsobject<id> mock_js_password_manager_; + + // Mock for the UI delegate. + base::scoped_nsobject<MockPasswordsUiDelegate> mock_ui_delegate_; + + // Controller that shows custom input accessory views. + base::scoped_nsobject<FormInputAccessoryViewController> + accessory_view_controller_; + + // The current generation agent. + base::scoped_nsobject<PasswordGenerationAgent> agent_; +}; + +// Tests that local heuristics skip forms with GAIA realm. +TEST_F(PasswordGenerationAgentTest, + OnParsedForms_ShouldIgnoreFormsWithGaiaRealm) { + // Send only a form with GAIA origin to the agent. + std::vector<autofill::PasswordForm> forms; + forms.push_back(GetGAIAForm()); + [agent() processParsedPasswordForms:forms]; + + // No account creation form should have been found. + EXPECT_FALSE(agent().possibleAccountCreationForm); + EXPECT_TRUE(agent().passwordFields.empty()); +} + +// Tests that local heuristics skip forms with no text fields. +TEST_F(PasswordGenerationAgentTest, + OnParsedForms_ShouldIgnoreFormsWithNotEnoughTextFields) { + // Send only a form with GAIA origin to the agent. + std::vector<autofill::PasswordForm> forms; + forms.push_back(GetFormWithNoTextFields()); + [agent() processParsedPasswordForms:forms]; + + // No account creation form should have been found. + EXPECT_FALSE(agent().possibleAccountCreationForm); + EXPECT_TRUE(agent().passwordFields.empty()); +} + +// Tests that local heuristics skip forms with no password fields. +TEST_F(PasswordGenerationAgentTest, + OnParsedForms_ShouldIgnoreFormsWithNoPasswordFields) { + // Send only a form with GAIA origin to the agent. + std::vector<autofill::PasswordForm> forms; + forms.push_back(GetFormWithNoPasswordFields()); + [agent() processParsedPasswordForms:forms]; + + // No account creation form should have been found. + EXPECT_FALSE(agent().possibleAccountCreationForm); + EXPECT_TRUE(agent().passwordFields.empty()); +} + +// Tests that local heuristics extract an account creation form from the page +// when one exists, along with its password fields. +TEST_F(PasswordGenerationAgentTest, OnParsedForms) { + // Send several forms. One should be selected. + std::vector<autofill::PasswordForm> forms; + forms.push_back(GetGAIAForm()); + forms.push_back(GetFormWithNoTextFields()); + forms.push_back(GetFormWithNoPasswordFields()); + forms.push_back(GetAccountCreationForm()); + [agent() processParsedPasswordForms:forms]; + + // Should have found an account creation form and extracted its password + // fields. + EXPECT_EQ(forms[3], *agent().possibleAccountCreationForm); + std::vector<autofill::FormFieldData> expectedPasswordFields( + GetPasswordFields(forms[3])); + EXPECT_EQ(expectedPasswordFields.size(), agent().passwordFields.size()); + for (size_t i = 0; i < expectedPasswordFields.size(); ++i) { + EXPECT_FORM_FIELD_DATA_EQUALS(expectedPasswordFields[i], + agent().passwordFields[i]); + } +} + +// Tests that password generation field identification waits until it has +// approval from autofill and the password manager and an account creation +// form has been identified with local heuristics.. +TEST_F(PasswordGenerationAgentTest, DeterminePasswordGenerationField) { + std::vector<autofill::PasswordForm> forms; + forms.push_back(GetAccountCreationForm()); + + autofill::PasswordForm form(GetAccountCreationForm()); + std::vector<autofill::FormFieldData> passwordFields(GetPasswordFields(form)); + + // The signals can be received in any order, so test them accordingly by + // breaking the steps into blocks and executing them in different orders. + id sendForms = ^{ + std::vector<autofill::PasswordForm> forms; + forms.push_back(form); + [agent() processParsedPasswordForms:forms]; + }; + id sendPasswordManagerWhitelist = ^{ + [agent() allowPasswordGenerationForForm:form]; + }; + id expectFieldNotFound = ^{ + EXPECT_FALSE(agent().passwordGenerationField); + }; + id expectFieldFound = ^{ + // When there are multiple password fields in the account creation form, + // the first one is used as the generation field. + EXPECT_FORM_FIELD_DATA_EQUALS(passwordFields[0], + (*agent().passwordGenerationField)); + }; + + // For each permutation of steps, the field should only be set after the third + // signal is received. + @autoreleasepool { + ExecuteBlocks(@[ + sendForms, expectFieldNotFound, sendPasswordManagerWhitelist, + expectFieldFound + ]); + [agent() clearState]; + + ExecuteBlocks(@[ + sendPasswordManagerWhitelist, expectFieldNotFound, sendForms, + expectFieldFound + ]); + [agent() clearState]; + } +} + +// Tests that the password generation UI is shown when the user focuses the +// password field in the account creation form. +TEST_F(PasswordGenerationAgentTest, + ShouldStartGenerationWhenPasswordFieldFocused) { + LoadAccountCreationForm(); + id mock = [OCMockObject partialMockForObject:accessory_controller()]; + [[mock expect] showCustomInputAccessoryView:[OCMArg any]]; + SimulateFormActivity(kAccountCreationFormName, kAccountCreationFieldName, + @"focus"); + + EXPECT_OCMOCK_VERIFY(mock); + [mock stop]; +} + +// Tests that requesting password generation shows the alert UI. +TEST_F(PasswordGenerationAgentTest, ShouldShowAlertWhenGenerationRequested) { + LoadAccountCreationForm(); + id mock = [OCMockObject partialMockForObject:accessory_controller()]; + [[mock expect] showCustomInputAccessoryView:[OCMArg any]]; + SimulateFormActivity(kAccountCreationFormName, kAccountCreationFieldName, + @"focus"); + EXPECT_EQ(NO, mock_ui_delegate().UIShown); + + [agent() generatePassword]; + EXPECT_EQ(YES, mock_ui_delegate().UIShown); + + EXPECT_OCMOCK_VERIFY(mock); + [mock stop]; +} + +// Tests that the password generation UI is hidden when the user changes focus +// from the password field. +TEST_F(PasswordGenerationAgentTest, + ShouldStopGenerationWhenDifferentFieldFocused) { + LoadAccountCreationForm(); + id mock = [OCMockObject partialMockForObject:accessory_controller()]; + [[mock expect] showCustomInputAccessoryView:[OCMArg any]]; + SimulateFormActivity(kAccountCreationFormName, kAccountCreationFieldName, + @"focus"); + + [[mock expect] restoreDefaultInputAccessoryView]; + SimulateFormActivity(kAccountCreationFormName, kEmailFieldName, @"focus"); + + EXPECT_OCMOCK_VERIFY(mock); + [mock stop]; +} + +// Tests that the password field is filled when the user accepts a generated +// password. +TEST_F(PasswordGenerationAgentTest, + ShouldFillPasswordFieldAndDismissAlertWhenUserAcceptsGeneratedPassword) { + LoadAccountCreationForm(); + // Focus the password field to start generation. + SimulateFormActivity(kAccountCreationFormName, kAccountCreationFieldName, + @"focus"); + NSString* password = @"abc"; + + [[[mock_js_password_manager() stub] andDo:^(NSInvocation* invocation) { + void (^completion_handler)(BOOL); + [invocation getArgument:&completion_handler atIndex:4]; + completion_handler(YES); + }] fillPasswordForm:kAccountCreationFormName + withGeneratedPassword:password + completionHandler:[OCMArg any]]; + + [agent() generatePassword]; + EXPECT_EQ(YES, mock_ui_delegate().UIShown); + + [agent() acceptPasswordGeneration:nil]; + EXPECT_EQ(NO, mock_ui_delegate().UIShown); + EXPECT_OCMOCK_VERIFY(mock_js_password_manager()); +} + +// Tests that the Save Passwords setting screen is shown when the user taps +// "show saved passwords". +TEST_F(PasswordGenerationAgentTest, + ShouldShowPasswordsAndDismissAlertWhenUserTapsShow) { + ScopedWindowSwizzler swizzler; + LoadAccountCreationForm(); + // Focus the password field to start generation. + SimulateFormActivity(kAccountCreationFormName, kAccountCreationFieldName, + @"focus"); + [agent() generatePassword]; + EXPECT_EQ(YES, mock_ui_delegate().UIShown); + + [agent() showSavedPasswords:nil]; + EXPECT_EQ(NO, mock_ui_delegate().UIShown); + + GenericChromeCommand* command = base::mac::ObjCCast<GenericChromeCommand>( + g_chrome_execute_command_sender); + EXPECT_TRUE(command); + EXPECT_EQ(IDC_SHOW_SAVE_PASSWORDS_SETTINGS, command.tag); +} + +} // namespace
diff --git a/ios/chrome/ios_chrome_tests.gyp b/ios/chrome/ios_chrome_tests.gyp index c3432d37..881e1541 100644 --- a/ios/chrome/ios_chrome_tests.gyp +++ b/ios/chrome/ios_chrome_tests.gyp
@@ -24,6 +24,7 @@ '../../components/components.gyp:update_client', '../../components/components.gyp:version_info', '../../components/prefs/prefs.gyp:prefs_test_support', + '../../ios/testing/ios_testing.gyp:ocmock_support', '../../net/net.gyp:net_test_support', '../../skia/skia.gyp:skia', '../../testing/gmock.gyp:gmock', @@ -61,7 +62,12 @@ 'browser/net/metrics_network_client_unittest.mm', 'browser/net/retryable_url_fetcher_unittest.mm', 'browser/notification_promo_unittest.cc', + 'browser/passwords/credential_manager_js_unittest.mm', + 'browser/passwords/credential_manager_unittest.mm', + 'browser/passwords/password_controller_js_unittest.mm', + 'browser/passwords/password_controller_off_the_record_unittest.mm', 'browser/passwords/password_controller_unittest.mm', + 'browser/passwords/password_generation_agent_unittest.mm', 'browser/reading_list/reading_list_entry_unittest.cc', 'browser/reading_list/reading_list_model_unittest.cc', 'browser/signin/chrome_identity_service_observer_bridge_unittest.mm',
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn index afaa495..8a82307 100644 --- a/ios/web/BUILD.gn +++ b/ios/web/BUILD.gn
@@ -318,6 +318,7 @@ deps = [ ":web", + "//base", "//base/test:test_support", "//ios/testing:ocmock_support", "//ios/third_party/gcdwebserver", @@ -368,6 +369,7 @@ "public/test/test_web_thread_bundle.h", "public/test/test_web_view_content_view.h", "public/test/test_web_view_content_view.mm", + "public/test/web_js_test.h", "public/test/web_test.h", "public/test/web_test.mm", "public/test/web_test_suite.h",
diff --git a/ios/web/ios_web.gyp b/ios/web/ios_web.gyp index a446e843..b6ef15f 100644 --- a/ios/web/ios_web.gyp +++ b/ios/web/ios_web.gyp
@@ -459,6 +459,7 @@ 'target_name': 'ios_web_test_support', 'type': 'static_library', 'dependencies': [ + '../../base/base.gyp:base', '../../base/base.gyp:test_support_base', '../../ios/testing/ios_testing.gyp:ocmock_support', '../../ios/third_party/gcdwebserver/gcdwebserver.gyp:gcdwebserver', @@ -512,6 +513,7 @@ 'public/test/test_web_thread_bundle.h', 'public/test/test_web_view_content_view.h', 'public/test/test_web_view_content_view.mm', + 'public/test/web_js_test.h', 'public/test/web_test.h', 'public/test/web_test.mm', 'public/test/web_test_suite.h',
diff --git a/ios/web/public/test/web_js_test.h b/ios/web/public/test/web_js_test.h new file mode 100644 index 0000000..d4dac04 --- /dev/null +++ b/ios/web/public/test/web_js_test.h
@@ -0,0 +1,122 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_INTERNAL_CHROME_BROWSER_WEB_WEB_JS_TEST_H_ +#define IOS_INTERNAL_CHROME_BROWSER_WEB_WEB_JS_TEST_H_ + +#import <Foundation/Foundation.h> + +#import "base/mac/bundle_locations.h" +#import "base/mac/scoped_nsobject.h" +#include "testing/gtest_mac.h" + +class GURL; + +namespace web { + +// Base fixture mixin for testing JavaScripts. +template <class WebTestT> +class WebJsTest : public WebTestT { + public: + WebJsTest(NSArray* java_script_paths) + : java_script_paths_([java_script_paths copy]) {} + + protected: + // Loads |html| and inject JavaScripts at |javaScriptPaths_|. + void LoadHtmlAndInject(NSString* html) { + WebTestT::LoadHtml(html); + Inject(); + } + + // Returns a NSString representation of the JavaScript's evaluation results; + // the JavaScript is passed in as a |format| and its arguments. + NSString* EvaluateJavaScriptWithFormat(NSString* format, ...) + __attribute__((format(__NSString__, 2, 3))); + + // Helper method that EXPECTs the |java_script| evaluation results on each + // element obtained by scripts in |get_element_javas_cripts|; the expected + // result is the corresponding entry in |expected_results|. + void EvaluateJavaScriptOnElementsAndCheck(NSString* java_script, + NSArray* get_element_java_scripts, + NSArray* expected_results); + + // Helper method that EXPECTs the |java_script| evaluation results on each + // element obtained by JavaScripts in |get_element_java_scripts|. The + // expected results are boolean and are true only for elements in + // |get_element_java_scripts_expecting_true| which is subset of + // |get_element_java_scripts|. + void EvaluateBooleanJavaScriptOnElementsAndCheck( + NSString* java_script, + NSArray* get_element_java_scripts, + NSArray* get_element_java_scripts_expecting_true); + + private: + // Injects JavaScript at |java_script_paths_|. + void Inject(); + + base::scoped_nsobject<NSArray> java_script_paths_; +}; + +template <class WebTestT> +void WebJsTest<WebTestT>::Inject() { + // Main web injection should have occured. + ASSERT_NSEQ(@"object", + WebTestT::EvaluateJavaScriptAsString(@"typeof __gCrWeb")); + + for (NSString* java_script_path in java_script_paths_.get()) { + NSString* path = + [base::mac::FrameworkBundle() pathForResource:java_script_path + ofType:@"js"]; + WebTestT::EvaluateJavaScriptAsString([NSString + stringWithContentsOfFile:path + encoding:NSUTF8StringEncoding + error:nil]); + } +} + +template <class WebTestT> +NSString* WebJsTest<WebTestT>::EvaluateJavaScriptWithFormat(NSString* format, + ...) { + va_list args; + va_start(args, format); + base::scoped_nsobject<NSString> java_script( + [[NSString alloc] initWithFormat:format arguments:args]); + va_end(args); + + return WebTestT::EvaluateJavaScriptAsString(java_script); +} + +template <class WebTestT> +void WebJsTest<WebTestT>::EvaluateJavaScriptOnElementsAndCheck( + NSString* java_script, + NSArray* get_element_java_scripts, + NSArray* expected_results) { + for (NSUInteger i = 0; i < get_element_java_scripts.count; ++i) { + EXPECT_NSEQ( + expected_results[i], + EvaluateJavaScriptWithFormat(java_script, get_element_java_scripts[i])); + } +} + +template <class WebTestT> +void WebJsTest<WebTestT>::EvaluateBooleanJavaScriptOnElementsAndCheck( + NSString* java_script, + NSArray* get_element_java_scripts, + NSArray* get_element_java_scripts_expecting_true) { + for (NSUInteger index = 0; index < get_element_java_scripts.count; ++index) { + NSString* get_element_java_script = get_element_java_scripts[index]; + NSString* expected = [get_element_java_scripts_expecting_true + containsObject:get_element_java_script] + ? @"true" + : @"false"; + EXPECT_NSEQ(expected, EvaluateJavaScriptWithFormat(java_script, + get_element_java_script)) + << [NSString stringWithFormat:@"%@ on %@ should return %@", java_script, + get_element_java_script, expected]; + } +} + +} // namespace web + +#endif // IOS_INTERNAL_CHROME_BROWSER_WEB_WEB_JS_TEST_H_
diff --git a/ipc/BUILD.gn b/ipc/BUILD.gn index 34cab68..8dba71d 100644 --- a/ipc/BUILD.gn +++ b/ipc/BUILD.gn
@@ -167,6 +167,13 @@ ] } +mojom("test_interfaces") { + testonly = true + sources = [ + "ipc_test.mojom", + ] +} + # This is provided as a separate target so other targets can provide param # traits implementations without necessarily linking to all of IPC. source_set("param_traits") { @@ -235,6 +242,7 @@ ":ipc", ":mojom", ":run_all_unittests", + ":test_interfaces", ":test_support", "//base", "//base:i18n",
diff --git a/ipc/ipc.gyp b/ipc/ipc.gyp index 3226899..56242d6 100644 --- a/ipc/ipc.gyp +++ b/ipc/ipc.gyp
@@ -61,6 +61,14 @@ ], }, { + 'target_name': 'ipc_test_interfaces', + 'type': 'static_library', + 'sources': [ + 'ipc_test.mojom', + ], + 'includes': [ '../mojo/mojom_bindings_generator.gypi' ], + }, + { 'target_name': 'ipc_run_all_unittests', 'type': 'static_library', 'dependencies': [ @@ -83,6 +91,7 @@ 'dependencies': [ 'ipc', 'ipc_run_all_unittests', + 'ipc_test_interfaces', 'test_support_ipc', '../base/base.gyp:base', '../base/base.gyp:base_i18n',
diff --git a/ipc/ipc.mojom b/ipc/ipc.mojom index 681da12..28d73fb 100644 --- a/ipc/ipc.mojom +++ b/ipc/ipc.mojom
@@ -17,8 +17,14 @@ Type type; }; +// A placeholder interface type since we don't yet support generic associated +// message pipe handles. +interface GenericInterface {}; + interface Channel { Receive(array<uint8> data, array<SerializedHandle>? handles); + + GetAssociatedInterface(string name, associated GenericInterface& request); }; // An interface for connecting a pair of Channel interfaces representing a
diff --git a/ipc/ipc_channel.h b/ipc/ipc_channel.h index 09baf6c..1fc9c6c 100644 --- a/ipc/ipc_channel.h +++ b/ipc/ipc_channel.h
@@ -18,6 +18,10 @@ #include "ipc/ipc_channel_handle.h" #include "ipc/ipc_endpoint.h" #include "ipc/ipc_message.h" +#include "mojo/public/cpp/bindings/associated_group.h" +#include "mojo/public/cpp/bindings/associated_interface_ptr.h" +#include "mojo/public/cpp/bindings/associated_interface_request.h" +#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" #if defined(OS_POSIX) #include <sys/types.h> @@ -93,6 +97,62 @@ CLOSE_FD_MESSAGE_TYPE = HELLO_MESSAGE_TYPE - 1 }; + // Helper interface a Channel may implement to expose support for associated + // Mojo interfaces. + class IPC_EXPORT AssociatedInterfaceSupport { + public: + using GenericAssociatedInterfaceFactory = + base::Callback<void(mojo::ScopedInterfaceEndpointHandle)>; + + virtual ~AssociatedInterfaceSupport() {} + + // Accesses the AssociatedGroup used to associate new interface endpoints + // with this Channel. + virtual mojo::AssociatedGroup* GetAssociatedGroup() = 0; + + // Adds an interface factory to this channel for interface |name|. + virtual void AddGenericAssociatedInterface( + const std::string& name, + const GenericAssociatedInterfaceFactory& factory) = 0; + + // Requests an associated interface from the remote endpoint. + virtual void GetGenericRemoteAssociatedInterface( + const std::string& name, + mojo::ScopedInterfaceEndpointHandle handle) = 0; + + // Template helper to add an interface factory to this channel. + template <typename Interface> + using AssociatedInterfaceFactory = + base::Callback<void(mojo::AssociatedInterfaceRequest<Interface>)>; + template <typename Interface> + void AddAssociatedInterface( + const AssociatedInterfaceFactory<Interface>& factory) { + AddGenericAssociatedInterface( + Interface::Name_, + base::Bind(&BindAssociatedInterfaceRequest<Interface>, factory)); + } + + // Template helper to request a remote associated interface. + template <typename Interface> + void GetRemoteAssociatedInterface( + mojo::AssociatedInterfacePtr<Interface>* proxy) { + mojo::AssociatedInterfaceRequest<Interface> request = + mojo::GetProxy(proxy, GetAssociatedGroup()); + GetGenericRemoteAssociatedInterface( + Interface::Name_, request.PassHandle()); + } + + private: + template <typename Interface> + static void BindAssociatedInterfaceRequest( + const AssociatedInterfaceFactory<Interface>& factory, + mojo::ScopedInterfaceEndpointHandle handle) { + mojo::AssociatedInterfaceRequest<Interface> request; + request.Bind(std::move(handle)); + factory.Run(std::move(request)); + } + }; + // The maximum message size in bytes. Attempting to receive a message of this // size or bigger results in a channel error. static const size_t kMaximumMessageSize = 128 * 1024 * 1024; @@ -181,6 +241,11 @@ // Get its own process id. This value is told to the peer. virtual base::ProcessId GetSelfPID() const = 0; + // Gets a helper for associating Mojo interfaces with this Channel. + // + // NOTE: Not all implementations support this. + virtual AssociatedInterfaceSupport* GetAssociatedInterfaceSupport(); + // Overridden from ipc::Sender. // Send a message over the Channel to the listener on the other end. //
diff --git a/ipc/ipc_channel_common.cc b/ipc/ipc_channel_common.cc index 3002b665..1d5d2f99 100644 --- a/ipc/ipc_channel_common.cc +++ b/ipc/ipc_channel_common.cc
@@ -84,6 +84,10 @@ Channel::~Channel() { } +Channel::AssociatedInterfaceSupport* Channel::GetAssociatedInterfaceSupport() { + return nullptr; +} + bool Channel::IsSendThreadSafe() const { return false; }
diff --git a/ipc/ipc_channel_mojo.cc b/ipc/ipc_channel_mojo.cc index 22efa3a..70a12f4 100644 --- a/ipc/ipc_channel_mojo.cc +++ b/ipc/ipc_channel_mojo.cc
@@ -307,6 +307,14 @@ listener_->OnChannelError(); } +void ChannelMojo::OnAssociatedInterfaceRequest( + const std::string& name, + mojo::ScopedInterfaceEndpointHandle handle) { + auto iter = associated_interfaces_.find(name); + if (iter != associated_interfaces_.end()) + iter->second.Run(std::move(handle)); +} + void ChannelMojo::InitMessageReader(mojom::ChannelAssociatedPtrInfo sender, mojom::ChannelAssociatedRequest receiver, base::ProcessId peer_pid) { @@ -392,6 +400,9 @@ return bootstrap_->GetSelfPID(); } +Channel::AssociatedInterfaceSupport* +ChannelMojo::GetAssociatedInterfaceSupport() { return this; } + void ChannelMojo::OnMessageReceived(const Message& message) { TRACE_EVENT2("ipc,toplevel", "ChannelMojo::OnMessageReceived", "class", IPC_MESSAGE_ID_CLASS(message.type()), @@ -468,4 +479,23 @@ return MOJO_RESULT_OK; } +mojo::AssociatedGroup* ChannelMojo::GetAssociatedGroup() { + DCHECK(bootstrap_); + return bootstrap_->GetAssociatedGroup(); +} + +void ChannelMojo::AddGenericAssociatedInterface( + const std::string& name, + const GenericAssociatedInterfaceFactory& factory) { + auto result = associated_interfaces_.insert({ name, factory }); + DCHECK(result.second); +} + +void ChannelMojo::GetGenericRemoteAssociatedInterface( + const std::string& name, + mojo::ScopedInterfaceEndpointHandle handle) { + DCHECK(message_reader_); + message_reader_->GetRemoteInterface(name, std::move(handle)); +} + } // namespace IPC
diff --git a/ipc/ipc_channel_mojo.h b/ipc/ipc_channel_mojo.h index 774a82a..c267649 100644 --- a/ipc/ipc_channel_mojo.h +++ b/ipc/ipc_channel_mojo.h
@@ -7,7 +7,9 @@ #include <stdint.h> +#include <map> #include <memory> +#include <string> #include <vector> #include "base/macros.h" @@ -37,6 +39,7 @@ // class IPC_EXPORT ChannelMojo : public Channel, + public Channel::AssociatedInterfaceSupport, public MojoBootstrap::Delegate, public NON_EXPORTED_BASE(internal::MessagePipeReader::Delegate) { public: @@ -62,6 +65,7 @@ bool IsSendThreadSafe() const override; base::ProcessId GetPeerPID() const override; base::ProcessId GetSelfPID() const override; + Channel::AssociatedInterfaceSupport* GetAssociatedInterfaceSupport() override; #if defined(OS_POSIX) && !defined(OS_NACL_SFI) int GetClientFileDescriptor() const override; @@ -82,6 +86,9 @@ mojom::ChannelAssociatedRequest receive_channel, int32_t peer_pid) override; void OnBootstrapError() override; + void OnAssociatedInterfaceRequest( + const std::string& name, + mojo::ScopedInterfaceEndpointHandle handle) override; // MessagePipeReader::Delegate void OnMessageReceived(const Message& message) override; @@ -96,6 +103,15 @@ mojom::ChannelAssociatedRequest receiver, base::ProcessId peer_pid); + // Channel::AssociatedInterfaceSupport: + mojo::AssociatedGroup* GetAssociatedGroup() override; + void AddGenericAssociatedInterface( + const std::string& name, + const GenericAssociatedInterfaceFactory& factory) override; + void GetGenericRemoteAssociatedInterface( + const std::string& name, + mojo::ScopedInterfaceEndpointHandle handle) override; + // ChannelMojo needs to kill its MessagePipeReader in delayed manner // because the channel wants to kill these readers during the // notifications invoked by them. @@ -108,6 +124,9 @@ std::unique_ptr<MojoBootstrap> bootstrap_; Listener* listener_; + std::map<std::string, GenericAssociatedInterfaceFactory> + associated_interfaces_; + // Guards access to the fields below. mutable base::Lock lock_; std::unique_ptr<internal::MessagePipeReader, ReaderDeleter> message_reader_;
diff --git a/ipc/ipc_channel_mojo_unittest.cc b/ipc/ipc_channel_mojo_unittest.cc index eec011b..e846c13 100644 --- a/ipc/ipc_channel_mojo_unittest.cc +++ b/ipc/ipc_channel_mojo_unittest.cc
@@ -6,6 +6,7 @@ #include <stddef.h> #include <stdint.h> + #include <memory> #include <utility> @@ -17,6 +18,7 @@ #include "base/pickle.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" +#include "base/strings/stringprintf.h" #include "base/test/test_io_thread.h" #include "base/test/test_timeouts.h" #include "base/threading/thread.h" @@ -26,6 +28,7 @@ #include "ipc/ipc_mojo_handle_attachment.h" #include "ipc/ipc_mojo_message_helper.h" #include "ipc/ipc_mojo_param_traits.h" +#include "ipc/ipc_test.mojom.h" #include "ipc/ipc_test_base.h" #include "ipc/ipc_test_channel_listener.h" #include "mojo/edk/test/mojo_test_base.h" @@ -60,6 +63,12 @@ namespace { +void SendString(IPC::Sender* sender, const std::string& str) { + IPC::Message* message = new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL); + message->WriteString(str); + ASSERT_TRUE(sender->Send(message)); +} + class ListenerThatExpectsOK : public IPC::Listener { public: ListenerThatExpectsOK() : received_ok_(false) {} @@ -83,12 +92,7 @@ DCHECK(received_ok_); } - static void SendOK(IPC::Sender* sender) { - IPC::Message* message = - new IPC::Message(0, 2, IPC::Message::PRIORITY_NORMAL); - message->WriteString(std::string("OK")); - ASSERT_TRUE(sender->Send(message)); - } + static void SendOK(IPC::Sender* sender) { SendString(sender, "OK"); } private: bool received_ok_; @@ -124,7 +128,7 @@ class IPCChannelMojoTest : public testing::Test { public: - IPCChannelMojoTest() : io_thread_(base::TestIOThread::Mode::kAutoStart) {} + IPCChannelMojoTest() {} void TearDown() override { base::RunLoop().RunUntilIdle(); } @@ -148,7 +152,6 @@ private: base::MessageLoop message_loop_; - base::TestIOThread io_thread_; mojo::edk::test::MultiprocessTestHelper helper_; mojo::ScopedMessagePipeHandle handle_; std::unique_ptr<IPC::Channel> channel_; @@ -582,6 +585,120 @@ Close(); } +class ListenerWithSimpleAssociatedInterface + : public IPC::Listener, + public IPC::mojom::SimpleTestDriver { + public: + static const int kNumMessages; + + ListenerWithSimpleAssociatedInterface() : binding_(this) {} + + ~ListenerWithSimpleAssociatedInterface() override {} + + bool OnMessageReceived(const IPC::Message& message) override { + base::PickleIterator iter(message); + std::string should_be_expected; + EXPECT_TRUE(iter.ReadString(&should_be_expected)); + EXPECT_EQ(should_be_expected, next_expected_string_); + num_messages_received_++; + return true; + } + + void OnChannelError() override { + DCHECK(received_quit_); + } + + void RegisterInterfaceFactory(IPC::Channel* channel) { + channel->GetAssociatedInterfaceSupport()->AddAssociatedInterface( + base::Bind(&ListenerWithSimpleAssociatedInterface::BindRequest, + base::Unretained(this))); + } + + private: + // IPC::mojom::SimpleTestDriver: + void ExpectString(const mojo::String& str) override { + next_expected_string_ = str; + } + + void RequestQuit(const RequestQuitCallback& callback) override { + EXPECT_EQ(kNumMessages, num_messages_received_); + received_quit_ = true; + callback.Run(); + base::MessageLoop::current()->QuitWhenIdle(); + } + + void BindRequest(IPC::mojom::SimpleTestDriverAssociatedRequest request) { + DCHECK(!binding_.is_bound()); + binding_.Bind(std::move(request)); + } + + std::string next_expected_string_; + int num_messages_received_ = 0; + bool received_quit_ = false; + + mojo::AssociatedBinding<IPC::mojom::SimpleTestDriver> binding_; +}; + +const int ListenerWithSimpleAssociatedInterface::kNumMessages = 1000; + +class ListenerSendingAssociatedMessages : public IPC::Listener { + public: + ListenerSendingAssociatedMessages() {} + + bool OnMessageReceived(const IPC::Message& message) override { return true; } + + void OnChannelConnected(int32_t peer_pid) override { + DCHECK(channel_); + channel_->GetAssociatedInterfaceSupport()->GetRemoteAssociatedInterface( + &driver_); + + // Send a bunch of interleaved messages, alternating between the associated + // interface and a legacy IPC::Message. + for (int i = 0; i < ListenerWithSimpleAssociatedInterface::kNumMessages; + ++i) { + std::string str = base::StringPrintf("Hello! %d", i); + driver_->ExpectString(str); + SendString(channel_, str); + } + driver_->RequestQuit(base::Bind(&OnQuitAck)); + } + + void set_channel(IPC::Channel* channel) { channel_ = channel; } + + private: + static void OnQuitAck() { base::MessageLoop::current()->QuitWhenIdle(); } + + IPC::Channel* channel_ = nullptr; + IPC::mojom::SimpleTestDriverAssociatedPtr driver_; +}; + +TEST_F(IPCChannelMojoTest, SimpleAssociatedInterface) { + InitWithMojo("SimpleAssociatedInterfaceClient"); + + ListenerWithSimpleAssociatedInterface listener; + CreateChannel(&listener); + ASSERT_TRUE(ConnectChannel()); + + listener.RegisterInterfaceFactory(channel()); + + base::RunLoop().Run(); + channel()->Close(); + + EXPECT_TRUE(WaitForClientShutdown()); + DestroyChannel(); +} + +DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT(SimpleAssociatedInterfaceClient, + ChannelClient) { + ListenerSendingAssociatedMessages listener; + Connect(&listener); + listener.set_channel(channel()); + + base::RunLoop().Run(); + + Close(); +} + #if defined(OS_POSIX) class ListenerThatExpectsFile : public IPC::Listener { public: @@ -696,7 +813,7 @@ Close(); } -#endif +#endif // defined(OS_POSIX) #if defined(OS_LINUX)
diff --git a/ipc/ipc_channel_posix_unittest.cc b/ipc/ipc_channel_posix_unittest.cc index 830ea30..3ea11c3 100644 --- a/ipc/ipc_channel_posix_unittest.cc +++ b/ipc/ipc_channel_posix_unittest.cc
@@ -17,14 +17,17 @@ #include <memory> +#include "base/command_line.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/location.h" #include "base/path_service.h" #include "base/posix/eintr_wrapper.h" #include "base/process/process.h" +#include "base/rand_util.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" +#include "base/strings/string_number_conversions.h" #include "base/test/multiprocess_test.h" #include "base/test/test_timeouts.h" #include "build/build_config.h" @@ -34,6 +37,8 @@ namespace { +const char kSocketNameSwitch[] = "connection-socket-name"; + static const uint32_t kQuitMessage = 47; class IPCChannelPosixTestListener : public IPC::Listener { @@ -112,8 +117,18 @@ static void SetUpSocket(IPC::ChannelHandle *handle, IPC::Channel::Mode mode); static void SpinRunLoop(base::TimeDelta delay); - static const std::string GetConnectionSocketName(); static const std::string GetChannelDirName(); + static std::string GetClientConnectionSocketName(); + + const std::string& GetConnectionSocketName(); + + base::Process SpawnChild(const std::string& procname) { + base::CommandLine command_line = MakeCmdLine(procname); + command_line.AppendSwitchASCII( + kSocketNameSwitch, GetConnectionSocketName()); + return base::SpawnMultiProcessTestChild( + procname, command_line, base::LaunchOptions()); + } bool WaitForExit(base::Process& process, int* exit_code) { #if defined(OS_ANDROID) @@ -130,6 +145,7 @@ private: std::unique_ptr<base::MessageLoopForIO> message_loop_; + std::string socket_name_; }; const std::string IPCChannelPosixTest::GetChannelDirName() { @@ -138,8 +154,20 @@ return tmp_dir.value(); } -const std::string IPCChannelPosixTest::GetConnectionSocketName() { - return GetChannelDirName() + "/chrome_IPCChannelPosixTest__ConnectionSocket"; +const std::string& IPCChannelPosixTest::GetConnectionSocketName() { + if (socket_name_.empty()) { + uint64_t id = base::RandUint64(); + socket_name_ = GetChannelDirName() + + "/chrome_IPCChannelPosixTest_" + + base::HexEncode(&id, sizeof(id)); + } + return socket_name_; +} + +std::string IPCChannelPosixTest::GetClientConnectionSocketName() { + DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(kSocketNameSwitch)); + return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + kSocketNameSwitch); } void IPCChannelPosixTest::SetUp() { @@ -439,7 +467,8 @@ MULTIPROCESS_TEST_MAIN(IPCChannelPosixTestConnectionProc) { base::MessageLoopForIO message_loop; IPCChannelPosixTestListener listener(true); - IPC::ChannelHandle handle(IPCChannelPosixTest::GetConnectionSocketName()); + IPC::ChannelHandle handle( + IPCChannelPosixTest::GetClientConnectionSocketName()); IPCChannelPosixTest::SetUpSocket(&handle, IPC::Channel::MODE_NAMED_CLIENT); std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( handle, IPC::Channel::MODE_NAMED_CLIENT, &listener)); @@ -453,7 +482,8 @@ MULTIPROCESS_TEST_MAIN(IPCChannelPosixFailConnectionProc) { base::MessageLoopForIO message_loop; IPCChannelPosixTestListener listener(false); - IPC::ChannelHandle handle(IPCChannelPosixTest::GetConnectionSocketName()); + IPC::ChannelHandle handle( + IPCChannelPosixTest::GetClientConnectionSocketName()); IPCChannelPosixTest::SetUpSocket(&handle, IPC::Channel::MODE_NAMED_CLIENT); std::unique_ptr<IPC::ChannelPosix> channel(new IPC::ChannelPosix( handle, IPC::Channel::MODE_NAMED_CLIENT, &listener));
diff --git a/ipc/ipc_message_pipe_reader.cc b/ipc/ipc_message_pipe_reader.cc index da2d85d..74c7285 100644 --- a/ipc/ipc_message_pipe_reader.cc +++ b/ipc/ipc_message_pipe_reader.cc
@@ -115,6 +115,14 @@ return result == MOJO_RESULT_OK; } +void MessagePipeReader::GetRemoteInterface( + const std::string& name, + mojo::ScopedInterfaceEndpointHandle handle) { + mojom::GenericInterfaceAssociatedRequest request; + request.Bind(std::move(handle)); + sender_->GetAssociatedInterface(name, std::move(request)); +} + void MessagePipeReader::Receive( mojo::Array<uint8_t> data, mojo::Array<mojom::SerializedHandlePtr> handles) { @@ -138,6 +146,14 @@ delegate_->OnMessageReceived(message); } +void MessagePipeReader::GetAssociatedInterface( + const mojo::String& name, + mojom::GenericInterfaceAssociatedRequest request) { + DCHECK(thread_checker_.CalledOnValidThread()); + if (delegate_) + delegate_->OnAssociatedInterfaceRequest(name, request.PassHandle()); +} + void MessagePipeReader::OnPipeError(MojoResult error) { DCHECK(thread_checker_.CalledOnValidThread()); if (delegate_)
diff --git a/ipc/ipc_message_pipe_reader.h b/ipc/ipc_message_pipe_reader.h index b15579d..5aec440 100644 --- a/ipc/ipc_message_pipe_reader.h +++ b/ipc/ipc_message_pipe_reader.h
@@ -15,8 +15,10 @@ #include "base/macros.h" #include "base/threading/thread_checker.h" #include "ipc/ipc.mojom.h" +#include "ipc/ipc_export.h" #include "ipc/ipc_message.h" #include "mojo/public/cpp/bindings/associated_binding.h" +#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" #include "mojo/public/cpp/system/core.h" #include "mojo/public/cpp/system/message_pipe.h" @@ -41,12 +43,15 @@ // be called on any thread. All |Delegate| functions will be called on the IO // thread. // -class MessagePipeReader : public mojom::Channel { +class IPC_EXPORT MessagePipeReader : public NON_EXPORTED_BASE(mojom::Channel) { public: class Delegate { public: virtual void OnMessageReceived(const Message& message) = 0; virtual void OnPipeError() = 0; + virtual void OnAssociatedInterfaceRequest( + const std::string& name, + mojo::ScopedInterfaceEndpointHandle handle) = 0; }; // Delay the object deletion using the current message loop. @@ -91,6 +96,10 @@ // thread. bool Send(std::unique_ptr<Message> message); + // Requests an associated interface from the other end of the pipe. + void GetRemoteInterface(const std::string& name, + mojo::ScopedInterfaceEndpointHandle handle); + base::ProcessId GetPeerPid() const { return peer_pid_; } protected: @@ -101,6 +110,9 @@ // mojom::Channel: void Receive(mojo::Array<uint8_t> data, mojo::Array<mojom::SerializedHandlePtr> handles) override; + void GetAssociatedInterface( + const mojo::String& name, + mojom::GenericInterfaceAssociatedRequest request) override; // |delegate_| is null once the message pipe is closed. Delegate* delegate_;
diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc index ba0ea46f..425f7948 100644 --- a/ipc/ipc_mojo_bootstrap.cc +++ b/ipc/ipc_mojo_bootstrap.cc
@@ -5,6 +5,9 @@ #include "ipc/ipc_mojo_bootstrap.h" #include <stdint.h> + +#include <map> +#include <memory> #include <utility> #include "base/callback.h" @@ -12,15 +15,608 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/process/process_handle.h" +#include "base/single_thread_task_runner.h" +#include "base/stl_util.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "ipc/ipc_message_utils.h" #include "ipc/ipc_platform_file.h" +#include "mojo/public/cpp/bindings/associated_group.h" +#include "mojo/public/cpp/bindings/associated_group_controller.h" #include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/connector.h" +#include "mojo/public/cpp/bindings/interface_endpoint_client.h" +#include "mojo/public/cpp/bindings/interface_endpoint_controller.h" +#include "mojo/public/cpp/bindings/interface_id.h" +#include "mojo/public/cpp/bindings/message_header_validator.h" +#include "mojo/public/cpp/bindings/pipe_control_message_handler.h" +#include "mojo/public/cpp/bindings/pipe_control_message_handler_delegate.h" +#include "mojo/public/cpp/bindings/pipe_control_message_proxy.h" namespace IPC { namespace { +class ChannelAssociatedGroupController + : public mojo::AssociatedGroupController, + public mojo::MessageReceiver, + public mojo::PipeControlMessageHandlerDelegate { + public: + ChannelAssociatedGroupController(bool set_interface_id_namespace_bit, + mojo::ScopedMessagePipeHandle handle) + : mojo::AssociatedGroupController(base::ThreadTaskRunnerHandle::Get()), + task_runner_(base::ThreadTaskRunnerHandle::Get()), + id_namespace_mask_(set_interface_id_namespace_bit ? + mojo::kInterfaceIdNamespaceMask : 0), + associated_group_(CreateAssociatedGroup()), + connector_(std::move(handle), mojo::Connector::SINGLE_THREADED_SEND, + base::ThreadTaskRunnerHandle::Get()), + header_validator_( + "IPC::mojom::Bootstrap [master] MessageHeaderValidator", this), + control_message_handler_(this), + control_message_proxy_(&connector_) { + connector_.set_incoming_receiver(&header_validator_); + connector_.set_connection_error_handler( + base::Bind(&ChannelAssociatedGroupController::OnPipeError, + base::Unretained(this))); + control_message_handler_.SetDescription( + "IPC::mojom::Bootstrap [master] PipeControlMessageHandler"); + } + + mojo::AssociatedGroup* associated_group() { return associated_group_.get(); } + + void ShutDown() { + DCHECK(thread_checker_.CalledOnValidThread()); + connector_.CloseMessagePipe(); + OnPipeError(); + associated_group_.reset(); + } + + void SetProxyTaskRunner( + scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner) { + proxy_task_runner_ = proxy_task_runner; + } + + // mojo::AssociatedGroupController: + void CreateEndpointHandlePair( + mojo::ScopedInterfaceEndpointHandle* local_endpoint, + mojo::ScopedInterfaceEndpointHandle* remote_endpoint) override { + base::AutoLock locker(lock_); + uint32_t id = 0; + do { + if (next_interface_id_ >= mojo::kInterfaceIdNamespaceMask) + next_interface_id_ = 1; + id = (next_interface_id_++) | id_namespace_mask_; + } while (ContainsKey(endpoints_, id)); + + Endpoint* endpoint = new Endpoint(this, id); + if (encountered_error_) + endpoint->set_peer_closed(); + endpoints_.insert({ id, endpoint }); + + *local_endpoint = CreateScopedInterfaceEndpointHandle(id, true); + *remote_endpoint = CreateScopedInterfaceEndpointHandle(id, false); + } + + mojo::ScopedInterfaceEndpointHandle CreateLocalEndpointHandle( + mojo::InterfaceId id) override { + if (!mojo::IsValidInterfaceId(id)) + return mojo::ScopedInterfaceEndpointHandle(); + + base::AutoLock locker(lock_); + bool inserted = false; + Endpoint* endpoint = FindOrInsertEndpoint(id, &inserted); + if (inserted && encountered_error_) + endpoint->set_peer_closed(); + + return CreateScopedInterfaceEndpointHandle(id, true); + } + + void CloseEndpointHandle(mojo::InterfaceId id, bool is_local) override { + if (!mojo::IsValidInterfaceId(id)) + return; + + base::AutoLock locker(lock_); + if (!is_local) { + DCHECK(ContainsKey(endpoints_, id)); + DCHECK(!mojo::IsMasterInterfaceId(id)); + control_message_proxy_.NotifyEndpointClosedBeforeSent(id); + return; + } + + DCHECK(ContainsKey(endpoints_, id)); + Endpoint* endpoint = endpoints_[id].get(); + DCHECK(!endpoint->client()); + DCHECK(!endpoint->closed()); + MarkClosedAndMaybeRemove(endpoint); + + if (!mojo::IsMasterInterfaceId(id)) + control_message_proxy_.NotifyPeerEndpointClosed(id); + } + + mojo::InterfaceEndpointController* AttachEndpointClient( + const mojo::ScopedInterfaceEndpointHandle& handle, + mojo::InterfaceEndpointClient* client, + scoped_refptr<base::SingleThreadTaskRunner> runner) override { + const mojo::InterfaceId id = handle.id(); + + DCHECK(mojo::IsValidInterfaceId(id)); + DCHECK(client); + + base::AutoLock locker(lock_); + DCHECK(ContainsKey(endpoints_, id)); + + Endpoint* endpoint = endpoints_[id].get(); + endpoint->AttachClient(client, std::move(runner)); + + if (endpoint->peer_closed()) + NotifyEndpointOfError(endpoint, true /* force_async */); + + return endpoint; + } + + void DetachEndpointClient( + const mojo::ScopedInterfaceEndpointHandle& handle) override { + const mojo::InterfaceId id = handle.id(); + + DCHECK(mojo::IsValidInterfaceId(id)); + + base::AutoLock locker(lock_); + DCHECK(ContainsKey(endpoints_, id)); + + Endpoint* endpoint = endpoints_[id].get(); + endpoint->DetachClient(); + } + + void RaiseError() override { + if (task_runner_->BelongsToCurrentThread()) { + connector_.RaiseError(); + } else { + task_runner_->PostTask( + FROM_HERE, + base::Bind(&ChannelAssociatedGroupController::RaiseError, this)); + } + } + + private: + class Endpoint; + friend class Endpoint; + + class Endpoint : public base::RefCountedThreadSafe<Endpoint>, + public mojo::InterfaceEndpointController { + public: + Endpoint(ChannelAssociatedGroupController* controller, mojo::InterfaceId id) + : controller_(controller), id_(id) {} + + mojo::InterfaceId id() const { return id_; } + + bool closed() const { + controller_->lock_.AssertAcquired(); + return closed_; + } + + void set_closed() { + controller_->lock_.AssertAcquired(); + closed_ = true; + } + + bool peer_closed() const { + controller_->lock_.AssertAcquired(); + return peer_closed_; + } + + void set_peer_closed() { + controller_->lock_.AssertAcquired(); + peer_closed_ = true; + } + + base::SingleThreadTaskRunner* task_runner() const { + return task_runner_.get(); + } + + mojo::InterfaceEndpointClient* client() const { + controller_->lock_.AssertAcquired(); + return client_; + } + + void AttachClient(mojo::InterfaceEndpointClient* client, + scoped_refptr<base::SingleThreadTaskRunner> runner) { + controller_->lock_.AssertAcquired(); + DCHECK(!client_); + DCHECK(!closed_); + DCHECK(runner->BelongsToCurrentThread()); + + task_runner_ = std::move(runner); + client_ = client; + } + + void DetachClient() { + controller_->lock_.AssertAcquired(); + DCHECK(client_); + DCHECK(task_runner_->BelongsToCurrentThread()); + DCHECK(!closed_); + + task_runner_ = nullptr; + client_ = nullptr; + } + + // mojo::InterfaceEndpointController: + bool SendMessage(mojo::Message* message) override { + DCHECK(task_runner_->BelongsToCurrentThread()); + message->set_interface_id(id_); + return controller_->SendMessage(message); + } + + void AllowWokenUpBySyncWatchOnSameThread() override { + DCHECK(task_runner_->BelongsToCurrentThread()); + + // TODO(rockot): Implement sync waiting. + NOTREACHED(); + } + + bool SyncWatch(const bool* should_stop) override { + DCHECK(task_runner_->BelongsToCurrentThread()); + + // It's not legal to make sync calls from the master endpoint's thread, + // and in fact they must only happen from the proxy task runner. + DCHECK(!controller_->task_runner_->BelongsToCurrentThread()); + DCHECK(controller_->proxy_task_runner_->BelongsToCurrentThread()); + + // TODO(rockot): Implement sync waiting. + NOTREACHED(); + return false; + } + + private: + friend class base::RefCountedThreadSafe<Endpoint>; + + ~Endpoint() override {} + + ChannelAssociatedGroupController* const controller_; + const mojo::InterfaceId id_; + + bool closed_ = false; + bool peer_closed_ = false; + mojo::InterfaceEndpointClient* client_ = nullptr; + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + + DISALLOW_COPY_AND_ASSIGN(Endpoint); + }; + + ~ChannelAssociatedGroupController() override { + base::AutoLock locker(lock_); + + for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { + Endpoint* endpoint = iter->second.get(); + ++iter; + + DCHECK(endpoint->closed()); + MarkPeerClosedAndMaybeRemove(endpoint); + } + + DCHECK(endpoints_.empty()); + } + + bool SendMessage(mojo::Message* message) { + if (task_runner_->BelongsToCurrentThread()) { + DCHECK(thread_checker_.CalledOnValidThread()); + return connector_.Accept(message); + } else { + // We always post tasks to the master endpoint thread when called from the + // proxy thread in order to simulate IPC::ChannelProxy::Send behavior. + DCHECK(proxy_task_runner_ && + proxy_task_runner_->BelongsToCurrentThread()); + std::unique_ptr<mojo::Message> passed_message(new mojo::Message); + message->MoveTo(passed_message.get()); + task_runner_->PostTask( + FROM_HERE, + base::Bind( + &ChannelAssociatedGroupController::SendMessageOnMasterThread, + this, base::Passed(&passed_message))); + return true; + } + } + + void SendMessageOnMasterThread(std::unique_ptr<mojo::Message> message) { + DCHECK(thread_checker_.CalledOnValidThread()); + if (!SendMessage(message.get())) + RaiseError(); + } + + void OnPipeError() { + DCHECK(thread_checker_.CalledOnValidThread()); + + // We keep |this| alive here because it's possible for the notifications + // below to release all other references. + scoped_refptr<ChannelAssociatedGroupController> keepalive(this); + + base::AutoLock locker(lock_); + encountered_error_ = true; + + std::vector<scoped_refptr<Endpoint>> endpoints_to_notify; + for (auto iter = endpoints_.begin(); iter != endpoints_.end();) { + Endpoint* endpoint = iter->second.get(); + ++iter; + + if (endpoint->client()) + endpoints_to_notify.push_back(endpoint); + + MarkPeerClosedAndMaybeRemove(endpoint); + } + + for (auto& endpoint : endpoints_to_notify) { + // Because an notification may in turn detach any endpoint, we have to + // check each client again here. + if (endpoint->client()) + NotifyEndpointOfError(endpoint.get(), false /* force_async */); + } + } + + void NotifyEndpointOfError(Endpoint* endpoint, bool force_async) { + lock_.AssertAcquired(); + DCHECK(endpoint->task_runner() && endpoint->client()); + if (endpoint->task_runner()->BelongsToCurrentThread() && !force_async) { + mojo::InterfaceEndpointClient* client = endpoint->client(); + + base::AutoUnlock unlocker(lock_); + client->NotifyError(); + } else { + endpoint->task_runner()->PostTask( + FROM_HERE, + base::Bind(&ChannelAssociatedGroupController + ::NotifyEndpointOfErrorOnEndpointThread, this, + make_scoped_refptr(endpoint))); + } + } + + void NotifyEndpointOfErrorOnEndpointThread(scoped_refptr<Endpoint> endpoint) { + base::AutoLock locker(lock_); + if (!endpoint->client()) + return; + DCHECK(endpoint->task_runner()->BelongsToCurrentThread()); + NotifyEndpointOfError(endpoint.get(), false /* force_async */); + } + + void MarkClosedAndMaybeRemove(Endpoint* endpoint) { + lock_.AssertAcquired(); + endpoint->set_closed(); + if (endpoint->closed() && endpoint->peer_closed()) + endpoints_.erase(endpoint->id()); + } + + void MarkPeerClosedAndMaybeRemove(Endpoint* endpoint) { + lock_.AssertAcquired(); + endpoint->set_peer_closed(); + if (endpoint->closed() && endpoint->peer_closed()) + endpoints_.erase(endpoint->id()); + } + + Endpoint* FindOrInsertEndpoint(mojo::InterfaceId id, bool* inserted) { + lock_.AssertAcquired(); + DCHECK(!inserted || !*inserted); + + auto iter = endpoints_.find(id); + if (iter != endpoints_.end()) + return iter->second.get(); + + Endpoint* endpoint = new Endpoint(this, id); + endpoints_.insert({ id, endpoint }); + if (inserted) + *inserted = true; + return endpoint; + } + + // mojo::MessageReceiver: + bool Accept(mojo::Message* message) override { + DCHECK(thread_checker_.CalledOnValidThread()); + + if (mojo::PipeControlMessageHandler::IsPipeControlMessage(message)) { + if (!control_message_handler_.Accept(message)) + RaiseError(); + return true; + } + + mojo::InterfaceId id = message->interface_id(); + DCHECK(mojo::IsValidInterfaceId(id)); + + base::AutoLock locker(lock_); + bool inserted = false; + Endpoint* endpoint = FindOrInsertEndpoint(id, &inserted); + if (inserted) { + MarkClosedAndMaybeRemove(endpoint); + if (!mojo::IsMasterInterfaceId(id)) + control_message_proxy_.NotifyPeerEndpointClosed(id); + return true; + } + + if (endpoint->closed()) + return true; + + mojo::InterfaceEndpointClient* client = endpoint->client(); + if (!client || !endpoint->task_runner()->BelongsToCurrentThread()) { + // No client has been bound yet or the client runs tasks on another + // thread. We assume the other thread must always be the one on which + // |proxy_task_runner_| runs tasks, since that's the only valid scenario. + // + // If the client is not yet bound, it must be bound by the time this task + // runs or else it's programmer error. + DCHECK(proxy_task_runner_); + CHECK(false); + std::unique_ptr<mojo::Message> passed_message(new mojo::Message); + message->MoveTo(passed_message.get()); + proxy_task_runner_->PostTask( + FROM_HERE, + base::Bind(&ChannelAssociatedGroupController::AcceptOnProxyThread, + this, base::Passed(&passed_message))); + return true; + } + + // We do not expect to receive sync responses on the master endpoint thread. + // If it's happening, it's a bug. + DCHECK(!message->has_flag(mojo::Message::kFlagIsSync)); + + bool result = false; + { + base::AutoUnlock unlocker(lock_); + result = client->HandleIncomingMessage(message); + } + + if (!result) + RaiseError(); + + return true; + } + + void AcceptOnProxyThread(std::unique_ptr<mojo::Message> message) { + DCHECK(proxy_task_runner_->BelongsToCurrentThread()); + + // TODO(rockot): Implement this. + NOTREACHED(); + } + + // mojo::PipeControlMessageHandlerDelegate: + bool OnPeerAssociatedEndpointClosed(mojo::InterfaceId id) override { + DCHECK(thread_checker_.CalledOnValidThread()); + + if (mojo::IsMasterInterfaceId(id)) + return false; + + base::AutoLock locker(lock_); + scoped_refptr<Endpoint> endpoint = FindOrInsertEndpoint(id, nullptr); + if (!endpoint->peer_closed()) { + if (endpoint->client()) + NotifyEndpointOfError(endpoint.get(), false /* force_async */); + MarkPeerClosedAndMaybeRemove(endpoint.get()); + } + + return true; + } + + bool OnAssociatedEndpointClosedBeforeSent(mojo::InterfaceId id) override { + DCHECK(thread_checker_.CalledOnValidThread()); + + if (mojo::IsMasterInterfaceId(id)) + return false; + + base::AutoLock locker(lock_); + Endpoint* endpoint = FindOrInsertEndpoint(id, nullptr); + DCHECK(!endpoint->closed()); + MarkClosedAndMaybeRemove(endpoint); + control_message_proxy_.NotifyPeerEndpointClosed(id); + return true; + } + + // Checked in places which must be run on the master endpoint's thread. + base::ThreadChecker thread_checker_; + + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner_; + const uint32_t id_namespace_mask_; + std::unique_ptr<mojo::AssociatedGroup> associated_group_; + mojo::Connector connector_; + mojo::MessageHeaderValidator header_validator_; + mojo::PipeControlMessageHandler control_message_handler_; + + // Guards the fields below for thread-safe access. + base::Lock lock_; + + bool encountered_error_ = false; + uint32_t next_interface_id_ = 1; + std::map<uint32_t, scoped_refptr<Endpoint>> endpoints_; + mojo::PipeControlMessageProxy control_message_proxy_; + + DISALLOW_COPY_AND_ASSIGN(ChannelAssociatedGroupController); +}; + +class BootstrapMasterProxy { + public: + BootstrapMasterProxy() {} + ~BootstrapMasterProxy() { + endpoint_client_.reset(); + proxy_.reset(); + if (controller_) + controller_->ShutDown(); + } + + void Bind(mojo::ScopedMessagePipeHandle handle) { + DCHECK(!controller_); + controller_ = new ChannelAssociatedGroupController(true, std::move(handle)); + endpoint_client_.reset(new mojo::InterfaceEndpointClient( + controller_->CreateLocalEndpointHandle(mojo::kMasterInterfaceId), + nullptr, + base::MakeUnique<typename mojom::Bootstrap::ResponseValidator_>(), + false, base::ThreadTaskRunnerHandle::Get())); + proxy_.reset(new mojom::BootstrapProxy(endpoint_client_.get())); + proxy_->serialization_context()->group_controller = controller_; + } + + void set_connection_error_handler(const base::Closure& handler) { + DCHECK(endpoint_client_); + endpoint_client_->set_connection_error_handler(handler); + } + + mojo::AssociatedGroup* associated_group() { + DCHECK(controller_); + return controller_->associated_group(); + } + + mojom::Bootstrap* operator->() { + DCHECK(proxy_); + return proxy_.get(); + } + + private: + std::unique_ptr<mojom::BootstrapProxy> proxy_; + scoped_refptr<ChannelAssociatedGroupController> controller_; + std::unique_ptr<mojo::InterfaceEndpointClient> endpoint_client_; + + DISALLOW_COPY_AND_ASSIGN(BootstrapMasterProxy); +}; + +class BootstrapMasterBinding { + public: + explicit BootstrapMasterBinding(mojom::Bootstrap* impl) { + stub_.set_sink(impl); + } + + ~BootstrapMasterBinding() { + endpoint_client_.reset(); + if (controller_) + controller_->ShutDown(); + } + + void set_connection_error_handler(const base::Closure& handler) { + DCHECK(endpoint_client_); + endpoint_client_->set_connection_error_handler(handler); + } + + mojo::AssociatedGroup* associated_group() { + DCHECK(controller_); + return controller_->associated_group(); + } + + void Bind(mojo::ScopedMessagePipeHandle handle) { + DCHECK(!controller_); + controller_ = + new ChannelAssociatedGroupController(false, std::move(handle)); + stub_.serialization_context()->group_controller = controller_; + + endpoint_client_.reset(new mojo::InterfaceEndpointClient( + controller_->CreateLocalEndpointHandle(mojo::kMasterInterfaceId), + &stub_, + base::MakeUnique<typename mojom::Bootstrap::RequestValidator_>(), + false, base::ThreadTaskRunnerHandle::Get())); + } + + private: + mojom::BootstrapStub stub_; + scoped_refptr<ChannelAssociatedGroupController> controller_; + std::unique_ptr<mojo::InterfaceEndpointClient> endpoint_client_; + + DISALLOW_COPY_AND_ASSIGN(BootstrapMasterBinding); +}; + // MojoBootstrap for the server process. You should create the instance // using MojoBootstrap::Create(). class MojoServerBootstrap : public MojoBootstrap { @@ -30,10 +626,13 @@ private: // MojoBootstrap implementation. void Connect() override; + mojo::AssociatedGroup* GetAssociatedGroup() override { + return bootstrap_.associated_group(); + } void OnInitDone(int32_t peer_pid); - mojom::BootstrapPtr bootstrap_; + BootstrapMasterProxy bootstrap_; IPC::mojom::ChannelAssociatedPtrInfo send_channel_; IPC::mojom::ChannelAssociatedRequest receive_channel_request_; @@ -45,7 +644,7 @@ void MojoServerBootstrap::Connect() { DCHECK_EQ(state(), STATE_INITIALIZED); - bootstrap_.Bind(mojom::BootstrapPtrInfo(TakeHandle(), 0)); + bootstrap_.Bind(TakeHandle()); bootstrap_.set_connection_error_handler( base::Bind(&MojoServerBootstrap::Fail, base::Unretained(this))); @@ -89,6 +688,9 @@ private: // MojoBootstrap implementation. void Connect() override; + mojo::AssociatedGroup* GetAssociatedGroup() override { + return binding_.associated_group(); + } // mojom::Bootstrap implementation. void Init(mojom::ChannelAssociatedRequest receive_channel, @@ -96,7 +698,7 @@ int32_t peer_pid, const InitCallback& callback) override; - mojo::Binding<mojom::Bootstrap> binding_; + BootstrapMasterBinding binding_; DISALLOW_COPY_AND_ASSIGN(MojoClientBootstrap); };
diff --git a/ipc/ipc_mojo_bootstrap.h b/ipc/ipc_mojo_bootstrap.h index 312003a..1d632d3 100644 --- a/ipc/ipc_mojo_bootstrap.h +++ b/ipc/ipc_mojo_bootstrap.h
@@ -15,6 +15,7 @@ #include "ipc/ipc.mojom.h" #include "ipc/ipc_channel.h" #include "ipc/ipc_listener.h" +#include "mojo/public/cpp/bindings/associated_group.h" #include "mojo/public/cpp/system/message_pipe.h" namespace IPC { @@ -51,6 +52,8 @@ // Start the handshake over the underlying message pipe. virtual void Connect() = 0; + virtual mojo::AssociatedGroup* GetAssociatedGroup() = 0; + // GetSelfPID returns our PID. base::ProcessId GetSelfPID() const;
diff --git a/ipc/ipc_test.mojom b/ipc/ipc_test.mojom new file mode 100644 index 0000000..9c1b30e --- /dev/null +++ b/ipc/ipc_test.mojom
@@ -0,0 +1,10 @@ +// 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. + +module IPC.mojom; + +interface SimpleTestDriver { + ExpectString(string str); + RequestQuit() => (); +};
diff --git a/media/audio/BUILD.gn b/media/audio/BUILD.gn index 95846d7..4d1a8072 100644 --- a/media/audio/BUILD.gn +++ b/media/audio/BUILD.gn
@@ -351,6 +351,10 @@ "sounds/wav_audio_handler_unittest.cc", ] + if (!is_chromecast) { + deps += [ "//chromeos:chromeos" ] + } + if (use_cras) { sources += [ "cras/cras_input_unittest.cc",
diff --git a/media/audio/android/opensles_output.cc b/media/audio/android/opensles_output.cc index 87daa9c6..5dc916ae 100644 --- a/media/audio/android/opensles_output.cc +++ b/media/audio/android/opensles_output.cc
@@ -87,13 +87,11 @@ base::AutoLock lock(lock_); DCHECK(!callback_); callback_ = callback; - delay_calculator_.SetBaseTimestamp(base::TimeDelta()); // Fill audio data with silence to avoid start-up glitches. Don't use // FillBufferQueueNoLock() since it can trigger recursive entry if an error // occurs while writing into the stream. See http://crbug.com/624877. memset(audio_data_[active_buffer_index_], 0, buffer_size_bytes_); - delay_calculator_.AddFrames(audio_bus_->frames()); LOG_ON_FAILURE_AND_RETURN((*simple_buffer_queue_) ->Enqueue(simple_buffer_queue_, audio_data_[active_buffer_index_], @@ -106,6 +104,15 @@ LOG_ON_FAILURE_AND_RETURN( (*player_)->SetPlayState(player_, SL_PLAYSTATE_PLAYING)); + // On older version of Android, the position may not be reset even though we + // call Clear() during Stop(), in this case the best we can do is assume that + // we're continuing on from this previous position. + uint32_t position_in_ms = 0; + LOG_ON_FAILURE_AND_RETURN((*player_)->GetPosition(player_, &position_in_ms)); + delay_calculator_.SetBaseTimestamp( + base::TimeDelta::FromMilliseconds(position_in_ms)); + delay_calculator_.AddFrames(audio_bus_->frames()); + started_ = true; }
diff --git a/media/audio/audio_manager_unittest.cc b/media/audio/audio_manager_unittest.cc index 0f9e37a..27c5144 100644 --- a/media/audio/audio_manager_unittest.cc +++ b/media/audio/audio_manager_unittest.cc
@@ -10,6 +10,7 @@ #include "base/environment.h" #include "base/logging.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/synchronization/waitable_event.h" #include "base/test/test_message_loop.h" #include "base/threading/thread_task_runner_handle.h" @@ -36,6 +37,14 @@ #include "media/audio/pulse/audio_manager_pulse.h" #endif // defined(USE_PULSEAUDIO) +#if defined(USE_CRAS) +#include "chromeos/audio/audio_devices_pref_handler_stub.h" +#include "chromeos/audio/cras_audio_handler.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/fake_cras_audio_client.h" +#include "media/audio/cras/audio_manager_cras.h" +#endif // defined(USE_CRAS) + namespace media { namespace { @@ -69,6 +78,79 @@ return AudioManager::CreateForTesting(base::ThreadTaskRunnerHandle::Get()); } }; + +#if defined(USE_CRAS) +using chromeos::AudioNode; +using chromeos::AudioNodeList; + +const uint64_t kJabraSpeaker1Id = 30001; +const uint64_t kJabraSpeaker1StableDeviceId = 80001; +const uint64_t kJabraSpeaker2Id = 30002; +const uint64_t kJabraSpeaker2StableDeviceId = 80002; +const uint64_t kHDMIOutputId = 30003; +const uint64_t kHDMIOutputStabeDevicelId = 80003; +const uint64_t kJabraMic1Id = 40001; +const uint64_t kJabraMic1StableDeviceId = 90001; +const uint64_t kJabraMic2Id = 40002; +const uint64_t kJabraMic2StableDeviceId = 90002; +const uint64_t kWebcamMicId = 40003; +const uint64_t kWebcamMicStableDeviceId = 90003; + +const AudioNode kJabraSpeaker1(false, + kJabraSpeaker1Id, + kJabraSpeaker1StableDeviceId, + "Jabra Speaker", + "USB", + "Jabra Speaker 1", + false, + 0); + +const AudioNode kJabraSpeaker2(false, + kJabraSpeaker2Id, + kJabraSpeaker2StableDeviceId, + "Jabra Speaker", + "USB", + "Jabra Speaker 2", + false, + 0); + +const AudioNode kHDMIOutput(false, + kHDMIOutputId, + kHDMIOutputStabeDevicelId, + "HDMI output", + "HDMI", + "HDA Intel MID", + false, + 0); + +const AudioNode kJabraMic1(true, + kJabraMic1Id, + kJabraMic1StableDeviceId, + "Jabra Mic", + "USB", + "Jabra Mic 1", + false, + 0); + +const AudioNode kJabraMic2(true, + kJabraMic2Id, + kJabraMic2StableDeviceId, + "Jabra Mic", + "USB", + "Jabra Mic 2", + false, + 0); + +const AudioNode kUSBCameraMic(true, + kWebcamMicId, + kWebcamMicStableDeviceId, + "Webcam Mic", + "USB", + "Logitech Webcam", + false, + 0); +#endif // defined(USE_CRAS) + } // namespace // Test fixture which allows us to override the default enumeration API on @@ -115,6 +197,25 @@ audio_manager_->GetAssociatedOutputDeviceID(input_device_id); } +#if defined(USE_CRAS) + void TearDown() override { + chromeos::CrasAudioHandler::Shutdown(); + audio_pref_handler_ = nullptr; + chromeos::DBusThreadManager::Shutdown(); + } + + void SetUpCrasAudioHandlerWithTestingNodes(const AudioNodeList& audio_nodes) { + chromeos::DBusThreadManager::Initialize(); + audio_client_ = static_cast<chromeos::FakeCrasAudioClient*>( + chromeos::DBusThreadManager::Get()->GetCrasAudioClient()); + audio_client_->SetAudioNodesForTesting(audio_nodes); + audio_pref_handler_ = new chromeos::AudioDevicesPrefHandlerStub(); + chromeos::CrasAudioHandler::Initialize(audio_pref_handler_); + cras_audio_handler_ = chromeos::CrasAudioHandler::Get(); + base::RunLoop().RunUntilIdle(); + } +#endif // defined(USE_CRAS) + protected: AudioManagerTest() { CreateAudioManagerForTesting(); } ~AudioManagerTest() override {} @@ -185,6 +286,48 @@ } } +#if defined(USE_CRAS) + // Helper method for (USE_CRAS) which verifies that the device list starts + // with a valid default record followed by physical device names. + static void CheckDeviceNamesCras( + const AudioDeviceNames& device_names, + const std::map<uint64_t, std::string>& expectation) { + DVLOG(2) << "Got " << device_names.size() << " audio devices."; + if (!device_names.empty()) { + AudioDeviceNames::const_iterator it = device_names.begin(); + + // The first device in the list should always be the default device. + EXPECT_EQ(AudioDeviceDescription::GetDefaultDeviceName(), + it->device_name); + EXPECT_EQ(std::string(AudioDeviceDescription::kDefaultDeviceId), + it->unique_id); + + // |device_names|'size should be |expectation|'s size plus one because of + // default device. + EXPECT_EQ(device_names.size(), expectation.size() + 1); + ++it; + // Check other devices that should have non-empty name and id, and should + // be contained in expectation. + while (it != device_names.end()) { + EXPECT_FALSE(it->device_name.empty()); + EXPECT_FALSE(it->unique_id.empty()); + DVLOG(2) << "Device ID(" << it->unique_id + << "), label: " << it->device_name; + uint64_t key; + EXPECT_TRUE(base::StringToUint64(it->unique_id, &key)); + EXPECT_TRUE(expectation.find(key) != expectation.end()); + EXPECT_EQ(expectation.find(key)->second, it->device_name); + ++it; + } + } else { + // Log a warning so we can see the status on the build bots. No need to + // break the test though since this does successfully test the code and + // some failure cases. + LOG(WARNING) << "No input devices detected"; + } + } +#endif // defined(USE_CRAS) + bool InputDevicesAvailable() { return audio_manager_->HasAudioInputDevices(); } @@ -212,8 +355,67 @@ base::TestMessageLoop message_loop_; FakeAudioLogFactory fake_audio_log_factory_; ScopedAudioManagerPtr audio_manager_; + +#if defined(USE_CRAS) + chromeos::CrasAudioHandler* cras_audio_handler_ = nullptr; // Not owned. + chromeos::FakeCrasAudioClient* audio_client_ = nullptr; // Not owned. + scoped_refptr<chromeos::AudioDevicesPrefHandlerStub> audio_pref_handler_; +#endif // defined(USE_CRAS) }; +#if defined(USE_CRAS) +TEST_F(AudioManagerTest, EnumerateInputDevicesCras) { + // Setup the devices without internal mic, so that it doesn't exist + // beamforming capable mic. + AudioNodeList audio_nodes; + audio_nodes.push_back(kJabraMic1); + audio_nodes.push_back(kJabraMic2); + audio_nodes.push_back(kUSBCameraMic); + audio_nodes.push_back(kHDMIOutput); + audio_nodes.push_back(kJabraSpeaker1); + SetUpCrasAudioHandlerWithTestingNodes(audio_nodes); + + ABORT_AUDIO_TEST_IF_NOT(InputDevicesAvailable()); + + // Setup expectation with physical devices. + std::map<uint64_t, std::string> expectation; + expectation[kJabraMic1.id] = kJabraMic1.device_name; + expectation[kJabraMic2.id] = kJabraMic2.device_name; + expectation[kUSBCameraMic.id] = kUSBCameraMic.device_name; + + DVLOG(2) << "Testing AudioManagerCras."; + CreateAudioManagerForTesting<AudioManagerCras>(); + AudioDeviceNames device_names; + audio_manager_->GetAudioInputDeviceNames(&device_names); + CheckDeviceNamesCras(device_names, expectation); +} + +TEST_F(AudioManagerTest, EnumerateOutputDevicesCras) { + // Setup the devices without internal mic, so that it doesn't exist + // beamforming capable mic. + AudioNodeList audio_nodes; + audio_nodes.push_back(kJabraMic1); + audio_nodes.push_back(kJabraMic2); + audio_nodes.push_back(kUSBCameraMic); + audio_nodes.push_back(kHDMIOutput); + audio_nodes.push_back(kJabraSpeaker1); + SetUpCrasAudioHandlerWithTestingNodes(audio_nodes); + + ABORT_AUDIO_TEST_IF_NOT(OutputDevicesAvailable()); + + // Setup expectation with physical devices. + std::map<uint64_t, std::string> expectation; + expectation[kHDMIOutput.id] = kHDMIOutput.device_name; + expectation[kJabraSpeaker1.id] = kJabraSpeaker1.device_name; + + DVLOG(2) << "Testing AudioManagerCras."; + CreateAudioManagerForTesting<AudioManagerCras>(); + AudioDeviceNames device_names; + audio_manager_->GetAudioOutputDeviceNames(&device_names); + CheckDeviceNamesCras(device_names, expectation); +} +#else // !defined(USE_CRAS) + TEST_F(AudioManagerTest, HandleDefaultDeviceIDs) { // Use a fake manager so we can makeup device ids, this will still use the // AudioManagerBase code. @@ -431,5 +633,6 @@ EXPECT_TRUE(found_an_associated_device); #endif // defined(OS_WIN) || defined(OS_MACOSX) } +#endif // defined(USE_CRAS) } // namespace media
diff --git a/media/audio/cras/audio_manager_cras.cc b/media/audio/cras/audio_manager_cras.cc index 7fdf072..a2f0cd3 100644 --- a/media/audio/cras/audio_manager_cras.cc +++ b/media/audio/cras/audio_manager_cras.cc
@@ -15,6 +15,7 @@ #include "base/metrics/histogram.h" #include "base/nix/xdg_util.h" #include "base/stl_util.h" +#include "base/strings/string_number_conversions.h" #include "chromeos/audio/audio_device.h" #include "chromeos/audio/cras_audio_handler.h" #include "media/audio/audio_device_description.h" @@ -65,13 +66,6 @@ "Enabled"; } -void AddDefaultDevice(AudioDeviceNames* device_names) { - DCHECK(device_names->empty()); - - // Cras will route audio from a proper physical device automatically. - device_names->push_back(AudioDeviceName::CreateDefault()); -} - // Returns a mic positions string if the machine has a beamforming capable // internal mic and otherwise an empty string. std::string MicPositions() { @@ -155,23 +149,35 @@ NOTIMPLEMENTED(); } -void AudioManagerCras::GetAudioInputDeviceNames( - AudioDeviceNames* device_names) { +void AudioManagerCras::GetAudioDeviceNamesImpl(bool is_input, + AudioDeviceNames* device_names) { DCHECK(device_names->empty()); - - mic_positions_ = ParsePointsFromString(MicPositions()); // At least two mic positions indicates we have a beamforming capable mic // array. Add the virtual beamforming device to the list. When this device is // queried through GetInputStreamParameters, provide the cached mic positions. - if (mic_positions_.size() > 1) + if (is_input && mic_positions_.size() > 1) AddBeamformingDevices(device_names); else - AddDefaultDevice(device_names); + device_names->push_back(media::AudioDeviceName::CreateDefault()); + chromeos::AudioDeviceList devices; + chromeos::CrasAudioHandler::Get()->GetAudioDevices(&devices); + for (const auto& device : devices) { + if (device.is_input == is_input && device.is_for_simple_usage()) { + device_names->emplace_back(device.display_name, + base::Uint64ToString(device.id)); + } + } +} + +void AudioManagerCras::GetAudioInputDeviceNames( + AudioDeviceNames* device_names) { + mic_positions_ = ParsePointsFromString(MicPositions()); + GetAudioDeviceNamesImpl(true, device_names); } void AudioManagerCras::GetAudioOutputDeviceNames( AudioDeviceNames* device_names) { - AddDefaultDevice(device_names); + GetAudioDeviceNamesImpl(false, device_names); } AudioParameters AudioManagerCras::GetInputStreamParameters(
diff --git a/media/audio/cras/audio_manager_cras.h b/media/audio/cras/audio_manager_cras.h index ae80f8c..ec739468 100644 --- a/media/audio/cras/audio_manager_cras.h +++ b/media/audio/cras/audio_manager_cras.h
@@ -66,6 +66,8 @@ AudioInputStream* MakeInputStream(const AudioParameters& params, const std::string& device_id); + void GetAudioDeviceNamesImpl(bool is_input, AudioDeviceNames* device_names); + void AddBeamformingDevices(AudioDeviceNames* device_names); // Stores the mic positions field from the device.
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn index 17eaec1..ccda689 100644 --- a/media/base/BUILD.gn +++ b/media/base/BUILD.gn
@@ -129,6 +129,7 @@ "eme_constants.h", "encryption_scheme.cc", "encryption_scheme.h", + "feedback_signal_accumulator.h", "key_system_names.cc", "key_system_names.h", "key_system_properties.cc", @@ -449,6 +450,7 @@ "decoder_buffer_unittest.cc", "djb2_unittest.cc", "fake_demuxer_stream_unittest.cc", + "feedback_signal_accumulator_unittest.cc", "gmock_callback_support_unittest.cc", "key_systems_unittest.cc", "mime_util_unittest.cc",
diff --git a/media/base/android/media_codec_loop.cc b/media/base/android/media_codec_loop.cc index 7a8132b..ab13717e 100644 --- a/media/base/android/media_codec_loop.cc +++ b/media/base/android/media_codec_loop.cc
@@ -38,7 +38,6 @@ iv(other.iv), subsamples(other.subsamples), presentation_time(other.presentation_time), - completion_cb(other.completion_cb), is_eos(other.is_eos), is_encrypted(other.is_encrypted) {} @@ -56,7 +55,9 @@ SetState(STATE_ERROR); } -MediaCodecLoop::~MediaCodecLoop() {} +MediaCodecLoop::~MediaCodecLoop() { + io_timer_.Stop(); +} void MediaCodecLoop::OnKeyAdded() { if (state_ == STATE_WAITING_FOR_KEY) @@ -70,7 +71,7 @@ // For decoder reset, then it is appropriate. Otherwise, the requests might // simply be sent to us later, such as on a format change. - // STATE_DRAINED seems like it allow flush, but it causes test failures. + // STATE_DRAINED seems like it allows flush, but it causes test failures. // crbug.com/624878 if (state_ == STATE_ERROR || state_ == STATE_DRAINED) return false; @@ -183,10 +184,7 @@ if (input_data.is_eos) { media_codec_->QueueEOS(input_buffer.index); SetState(STATE_DRAINING); - - // For EOS, the completion callback is called when the EOS arrives at the - // output queue. - pending_eos_completion_cb_ = input_data.completion_cb; + client_->OnInputDataQueued(true); return; } @@ -211,7 +209,7 @@ case MEDIA_CODEC_ERROR: DLOG(ERROR) << __FUNCTION__ << ": MEDIA_CODEC_ERROR from QueueInputBuffer"; - input_data.completion_cb.Run(DecodeStatus::DECODE_ERROR); + client_->OnInputDataQueued(false); // Transition to the error state after running the completion cb, to keep // it in order if the client chooses to flush its queue. SetState(STATE_ERROR); @@ -227,15 +225,16 @@ // guarantee that the pointer will remain valid after we return anyway. pending_input_buf_data_.memory = nullptr; SetState(STATE_WAITING_FOR_KEY); + // Do not call OnInputDataQueued yet. break; case MEDIA_CODEC_OK: - input_data.completion_cb.Run(DecodeStatus::OK); + client_->OnInputDataQueued(true); break; default: NOTREACHED() << "Unknown Queue(Secure)InputBuffer status " << status; - input_data.completion_cb.Run(DecodeStatus::DECODE_ERROR); + client_->OnInputDataQueued(false); SetState(STATE_ERROR); break; } @@ -277,11 +276,6 @@ media_codec_->ReleaseOutputBuffer(out.index, false); - // Run the EOS completion callback now, since we deferred it until - // the EOS was completely processed. - pending_eos_completion_cb_.Run(DecodeStatus::OK); - pending_eos_completion_cb_ = DecodeCB(); - client_->OnDecodedEos(out); } else { if (!client_->OnDecodedFrame(out))
diff --git a/media/base/android/media_codec_loop.h b/media/base/android/media_codec_loop.h index 6889f8e..8d257dea 100644 --- a/media/base/android/media_codec_loop.h +++ b/media/base/android/media_codec_loop.h
@@ -126,9 +126,6 @@ base::TimeDelta presentation_time; - // Called when this is queued. - DecodeCB completion_cb; - bool is_eos = false; bool is_encrypted = false; }; @@ -162,13 +159,21 @@ // Return true if and only if there is input that is pending to be // queued with MediaCodec. ProvideInputData() will not be called more than // once in response to this returning true once. It is not guaranteed that - // ProvideInputData will be called at all. + // ProvideInputData will be called at all. If ProvideInputData is called, + // then OnInputDataQueued will also be called before calling again. virtual bool IsAnyInputPending() const = 0; // Fills and returns an input buffer for MediaCodecLoop to queue. It is // an error for MediaCodecLoop to call this while !IsAnyInputPending(). virtual InputData ProvideInputData() = 0; + // Called to notify the client that the previous data (or eos) provided by + // ProvideInputData has been queued with the codec. IsAnyInputPending and + // ProvideInputData will not be called again until this is called. + // Note that if the codec is flushed while a call back is pending, then that + // call back won't happen. + virtual void OnInputDataQueued(bool success) = 0; + // Called when an EOS buffer is dequeued from the output. virtual void OnDecodedEos(const OutputBuffer& out) = 0; @@ -205,6 +210,9 @@ // Try to flush this media codec. Returns true on success, false on failure. // Failures can result in a state change to the Error state. If this returns // false but the state is still READY, then the codec may continue to be used. + // In that case, we may still call back into the client for decoding later. + // The client must handle this case if it really does want to switch codecs. + // If it immediately destroys us, then that's fine. bool TryFlush(); // This should be called when a new key is added. Decoding will resume if it @@ -293,10 +301,6 @@ // to us by the client. |memory| has been cleared, since the codec has it. InputData pending_input_buf_data_; - // When an EOS is queued, we defer its completion callback until the EOS - // arrives at the output queue. This is valid when we're in STATE_DRAINING. - DecodeCB pending_eos_completion_cb_; - // NOTE: Weak pointers must be invalidated before all other member variables. base::WeakPtrFactory<MediaCodecLoop> weak_factory_;
diff --git a/media/base/android/media_codec_loop_unittest.cc b/media/base/android/media_codec_loop_unittest.cc index b29d109..2b08fe0e 100644 --- a/media/base/android/media_codec_loop_unittest.cc +++ b/media/base/android/media_codec_loop_unittest.cc
@@ -15,6 +15,7 @@ public: MOCK_CONST_METHOD0(IsAnyInputPending, bool()); MOCK_METHOD0(ProvideInputData, MediaCodecLoop::InputData()); + MOCK_METHOD1(OnInputDataQueued, void(bool)); MOCK_METHOD1(OnDecodedEos, void(const MediaCodecLoop::OutputBuffer&)); MOCK_METHOD1(OnDecodedFrame, bool(const MediaCodecLoop::OutputBuffer&)); MOCK_METHOD0(OnOutputFormatChanged, bool());
diff --git a/media/base/feedback_signal_accumulator.h b/media/base/feedback_signal_accumulator.h new file mode 100644 index 0000000..1acc6998 --- /dev/null +++ b/media/base/feedback_signal_accumulator.h
@@ -0,0 +1,108 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_BASE_FEEDBACK_SIGNAL_ACCUMULATOR_H_ +#define MEDIA_BASE_FEEDBACK_SIGNAL_ACCUMULATOR_H_ + +#include "base/time/time.h" + +namespace media { + +// Utility class for maintaining an exponentially-decaying average of feedback +// signal values whose updates occur at undetermined, possibly irregular time +// intervals. +// +// Feedback signals can be made by multiple sources. Meaning, there can be +// several values provided for the same timestamp. In this case, the greatest +// value is retained and used to re-compute the average. Therefore, the values +// provided to this class' methods should be appropriately translated with this +// in mind. For example, an "fraction available" metric should be translated +// into a "fraction utilized" one. +// +// Usage note: Reset() must be called at least once before the first call to +// Update(). +// +// This template class supports data points that are timestamped using either +// |base::TimeDelta| or |base::TimeTicks|. +template <typename TimeType> +class FeedbackSignalAccumulator { + public: + // |half_life| is the amount of time that must pass between two data points to + // move the accumulated average value halfway in-between. Example: If + // |half_life| is one second, then calling Reset(0.0, t=0s) and then + // Update(1.0, t=1s) will result in an accumulated average value of 0.5. + explicit FeedbackSignalAccumulator(base::TimeDelta half_life) + : half_life_(half_life), average_(NAN) { + DCHECK(half_life_ > base::TimeDelta()); + } + + // Erase all memory of historical values, re-starting with the given + // |starting_value|. + void Reset(double starting_value, TimeType timestamp) { + average_ = update_value_ = prior_average_ = starting_value; + reset_time_ = update_time_ = prior_update_time_ = timestamp; + } + + TimeType reset_time() const { return reset_time_; } + + // Apply the given |value|, which was observed at the given |timestamp|, to + // the accumulated average. If the timestamp is in chronological order, the + // update succeeds and this method returns true. Otherwise the update has no + // effect and false is returned. If there are two or more updates at the same + // |timestamp|, only the one with the greatest value will be accounted for + // (see class comments for elaboration). + bool Update(double value, TimeType timestamp) { + DCHECK(!std::isnan(average_)) << "Reset() must be called once."; + + if (timestamp < update_time_) { + return false; // Not in chronological order. + } else if (timestamp == update_time_) { + if (timestamp == reset_time_) { + // Edge case: Multiple updates at reset timestamp. + average_ = update_value_ = prior_average_ = + std::max(value, update_value_); + return true; + } + if (value <= update_value_) + return true; + update_value_ = value; + } else { + prior_average_ = average_; + prior_update_time_ = update_time_; + update_value_ = value; + update_time_ = timestamp; + } + + const double elapsed_us = static_cast<double>( + (update_time_ - prior_update_time_).InMicroseconds()); + const double weight = + elapsed_us / (elapsed_us + half_life_.InMicroseconds()); + average_ = weight * update_value_ + (1.0 - weight) * prior_average_; + DCHECK(std::isfinite(average_)); + + return true; + } + + TimeType update_time() const { return update_time_; } + + // Returns the current accumulated average value. + double current() const { return average_; } + + private: + // In conjunction with the |update_time_| and |prior_update_time_|, this is + // used to compute the weight of the current update value versus the prior + // accumulated average. + const base::TimeDelta half_life_; + + TimeType reset_time_; // |timestamp| passed in last call to Reset(). + double average_; // Current accumulated average. + double update_value_; // Latest |value| accepted by Update(). + TimeType update_time_; // Latest |timestamp| accepted by Update(). + double prior_average_; // Accumulated average before last call to Update(). + TimeType prior_update_time_; // |timestamp| in prior call to Update(). +}; + +} // namespace media + +#endif // MEDIA_BASE_FEEDBACK_SIGNAL_ACCUMULATOR_H_
diff --git a/media/base/feedback_signal_accumulator_unittest.cc b/media/base/feedback_signal_accumulator_unittest.cc new file mode 100644 index 0000000..2a28fe7d --- /dev/null +++ b/media/base/feedback_signal_accumulator_unittest.cc
@@ -0,0 +1,202 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/feedback_signal_accumulator.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +class FeedbackSignalAccumulatorTest : public ::testing::Test { + public: + FeedbackSignalAccumulatorTest() + : half_life_(base::TimeDelta::FromSeconds(1)), + acc_(half_life_), + t_(base::TimeTicks() + base::TimeDelta::FromSeconds(120)) { + acc_.Reset(0.0, t_); + } + + protected: + const base::TimeDelta half_life_; + FeedbackSignalAccumulator<base::TimeTicks> acc_; + base::TimeTicks t_; +}; + +TEST_F(FeedbackSignalAccumulatorTest, HasCorrectStartingValueAfterReset) { + ASSERT_EQ(0.0, acc_.current()); + ASSERT_EQ(t_, acc_.reset_time()); + ASSERT_EQ(t_, acc_.update_time()); + + acc_.Reset(1.0, t_); + ASSERT_EQ(1.0, acc_.current()); + ASSERT_EQ(t_, acc_.reset_time()); + ASSERT_EQ(t_, acc_.update_time()); + + t_ += half_life_; + acc_.Reset(2.0, t_); + ASSERT_EQ(2.0, acc_.current()); + ASSERT_EQ(t_, acc_.reset_time()); + ASSERT_EQ(t_, acc_.update_time()); +} + +TEST_F(FeedbackSignalAccumulatorTest, DoesNotUpdateIfBeforeResetTime) { + acc_.Reset(0.0, t_); + ASSERT_EQ(0.0, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + + const base::TimeTicks one_usec_before = + t_ - base::TimeDelta::FromMicroseconds(1); + ASSERT_FALSE(acc_.Update(1.0, one_usec_before)); + ASSERT_EQ(0.0, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + + const base::TimeTicks one_usec_after = + t_ + base::TimeDelta::FromMicroseconds(1); + ASSERT_TRUE(acc_.Update(1.0, one_usec_after)); + ASSERT_LT(0.0, acc_.current()); + ASSERT_EQ(one_usec_after, acc_.update_time()); +} + +TEST_F(FeedbackSignalAccumulatorTest, TakesMaxOfUpdatesAtResetTime) { + acc_.Reset(0.0, t_); + ASSERT_EQ(0.0, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + + ASSERT_TRUE(acc_.Update(1.0, t_)); + ASSERT_EQ(1.0, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + + ASSERT_TRUE(acc_.Update(2.0, t_)); + ASSERT_EQ(2.0, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + + ASSERT_TRUE(acc_.Update(1.0, t_)); + ASSERT_EQ(2.0, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); +} + +TEST_F(FeedbackSignalAccumulatorTest, AppliesMaxOfUpdatesWithSameTimestamp) { + acc_.Reset(0.0, t_); + ASSERT_EQ(0.0, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + t_ += 1 * half_life_; + + // Update with an identical value at the same timestamp. + for (int i = 0; i < 3; ++i) { + ASSERT_TRUE(acc_.Update(1.0, t_)); + ASSERT_EQ(0.5, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + } + + // Now continue updating with different values at the same timestamp. + ASSERT_TRUE(acc_.Update(2.0, t_)); + ASSERT_EQ(1.0, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + ASSERT_TRUE(acc_.Update(3.0, t_)); + ASSERT_EQ(1.5, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + ASSERT_TRUE(acc_.Update(1.0, t_)); + ASSERT_EQ(1.5, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); +} + +TEST_F(FeedbackSignalAccumulatorTest, ProvidesExpectedHoldResponse) { + // Step one half-life interval per update. + acc_.Reset(0.0, t_); + ASSERT_EQ(0.0, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + t_ += 1 * half_life_; + ASSERT_TRUE(acc_.Update(1.0, t_)); + ASSERT_EQ(0.5, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + t_ += 1 * half_life_; + ASSERT_TRUE(acc_.Update(1.0, t_)); + ASSERT_EQ(0.75, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + t_ += 1 * half_life_; + ASSERT_TRUE(acc_.Update(1.0, t_)); + ASSERT_EQ(0.875, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + t_ += 1 * half_life_; + ASSERT_TRUE(acc_.Update(1.0, t_)); + ASSERT_EQ(0.9375, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + + // Step two half-life intervals per update. + acc_.Reset(0.0, t_); + ASSERT_EQ(0.0, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + t_ += 2 * half_life_; + ASSERT_TRUE(acc_.Update(1.0, t_)); + ASSERT_NEAR(0.666666667, acc_.current(), 0.000000001); + ASSERT_EQ(t_, acc_.update_time()); + t_ += 2 * half_life_; + ASSERT_TRUE(acc_.Update(1.0, t_)); + ASSERT_NEAR(0.888888889, acc_.current(), 0.000000001); + ASSERT_EQ(t_, acc_.update_time()); + t_ += 2 * half_life_; + ASSERT_TRUE(acc_.Update(1.0, t_)); + ASSERT_NEAR(0.962962963, acc_.current(), 0.000000001); + ASSERT_EQ(t_, acc_.update_time()); + t_ += 2 * half_life_; + ASSERT_TRUE(acc_.Update(1.0, t_)); + ASSERT_NEAR(0.987654321, acc_.current(), 0.000000001); + ASSERT_EQ(t_, acc_.update_time()); + + // Step three half-life intervals per update. + acc_.Reset(0.0, t_); + ASSERT_EQ(0.0, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + t_ += 3 * half_life_; + ASSERT_TRUE(acc_.Update(1.0, t_)); + ASSERT_EQ(0.75, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + t_ += 3 * half_life_; + ASSERT_TRUE(acc_.Update(1.0, t_)); + ASSERT_EQ(0.9375, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + t_ += 3 * half_life_; + ASSERT_TRUE(acc_.Update(1.0, t_)); + ASSERT_EQ(0.984375, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + t_ += 3 * half_life_; + ASSERT_TRUE(acc_.Update(1.0, t_)); + ASSERT_EQ(0.99609375, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); +} + +TEST_F(FeedbackSignalAccumulatorTest, IgnoresUpdatesThatAreOutOfOrder) { + // First, go forward several steps, in order. + acc_.Reset(0.0, t_); + ASSERT_EQ(0.0, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + t_ += 1 * half_life_; + ASSERT_TRUE(acc_.Update(2.0, t_)); + ASSERT_EQ(1.0, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + t_ += 1 * half_life_; + ASSERT_TRUE(acc_.Update(2.0, t_)); + ASSERT_EQ(1.5, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + t_ += 1 * half_life_; + ASSERT_TRUE(acc_.Update(2.0, t_)); + ASSERT_EQ(1.75, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + t_ += 1 * half_life_; + ASSERT_TRUE(acc_.Update(2.0, t_)); + ASSERT_EQ(1.875, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + + // Go back 1 steps, then 1.5, then 2, then 2.5, etc. and expect the update to + // fail each time. + base::TimeTicks earlier = t_ - 1 * half_life_; + for (int i = 0; i < 5; ++i) { + ASSERT_FALSE(acc_.Update(999.0, earlier)); + ASSERT_EQ(1.875, acc_.current()); + ASSERT_EQ(t_, acc_.update_time()); + earlier -= half_life_ / 2; + } +} + +} // namespace media
diff --git a/media/base/key_systems.cc b/media/base/key_systems.cc index e970f0a4..4567bf4c 100644 --- a/media/base/key_systems.cc +++ b/media/base/key_systems.cc
@@ -169,10 +169,8 @@ // can use the "x-" prefix to avoid conflicting with and advertising support // for real key system names. Use is discouraged. const char kExcludedPrefix[] = "x-"; - if (key_system.find(kExcludedPrefix, 0, arraysize(kExcludedPrefix) - 1) == 0) - return true; - - return false; + return base::StartsWith(key_system, kExcludedPrefix, + base::CompareCase::SENSITIVE); } class KeySystemsImpl : public KeySystems {
diff --git a/media/base/mac/avfoundation_glue.h b/media/base/mac/avfoundation_glue.h index fb76958ae..a5b4304 100644 --- a/media/base/mac/avfoundation_glue.h +++ b/media/base/mac/avfoundation_glue.h
@@ -2,9 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// TODO(mcasas): Remove this whole glue, https://crbug.com/579648. This glue was -// introduced to support Mac OS X <= 10.6 where AVFoundation was not available, -// and had to happen in runtime. +// AVFoundation API is only introduced in Mac OS X > 10.6, and there is only one +// build of Chromium, so the (potential) linking with AVFoundation has to happen +// in runtime. For this to be clean, an AVFoundationGlue class is defined to try +// and load these AVFoundation system libraries. If it succeeds, subsequent +// clients can use AVFoundation via the rest of the classes declared in this +// file. #ifndef MEDIA_BASE_MAC_AVFOUNDATION_GLUE_H_ #define MEDIA_BASE_MAC_AVFOUNDATION_GLUE_H_ @@ -48,7 +51,6 @@ static Class AVCaptureSessionClass(); static Class AVCaptureVideoDataOutputClass(); - static Class AVCaptureStillImageOutputClass(); #endif // defined(__OBJC__) private: @@ -93,9 +95,6 @@ MEDIA_EXPORT @interface CrAVCaptureOutput : NSObject // Originally from AVCaptureOutput.h. - -- (NSArray*)connections; - @end // Originally AVCaptureSession and coming from AVCaptureSession.h. @@ -105,7 +104,6 @@ - (void)release; - (void)addInput:(CrAVCaptureInput*)input; - (void)removeInput:(CrAVCaptureInput*)input; -- (NSArray*)outputs; - (void)addOutput:(CrAVCaptureOutput*)output; - (void)removeOutput:(CrAVCaptureOutput*)output; - (BOOL)isRunning; @@ -158,17 +156,6 @@ @end -// Originally AVCaptureStillImageOutput and coming from AVCaptureOutput.h. -MEDIA_EXPORT -@interface CrAVCaptureStillImageOutput : CrAVCaptureOutput - -typedef void (^CompletionHandler)(CoreMediaGlue::CMSampleBufferRef, NSError*); -- (void) -captureStillImageAsynchronouslyFromConnection:(CrAVCaptureConnection*)connection - completionHandler:(CompletionHandler)handler; - -@end - // Class to provide access to class methods of AVCaptureDevice. MEDIA_EXPORT @interface AVCaptureDeviceGlue : NSObject
diff --git a/media/base/mac/avfoundation_glue.mm b/media/base/mac/avfoundation_glue.mm index 4bd6d72..56f51aa 100644 --- a/media/base/mac/avfoundation_glue.mm +++ b/media/base/mac/avfoundation_glue.mm
@@ -167,10 +167,6 @@ return [AVFoundationBundle() classNamed:@"AVCaptureVideoDataOutput"]; } -Class AVFoundationGlue::AVCaptureStillImageOutputClass() { - return [AVFoundationBundle() classNamed:@"AVCaptureStillImageOutput"]; -} - @implementation AVCaptureDeviceGlue + (NSArray*)devices {
diff --git a/media/base/mac/coremedia_glue.h b/media/base/mac/coremedia_glue.h index 093427cd..9f69f96f 100644 --- a/media/base/mac/coremedia_glue.h +++ b/media/base/mac/coremedia_glue.h
@@ -52,7 +52,6 @@ kCMPixelFormat_422YpCbCr8_yuvs = 'yuvs', }; enum { - kCMVideoCodecType_JPEG = 'jpeg', kCMVideoCodecType_JPEG_OpenDML = 'dmb1', kCMVideoCodecType_H264 = 'avc1', };
diff --git a/media/blink/multibuffer_data_source_unittest.cc b/media/blink/multibuffer_data_source_unittest.cc index db4edbe..ec1b6ab 100644 --- a/media/blink/multibuffer_data_source_unittest.cc +++ b/media/blink/multibuffer_data_source_unittest.cc
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "media/base/media_log.h" #include "media/base/mock_filters.h" #include "media/base/test_helpers.h" @@ -1425,4 +1426,26 @@ Stop(); } +TEST_F(MultibufferDataSourceTest, FileSizeLessThanBlockSize) { + Initialize(kHttpUrl, true); + GURL gurl(kHttpUrl); + blink::WebURLResponse response(gurl); + response.setHTTPStatusCode(200); + response.setHTTPHeaderField( + WebString::fromUTF8("Content-Length"), + WebString::fromUTF8(base::Int64ToString(kDataSize / 2))); + response.setExpectedContentLength(kDataSize / 2); + Respond(response); + EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize / 2)); + EXPECT_CALL(host_, SetTotalBytes(kDataSize / 2)); + EXPECT_CALL(host_, AddBufferedByteRange(0, kDataSize * 2)); + ReceiveData(kDataSize / 2); + FinishLoading(); + + int64_t len = 0; + EXPECT_TRUE(data_source_->GetSize(&len)); + EXPECT_EQ(kDataSize / 2, len); + Stop(); +} + } // namespace media
diff --git a/media/blink/resource_multibuffer_data_provider.cc b/media/blink/resource_multibuffer_data_provider.cc index d8f3458..c07cf86 100644 --- a/media/blink/resource_multibuffer_data_provider.cc +++ b/media/blink/resource_multibuffer_data_provider.cc
@@ -72,8 +72,11 @@ request.setRequestContext(WebURLRequest::RequestContextVideo); DVLOG(1) << __FUNCTION__ << " @ " << byte_pos(); - if (url_data_->length() > 0) { - DCHECK_LT(byte_pos(), url_data_->length()) << " " << url_data_->url(); + if (url_data_->length() > 0 && byte_pos() >= url_data_->length()) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&ResourceMultiBufferDataProvider::Terminate, + weak_factory_.GetWeakPtr())); + return; } request.setHTTPHeaderField( @@ -403,8 +406,6 @@ // If we didn't know the |instance_size_| we do now. int64_t size = byte_pos(); - if (!fifo_.empty()) - size += fifo_.back()->data_size(); // This request reports something smaller than what we've seen in the past, // Maybe it's transient error? @@ -501,6 +502,11 @@ return true; } +void ResourceMultiBufferDataProvider::Terminate() { + fifo_.push_back(DataBuffer::CreateEOSBuffer()); + url_data_->multibuffer()->OnDataProviderEvent(this); +} + int64_t ResourceMultiBufferDataProvider::byte_pos() const { int64_t ret = pos_; ret += fifo_.size();
diff --git a/media/blink/resource_multibuffer_data_provider.h b/media/blink/resource_multibuffer_data_provider.h index 963bb28..d08fb34d 100644 --- a/media/blink/resource_multibuffer_data_provider.h +++ b/media/blink/resource_multibuffer_data_provider.h
@@ -75,6 +75,9 @@ friend class ResourceMultiBufferDataProviderTest; friend class MockBufferedDataSource; + // Callback used when we're asked to fetch data after the end of the file. + void Terminate(); + // Parse a Content-Range header into its component pieces and return true if // each of the expected elements was found & parsed correctly. // |*instance_size| may be set to kPositionNotSpecified if the range ends in
diff --git a/media/capture/BUILD.gn b/media/capture/BUILD.gn index 70f2871d..e732807 100644 --- a/media/capture/BUILD.gn +++ b/media/capture/BUILD.gn
@@ -14,7 +14,6 @@ "content/animated_content_sampler.h", "content/capture_resolution_chooser.cc", "content/capture_resolution_chooser.h", - "content/feedback_signal_accumulator.h", "content/screen_capture_device_core.cc", "content/screen_capture_device_core.h", "content/smooth_event_sampler.cc", @@ -152,7 +151,6 @@ sources = [ "content/animated_content_sampler_unittest.cc", "content/capture_resolution_chooser_unittest.cc", - "content/feedback_signal_accumulator_unittest.cc", "content/smooth_event_sampler_unittest.cc", "content/video_capture_oracle_unittest.cc", "system_message_window_win_unittest.cc",
diff --git a/media/capture/capture.gyp b/media/capture/capture.gyp index 097167a8..b634f95 100644 --- a/media/capture/capture.gyp +++ b/media/capture/capture.gyp
@@ -11,7 +11,6 @@ 'content/animated_content_sampler.h', 'content/capture_resolution_chooser.cc', 'content/capture_resolution_chooser.h', - 'content/feedback_signal_accumulator.h', 'content/screen_capture_device_core.cc', 'content/screen_capture_device_core.h', 'content/smooth_event_sampler.cc', @@ -81,7 +80,6 @@ 'capture_unittests_sources': [ 'content/animated_content_sampler_unittest.cc', 'content/capture_resolution_chooser_unittest.cc', - 'content/feedback_signal_accumulator_unittest.cc', 'content/smooth_event_sampler_unittest.cc', 'content/video_capture_oracle_unittest.cc', 'system_message_window_win_unittest.cc',
diff --git a/media/capture/content/feedback_signal_accumulator.h b/media/capture/content/feedback_signal_accumulator.h deleted file mode 100644 index 33873f1..0000000 --- a/media/capture/content/feedback_signal_accumulator.h +++ /dev/null
@@ -1,109 +0,0 @@ -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_CAPTURE_CONTENT_FEEDBACK_SIGNAL_ACCUMULATOR_H_ -#define MEDIA_CAPTURE_CONTENT_FEEDBACK_SIGNAL_ACCUMULATOR_H_ - -#include "base/time/time.h" -#include "media/capture/capture_export.h" - -namespace media { - -// Utility class for maintaining an exponentially-decaying average of feedback -// signal values whose updates occur at undetermined, possibly irregular time -// intervals. -// -// Feedback signals can be made by multiple sources. Meaning, there can be -// several values provided for the same timestamp. In this case, the greatest -// value is retained and used to re-compute the average. Therefore, the values -// provided to this class' methods should be appropriately translated with this -// in mind. For example, an "fraction available" metric should be translated -// into a "fraction utilized" one. -// -// Usage note: Reset() must be called at least once before the first call to -// Update(). -// -// This template class supports data points that are timestamped using either -// |base::TimeDelta| or |base::TimeTicks|. -template <typename TimeType> -class FeedbackSignalAccumulator { - public: - // |half_life| is the amount of time that must pass between two data points to - // move the accumulated average value halfway in-between. Example: If - // |half_life| is one second, then calling Reset(0.0, t=0s) and then - // Update(1.0, t=1s) will result in an accumulated average value of 0.5. - explicit FeedbackSignalAccumulator(base::TimeDelta half_life) - : half_life_(half_life), average_(NAN) { - DCHECK(half_life_ > base::TimeDelta()); - } - - // Erase all memory of historical values, re-starting with the given - // |starting_value|. - void Reset(double starting_value, TimeType timestamp) { - average_ = update_value_ = prior_average_ = starting_value; - reset_time_ = update_time_ = prior_update_time_ = timestamp; - } - - TimeType reset_time() const { return reset_time_; } - - // Apply the given |value|, which was observed at the given |timestamp|, to - // the accumulated average. If the timestamp is in chronological order, the - // update succeeds and this method returns true. Otherwise the update has no - // effect and false is returned. If there are two or more updates at the same - // |timestamp|, only the one with the greatest value will be accounted for - // (see class comments for elaboration). - bool Update(double value, TimeType timestamp) { - DCHECK(!std::isnan(average_)) << "Reset() must be called once."; - - if (timestamp < update_time_) { - return false; // Not in chronological order. - } else if (timestamp == update_time_) { - if (timestamp == reset_time_) { - // Edge case: Multiple updates at reset timestamp. - average_ = update_value_ = prior_average_ = - std::max(value, update_value_); - return true; - } - if (value <= update_value_) - return true; - update_value_ = value; - } else { - prior_average_ = average_; - prior_update_time_ = update_time_; - update_value_ = value; - update_time_ = timestamp; - } - - const double elapsed_us = static_cast<double>( - (update_time_ - prior_update_time_).InMicroseconds()); - const double weight = - elapsed_us / (elapsed_us + half_life_.InMicroseconds()); - average_ = weight * update_value_ + (1.0 - weight) * prior_average_; - DCHECK(std::isfinite(average_)); - - return true; - } - - TimeType update_time() const { return update_time_; } - - // Returns the current accumulated average value. - double current() const { return average_; } - - private: - // In conjunction with the |update_time_| and |prior_update_time_|, this is - // used to compute the weight of the current update value versus the prior - // accumulated average. - const base::TimeDelta half_life_; - - TimeType reset_time_; // |timestamp| passed in last call to Reset(). - double average_; // Current accumulated average. - double update_value_; // Latest |value| accepted by Update(). - TimeType update_time_; // Latest |timestamp| accepted by Update(). - double prior_average_; // Accumulated average before last call to Update(). - TimeType prior_update_time_; // |timestamp| in prior call to Update(). -}; - -} // namespace media - -#endif // MEDIA_CAPTURE_CONTENT_FEEDBACK_SIGNAL_ACCUMULATOR_H_
diff --git a/media/capture/content/feedback_signal_accumulator_unittest.cc b/media/capture/content/feedback_signal_accumulator_unittest.cc deleted file mode 100644 index 7195a367..0000000 --- a/media/capture/content/feedback_signal_accumulator_unittest.cc +++ /dev/null
@@ -1,202 +0,0 @@ -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/capture/content/feedback_signal_accumulator.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace media { - -class FeedbackSignalAccumulatorTest : public ::testing::Test { - public: - FeedbackSignalAccumulatorTest() - : half_life_(base::TimeDelta::FromSeconds(1)), - acc_(half_life_), - t_(base::TimeTicks() + base::TimeDelta::FromSeconds(120)) { - acc_.Reset(0.0, t_); - } - - protected: - const base::TimeDelta half_life_; - FeedbackSignalAccumulator<base::TimeTicks> acc_; - base::TimeTicks t_; -}; - -TEST_F(FeedbackSignalAccumulatorTest, HasCorrectStartingValueAfterReset) { - ASSERT_EQ(0.0, acc_.current()); - ASSERT_EQ(t_, acc_.reset_time()); - ASSERT_EQ(t_, acc_.update_time()); - - acc_.Reset(1.0, t_); - ASSERT_EQ(1.0, acc_.current()); - ASSERT_EQ(t_, acc_.reset_time()); - ASSERT_EQ(t_, acc_.update_time()); - - t_ += half_life_; - acc_.Reset(2.0, t_); - ASSERT_EQ(2.0, acc_.current()); - ASSERT_EQ(t_, acc_.reset_time()); - ASSERT_EQ(t_, acc_.update_time()); -} - -TEST_F(FeedbackSignalAccumulatorTest, DoesNotUpdateIfBeforeResetTime) { - acc_.Reset(0.0, t_); - ASSERT_EQ(0.0, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - - const base::TimeTicks one_usec_before = - t_ - base::TimeDelta::FromMicroseconds(1); - ASSERT_FALSE(acc_.Update(1.0, one_usec_before)); - ASSERT_EQ(0.0, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - - const base::TimeTicks one_usec_after = - t_ + base::TimeDelta::FromMicroseconds(1); - ASSERT_TRUE(acc_.Update(1.0, one_usec_after)); - ASSERT_LT(0.0, acc_.current()); - ASSERT_EQ(one_usec_after, acc_.update_time()); -} - -TEST_F(FeedbackSignalAccumulatorTest, TakesMaxOfUpdatesAtResetTime) { - acc_.Reset(0.0, t_); - ASSERT_EQ(0.0, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - - ASSERT_TRUE(acc_.Update(1.0, t_)); - ASSERT_EQ(1.0, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - - ASSERT_TRUE(acc_.Update(2.0, t_)); - ASSERT_EQ(2.0, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - - ASSERT_TRUE(acc_.Update(1.0, t_)); - ASSERT_EQ(2.0, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); -} - -TEST_F(FeedbackSignalAccumulatorTest, AppliesMaxOfUpdatesWithSameTimestamp) { - acc_.Reset(0.0, t_); - ASSERT_EQ(0.0, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - t_ += 1 * half_life_; - - // Update with an identical value at the same timestamp. - for (int i = 0; i < 3; ++i) { - ASSERT_TRUE(acc_.Update(1.0, t_)); - ASSERT_EQ(0.5, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - } - - // Now continue updating with different values at the same timestamp. - ASSERT_TRUE(acc_.Update(2.0, t_)); - ASSERT_EQ(1.0, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - ASSERT_TRUE(acc_.Update(3.0, t_)); - ASSERT_EQ(1.5, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - ASSERT_TRUE(acc_.Update(1.0, t_)); - ASSERT_EQ(1.5, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); -} - -TEST_F(FeedbackSignalAccumulatorTest, ProvidesExpectedHoldResponse) { - // Step one half-life interval per update. - acc_.Reset(0.0, t_); - ASSERT_EQ(0.0, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - t_ += 1 * half_life_; - ASSERT_TRUE(acc_.Update(1.0, t_)); - ASSERT_EQ(0.5, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - t_ += 1 * half_life_; - ASSERT_TRUE(acc_.Update(1.0, t_)); - ASSERT_EQ(0.75, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - t_ += 1 * half_life_; - ASSERT_TRUE(acc_.Update(1.0, t_)); - ASSERT_EQ(0.875, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - t_ += 1 * half_life_; - ASSERT_TRUE(acc_.Update(1.0, t_)); - ASSERT_EQ(0.9375, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - - // Step two half-life intervals per update. - acc_.Reset(0.0, t_); - ASSERT_EQ(0.0, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - t_ += 2 * half_life_; - ASSERT_TRUE(acc_.Update(1.0, t_)); - ASSERT_NEAR(0.666666667, acc_.current(), 0.000000001); - ASSERT_EQ(t_, acc_.update_time()); - t_ += 2 * half_life_; - ASSERT_TRUE(acc_.Update(1.0, t_)); - ASSERT_NEAR(0.888888889, acc_.current(), 0.000000001); - ASSERT_EQ(t_, acc_.update_time()); - t_ += 2 * half_life_; - ASSERT_TRUE(acc_.Update(1.0, t_)); - ASSERT_NEAR(0.962962963, acc_.current(), 0.000000001); - ASSERT_EQ(t_, acc_.update_time()); - t_ += 2 * half_life_; - ASSERT_TRUE(acc_.Update(1.0, t_)); - ASSERT_NEAR(0.987654321, acc_.current(), 0.000000001); - ASSERT_EQ(t_, acc_.update_time()); - - // Step three half-life intervals per update. - acc_.Reset(0.0, t_); - ASSERT_EQ(0.0, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - t_ += 3 * half_life_; - ASSERT_TRUE(acc_.Update(1.0, t_)); - ASSERT_EQ(0.75, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - t_ += 3 * half_life_; - ASSERT_TRUE(acc_.Update(1.0, t_)); - ASSERT_EQ(0.9375, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - t_ += 3 * half_life_; - ASSERT_TRUE(acc_.Update(1.0, t_)); - ASSERT_EQ(0.984375, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - t_ += 3 * half_life_; - ASSERT_TRUE(acc_.Update(1.0, t_)); - ASSERT_EQ(0.99609375, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); -} - -TEST_F(FeedbackSignalAccumulatorTest, IgnoresUpdatesThatAreOutOfOrder) { - // First, go forward several steps, in order. - acc_.Reset(0.0, t_); - ASSERT_EQ(0.0, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - t_ += 1 * half_life_; - ASSERT_TRUE(acc_.Update(2.0, t_)); - ASSERT_EQ(1.0, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - t_ += 1 * half_life_; - ASSERT_TRUE(acc_.Update(2.0, t_)); - ASSERT_EQ(1.5, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - t_ += 1 * half_life_; - ASSERT_TRUE(acc_.Update(2.0, t_)); - ASSERT_EQ(1.75, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - t_ += 1 * half_life_; - ASSERT_TRUE(acc_.Update(2.0, t_)); - ASSERT_EQ(1.875, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - - // Go back 1 steps, then 1.5, then 2, then 2.5, etc. and expect the update to - // fail each time. - base::TimeTicks earlier = t_ - 1 * half_life_; - for (int i = 0; i < 5; ++i) { - ASSERT_FALSE(acc_.Update(999.0, earlier)); - ASSERT_EQ(1.875, acc_.current()); - ASSERT_EQ(t_, acc_.update_time()); - earlier -= half_life_ / 2; - } -} - -} // namespace media
diff --git a/media/capture/content/video_capture_oracle.h b/media/capture/content/video_capture_oracle.h index 3fdb35c..82898f9 100644 --- a/media/capture/content/video_capture_oracle.h +++ b/media/capture/content/video_capture_oracle.h
@@ -7,10 +7,10 @@ #include "base/callback_forward.h" #include "base/time/time.h" +#include "media/base/feedback_signal_accumulator.h" #include "media/capture/capture_export.h" #include "media/capture/content/animated_content_sampler.h" #include "media/capture/content/capture_resolution_chooser.h" -#include "media/capture/content/feedback_signal_accumulator.h" #include "media/capture/content/smooth_event_sampler.h" #include "ui/gfx/geometry/rect.h"
diff --git a/media/capture/video/android/java/src/org/chromium/media/PhotoCapabilities.java b/media/capture/video/android/java/src/org/chromium/media/PhotoCapabilities.java index 304c6e17..20f9c37 100644 --- a/media/capture/video/android/java/src/org/chromium/media/PhotoCapabilities.java +++ b/media/capture/video/android/java/src/org/chromium/media/PhotoCapabilities.java
@@ -15,23 +15,32 @@ public final int maxZoom; public final int minZoom; public final int currentZoom; + public final boolean autoFocusInUse; - PhotoCapabilities(int maxZoom, int minZoom, int currentZoom) { + PhotoCapabilities(int maxZoom, int minZoom, int currentZoom, boolean autoFocusInUse) { this.maxZoom = maxZoom; this.minZoom = minZoom; this.currentZoom = currentZoom; + this.autoFocusInUse = autoFocusInUse; } @CalledByNative public int getMinZoom() { return minZoom; } + @CalledByNative public int getMaxZoom() { return maxZoom; } + @CalledByNative public int getCurrentZoom() { return currentZoom; } + + @CalledByNative + public boolean getAutoFocusInUse() { + return autoFocusInUse; + } }
diff --git a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera.java b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera.java index 65784c08..112f876 100644 --- a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera.java +++ b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera.java
@@ -296,16 +296,27 @@ @Override public PhotoCapabilities getPhotoCapabilities() { final android.hardware.Camera.Parameters parameters = getCameraParameters(mCamera); - if (!parameters.isZoomSupported()) return new PhotoCapabilities(0, 0, 0); - Log.d(TAG, "parameters.getZoomRatios(): " + parameters.getZoomRatios().toString()); + int maxZoom = 0; + int currentZoom = 0; + int minZoom = 0; + if (parameters.isZoomSupported()) { + Log.d(TAG, "parameters.getZoomRatios(): " + parameters.getZoomRatios().toString()); - // The Max zoom is returned as x100 by the API to avoid using floating point. - final int maxZoom = parameters.getZoomRatios().get(parameters.getMaxZoom()); - final int currentZoom = 100 + 100 * parameters.getZoom(); + // The Max zoom is returned as x100 by the API to avoid using floating point. + maxZoom = parameters.getZoomRatios().get(parameters.getMaxZoom()); + currentZoom = 100 + 100 * parameters.getZoom(); + minZoom = parameters.getZoomRatios().get(0); + } - // Min zoom is always 100. TODO(mcasas): consider double-checking. - return new PhotoCapabilities(maxZoom, 100, currentZoom); + Log.d(TAG, "parameters.getFocusMode(): " + parameters.getFocusMode()); + final String focusMode = parameters.getFocusMode(); + final boolean isFocusManual = + focusMode.equals(android.hardware.Camera.Parameters.FOCUS_MODE_FIXED) + || focusMode.equals(android.hardware.Camera.Parameters.FOCUS_MODE_INFINITY) + || focusMode.equals(android.hardware.Camera.Parameters.FOCUS_MODE_EDOF); + + return new PhotoCapabilities(maxZoom, minZoom, currentZoom, !isFocusManual); } @Override
diff --git a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java index 3467e81..51a32dc 100644 --- a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java +++ b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java
@@ -572,7 +572,12 @@ / cameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE) .width(); - return new PhotoCapabilities(maxZoom, minZoom, currentZoom); + final int focusMode = mPreviewRequest.get(CaptureRequest.CONTROL_AF_MODE); + Log.d(TAG, "focusMode " + focusMode); + final boolean isFocusManual = (focusMode == CameraMetadata.CONTROL_AF_MODE_OFF) + || (focusMode == CameraMetadata.CONTROL_AF_MODE_EDOF); + + return new PhotoCapabilities(maxZoom, minZoom, currentZoom, !isFocusManual); } @Override
diff --git a/media/capture/video/android/photo_capabilities.cc b/media/capture/video/android/photo_capabilities.cc index 2ce70f0..69c9440 100644 --- a/media/capture/video/android/photo_capabilities.cc +++ b/media/capture/video/android/photo_capabilities.cc
@@ -42,4 +42,10 @@ object_.obj()); } +bool PhotoCapabilities::getAutoFocusInUse() const { + DCHECK(!object_.is_null()); + return Java_PhotoCapabilities_getAutoFocusInUse(AttachCurrentThread(), + object_.obj()); +} + } // namespace media
diff --git a/media/capture/video/android/photo_capabilities.h b/media/capture/video/android/photo_capabilities.h index 815395b..304bf9c 100644 --- a/media/capture/video/android/photo_capabilities.h +++ b/media/capture/video/android/photo_capabilities.h
@@ -22,6 +22,7 @@ int getMinZoom() const; int getMaxZoom() const; int getCurrentZoom() const; + bool getAutoFocusInUse() const; private: const base::android::ScopedJavaLocalRef<jobject> object_;
diff --git a/media/capture/video/android/video_capture_device_android.cc b/media/capture/video/android/video_capture_device_android.cc index 99e3975..3209761 100644 --- a/media/capture/video/android/video_capture_device_android.cc +++ b/media/capture/video/android/video_capture_device_android.cc
@@ -175,6 +175,9 @@ photo_capabilities->zoom->current = caps.getCurrentZoom(); photo_capabilities->zoom->max = caps.getMaxZoom(); photo_capabilities->zoom->min = caps.getMinZoom(); + photo_capabilities->focus_mode = caps.getAutoFocusInUse() + ? mojom::FocusMode::AUTO + : mojom::FocusMode::MANUAL; callback.Run(std::move(photo_capabilities)); }
diff --git a/media/capture/video/fake_video_capture_device.cc b/media/capture/video/fake_video_capture_device.cc index d66fbb4..a8f4dc3 100644 --- a/media/capture/video/fake_video_capture_device.cc +++ b/media/capture/video/fake_video_capture_device.cc
@@ -186,6 +186,7 @@ photo_capabilities->zoom->current = current_zoom_; photo_capabilities->zoom->max = kMaxZoom; photo_capabilities->zoom->min = kMinZoom; + photo_capabilities->focus_mode = mojom::FocusMode::UNAVAILABLE; callback.Run(std::move(photo_capabilities)); }
diff --git a/media/capture/video/fake_video_capture_device_unittest.cc b/media/capture/video/fake_video_capture_device_unittest.cc index 21d8c94d..d090e33 100644 --- a/media/capture/video/fake_video_capture_device_unittest.cc +++ b/media/capture/video/fake_video_capture_device_unittest.cc
@@ -324,6 +324,7 @@ EXPECT_EQ(400u, capabilities->zoom->max); EXPECT_GE(capabilities->zoom->current, capabilities->zoom->min); EXPECT_GE(capabilities->zoom->max, capabilities->zoom->current); + EXPECT_EQ(mojom::FocusMode::UNAVAILABLE, capabilities->focus_mode); // Set options: zoom to the maximum value. const unsigned int max_zoom_value = capabilities->zoom->max;
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.h b/media/capture/video/mac/video_capture_device_avfoundation_mac.h index 69082e7a..8198bcd 100644 --- a/media/capture/video/mac/video_capture_device_avfoundation_mac.h +++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.h
@@ -21,9 +21,8 @@ @class CrAVCaptureDevice; @class CrAVCaptureSession; @class CrAVCaptureVideoDataOutput; -@class CrAVCaptureStillImageOutput; -// Class used by VideoCaptureDeviceMac (VCDM) for video and image capture using +// Class used by VideoCaptureDeviceMac (VCDM) for video capture using // AVFoundation API. This class lives inside the thread created by its owner // VCDM. // @@ -63,7 +62,7 @@ int frameHeight_; float frameRate_; - base::Lock lock_; // Protects concurrent setting and using |frameReceiver_|. + base::Lock lock_; // Protects concurrent setting and using of frameReceiver_. media::VideoCaptureDeviceMac* frameReceiver_; // weak. base::scoped_nsobject<CrAVCaptureSession> captureSession_; @@ -75,9 +74,6 @@ CrAVCaptureDeviceInput* captureDeviceInput_; base::scoped_nsobject<CrAVCaptureVideoDataOutput> captureVideoDataOutput_; - // An AVDataOutput specialized for taking pictures out of |captureSession_|. - base::scoped_nsobject<CrAVCaptureStillImageOutput> stillImageOutput_; - base::ThreadChecker main_thread_checker_; } @@ -118,10 +114,6 @@ // Stops video capturing and stops listening to notifications. - (void)stopCapture; -// Takes a photo. This method should only be called between -startCapture and -// -stopCapture. -- (void)takePhoto; - @end #endif // MEDIA_CAPTURE_VIDEO_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm index c47ff9c4..0f89a031 100644 --- a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm +++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
@@ -95,6 +95,8 @@ } } +} // anonymous namespace + // This function translates Mac Core Video pixel formats to Chromium pixel // formats. media::VideoPixelFormat FourCCToChromiumPixelFormat(FourCharCode code) { @@ -110,26 +112,6 @@ } } -// Extracts |base_address| and |length| out of a SampleBuffer. -void ExtractBaseAddressAndLength( - char** base_address, - size_t* length, - CoreMediaGlue::CMSampleBufferRef sample_buffer) { - CoreMediaGlue::CMBlockBufferRef block_buffer = - CoreMediaGlue::CMSampleBufferGetDataBuffer(sample_buffer); - DCHECK(block_buffer); - - size_t length_at_offset; - const OSStatus status = CoreMediaGlue::CMBlockBufferGetDataPointer( - block_buffer, 0, &length_at_offset, length, base_address); - DCHECK_EQ(noErr, status); - // Expect the (M)JPEG data to be available as a contiguous reference, i.e. - // not covered by multiple memory blocks. - DCHECK_EQ(length_at_offset, *length); -} - -} // anonymous namespace - @implementation VideoCaptureDeviceAVFoundation #pragma mark Class methods @@ -235,8 +217,6 @@ // No need to release |captureDeviceInput_|, is owned by the session. captureDeviceInput_ = nil; } - if (stillImageOutput_) - [captureSession_ removeOutput:stillImageOutput_]; return YES; } @@ -281,13 +261,6 @@ queue:dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; [captureSession_ addOutput:captureVideoDataOutput_]; - - // Create and plug the still image capture output. This should happen in - // advance of the actual picture to allow for the 3A to stabilize. - stillImageOutput_.reset( - [[AVFoundationGlue::AVCaptureStillImageOutputClass() alloc] init]); - [captureSession_ addOutput:stillImageOutput_]; - return YES; } @@ -386,48 +359,6 @@ [[NSNotificationCenter defaultCenter] removeObserver:self]; } -- (void)takePhoto { - DCHECK(main_thread_checker_.CalledOnValidThread()); - DCHECK([captureSession_ isRunning]); - - DCHECK_EQ(1u, [[stillImageOutput_ connections] count]); - CrAVCaptureConnection* const connection = - [[stillImageOutput_ connections] firstObject]; - if (!connection) { - base::AutoLock lock(lock_); - frameReceiver_->OnPhotoError(); - return; - } - - const auto handler = ^(CoreMediaGlue::CMSampleBufferRef sampleBuffer, - NSError* error) { - base::AutoLock lock(lock_); - if (!frameReceiver_) - return; - if (error != nil) { - frameReceiver_->OnPhotoError(); - return; - } - - // Recommended compressed pixel format is JPEG, we don't expect surprises. - // TODO(mcasas): Consider using [1] for merging EXIF output information: - // [1] +(NSData*)jpegStillImageNSDataRepresentation:jpegSampleBuffer; - DCHECK_EQ( - CoreMediaGlue::kCMVideoCodecType_JPEG, - CoreMediaGlue::CMFormatDescriptionGetMediaSubType( - CoreMediaGlue::CMSampleBufferGetFormatDescription(sampleBuffer))); - - char* baseAddress = 0; - size_t length = 0; - ExtractBaseAddressAndLength(&baseAddress, &length, sampleBuffer); - frameReceiver_->OnPhotoTaken(reinterpret_cast<uint8_t*>(baseAddress), - length, "image/jpeg"); - }; - - [stillImageOutput_ captureStillImageAsynchronouslyFromConnection:connection - completionHandler:handler]; -} - #pragma mark Private methods // |captureOutput| is called by the capture device to deliver a new frame. @@ -450,7 +381,17 @@ size_t frameSize = 0; CVImageBufferRef videoFrame = nil; if (fourcc == CoreMediaGlue::kCMVideoCodecType_JPEG_OpenDML) { - ExtractBaseAddressAndLength(&baseAddress, &frameSize, sampleBuffer); + // If MJPEG, use block buffer instead of pixel buffer. + CoreMediaGlue::CMBlockBufferRef blockBuffer = + CoreMediaGlue::CMSampleBufferGetDataBuffer(sampleBuffer); + if (blockBuffer) { + size_t lengthAtOffset; + CoreMediaGlue::CMBlockBufferGetDataPointer( + blockBuffer, 0, &lengthAtOffset, &frameSize, &baseAddress); + // Expect the MJPEG data to be available as a contiguous reference, i.e. + // not covered by multiple memory blocks. + CHECK_EQ(lengthAtOffset, frameSize); + } } else { videoFrame = CoreMediaGlue::CMSampleBufferGetImageBuffer(sampleBuffer); // Lock the frame and calculate frame size.
diff --git a/media/capture/video/mac/video_capture_device_mac.h b/media/capture/video/mac/video_capture_device_mac.h index 7eff128..88b986b 100644 --- a/media/capture/video/mac/video_capture_device_mac.h +++ b/media/capture/video/mac/video_capture_device_mac.h
@@ -62,12 +62,10 @@ const VideoCaptureParams& params, std::unique_ptr<VideoCaptureDevice::Client> client) override; void StopAndDeAllocate() override; - void TakePhoto(TakePhotoCallback callback) override; bool Init(VideoCaptureDevice::Name::CaptureApiType capture_api_type); - // Called to deliver captured video frames. It's safe to call this method - // from any thread, including those controlled by AVFoundation. + // Called to deliver captured video frames. void ReceiveFrame(const uint8_t* video_frame, int video_frame_length, const VideoCaptureFormat& frame_format, @@ -75,13 +73,6 @@ int aspect_denominator, base::TimeDelta timestamp); - // Callbacks with the result of a still image capture, or in case of error, - // respectively. It's safe to call these methods from any thread. - void OnPhotoTaken(const uint8_t* image_data, - size_t image_length, - const std::string& mime_type); - void OnPhotoError(); - // Forwarder to VideoCaptureDevice::Client::OnError(). void ReceiveError(const tracked_objects::Location& from_here, const std::string& reason); @@ -108,9 +99,6 @@ base::scoped_nsobject<VideoCaptureDeviceAVFoundation> capture_device_; - // To hold on to the TakePhotoCallback while the picture is being taken. - std::unique_ptr<TakePhotoCallback> photo_callback_; - // Used with Bind and PostTask to ensure that methods aren't called after the // VideoCaptureDeviceMac is destroyed. // NOTE: Weak pointers must be invalidated before all other member variables.
diff --git a/media/capture/video/mac/video_capture_device_mac.mm b/media/capture/video/mac/video_capture_device_mac.mm index 6ae6b8c..f032280 100644 --- a/media/capture/video/mac/video_capture_device_mac.mm +++ b/media/capture/video/mac/video_capture_device_mac.mm
@@ -389,17 +389,6 @@ state_ = kIdle; } -void VideoCaptureDeviceMac::TakePhoto(TakePhotoCallback callback) { - DCHECK(task_runner_->BelongsToCurrentThread()); - DCHECK(state_ == kCapturing) << state_; - - if (photo_callback_) // Only one picture can be in flight at a time. - return; - - photo_callback_.reset(new TakePhotoCallback(std::move(callback))); - [capture_device_ takePhoto]; -} - bool VideoCaptureDeviceMac::Init( VideoCaptureDevice::Name::CaptureApiType capture_api_type) { DCHECK(task_runner_->BelongsToCurrentThread()); @@ -424,6 +413,8 @@ int aspect_numerator, int aspect_denominator, base::TimeDelta timestamp) { + // This method is safe to call from a device capture thread, i.e. any thread + // controlled by AVFoundation. if (capture_format_.frame_size != frame_format.frame_size) { ReceiveError(FROM_HERE, "Captured resolution " + frame_format.frame_size.ToString() + @@ -435,26 +426,6 @@ 0, base::TimeTicks::Now(), timestamp); } -void VideoCaptureDeviceMac::OnPhotoTaken(const uint8_t* image_data, - size_t image_length, - const std::string& mime_type) { - DCHECK(photo_callback_); - if (!image_data || !image_length) { - OnPhotoError(); - return; - } - - photo_callback_->Run(mojo::String::From(mime_type), - mojo::Array<uint8_t>(std::vector<uint8_t>( - image_data, image_data + image_length))); - photo_callback_.reset(); -} - -void VideoCaptureDeviceMac::OnPhotoError() { - DLOG(ERROR) << __FUNCTION__ << " error taking picture"; - photo_callback_.reset(); -} - void VideoCaptureDeviceMac::ReceiveError( const tracked_objects::Location& from_here, const std::string& reason) {
diff --git a/media/capture/video/video_capture_device_unittest.cc b/media/capture/video/video_capture_device_unittest.cc index e71fb71..0ea3fb9 100644 --- a/media/capture/video/video_capture_device_unittest.cc +++ b/media/capture/video/video_capture_device_unittest.cc
@@ -19,7 +19,6 @@ #include "base/threading/thread.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" -#include "media/base/bind_to_current_loop.h" #include "media/base/video_capture_types.h" #include "media/capture/video/video_capture_device_factory.h" #include "testing/gmock/include/gmock/gmock.h" @@ -46,11 +45,9 @@ #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize // We will always get YUYV from the Mac AVFoundation implementations. #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg -#define MAYBE_TakePhoto TakePhoto #elif defined(OS_WIN) #define MAYBE_AllocateBadSize AllocateBadSize #define MAYBE_CaptureMjpeg CaptureMjpeg -#define MAYBE_TakePhoto DISABLED_TakePhoto #elif defined(OS_ANDROID) // TODO(wjia): enable those tests on Android. // On Android, native camera (JAVA) delivers frames on UI thread which is the @@ -60,7 +57,6 @@ #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning #define DeAllocateCameraWhileRunning DISABLED_DeAllocateCameraWhileRunning #define MAYBE_CaptureMjpeg DISABLED_CaptureMjpeg -#define MAYBE_TakePhoto DISABLED_TakePhoto #elif defined(OS_LINUX) // AllocateBadSize will hang when a real camera is attached and if more than one // test is trying to use the camera (even across processes). Do NOT renable @@ -68,11 +64,9 @@ // http://crbug.com/94134 http://crbug.com/137260 http://crbug.com/417824 #define MAYBE_AllocateBadSize DISABLED_AllocateBadSize #define MAYBE_CaptureMjpeg CaptureMjpeg -#define MAYBE_TakePhoto DISABLED_TakePhoto #else #define MAYBE_AllocateBadSize AllocateBadSize #define MAYBE_CaptureMjpeg CaptureMjpeg -#define MAYBE_TakePhoto DISABLED_TakePhoto #endif using ::testing::_; @@ -142,30 +136,6 @@ base::Callback<void(const VideoCaptureFormat&)> frame_cb_; }; -class MockImageCaptureClient : public base::RefCounted<MockImageCaptureClient> { - public: - // GMock doesn't support move-only arguments, so we use this forward method. - void DoOnPhotoTaken(mojo::String mime_type, mojo::Array<uint8_t> data) { - EXPECT_STREQ("image/jpeg", mime_type.storage().c_str()); - ASSERT_GT(data.size(), 4u); - // Check some bytes that univocally identify |data| as a JPEG File. - // https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format#File_format_structure - EXPECT_EQ(0xFF, data[0]); // First SOI byte - EXPECT_EQ(0xD8, data[1]); // Second SOI byte - EXPECT_EQ(0xFF, data[2]); // First JFIF-APP0 byte - EXPECT_EQ(0xE0, data[3]); // Second JFIF-APP0 byte - OnCorrectPhotoTaken(); - } - MOCK_METHOD0(OnCorrectPhotoTaken, void(void)); - MOCK_METHOD1( - OnTakePhotoFailure, - void(const base::Callback<void(mojo::String, mojo::Array<uint8_t>)>&)); - - private: - friend class base::RefCounted<MockImageCaptureClient>; - virtual ~MockImageCaptureClient() {} -}; - class DeviceEnumerationListener : public base::RefCounted<DeviceEnumerationListener> { public: @@ -193,10 +163,10 @@ video_capture_client_(new MockVideoCaptureClient( base::Bind(&VideoCaptureDeviceTest::OnFrameCaptured, base::Unretained(this)))), - device_enumeration_listener_(new DeviceEnumerationListener()), - image_capture_client_(new MockImageCaptureClient()), video_capture_device_factory_(VideoCaptureDeviceFactory::CreateFactory( - base::ThreadTaskRunnerHandle::Get())) {} + base::ThreadTaskRunnerHandle::Get())) { + device_enumeration_listener_ = new DeviceEnumerationListener(); + } void SetUp() override { #if defined(OS_ANDROID) @@ -285,14 +255,12 @@ base::win::ScopedCOMInitializer initialize_com_; #endif std::unique_ptr<VideoCaptureDevice::Names> names_; - const std::unique_ptr<base::MessageLoop> loop_; + std::unique_ptr<base::MessageLoop> loop_; std::unique_ptr<base::RunLoop> run_loop_; std::unique_ptr<MockVideoCaptureClient> video_capture_client_; - const scoped_refptr<DeviceEnumerationListener> device_enumeration_listener_; - const scoped_refptr<MockImageCaptureClient> image_capture_client_; + scoped_refptr<DeviceEnumerationListener> device_enumeration_listener_; VideoCaptureFormat last_format_; - const std::unique_ptr<VideoCaptureDeviceFactory> - video_capture_device_factory_; + std::unique_ptr<VideoCaptureDeviceFactory> video_capture_device_factory_; }; // Cause hangs on Windows Debug. http://crbug.com/417824 @@ -357,7 +325,8 @@ VideoCaptureParams capture_params; capture_params.requested_format.frame_size.SetSize(width, height); capture_params.requested_format.frame_rate = 30.0f; - capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; + capture_params.requested_format.pixel_format = + PIXEL_FORMAT_I420; device->AllocateAndStart(capture_params, std::move(video_capture_client_)); // Get captured video frames. WaitForCapturedFrame(); @@ -392,7 +361,8 @@ VideoCaptureParams capture_params; capture_params.requested_format.frame_size.SetSize(637, 472); capture_params.requested_format.frame_rate = 35; - capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; + capture_params.requested_format.pixel_format = + PIXEL_FORMAT_I420; device->AllocateAndStart(capture_params, std::move(video_capture_client_)); WaitForCapturedFrame(); device->StopAndDeAllocate(); @@ -514,42 +484,10 @@ // GetDeviceSupportedFormats(). std::unique_ptr<VideoCaptureDevice::Name> name = GetFirstDeviceNameSupportingPixelFormat(PIXEL_FORMAT_MAX); - // Verify no camera returned for PIXEL_FORMAT_MAX. Nothing else to test here + // Verify no camera returned for PIXEL_FORMAT_MAX. Nothing else + // to test here // since we cannot forecast the hardware capabilities. ASSERT_FALSE(name); } -// Start the camera and take a photo. -TEST_F(VideoCaptureDeviceTest, MAYBE_TakePhoto) { - names_ = EnumerateDevices(); - if (names_->empty()) { - VLOG(1) << "No camera available. Exiting test."; - return; - } - std::unique_ptr<VideoCaptureDevice> device( - video_capture_device_factory_->Create(names_->front())); - ASSERT_TRUE(device); - - EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); - - VideoCaptureParams capture_params; - capture_params.requested_format.frame_size.SetSize(640, 480); - capture_params.requested_format.frame_rate = 30; - capture_params.requested_format.pixel_format = PIXEL_FORMAT_I420; - device->AllocateAndStart(capture_params, std::move(video_capture_client_)); - WaitForCapturedFrame(); - - VideoCaptureDevice::TakePhotoCallback scoped_callback( - base::Bind(&MockImageCaptureClient::DoOnPhotoTaken, - image_capture_client_), - media::BindToCurrentLoop(base::Bind( - &MockImageCaptureClient::OnTakePhotoFailure, image_capture_client_))); - - EXPECT_CALL(*image_capture_client_.get(), OnCorrectPhotoTaken()).Times(1); - device->TakePhoto(std::move(scoped_callback)); - WaitForCapturedFrame(); - - device->StopAndDeAllocate(); -} - }; // namespace media
diff --git a/media/cast/BUILD.gn b/media/cast/BUILD.gn index fce89dd..68912bf 100644 --- a/media/cast/BUILD.gn +++ b/media/cast/BUILD.gn
@@ -365,23 +365,11 @@ if (is_android) { deps += [ "//testing/android/native_test:native_test_native_code" ] } -} -# TODO(miu): This can be rolled into cast_unittests now that FFMPEG dependency -# issues are resolved for iOS; but there are bot/isolates to update too. -if (is_ios || is_mac) { - test("cast_h264_vt_encoder_unittests") { - sources = [ - "sender/h264_vt_encoder_unittest.cc", - ] - deps = [ - ":common", - ":sender", - ":test_support", - "//testing/gmock", - "//testing/gtest", - "//third_party/ffmpeg", - ] + if (is_ios || is_mac) { + sources += [ "sender/h264_vt_encoder_unittest.cc" ] + + deps += [ "//third_party/ffmpeg" ] } }
diff --git a/media/cast/cast_config.cc b/media/cast/cast_config.cc index f1a4a69..0683925 100644 --- a/media/cast/cast_config.cc +++ b/media/cast/cast_config.cc
@@ -4,79 +4,43 @@ #include "media/cast/cast_config.h" -namespace { - -const float kDefaultCongestionControlBackOff = 0.875f; - -enum { - // Minimum and Maximum VP8 quantizer in default configuration. - kDefaultMaxQp = 63, - kDefaultMinQp = 4, - - kDefaultMaxCpuSaverQp = 25, - - // Number of video buffers in default configuration (applies only to certain - // external codecs). - kDefaultNumberOfVideoBuffers = 1, -}; - -} // namespace - namespace media { namespace cast { -// TODO(miu): Revisit code factoring of these structs. There are a number of -// common elements between them all, so it might be reasonable to only have one -// or two structs; or, at least a common base class. +VideoCodecParams::VideoCodecParams() + : max_qp(kDefaultMaxQp), + min_qp(kDefaultMinQp), + max_cpu_saver_qp(kDefaultMaxCpuSaverQp), + max_number_of_video_buffers_used(kDefaultNumberOfVideoBuffers), + number_of_encode_threads(1) {} -// TODO(miu): Make sure all POD members are initialized by ctors. Policy -// decision: Reasonable defaults or use invalid placeholder values to expose -// unset members? +VideoCodecParams::VideoCodecParams(const VideoCodecParams& other) = default; + +VideoCodecParams::~VideoCodecParams() {} // TODO(miu): Provide IsValidConfig() functions? -// TODO(miu): Throughout the code, there is a lot of copy-and-paste of the same -// calculations based on these config values. So, why don't we add methods to -// these classes to centralize the logic? - -VideoSenderConfig::VideoSenderConfig() - : ssrc(0), +FrameSenderConfig::FrameSenderConfig() + : sender_ssrc(0), receiver_ssrc(0), + min_playout_delay( + base::TimeDelta::FromMilliseconds(kDefaultRtpMaxDelayMs)), max_playout_delay( base::TimeDelta::FromMilliseconds(kDefaultRtpMaxDelayMs)), + animated_playout_delay(min_playout_delay), rtp_payload_type(RtpPayloadType::UNKNOWN), use_external_encoder(false), - congestion_control_back_off(kDefaultCongestionControlBackOff), - max_bitrate(kDefaultMaxVideoKbps * 1000), - min_bitrate(kDefaultMinVideoKbps * 1000), - start_bitrate(kDefaultMaxVideoKbps * 1000), - max_qp(kDefaultMaxQp), - min_qp(kDefaultMinQp), - max_cpu_saver_qp(kDefaultMaxCpuSaverQp), - max_frame_rate(kDefaultMaxFrameRate), - max_number_of_video_buffers_used(kDefaultNumberOfVideoBuffers), - codec(CODEC_VIDEO_VP8), - number_of_encode_threads(1) {} - -VideoSenderConfig::VideoSenderConfig(const VideoSenderConfig& other) = default; - -VideoSenderConfig::~VideoSenderConfig() {} - -AudioSenderConfig::AudioSenderConfig() - : ssrc(0), - receiver_ssrc(0), - max_playout_delay( - base::TimeDelta::FromMilliseconds(kDefaultRtpMaxDelayMs)), - rtp_payload_type(RtpPayloadType::UNKNOWN), - use_external_encoder(false), - frequency(0), + rtp_timebase(0), channels(0), - bitrate(kDefaultAudioEncoderBitrate), - codec(CODEC_AUDIO_OPUS) {} + max_bitrate(0), + min_bitrate(0), + start_bitrate(0), + max_frame_rate(kDefaultMaxFrameRate), + codec(CODEC_UNKNOWN) {} -AudioSenderConfig::AudioSenderConfig(const AudioSenderConfig& other) = default; +FrameSenderConfig::FrameSenderConfig(const FrameSenderConfig& other) = default; -AudioSenderConfig::~AudioSenderConfig() {} +FrameSenderConfig::~FrameSenderConfig() {} FrameReceiverConfig::FrameReceiverConfig() : receiver_ssrc(0),
diff --git a/media/cast/cast_config.h b/media/cast/cast_config.h index f99358a..bad2432 100644 --- a/media/cast/cast_config.h +++ b/media/cast/cast_config.h
@@ -46,84 +46,26 @@ // Suggested minimum and maximum video bitrates for general-purpose use (up to // 1080p, 30 FPS). - kDefaultMinVideoKbps = 300, - kDefaultMaxVideoKbps = 5000, + kDefaultMinVideoBitrate = 300000, + kDefaultMaxVideoBitrate = 5000000, + + // Minimum and Maximum VP8 quantizer in default configuration. + kDefaultMaxQp = 63, + kDefaultMinQp = 4, + + kDefaultMaxCpuSaverQp = 25, + + // Number of video buffers in default configuration (applies only to certain + // external codecs). + kDefaultNumberOfVideoBuffers = 1, }; -// TODO(miu): Merge AudioSenderConfig and VideoSenderConfig and make their -// naming/documentation consistent with FrameReceiverConfig. -// http://crbug.com/530839 -struct AudioSenderConfig { - AudioSenderConfig(); - AudioSenderConfig(const AudioSenderConfig& other); - ~AudioSenderConfig(); +// These parameters are only for video encoders. +struct VideoCodecParams { + VideoCodecParams(); + VideoCodecParams(const VideoCodecParams& other); + ~VideoCodecParams(); - // Identifier referring to the sender, used by the receiver. - uint32_t ssrc; - - // The receiver's SSRC identifier. - uint32_t receiver_ssrc; - - // The total amount of time between a frame's capture/recording on the sender - // and its playback on the receiver (i.e., shown to a user). This should be - // set to a value large enough to give the system sufficient time to encode, - // transmit/retransmit, receive, decode, and render; given its run-time - // environment (sender/receiver hardware performance, network conditions, - // etc.). - base::TimeDelta min_playout_delay; - base::TimeDelta max_playout_delay; - - // Starting playout delay when streaming animated content. - base::TimeDelta animated_playout_delay; - - // RTP payload type enum: Specifies the type/encoding of frame data. - RtpPayloadType rtp_payload_type; - - bool use_external_encoder; - int frequency; - int channels; - int bitrate; // Set to <= 0 for "auto variable bitrate" (libopus knows best). - Codec codec; - - // The AES crypto key and initialization vector. Each of these strings - // contains the data in binary form, of size kAesKeySize. If they are empty - // strings, crypto is not being used. - std::string aes_key; - std::string aes_iv_mask; -}; - -struct VideoSenderConfig { - VideoSenderConfig(); - VideoSenderConfig(const VideoSenderConfig& other); - ~VideoSenderConfig(); - - // Identifier referring to the sender, used by the receiver. - uint32_t ssrc; - - // The receiver's SSRC identifier. - uint32_t receiver_ssrc; - - // The total amount of time between a frame's capture/recording on the sender - // and its playback on the receiver (i.e., shown to a user). This should be - // set to a value large enough to give the system sufficient time to encode, - // transmit/retransmit, receive, decode, and render; given its run-time - // environment (sender/receiver hardware performance, network conditions, - // etc.). - base::TimeDelta min_playout_delay; - base::TimeDelta max_playout_delay; - - // Starting playout delay when streaming animated content. - base::TimeDelta animated_playout_delay; - - // RTP payload type enum: Specifies the type/encoding of frame data. - RtpPayloadType rtp_payload_type; - - bool use_external_encoder; - - float congestion_control_back_off; - int max_bitrate; - int min_bitrate; - int start_bitrate; int max_qp; int min_qp; @@ -133,12 +75,12 @@ // the maximum quantizer that the encoder might produce better quality video // at this resolution than lowering resolution with similar CPU usage and // smaller quantizer. The set value has to be between |min_qp| and |max_qp|. - // Suggested value range: [4, 30]. + // Suggested value range: [4, 30]. It is only used by software VP8 codec. int max_cpu_saver_qp; - int max_frame_rate; // TODO(miu): Should be double, not int. - - // This field is used differently by various encoders. It defaults to 1. + // This field is used differently by various encoders. + // + // It defaults to 1. // // For VP8, this field is ignored. // @@ -148,14 +90,67 @@ // choose a suitable value for the platform and other encoding settings. int max_number_of_video_buffers_used; - Codec codec; int number_of_encode_threads; +}; + +struct FrameSenderConfig { + FrameSenderConfig(); + FrameSenderConfig(const FrameSenderConfig& other); + ~FrameSenderConfig(); + + // The sender's SSRC identifier. + uint32_t sender_ssrc; + + // The receiver's SSRC identifier. + uint32_t receiver_ssrc; + + // The total amount of time between a frame's capture/recording on the sender + // and its playback on the receiver (i.e., shown to a user). This should be + // set to a value large enough to give the system sufficient time to encode, + // transmit/retransmit, receive, decode, and render; given its run-time + // environment (sender/receiver hardware performance, network conditions, + // etc.). + base::TimeDelta min_playout_delay; + base::TimeDelta max_playout_delay; + + // Starting playout delay when streaming animated content. + base::TimeDelta animated_playout_delay; + + // RTP payload type enum: Specifies the type/encoding of frame data. + RtpPayloadType rtp_payload_type; + + // If true, use an external HW encoder rather than the built-in + // software-based one. + bool use_external_encoder; + + // RTP timebase: The number of RTP units advanced per one second. For audio, + // this is the sampling rate. For video, by convention, this is 90 kHz. + int rtp_timebase; + + // Number of channels. For audio, this is normally 2. For video, this must + // be 1 as Cast does not have support for stereoscopic video. + int channels; + + // For now, only fixed bitrate is used for audio encoding. So for audio, + // |max_bitrate| is used, and the other two will be overriden if they are not + // equal to |max_bitrate|. + int max_bitrate; + int min_bitrate; + int start_bitrate; + + double max_frame_rate; + + // Codec used for the compression of signal data. + Codec codec; // The AES crypto key and initialization vector. Each of these strings // contains the data in binary form, of size kAesKeySize. If they are empty // strings, crypto is not being used. std::string aes_key; std::string aes_iv_mask; + + // These are codec specific parameters for video streams only. + VideoCodecParams video_codec_params; }; // TODO(miu): Naming and minor type changes are badly needed in a later CL. @@ -192,7 +187,7 @@ // The target frame rate. For audio, this is normally 100 (i.e., frames have // a duration of 10ms each). For video, this is normally 30, but any frame // rate is supported. - int target_frame_rate; + double target_frame_rate; // Codec used for the compression of signal data. // TODO(miu): Merge the AudioCodec and VideoCodec enums into one so this union
diff --git a/media/cast/cast_sender.h b/media/cast/cast_sender.h index 9e02c35..12c570b7 100644 --- a/media/cast/cast_sender.h +++ b/media/cast/cast_sender.h
@@ -104,7 +104,7 @@ // Initialize the audio stack. Must be called in order to send audio frames. // |status_change_cb| will be run as operational status changes. virtual void InitializeAudio( - const AudioSenderConfig& audio_config, + const FrameSenderConfig& audio_config, const StatusChangeCallback& status_change_cb) = 0; // Initialize the video stack. Must be called in order to send video frames. @@ -112,7 +112,7 @@ // // TODO(miu): Remove the VEA-specific callbacks. http://crbug.com/454029 virtual void InitializeVideo( - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const StatusChangeCallback& status_change_cb, const CreateVideoEncodeAcceleratorCallback& create_vea_cb, const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb) = 0;
diff --git a/media/cast/cast_sender_impl.cc b/media/cast/cast_sender_impl.cc index 06fc1894..07a4cc1 100644 --- a/media/cast/cast_sender_impl.cc +++ b/media/cast/cast_sender_impl.cc
@@ -108,7 +108,7 @@ } void CastSenderImpl::InitializeAudio( - const AudioSenderConfig& audio_config, + const FrameSenderConfig& audio_config, const StatusChangeCallback& status_change_cb) { DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); CHECK(audio_config.use_external_encoder || @@ -130,7 +130,7 @@ } void CastSenderImpl::InitializeVideo( - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const StatusChangeCallback& status_change_cb, const CreateVideoEncodeAcceleratorCallback& create_vea_cb, const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb) {
diff --git a/media/cast/cast_sender_impl.h b/media/cast/cast_sender_impl.h index 511c458..a16bc0f9 100644 --- a/media/cast/cast_sender_impl.h +++ b/media/cast/cast_sender_impl.h
@@ -27,14 +27,13 @@ CastSenderImpl(scoped_refptr<CastEnvironment> cast_environment, CastTransport* const transport_sender); - void InitializeAudio(const AudioSenderConfig& audio_config, + void InitializeAudio(const FrameSenderConfig& audio_config, const StatusChangeCallback& status_change_cb) final; void InitializeVideo( - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const StatusChangeCallback& status_change_cb, const CreateVideoEncodeAcceleratorCallback& create_vea_cb, - const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb) - final; + const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb) final; void SetTargetPlayoutDelay(base::TimeDelta new_target_playout_delay) final;
diff --git a/media/cast/cast_testing.gypi b/media/cast/cast_testing.gypi index 8700d32..08b2a03 100644 --- a/media/cast/cast_testing.gypi +++ b/media/cast/cast_testing.gypi
@@ -142,35 +142,19 @@ '<(DEPTH)/testing/android/native_test.gyp:native_test_native_code', ], }], + ['OS=="ios" or OS=="mac"', { + 'sources': [ + 'sender/h264_vt_encoder_unittest.cc', + ], + + 'dependencies': [ + '<(DEPTH)/third_party/ffmpeg/ffmpeg.gyp:ffmpeg', + ], + }] # OS=="ios" or OS=="mac" ], # conditions }, ], # targets 'conditions': [ - ['OS=="ios" or OS=="mac"', { - 'targets': [ - { - # GN version: //media/cast:cast_h264_vt_encoder_unittests - # TODO(miu): This can be rolled into cast_unittests now that FFMPEG - # dependency issues are resolved for iOS; but there are bot/isolates - # to update too. - 'target_name': 'cast_h264_vt_encoder_unittests', - 'type': '<(gtest_target_type)', - 'include_dirs': [ - '<(DEPTH)/', - ], - 'dependencies': [ - 'cast_common', - 'cast_sender', - 'cast_test_utility', - '<(DEPTH)/testing/gmock.gyp:gmock', - '<(DEPTH)/testing/gtest.gyp:gtest', - '<(DEPTH)/third_party/ffmpeg/ffmpeg.gyp:ffmpeg', - ], - 'sources': [ - 'sender/h264_vt_encoder_unittest.cc', - ], - }], # targets - }], # OS=="ios" or OS=="mac" ['OS=="android"', { 'targets': [ {
diff --git a/media/cast/receiver/frame_receiver.cc b/media/cast/receiver/frame_receiver.cc index 0e5d2581..8787f09 100644 --- a/media/cast/receiver/frame_receiver.cc +++ b/media/cast/receiver/frame_receiver.cc
@@ -48,14 +48,15 @@ rtp_timebase_(config.rtp_timebase), target_playout_delay_( base::TimeDelta::FromMilliseconds(config.rtp_max_delay_ms)), - expected_frame_duration_(base::TimeDelta::FromSeconds(1) / - config.target_frame_rate), + expected_frame_duration_( + base::TimeDelta::FromSecondsD(1.0 / config.target_frame_rate)), reports_are_scheduled_(false), framer_(cast_environment->Clock(), this, config.sender_ssrc, true, - config.rtp_max_delay_ms * config.target_frame_rate / 1000), + static_cast<int>( + config.rtp_max_delay_ms * config.target_frame_rate / 1000)), rtcp_(cast_environment_->Clock(), config.receiver_ssrc, config.sender_ssrc),
diff --git a/media/cast/receiver/video_decoder_unittest.cc b/media/cast/receiver/video_decoder_unittest.cc index 39d55d1b..da3d1266 100644 --- a/media/cast/receiver/video_decoder_unittest.cc +++ b/media/cast/receiver/video_decoder_unittest.cc
@@ -31,8 +31,8 @@ const int kStartingHeight = 240; const int kFrameRate = 10; -VideoSenderConfig GetVideoSenderConfigForTest() { - VideoSenderConfig config = GetDefaultVideoSenderConfig(); +FrameSenderConfig GetVideoSenderConfigForTest() { + FrameSenderConfig config = GetDefaultVideoSenderConfig(); config.max_frame_rate = kFrameRate; return config; }
diff --git a/media/cast/sender/audio_sender.cc b/media/cast/sender/audio_sender.cc index 12580f8c..634afa6 100644 --- a/media/cast/sender/audio_sender.cc +++ b/media/cast/sender/audio_sender.cc
@@ -18,31 +18,27 @@ namespace cast { AudioSender::AudioSender(scoped_refptr<CastEnvironment> cast_environment, - const AudioSenderConfig& audio_config, + const FrameSenderConfig& audio_config, const StatusChangeCallback& status_change_cb, CastTransport* const transport_sender) : FrameSender(cast_environment, true, transport_sender, - audio_config.frequency, - audio_config.ssrc, + audio_config.rtp_timebase, + audio_config.sender_ssrc, 0, // |max_frame_rate_| is set after encoder initialization. audio_config.min_playout_delay, audio_config.max_playout_delay, audio_config.animated_playout_delay, - NewFixedCongestionControl(audio_config.bitrate)), + NewFixedCongestionControl(audio_config.max_bitrate)), samples_in_encoder_(0), weak_factory_(this) { if (!audio_config.use_external_encoder) { - audio_encoder_.reset( - new AudioEncoder(cast_environment, - audio_config.channels, - audio_config.frequency, - audio_config.bitrate, - audio_config.codec, - base::Bind(&AudioSender::OnEncodedAudioFrame, - weak_factory_.GetWeakPtr(), - audio_config.bitrate))); + audio_encoder_.reset(new AudioEncoder( + cast_environment, audio_config.channels, audio_config.rtp_timebase, + audio_config.max_bitrate, audio_config.codec, + base::Bind(&AudioSender::OnEncodedAudioFrame, + weak_factory_.GetWeakPtr(), audio_config.max_bitrate))); } // AudioEncoder provides no operational status changes during normal use. @@ -59,10 +55,10 @@ // initialization parameters. Now that we have an encoder, we can calculate // the maximum frame rate. max_frame_rate_ = - audio_config.frequency / audio_encoder_->GetSamplesPerFrame(); + audio_config.rtp_timebase / audio_encoder_->GetSamplesPerFrame(); media::cast::CastTransportRtpConfig transport_config; - transport_config.ssrc = audio_config.ssrc; + transport_config.ssrc = audio_config.sender_ssrc; transport_config.feedback_ssrc = audio_config.receiver_ssrc; transport_config.rtp_payload_type = audio_config.rtp_payload_type; transport_config.aes_key = audio_config.aes_key;
diff --git a/media/cast/sender/audio_sender.h b/media/cast/sender/audio_sender.h index 3abbfc8..17fda1f7 100644 --- a/media/cast/sender/audio_sender.h +++ b/media/cast/sender/audio_sender.h
@@ -35,7 +35,7 @@ public base::SupportsWeakPtr<AudioSender> { public: AudioSender(scoped_refptr<CastEnvironment> cast_environment, - const AudioSenderConfig& audio_config, + const FrameSenderConfig& audio_config, const StatusChangeCallback& status_change_cb, CastTransport* const transport_sender);
diff --git a/media/cast/sender/audio_sender_unittest.cc b/media/cast/sender/audio_sender_unittest.cc index 6737ffd..f7c76257 100644 --- a/media/cast/sender/audio_sender_unittest.cc +++ b/media/cast/sender/audio_sender_unittest.cc
@@ -103,9 +103,9 @@ task_runner_, task_runner_, task_runner_); audio_config_.codec = CODEC_AUDIO_OPUS; audio_config_.use_external_encoder = false; - audio_config_.frequency = kDefaultAudioSamplingRate; + audio_config_.rtp_timebase = kDefaultAudioSamplingRate; audio_config_.channels = 2; - audio_config_.bitrate = kDefaultAudioEncoderBitrate; + audio_config_.max_bitrate = kDefaultAudioEncoderBitrate; audio_config_.rtp_payload_type = RtpPayloadType::AUDIO_OPUS; transport_ = new TestPacketSender(); @@ -131,13 +131,13 @@ scoped_refptr<FakeSingleThreadTaskRunner> task_runner_; std::unique_ptr<AudioSender> audio_sender_; scoped_refptr<CastEnvironment> cast_environment_; - AudioSenderConfig audio_config_; + FrameSenderConfig audio_config_; }; TEST_F(AudioSenderTest, Encode20ms) { const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(20); std::unique_ptr<AudioBus> bus( - TestAudioBusFactory(audio_config_.channels, audio_config_.frequency, + TestAudioBusFactory(audio_config_.channels, audio_config_.rtp_timebase, TestAudioBusFactory::kMiddleANoteFreq, 0.5f) .NextAudioBus(kDuration)); @@ -150,7 +150,7 @@ TEST_F(AudioSenderTest, RtcpTimer) { const base::TimeDelta kDuration = base::TimeDelta::FromMilliseconds(20); std::unique_ptr<AudioBus> bus( - TestAudioBusFactory(audio_config_.channels, audio_config_.frequency, + TestAudioBusFactory(audio_config_.channels, audio_config_.rtp_timebase, TestAudioBusFactory::kMiddleANoteFreq, 0.5f) .NextAudioBus(kDuration));
diff --git a/media/cast/sender/external_video_encoder.cc b/media/cast/sender/external_video_encoder.cc index bff088c..396ad38 100644 --- a/media/cast/sender/external_video_encoder.cc +++ b/media/cast/sender/external_video_encoder.cc
@@ -18,6 +18,7 @@ #include "base/message_loop/message_loop.h" #include "base/metrics/histogram.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" #include "media/base/bind_to_current_loop.h" @@ -64,17 +65,19 @@ const std::string& switch_value = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kCastEncoderUtilHeuristic); - if (switch_value.find(kBacklogSwitchValue) == 0) { - int redline = kBacklogDefaultRedline; - if (!base::StringToInt(switch_value.substr(sizeof(kBacklogSwitchValue) - 1), - &redline)) { - redline = kBacklogDefaultRedline; - } - VLOG(1) << "Using 'backlog' heuristic with a redline of " << redline - << " to compute encoder utilization."; - return redline; + if (!base::StartsWith(switch_value, kBacklogSwitchValue, + base::CompareCase::SENSITIVE)) { + return 0; } - return 0; + + int redline = kBacklogDefaultRedline; + if (!base::StringToInt(switch_value.substr(sizeof(kBacklogSwitchValue) - 1), + &redline)) { + redline = kBacklogDefaultRedline; + } + VLOG(1) << "Using 'backlog' heuristic with a redline of " << redline + << " to compute encoder utilization."; + return redline; } } // namespace @@ -124,7 +127,7 @@ const scoped_refptr<CastEnvironment>& cast_environment, const scoped_refptr<base::SingleThreadTaskRunner>& encoder_task_runner, std::unique_ptr<media::VideoEncodeAccelerator> vea, - int max_frame_rate, + double max_frame_rate, const StatusChangeCallback& status_change_cb, const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb) : cast_environment_(cast_environment), @@ -176,8 +179,8 @@ DCHECK(task_runner_->RunsTasksOnCurrentThread()); requested_bit_rate_ = bit_rate; - video_encode_accelerator_->RequestEncodingParametersChange(bit_rate, - max_frame_rate_); + video_encode_accelerator_->RequestEncodingParametersChange( + bit_rate, static_cast<uint32_t>(max_frame_rate_ + 0.5)); } // The destruction call back of the copied video frame to free its use of @@ -592,7 +595,7 @@ const scoped_refptr<CastEnvironment> cast_environment_; const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - const int max_frame_rate_; + const double max_frame_rate_; const StatusChangeCallback status_change_cb_; // Must be run on MAIN thread. const CreateVideoEncodeMemoryCallback create_video_encode_memory_cb_; std::unique_ptr<media::VideoEncodeAccelerator> video_encode_accelerator_; @@ -647,7 +650,7 @@ }; // static -bool ExternalVideoEncoder::IsSupported(const VideoSenderConfig& video_config) { +bool ExternalVideoEncoder::IsSupported(const FrameSenderConfig& video_config) { if (video_config.codec != CODEC_VIDEO_VP8 && video_config.codec != CODEC_VIDEO_H264) return false; @@ -661,7 +664,7 @@ ExternalVideoEncoder::ExternalVideoEncoder( const scoped_refptr<CastEnvironment>& cast_environment, - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const gfx::Size& frame_size, FrameId first_frame_id, const StatusChangeCallback& status_change_cb, @@ -730,7 +733,7 @@ } void ExternalVideoEncoder::OnCreateVideoEncodeAccelerator( - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, FrameId first_frame_id, const StatusChangeCallback& status_change_cb, scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner, @@ -782,7 +785,7 @@ SizeAdaptableExternalVideoEncoder::SizeAdaptableExternalVideoEncoder( const scoped_refptr<CastEnvironment>& cast_environment, - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const StatusChangeCallback& status_change_cb, const CreateVideoEncodeAcceleratorCallback& create_vea_cb, const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb)
diff --git a/media/cast/sender/external_video_encoder.h b/media/cast/sender/external_video_encoder.h index f5cbd8b..fb926f5e 100644 --- a/media/cast/sender/external_video_encoder.h +++ b/media/cast/sender/external_video_encoder.h
@@ -28,11 +28,11 @@ public: // Returns true if the current platform and system configuration supports // using ExternalVideoEncoder with the given |video_config|. - static bool IsSupported(const VideoSenderConfig& video_config); + static bool IsSupported(const FrameSenderConfig& video_config); ExternalVideoEncoder( const scoped_refptr<CastEnvironment>& cast_environment, - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const gfx::Size& frame_size, FrameId first_frame_id, const StatusChangeCallback& status_change_cb, @@ -56,7 +56,7 @@ // VEAClientImpl to own and interface with a new |vea|. Upon return, // |client_| holds a reference to the new VEAClientImpl. void OnCreateVideoEncodeAccelerator( - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, FrameId first_frame_id, const StatusChangeCallback& status_change_cb, scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner, @@ -86,7 +86,7 @@ public: SizeAdaptableExternalVideoEncoder( const scoped_refptr<CastEnvironment>& cast_environment, - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const StatusChangeCallback& status_change_cb, const CreateVideoEncodeAcceleratorCallback& create_vea_cb, const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb);
diff --git a/media/cast/sender/fake_software_video_encoder.cc b/media/cast/sender/fake_software_video_encoder.cc index a919046..7a24750 100644 --- a/media/cast/sender/fake_software_video_encoder.cc +++ b/media/cast/sender/fake_software_video_encoder.cc
@@ -18,11 +18,13 @@ namespace cast { FakeSoftwareVideoEncoder::FakeSoftwareVideoEncoder( - const VideoSenderConfig& video_config) + const FrameSenderConfig& video_config) : video_config_(video_config), next_frame_is_key_(true), frame_id_(FrameId::first()), - frame_size_(0) {} + frame_size_(0) { + DCHECK_GT(video_config_.max_frame_rate, 0); +} FakeSoftwareVideoEncoder::~FakeSoftwareVideoEncoder() {}
diff --git a/media/cast/sender/fake_software_video_encoder.h b/media/cast/sender/fake_software_video_encoder.h index 6be2d256..7061b7e 100644 --- a/media/cast/sender/fake_software_video_encoder.h +++ b/media/cast/sender/fake_software_video_encoder.h
@@ -16,7 +16,7 @@ class FakeSoftwareVideoEncoder : public SoftwareVideoEncoder { public: - FakeSoftwareVideoEncoder(const VideoSenderConfig& video_config); + FakeSoftwareVideoEncoder(const FrameSenderConfig& video_config); ~FakeSoftwareVideoEncoder() final; // SoftwareVideoEncoder implementations. @@ -28,7 +28,7 @@ void GenerateKeyFrame() final; private: - VideoSenderConfig video_config_; + const FrameSenderConfig video_config_; gfx::Size last_frame_size_; bool next_frame_is_key_; FrameId frame_id_;
diff --git a/media/cast/sender/h264_vt_encoder.cc b/media/cast/sender/h264_vt_encoder.cc index 7031c54..c11f6db 100644 --- a/media/cast/sender/h264_vt_encoder.cc +++ b/media/cast/sender/h264_vt_encoder.cc
@@ -147,13 +147,13 @@ // static bool H264VideoToolboxEncoder::IsSupported( - const VideoSenderConfig& video_config) { + const FrameSenderConfig& video_config) { return video_config.codec == CODEC_VIDEO_H264 && VideoToolboxGlue::Get(); } H264VideoToolboxEncoder::H264VideoToolboxEncoder( const scoped_refptr<CastEnvironment>& cast_environment, - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const StatusChangeCallback& status_change_cb) : cast_environment_(cast_environment), videotoolbox_glue_(VideoToolboxGlue::Get()), @@ -322,7 +322,7 @@ (video_config_.min_bitrate + video_config_.max_bitrate) / 2); session_property_setter.Set( videotoolbox_glue_->kVTCompressionPropertyKey_ExpectedFrameRate(), - video_config_.max_frame_rate); + static_cast<int>(video_config_.max_frame_rate + 0.5)); // Keep these attachment settings in-sync with those in Initialize(). session_property_setter.Set( videotoolbox_glue_->kVTCompressionPropertyKey_ColorPrimaries(), @@ -333,10 +333,10 @@ session_property_setter.Set( videotoolbox_glue_->kVTCompressionPropertyKey_YCbCrMatrix(), kCVImageBufferYCbCrMatrix_ITU_R_709_2); - if (video_config_.max_number_of_video_buffers_used > 0) { + if (video_config_.video_codec_params.max_number_of_video_buffers_used > 0) { session_property_setter.Set( videotoolbox_glue_->kVTCompressionPropertyKey_MaxFrameDelayCount(), - video_config_.max_number_of_video_buffers_used); + video_config_.video_codec_params.max_number_of_video_buffers_used); } }
diff --git a/media/cast/sender/h264_vt_encoder.h b/media/cast/sender/h264_vt_encoder.h index b6dbd9d..2e4c3f0 100644 --- a/media/cast/sender/h264_vt_encoder.h +++ b/media/cast/sender/h264_vt_encoder.h
@@ -33,11 +33,11 @@ public: // Returns true if the current platform and system configuration supports // using H264VideoToolboxEncoder with the given |video_config|. - static bool IsSupported(const VideoSenderConfig& video_config); + static bool IsSupported(const FrameSenderConfig& video_config); H264VideoToolboxEncoder( const scoped_refptr<CastEnvironment>& cast_environment, - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const StatusChangeCallback& status_change_cb); ~H264VideoToolboxEncoder() final; @@ -92,7 +92,7 @@ // VideoSenderConfig copy so we can create compression sessions on demand. // This is needed to recover from backgrounding and other events that can // invalidate compression sessions. - const VideoSenderConfig video_config_; + const FrameSenderConfig video_config_; // Frame size of the current compression session. Can be changed by submitting // a frame of a different size, which will cause a compression session reset.
diff --git a/media/cast/sender/h264_vt_encoder_unittest.cc b/media/cast/sender/h264_vt_encoder_unittest.cc index 7d6c69d..5a33ffa 100644 --- a/media/cast/sender/h264_vt_encoder_unittest.cc +++ b/media/cast/sender/h264_vt_encoder_unittest.cc
@@ -55,18 +55,6 @@ } // namespace -int main(int argc, char** argv) { - { - base::AtExitManager at_exit_manager; - CHECK(VideoToolboxGlue::Get()) - << "VideoToolbox is not available. Requires OS X 10.8 or iOS 8.0."; - } - MediaTestSuite test_suite(argc, argv); - return base::LaunchUnitTests( - argc, argv, - base::Bind(&MediaTestSuite::Run, base::Unretained(&test_suite))); -} - namespace media { namespace cast { @@ -222,6 +210,8 @@ H264VideoToolboxEncoderTest() = default; void SetUp() final { + CHECK(VideoToolboxGlue::Get()) + << "VideoToolbox is not available. Requires OS X 10.8 or iOS 8.0."; clock_ = new base::SimpleTestTickClock(); clock_->Advance(base::TimeTicks::Now() - base::TimeTicks()); @@ -264,7 +254,7 @@ static void TearDownTestCase() { frame_ = nullptr; } static scoped_refptr<media::VideoFrame> frame_; - static VideoSenderConfig video_sender_config_; + static FrameSenderConfig video_sender_config_; base::SimpleTestTickClock* clock_; // Owned by CastEnvironment. base::MessageLoop message_loop_; @@ -280,9 +270,10 @@ // static scoped_refptr<media::VideoFrame> H264VideoToolboxEncoderTest::frame_; -VideoSenderConfig H264VideoToolboxEncoderTest::video_sender_config_; +FrameSenderConfig H264VideoToolboxEncoderTest::video_sender_config_; -TEST_F(H264VideoToolboxEncoderTest, CheckFrameMetadataSequence) { +// Failed on mac_chromium_rel_ng trybot. http://crbug.com/627260 +TEST_F(H264VideoToolboxEncoderTest, DISABLED_CheckFrameMetadataSequence) { scoped_refptr<MetadataRecorder> metadata_recorder(new MetadataRecorder()); VideoEncoder::FrameEncodedCallback cb = base::Bind( &MetadataRecorder::CompareFrameWithExpected, metadata_recorder.get()); @@ -311,7 +302,8 @@ } #if defined(USE_PROPRIETARY_CODECS) -TEST_F(H264VideoToolboxEncoderTest, CheckFramesAreDecodable) { +// Failed on mac_chromium_rel_ng trybot. http://crbug.com/627260 +TEST_F(H264VideoToolboxEncoderTest, DISABLED_CheckFramesAreDecodable) { VideoDecoderConfig config(kCodecH264, H264PROFILE_MAIN, frame_->format(), COLOR_SPACE_UNSPECIFIED, frame_->coded_size(), frame_->visible_rect(), frame_->natural_size(),
diff --git a/media/cast/sender/size_adaptable_video_encoder_base.cc b/media/cast/sender/size_adaptable_video_encoder_base.cc index a803347..f4464cc 100644 --- a/media/cast/sender/size_adaptable_video_encoder_base.cc +++ b/media/cast/sender/size_adaptable_video_encoder_base.cc
@@ -15,7 +15,7 @@ SizeAdaptableVideoEncoderBase::SizeAdaptableVideoEncoderBase( const scoped_refptr<CastEnvironment>& cast_environment, - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const StatusChangeCallback& status_change_cb) : cast_environment_(cast_environment), video_config_(video_config),
diff --git a/media/cast/sender/size_adaptable_video_encoder_base.h b/media/cast/sender/size_adaptable_video_encoder_base.h index ac2fd23..8443e2c 100644 --- a/media/cast/sender/size_adaptable_video_encoder_base.h +++ b/media/cast/sender/size_adaptable_video_encoder_base.h
@@ -30,7 +30,7 @@ public: SizeAdaptableVideoEncoderBase( const scoped_refptr<CastEnvironment>& cast_environment, - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const StatusChangeCallback& status_change_cb); ~SizeAdaptableVideoEncoderBase() override; @@ -50,9 +50,7 @@ CastEnvironment* cast_environment() const { return cast_environment_.get(); } - const VideoSenderConfig& video_config() const { - return video_config_; - } + const FrameSenderConfig& video_config() const { return video_config_; } const gfx::Size& frame_size() const { return frame_size_; } @@ -93,7 +91,7 @@ // This is not const since |video_config_.starting_bitrate| is modified by // SetBitRate(), for when a replacement encoder is spawned. - VideoSenderConfig video_config_; + FrameSenderConfig video_config_; // Run whenever the underlying encoder reports a status change. const StatusChangeCallback status_change_cb_;
diff --git a/media/cast/sender/video_encoder.cc b/media/cast/sender/video_encoder.cc index 46bb6d42..e6e5c1c 100644 --- a/media/cast/sender/video_encoder.cc +++ b/media/cast/sender/video_encoder.cc
@@ -18,7 +18,7 @@ // static std::unique_ptr<VideoEncoder> VideoEncoder::Create( const scoped_refptr<CastEnvironment>& cast_environment, - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const StatusChangeCallback& status_change_cb, const CreateVideoEncodeAcceleratorCallback& create_vea_cb, const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb) {
diff --git a/media/cast/sender/video_encoder.h b/media/cast/sender/video_encoder.h index e82315d..74cec93 100644 --- a/media/cast/sender/video_encoder.h +++ b/media/cast/sender/video_encoder.h
@@ -38,7 +38,7 @@ // TODO(miu): Remove the CreateVEA callbacks. http://crbug.com/454029 static std::unique_ptr<VideoEncoder> Create( const scoped_refptr<CastEnvironment>& cast_environment, - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const StatusChangeCallback& status_change_cb, const CreateVideoEncodeAcceleratorCallback& create_vea_cb, const CreateVideoEncodeMemoryCallback& create_video_encode_memory_cb);
diff --git a/media/cast/sender/video_encoder_impl.cc b/media/cast/sender/video_encoder_impl.cc index 3a8042b8..41651729 100644 --- a/media/cast/sender/video_encoder_impl.cc +++ b/media/cast/sender/video_encoder_impl.cc
@@ -51,7 +51,7 @@ } // namespace // static -bool VideoEncoderImpl::IsSupported(const VideoSenderConfig& video_config) { +bool VideoEncoderImpl::IsSupported(const FrameSenderConfig& video_config) { #ifndef OFFICIAL_BUILD if (video_config.codec == CODEC_VIDEO_FAKE) return true; @@ -61,7 +61,7 @@ VideoEncoderImpl::VideoEncoderImpl( scoped_refptr<CastEnvironment> cast_environment, - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const StatusChangeCallback& status_change_cb) : cast_environment_(cast_environment) { CHECK(cast_environment_->HasVideoThread());
diff --git a/media/cast/sender/video_encoder_impl.h b/media/cast/sender/video_encoder_impl.h index fa5b9c3b..cd350e6 100644 --- a/media/cast/sender/video_encoder_impl.h +++ b/media/cast/sender/video_encoder_impl.h
@@ -28,10 +28,10 @@ }; // Returns true if VideoEncoderImpl can be used with the given |video_config|. - static bool IsSupported(const VideoSenderConfig& video_config); + static bool IsSupported(const FrameSenderConfig& video_config); VideoEncoderImpl(scoped_refptr<CastEnvironment> cast_environment, - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const StatusChangeCallback& status_change_cb); ~VideoEncoderImpl() final;
diff --git a/media/cast/sender/video_encoder_unittest.cc b/media/cast/sender/video_encoder_unittest.cc index b907e3c..0c71b63 100644 --- a/media/cast/sender/video_encoder_unittest.cc +++ b/media/cast/sender/video_encoder_unittest.cc
@@ -66,7 +66,7 @@ void CreateEncoder() { ASSERT_EQ(STATUS_UNINITIALIZED, operational_status_); - video_config_.max_number_of_video_buffers_used = 1; + video_config_.video_codec_params.max_number_of_video_buffers_used = 1; video_encoder_ = VideoEncoder::Create( cast_environment_, video_config_, base::Bind(&VideoEncoderTest::OnOperationalStatusChange, @@ -121,6 +121,7 @@ } void RunTasksAndAdvanceClock() const { + DCHECK_GT(video_config_.max_frame_rate, 0); const base::TimeDelta frame_duration = base::TimeDelta::FromMicroseconds( 1000000.0 / video_config_.max_frame_rate); #if defined(OS_MACOSX) @@ -247,7 +248,8 @@ } else { if (expected_frame_id != expected_last_referenced_frame_id) { EXPECT_EQ(EncodedFrame::DEPENDENT, encoded_frame->dependency); - } else if (video_config_.max_number_of_video_buffers_used == 1) { + } else if (video_config_.video_codec_params + .max_number_of_video_buffers_used == 1) { EXPECT_EQ(EncodedFrame::KEY, encoded_frame->dependency); } EXPECT_EQ(expected_last_referenced_frame_id, @@ -265,7 +267,7 @@ base::SimpleTestTickClock* const testing_clock_; // Owned by CastEnvironment. const scoped_refptr<FakeSingleThreadTaskRunner> task_runner_; const scoped_refptr<CastEnvironment> cast_environment_; - VideoSenderConfig video_config_; + FrameSenderConfig video_config_; std::unique_ptr<FakeVideoEncodeAcceleratorFactory> vea_factory_; base::TimeTicks first_frame_time_; OperationalStatus operational_status_; @@ -414,7 +416,7 @@ values.push_back(std::make_pair(CODEC_VIDEO_VP8, true)); #if defined(OS_MACOSX) // VideoToolbox encoder (when VideoToolbox is present). - VideoSenderConfig video_config = GetDefaultVideoSenderConfig(); + FrameSenderConfig video_config = GetDefaultVideoSenderConfig(); video_config.use_external_encoder = false; video_config.codec = CODEC_VIDEO_H264; if (H264VideoToolboxEncoder::IsSupported(video_config))
diff --git a/media/cast/sender/video_sender.cc b/media/cast/sender/video_sender.cc index b4a2ff63..07639b8 100644 --- a/media/cast/sender/video_sender.cc +++ b/media/cast/sender/video_sender.cc
@@ -89,7 +89,7 @@ // See details: crbug.com/392086. VideoSender::VideoSender( scoped_refptr<CastEnvironment> cast_environment, - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const StatusChangeCallback& status_change_cb, const CreateVideoEncodeAcceleratorCallback& create_vea_cb, const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, @@ -100,7 +100,7 @@ false, transport_sender, kVideoFrequency, - video_config.ssrc, + video_config.sender_ssrc, video_config.max_frame_rate, video_config.min_playout_delay, video_config.max_playout_delay, @@ -133,7 +133,7 @@ } media::cast::CastTransportRtpConfig transport_config; - transport_config.ssrc = video_config.ssrc; + transport_config.ssrc = video_config.sender_ssrc; transport_config.feedback_ssrc = video_config.receiver_ssrc; transport_config.rtp_payload_type = video_config.rtp_payload_type; transport_config.aes_key = video_config.aes_key;
diff --git a/media/cast/sender/video_sender.h b/media/cast/sender/video_sender.h index b2cd320b..778ba03 100644 --- a/media/cast/sender/video_sender.h +++ b/media/cast/sender/video_sender.h
@@ -43,7 +43,7 @@ public base::SupportsWeakPtr<VideoSender> { public: VideoSender(scoped_refptr<CastEnvironment> cast_environment, - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const StatusChangeCallback& status_change_cb, const CreateVideoEncodeAcceleratorCallback& create_vea_cb, const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
diff --git a/media/cast/sender/video_sender_unittest.cc b/media/cast/sender/video_sender_unittest.cc index 480edd1..acfe83c 100644 --- a/media/cast/sender/video_sender_unittest.cc +++ b/media/cast/sender/video_sender_unittest.cc
@@ -113,7 +113,7 @@ public: PeerVideoSender( scoped_refptr<CastEnvironment> cast_environment, - const VideoSenderConfig& video_config, + const FrameSenderConfig& video_config, const StatusChangeCallback& status_change_cb, const CreateVideoEncodeAcceleratorCallback& create_vea_cb, const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb, @@ -178,7 +178,7 @@ // If |external| is true then external video encoder (VEA) is used. // |expect_init_success| is true if initialization is expected to succeed. void InitEncoder(bool external, bool expect_init_success) { - VideoSenderConfig video_config = GetDefaultVideoSenderConfig(); + FrameSenderConfig video_config = GetDefaultVideoSenderConfig(); video_config.use_external_encoder = external; ASSERT_EQ(operational_status_, STATUS_UNINITIALIZED);
diff --git a/media/cast/sender/vp8_encoder.cc b/media/cast/sender/vp8_encoder.cc index f6bad07..39c8971 100644 --- a/media/cast/sender/vp8_encoder.cc +++ b/media/cast/sender/vp8_encoder.cc
@@ -63,12 +63,12 @@ } // namespace -Vp8Encoder::Vp8Encoder(const VideoSenderConfig& video_config) +Vp8Encoder::Vp8Encoder(const FrameSenderConfig& video_config) : cast_config_(video_config), target_encoder_utilization_( - video_config.number_of_encode_threads > 2 + video_config.video_codec_params.number_of_encode_threads > 2 ? kHiTargetEncoderUtilization - : (video_config.number_of_encode_threads > 1 + : (video_config.video_codec_params.number_of_encode_threads > 1 ? kMidTargetEncoderUtilization : kLoTargetEncoderUtilization)), key_frame_requested_(true), @@ -79,8 +79,10 @@ base::TimeDelta::FromMicroseconds(kEncodingSpeedAccHalfLife)), encoding_speed_(kHighestEncodingSpeed) { config_.g_timebase.den = 0; // Not initialized. - DCHECK_LE(cast_config_.min_qp, cast_config_.max_cpu_saver_qp); - DCHECK_LE(cast_config_.max_cpu_saver_qp, cast_config_.max_qp); + DCHECK_LE(cast_config_.video_codec_params.min_qp, + cast_config_.video_codec_params.max_cpu_saver_qp); + DCHECK_LE(cast_config_.video_codec_params.max_cpu_saver_qp, + cast_config_.video_codec_params.max_qp); thread_checker_.DetachFromThread(); } @@ -110,7 +112,7 @@ << frame_size.ToString(); config_.g_w = frame_size.width(); config_.g_h = frame_size.height(); - config_.rc_min_quantizer = cast_config_.min_qp; + config_.rc_min_quantizer = cast_config_.video_codec_params.min_qp; if (vpx_codec_enc_config_set(&encoder_, &config_) == VPX_CODEC_OK) return; DVLOG(1) << "libvpx rejected the attempt to use a smaller frame size in " @@ -130,7 +132,7 @@ CHECK_EQ(vpx_codec_enc_config_default(vpx_codec_vp8_cx(), &config_, 0), VPX_CODEC_OK); - config_.g_threads = cast_config_.number_of_encode_threads; + config_.g_threads = cast_config_.video_codec_params.number_of_encode_threads; config_.g_w = frame_size.width(); config_.g_h = frame_size.height(); // Set the timebase to match that of base::TimeDelta. @@ -147,8 +149,8 @@ config_.rc_resize_allowed = 0; // TODO(miu): Why not? Investigate this. config_.rc_end_usage = VPX_CBR; config_.rc_target_bitrate = bitrate_kbit_; - config_.rc_min_quantizer = cast_config_.min_qp; - config_.rc_max_quantizer = cast_config_.max_qp; + config_.rc_min_quantizer = cast_config_.video_codec_params.min_qp; + config_.rc_max_quantizer = cast_config_.video_codec_params.max_qp; // TODO(miu): Revisit these now that the encoder is being successfully // micro-managed. config_.rc_undershoot_pct = 100; @@ -351,7 +353,7 @@ double actual_encoding_speed = encoding_speed_ + kEquivalentEncodingSpeedStepPerQpStep * - std::max(0, quantizer - cast_config_.min_qp); + std::max(0, quantizer - cast_config_.video_codec_params.min_qp); double adjusted_encoding_speed = actual_encoding_speed * encoded_frame->encoder_utilization / target_encoder_utilization_; @@ -370,12 +372,13 @@ next_encoding_speed = kHighestEncodingSpeed; next_min_qp = static_cast<int>(remainder / kEquivalentEncodingSpeedStepPerQpStep + - cast_config_.min_qp + 0.5); - next_min_qp = std::min(next_min_qp, cast_config_.max_cpu_saver_qp); + cast_config_.video_codec_params.min_qp + 0.5); + next_min_qp = std::min(next_min_qp, + cast_config_.video_codec_params.max_cpu_saver_qp); } else { next_encoding_speed = std::max<double>(kLowestEncodingSpeed, next_encoding_speed) + 0.5; - next_min_qp = cast_config_.min_qp; + next_min_qp = cast_config_.video_codec_params.min_qp; } if (encoding_speed_ != static_cast<int>(next_encoding_speed)) { encoding_speed_ = static_cast<int>(next_encoding_speed);
diff --git a/media/cast/sender/vp8_encoder.h b/media/cast/sender/vp8_encoder.h index 703c22d1..df06477 100644 --- a/media/cast/sender/vp8_encoder.h +++ b/media/cast/sender/vp8_encoder.h
@@ -11,7 +11,7 @@ #include "base/macros.h" #include "base/threading/thread_checker.h" -#include "media/capture/content/feedback_signal_accumulator.h" +#include "media/base/feedback_signal_accumulator.h" #include "media/cast/cast_config.h" #include "media/cast/sender/software_video_encoder.h" #include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h" @@ -26,7 +26,7 @@ class Vp8Encoder : public SoftwareVideoEncoder { public: - explicit Vp8Encoder(const VideoSenderConfig& video_config); + explicit Vp8Encoder(const FrameSenderConfig& video_config); ~Vp8Encoder() final; @@ -51,7 +51,7 @@ // |encoder_| instance. void ConfigureForNewFrameSize(const gfx::Size& frame_size); - const VideoSenderConfig cast_config_; + const FrameSenderConfig cast_config_; const double target_encoder_utilization_;
diff --git a/media/cast/sender/vp8_quantizer_parser_unittest.cc b/media/cast/sender/vp8_quantizer_parser_unittest.cc index e323a89..65db392 100644 --- a/media/cast/sender/vp8_quantizer_parser_unittest.cc +++ b/media/cast/sender/vp8_quantizer_parser_unittest.cc
@@ -26,14 +26,14 @@ const int kFrameRate = 10; const int kQp = 20; -VideoSenderConfig GetVideoConfigForTest() { - VideoSenderConfig config = GetDefaultVideoSenderConfig(); +FrameSenderConfig GetVideoConfigForTest() { + FrameSenderConfig config = GetDefaultVideoSenderConfig(); config.codec = CODEC_VIDEO_VP8; config.use_external_encoder = false; config.max_frame_rate = kFrameRate; - config.min_qp = kQp; - config.max_qp = kQp; - config.max_cpu_saver_qp = kQp; + config.video_codec_params.min_qp = kQp; + config.video_codec_params.max_qp = kQp; + config.video_codec_params.max_cpu_saver_qp = kQp; return config; } } // unnamed namespace @@ -58,9 +58,9 @@ // Update the vp8 encoder with the new quantizer. void UpdateQuantizer(int qp) { DCHECK((qp > 3) && (qp < 64)); - video_config_.min_qp = qp; - video_config_.max_qp = qp; - video_config_.max_cpu_saver_qp = qp; + video_config_.video_codec_params.min_qp = qp; + video_config_.video_codec_params.max_qp = qp; + video_config_.video_codec_params.max_cpu_saver_qp = qp; RecreateVp8Encoder(); } @@ -79,7 +79,7 @@ } base::TimeDelta next_frame_timestamp_; - VideoSenderConfig video_config_; + FrameSenderConfig video_config_; std::unique_ptr<Vp8Encoder> vp8_encoder_; DISALLOW_COPY_AND_ASSIGN(Vp8QuantizerParserTest);
diff --git a/media/cast/test/cast_benchmarks.cc b/media/cast/test/cast_benchmarks.cc index 4bebe4a0..018b287c2 100644 --- a/media/cast/test/cast_benchmarks.cc +++ b/media/cast/test/cast_benchmarks.cc
@@ -258,8 +258,9 @@ video_receiver_config_.rtp_max_delay_ms = kTargetPlayoutDelayMs; video_receiver_config_.codec = video_codec; - frame_duration_ = base::TimeDelta::FromSeconds(1) / - video_sender_config_.max_frame_rate; + DCHECK_GT(video_sender_config_.max_frame_rate, 0); + frame_duration_ = base::TimeDelta::FromSecondsD( + 1.0 / video_sender_config_.max_frame_rate); } void SetSenderClockSkew(double skew, base::TimeDelta offset) { @@ -285,8 +286,8 @@ } base::TimeDelta VideoTimestamp(int frame_number) { - return (frame_number * base::TimeDelta::FromSeconds(1)) / - video_sender_config_.max_frame_rate; + return frame_number * base::TimeDelta::FromSecondsD( + 1.0 / video_sender_config_.max_frame_rate); } void SendFakeVideoFrame() { @@ -410,8 +411,8 @@ private: FrameReceiverConfig audio_receiver_config_; FrameReceiverConfig video_receiver_config_; - AudioSenderConfig audio_sender_config_; - VideoSenderConfig video_sender_config_; + FrameSenderConfig audio_sender_config_; + FrameSenderConfig video_sender_config_; base::TimeTicks start_time_;
diff --git a/media/cast/test/end2end_unittest.cc b/media/cast/test/end2end_unittest.cc index c29e3cc..c101232 100644 --- a/media/cast/test/end2end_unittest.cc +++ b/media/cast/test/end2end_unittest.cc
@@ -432,15 +432,15 @@ } void Configure(Codec video_codec, Codec audio_codec) { - audio_sender_config_.ssrc = 1; + audio_sender_config_.sender_ssrc = 1; audio_sender_config_.receiver_ssrc = 2; audio_sender_config_.max_playout_delay = base::TimeDelta::FromMilliseconds(kTargetPlayoutDelayMs); audio_sender_config_.rtp_payload_type = RtpPayloadType::AUDIO_OPUS; audio_sender_config_.use_external_encoder = false; - audio_sender_config_.frequency = kDefaultAudioSamplingRate; + audio_sender_config_.rtp_timebase = kDefaultAudioSamplingRate; audio_sender_config_.channels = kAudioChannels; - audio_sender_config_.bitrate = kDefaultAudioEncoderBitrate; + audio_sender_config_.max_bitrate = kDefaultAudioEncoderBitrate; audio_sender_config_.codec = audio_codec; audio_sender_config_.aes_iv_mask = ConvertFromBase16String("abcdeffedcba12345678900987654321"); @@ -449,11 +449,11 @@ audio_receiver_config_.receiver_ssrc = audio_sender_config_.receiver_ssrc; - audio_receiver_config_.sender_ssrc = audio_sender_config_.ssrc; + audio_receiver_config_.sender_ssrc = audio_sender_config_.sender_ssrc; audio_receiver_config_.rtp_max_delay_ms = kTargetPlayoutDelayMs; audio_receiver_config_.rtp_payload_type = audio_sender_config_.rtp_payload_type; - audio_receiver_config_.rtp_timebase = audio_sender_config_.frequency; + audio_receiver_config_.rtp_timebase = audio_sender_config_.rtp_timebase; audio_receiver_config_.channels = kAudioChannels; audio_receiver_config_.target_frame_rate = 100; audio_receiver_config_.codec = audio_sender_config_.codec; @@ -463,7 +463,7 @@ test_receiver_audio_callback_->SetExpectedSamplingFrequency( audio_receiver_config_.rtp_timebase); - video_sender_config_.ssrc = 3; + video_sender_config_.sender_ssrc = 3; video_sender_config_.receiver_ssrc = 4; video_sender_config_.max_playout_delay = base::TimeDelta::FromMilliseconds(kTargetPlayoutDelayMs); @@ -472,8 +472,8 @@ video_sender_config_.max_bitrate = 50000; video_sender_config_.min_bitrate = 10000; video_sender_config_.start_bitrate = 10000; - video_sender_config_.max_qp = 30; - video_sender_config_.min_qp = 4; + video_sender_config_.video_codec_params.max_qp = 30; + video_sender_config_.video_codec_params.min_qp = 4; video_sender_config_.max_frame_rate = 30; video_sender_config_.codec = video_codec; video_sender_config_.aes_iv_mask = @@ -483,7 +483,7 @@ video_receiver_config_.receiver_ssrc = video_sender_config_.receiver_ssrc; - video_receiver_config_.sender_ssrc = video_sender_config_.ssrc; + video_receiver_config_.sender_ssrc = video_sender_config_.sender_ssrc; video_receiver_config_.rtp_max_delay_ms = kTargetPlayoutDelayMs; video_receiver_config_.rtp_payload_type = video_sender_config_.rtp_payload_type; @@ -834,8 +834,8 @@ FrameReceiverConfig audio_receiver_config_; FrameReceiverConfig video_receiver_config_; - AudioSenderConfig audio_sender_config_; - VideoSenderConfig video_sender_config_; + FrameSenderConfig audio_sender_config_; + FrameSenderConfig video_sender_config_; base::TimeTicks start_time_; @@ -958,7 +958,7 @@ video_frame_input_ = cast_sender_->video_frame_input(); audio_bus_factory_.reset(new TestAudioBusFactory( - audio_sender_config_.channels, audio_sender_config_.frequency, + audio_sender_config_.channels, audio_sender_config_.rtp_timebase, kSoundFrequency, kSoundVolume)); }
diff --git a/media/cast/test/fake_media_source.cc b/media/cast/test/fake_media_source.cc index d038eda..006b12ba 100644 --- a/media/cast/test/fake_media_source.cc +++ b/media/cast/test/fake_media_source.cc
@@ -76,15 +76,15 @@ FakeMediaSource::FakeMediaSource( scoped_refptr<base::SingleThreadTaskRunner> task_runner, base::TickClock* clock, - const AudioSenderConfig& audio_config, - const VideoSenderConfig& video_config, + const FrameSenderConfig& audio_config, + const FrameSenderConfig& video_config, bool keep_frames) : task_runner_(task_runner), output_audio_params_(AudioParameters::AUDIO_PCM_LINEAR, media::GuessChannelLayout(audio_config.channels), - audio_config.frequency, + audio_config.rtp_timebase, 32, - audio_config.frequency / kAudioPacketsPerSecond), + audio_config.rtp_timebase / kAudioPacketsPerSecond), video_config_(video_config), keep_frames_(keep_frames), variable_frame_size_mode_(false), @@ -102,10 +102,9 @@ video_first_pts_set_(false), weak_factory_(this) { CHECK(output_audio_params_.IsValid()); - audio_bus_factory_.reset(new TestAudioBusFactory(audio_config.channels, - audio_config.frequency, - kSoundFrequency, - kSoundVolume)); + audio_bus_factory_.reset( + new TestAudioBusFactory(audio_config.channels, audio_config.rtp_timebase, + kSoundFrequency, kSoundVolume)); } FakeMediaSource::~FakeMediaSource() {
diff --git a/media/cast/test/fake_media_source.h b/media/cast/test/fake_media_source.h index 8fb9fab..f8affbd 100644 --- a/media/cast/test/fake_media_source.h +++ b/media/cast/test/fake_media_source.h
@@ -55,8 +55,8 @@ // |keep_frames| is true if all VideoFrames are saved in a queue. FakeMediaSource(scoped_refptr<base::SingleThreadTaskRunner> task_runner, base::TickClock* clock, - const AudioSenderConfig& audio_config, - const VideoSenderConfig& video_config, + const FrameSenderConfig& audio_config, + const FrameSenderConfig& video_config, bool keep_frames); ~FakeMediaSource() final; @@ -71,7 +71,7 @@ void Start(scoped_refptr<AudioFrameInput> audio_frame_input, scoped_refptr<VideoFrameInput> video_frame_input); - const VideoSenderConfig& get_video_config() const { return video_config_; } + const FrameSenderConfig& get_video_config() const { return video_config_; } scoped_refptr<media::VideoFrame> PopOldestInsertedVideoFrame(); @@ -118,7 +118,7 @@ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; const media::AudioParameters output_audio_params_; - const VideoSenderConfig video_config_; + const FrameSenderConfig video_config_; const bool keep_frames_; bool variable_frame_size_mode_; gfx::Size current_frame_size_;
diff --git a/media/cast/test/sender.cc b/media/cast/test/sender.cc index 0938377..b2be793 100644 --- a/media/cast/test/sender.cc +++ b/media/cast/test/sender.cc
@@ -224,9 +224,9 @@ LOG(INFO) << "Sending to " << remote_ip_address << ":" << remote_port << "."; - media::cast::AudioSenderConfig audio_config = + media::cast::FrameSenderConfig audio_config = media::cast::GetDefaultAudioSenderConfig(); - media::cast::VideoSenderConfig video_config = + media::cast::FrameSenderConfig video_config = media::cast::GetDefaultVideoSenderConfig(); // Running transport on the main thread.
diff --git a/media/cast/test/simulator.cc b/media/cast/test/simulator.cc index 0e2f1ea..160eae65 100644 --- a/media/cast/test/simulator.cc +++ b/media/cast/test/simulator.cc
@@ -356,7 +356,7 @@ sender_env->logger()->Subscribe(&video_event_subscriber); // Audio sender config. - AudioSenderConfig audio_sender_config = GetDefaultAudioSenderConfig(); + FrameSenderConfig audio_sender_config = GetDefaultAudioSenderConfig(); audio_sender_config.min_playout_delay = audio_sender_config.max_playout_delay = base::TimeDelta::FromMilliseconds( GetIntegerSwitchValue(kTargetDelay, 400)); @@ -368,7 +368,7 @@ audio_sender_config.max_playout_delay.InMilliseconds(); // Video sender config. - VideoSenderConfig video_sender_config = GetDefaultVideoSenderConfig(); + FrameSenderConfig video_sender_config = GetDefaultVideoSenderConfig(); video_sender_config.max_bitrate = 2500000; video_sender_config.min_bitrate = 2000000; video_sender_config.start_bitrate = 2000000;
diff --git a/media/cast/test/utility/default_config.cc b/media/cast/test/utility/default_config.cc index 30768b0..c89afb7 100644 --- a/media/cast/test/utility/default_config.cc +++ b/media/cast/test/utility/default_config.cc
@@ -55,38 +55,41 @@ return config; } -AudioSenderConfig GetDefaultAudioSenderConfig() { +FrameSenderConfig GetDefaultAudioSenderConfig() { FrameReceiverConfig recv_config = GetDefaultAudioReceiverConfig(); - AudioSenderConfig config; - config.ssrc = recv_config.sender_ssrc; + FrameSenderConfig config; + config.sender_ssrc = recv_config.sender_ssrc; config.receiver_ssrc = recv_config.receiver_ssrc; config.rtp_payload_type = recv_config.rtp_payload_type; config.use_external_encoder = false; - config.frequency = recv_config.rtp_timebase; + config.rtp_timebase = recv_config.rtp_timebase; config.channels = recv_config.channels; - config.bitrate = kDefaultAudioEncoderBitrate; + config.max_bitrate = config.min_bitrate = config.start_bitrate = + kDefaultAudioEncoderBitrate; + config.max_frame_rate = recv_config.target_frame_rate; config.codec = recv_config.codec; - config.max_playout_delay = - base::TimeDelta::FromMilliseconds(kDefaultRtpMaxDelayMs); return config; } -VideoSenderConfig GetDefaultVideoSenderConfig() { +FrameSenderConfig GetDefaultVideoSenderConfig() { FrameReceiverConfig recv_config = GetDefaultVideoReceiverConfig(); - VideoSenderConfig config; - config.ssrc = recv_config.sender_ssrc; + FrameSenderConfig config; + config.sender_ssrc = recv_config.sender_ssrc; config.receiver_ssrc = recv_config.receiver_ssrc; config.rtp_payload_type = recv_config.rtp_payload_type; config.use_external_encoder = false; - config.max_bitrate = 4000000; - config.min_bitrate = 2000000; - config.start_bitrate = 4000000; + config.rtp_timebase = recv_config.rtp_timebase; + config.max_bitrate = kDefaultMaxVideoBitrate; + config.min_bitrate = kDefaultMinVideoBitrate; + config.start_bitrate = config.max_bitrate; config.max_frame_rate = recv_config.target_frame_rate; - config.max_number_of_video_buffers_used = 1; config.codec = recv_config.codec; - config.number_of_encode_threads = 2; - config.max_playout_delay = - base::TimeDelta::FromMilliseconds(kDefaultRtpMaxDelayMs); + config.video_codec_params.max_qp = kDefaultMaxQp; + config.video_codec_params.min_qp = kDefaultMinQp; + config.video_codec_params.max_cpu_saver_qp = kDefaultMaxCpuSaverQp; + config.video_codec_params.max_number_of_video_buffers_used = + kDefaultNumberOfVideoBuffers; + config.video_codec_params.number_of_encode_threads = 2; return config; }
diff --git a/media/cast/test/utility/default_config.h b/media/cast/test/utility/default_config.h index 2cc52a7..0357a973 100644 --- a/media/cast/test/utility/default_config.h +++ b/media/cast/test/utility/default_config.h
@@ -20,14 +20,14 @@ // name. FrameReceiverConfig GetDefaultVideoReceiverConfig(); -// Returns a AudioSenderConfig initialized to default values. This means +// Returns a FrameSenderConfig initialized to default values. This means // 48 kHz, 2-channel Opus-coded audio. Default values for SSRCs and payload // type. -AudioSenderConfig GetDefaultAudioSenderConfig(); +FrameSenderConfig GetDefaultAudioSenderConfig(); -// Returns a VideoSenderConfig initialized to default values. This means +// Returns a FrameSenderConfig initialized to default values. This means // 30 Hz VP8 coded code. Default values for SSRCs and payload type. -VideoSenderConfig GetDefaultVideoSenderConfig(); +FrameSenderConfig GetDefaultVideoSenderConfig(); // Returns a callback that does nothing. CreateVideoEncodeAcceleratorCallback
diff --git a/media/filters/android/media_codec_audio_decoder.cc b/media/filters/android/media_codec_audio_decoder.cc index 01c0b08..d67088d 100644 --- a/media/filters/android/media_codec_audio_decoder.cc +++ b/media/filters/android/media_codec_audio_decoder.cc
@@ -321,14 +321,25 @@ input_data.presentation_time = decoder_buffer->timestamp(); } - // Note that for EOS, the completion callback will be delayed until the EOS - // actually arrives on the output queue. - input_data.completion_cb = input_queue_.front().second; - input_queue_.pop_front(); + // We do not pop |input_queue_| here. MediaCodecLoop may refer to data that + // it owns until OnInputDataQueued is called. return input_data; } +void MediaCodecAudioDecoder::OnInputDataQueued(bool success) { + // If this is an EOS buffer, then wait to call back until we are notified that + // it has been processed via OnDecodedEos(). If the EOS was not queued + // successfully, then we do want to signal error now since there is no queued + // EOS to process later. + if (input_queue_.front().first->end_of_stream() && success) + return; + + input_queue_.front().second.Run(success ? DecodeStatus::OK + : DecodeStatus::DECODE_ERROR); + input_queue_.pop_front(); +} + void MediaCodecAudioDecoder::ClearInputQueue(DecodeStatus decode_status) { DVLOG(2) << __FUNCTION__; @@ -353,6 +364,11 @@ void MediaCodecAudioDecoder::OnDecodedEos( const MediaCodecLoop::OutputBuffer& out) { DVLOG(2) << __FUNCTION__ << " pts:" << out.pts; + + DCHECK(input_queue_.size()); + DCHECK(input_queue_.front().first->end_of_stream()); + input_queue_.front().second.Run(DecodeStatus::OK); + input_queue_.pop_front(); } bool MediaCodecAudioDecoder::OnDecodedFrame(
diff --git a/media/filters/android/media_codec_audio_decoder.h b/media/filters/android/media_codec_audio_decoder.h index d19fdf5..f9c7842b 100644 --- a/media/filters/android/media_codec_audio_decoder.h +++ b/media/filters/android/media_codec_audio_decoder.h
@@ -96,6 +96,7 @@ // MediaCodecLoop::Client implementation bool IsAnyInputPending() const override; MediaCodecLoop::InputData ProvideInputData() override; + void OnInputDataQueued(bool) override; void OnDecodedEos(const MediaCodecLoop::OutputBuffer& out) override; bool OnDecodedFrame(const MediaCodecLoop::OutputBuffer& out) override; bool OnOutputFormatChanged() override;
diff --git a/media/filters/audio_renderer_algorithm.cc b/media/filters/audio_renderer_algorithm.cc index df2e5369..ebe334a 100644 --- a/media/filters/audio_renderer_algorithm.cc +++ b/media/filters/audio_renderer_algorithm.cc
@@ -146,6 +146,7 @@ if (playback_rate == 0) return 0; + DCHECK_GT(playback_rate, 0); DCHECK_EQ(channels_, dest->channels()); // Optimize the muted case to issue a single clear instead of performing @@ -160,7 +161,10 @@ // only skip over complete frames, so a partial frame may remain for next // time. muted_partial_frame_ += frames_to_render * playback_rate; - int seek_frames = static_cast<int>(muted_partial_frame_); + // Handle the case where muted_partial_frame_ rounds up to + // audio_buffer_.frames()+1. + int seek_frames = std::min(static_cast<int>(muted_partial_frame_), + audio_buffer_.frames()); dest->ZeroFramesPartial(dest_offset, frames_to_render); audio_buffer_.SeekFrames(seek_frames);
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn index 31e23274..666f207 100644 --- a/media/gpu/BUILD.gn +++ b/media/gpu/BUILD.gn
@@ -131,6 +131,9 @@ if (is_chromeos && use_v4lplugin) { defines += [ "USE_LIBV4L2" ] } + if (is_chromeos && use_v4l2_codec) { + defines += [ "USE_V4L2_CODEC" ] + } } component("gpu") { @@ -257,7 +260,6 @@ deps += [ ":libv4l2_generate_stubs" ] } if (use_v4l2_codec) { - defines += [ "USE_V4L2_CODEC" ] deps += [ "//third_party/libyuv" ] sources += [ "generic_v4l2_device.cc", @@ -383,7 +385,10 @@ "//ui/gl/init", ] - configs += [ "//third_party/khronos:khronos_headers" ] + configs += [ + "//third_party/khronos:khronos_headers", + ":gpu_config", + ] if (is_chromeos && current_cpu != "arm") { configs += [ "//third_party/libva:libva_config" ] } @@ -448,6 +453,7 @@ configs += [ "//third_party/libva:libva_config", "//third_party/libyuv:libyuv_config", + ":gpu_config", ] sources = [ "video_accelerator_unittest_helpers.h",
diff --git a/media/gpu/ipc/client/BUILD.gn b/media/gpu/ipc/client/BUILD.gn index 1480054..16dde2d 100644 --- a/media/gpu/ipc/client/BUILD.gn +++ b/media/gpu/ipc/client/BUILD.gn
@@ -12,8 +12,10 @@ "gpu_video_encode_accelerator_host.h", ] - public_configs = [ "//media/gpu:gpu_config" ] - configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] + configs += [ + "//build/config/compiler:no_size_t_to_int_warning", + "//media/gpu:gpu_config", + ] deps = [ "//base",
diff --git a/media/gpu/ipc/service/BUILD.gn b/media/gpu/ipc/service/BUILD.gn index 17acc26..0b167ed 100644 --- a/media/gpu/ipc/service/BUILD.gn +++ b/media/gpu/ipc/service/BUILD.gn
@@ -38,6 +38,8 @@ "//third_party/mesa:mesa_headers", ] + configs += [ "//media/gpu:gpu_config" ] + if (is_chromeos && current_cpu != "arm") { configs += [ "//third_party/libva:libva_config" ] }
diff --git a/media/gpu/video_encode_accelerator_unittest.cc b/media/gpu/video_encode_accelerator_unittest.cc index f32fc45a..eb13008 100644 --- a/media/gpu/video_encode_accelerator_unittest.cc +++ b/media/gpu/video_encode_accelerator_unittest.cc
@@ -50,7 +50,7 @@ #include "testing/gtest/include/gtest/gtest.h" #if defined(OS_CHROMEOS) -#if defined(ARCH_CPU_ARMEL) || (defined(USE_OZONE) && defined(USE_V4L2_CODEC)) +#if defined(USE_V4L2_CODEC) #include "media/gpu/v4l2_video_encode_accelerator.h" #endif #if defined(ARCH_CPU_X86_FAMILY) @@ -1078,8 +1078,7 @@ std::unique_ptr<VideoEncodeAccelerator> VEAClient::CreateV4L2VEA() { std::unique_ptr<VideoEncodeAccelerator> encoder; -#if defined(OS_CHROMEOS) && (defined(ARCH_CPU_ARMEL) || \ - (defined(USE_OZONE) && defined(USE_V4L2_CODEC))) +#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC) scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kEncoder); if (device) encoder.reset(new V4L2VideoEncodeAccelerator(device));
diff --git a/media/media.gyp b/media/media.gyp index d2baca7..1c02bdc1 100644 --- a/media/media.gyp +++ b/media/media.gyp
@@ -342,6 +342,7 @@ 'base/eme_constants.h', 'base/encryption_scheme.cc', 'base/encryption_scheme.h', + 'base/feedback_signal_accumulator.h', 'base/key_system_names.cc', 'base/key_system_names.h', 'base/key_system_properties.cc', @@ -1121,7 +1122,7 @@ 'base/audio_fifo_unittest.cc', 'base/audio_hardware_config_unittest.cc', 'base/audio_hash_unittest.cc', - 'base/audio_latency_unittest.cc', + 'base/audio_latency_unittest.cc', 'base/audio_parameters_unittest.cc', 'base/audio_point_unittest.cc', 'base/audio_pull_fifo_unittest.cc', @@ -1145,6 +1146,7 @@ 'base/decoder_buffer_unittest.cc', 'base/djb2_unittest.cc', 'base/fake_demuxer_stream_unittest.cc', + 'base/feedback_signal_accumulator_unittest.cc', 'base/gmock_callback_support_unittest.cc', 'base/key_systems_unittest.cc', 'base/mac/video_frame_mac_unittests.cc', @@ -1357,6 +1359,22 @@ '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck', ], }], + ['use_cras==1', { + 'dependencies': [ + '../chromeos/chromeos.gyp:chromeos', + ], + 'cflags': [ + '<!@(<(pkg-config) --cflags libcras)', + ], + 'link_settings': { + 'libraries': [ + '<!@(<(pkg-config) --libs libcras)', + ], + }, + 'defines': [ + 'USE_CRAS', + ], + }], ], }, {
diff --git a/media/media_gpu.gypi b/media/media_gpu.gypi index 8bea3e23..a11084b 100644 --- a/media/media_gpu.gypi +++ b/media/media_gpu.gypi
@@ -11,6 +11,7 @@ '../gpu/gpu.gyp:gpu', '../media/media.gyp:media', '../ui/display/display.gyp:display_types', + '../ui/gfx/gfx.gyp:gfx', '../ui/gfx/gfx.gyp:gfx_geometry', '../ui/gl/gl.gyp:gl', '../ui/gl/init/gl_init.gyp:gl_init',
diff --git a/media/mojo/interfaces/image_capture.mojom b/media/mojo/interfaces/image_capture.mojom index f712837..3546651c 100644 --- a/media/mojo/interfaces/image_capture.mojom +++ b/media/mojo/interfaces/image_capture.mojom
@@ -13,10 +13,14 @@ uint32 current; }; +// https://w3c.github.io/mediacapture-image/#idl-def-FocusMode +enum FocusMode { UNAVAILABLE, AUTO, MANUAL }; + // Equivalent to idl PhotoCapabilities, // https://w3c.github.io/mediacapture-image/#photocapabilities struct PhotoCapabilities { Range zoom; + FocusMode focus_mode; }; // Equivalent to idl PhotoSettings,
diff --git a/media/mojo/interfaces/service_factory.mojom b/media/mojo/interfaces/service_factory.mojom index b55e284..ebcf5248d 100644 --- a/media/mojo/interfaces/service_factory.mojom +++ b/media/mojo/interfaces/service_factory.mojom
@@ -19,7 +19,10 @@ CreateVideoDecoder(VideoDecoder& video_decoder); // Creates a Renderer service. - CreateRenderer(Renderer& renderer); + // Audio stream will be played on device_id, which is defined in + // media/audio/audio_device_description.h. If audio_device_id + // is empty, kDefaultDeviceId will be used. + CreateRenderer(string audio_device_id, Renderer& renderer); // Creates a ContentDecryptionModule service. CreateCdm(ContentDecryptionModule& cdm);
diff --git a/media/mojo/services/media_mojo_unittest.cc b/media/mojo/services/media_mojo_unittest.cc index 6553dd8c..12db5dd6 100644 --- a/media/mojo/services/media_mojo_unittest.cc +++ b/media/mojo/services/media_mojo_unittest.cc
@@ -104,7 +104,7 @@ void InitializeRenderer(const VideoDecoderConfig& video_config, bool expected_result) { - service_factory_->CreateRenderer(mojo::GetProxy(&renderer_)); + service_factory_->CreateRenderer(std::string(), mojo::GetProxy(&renderer_)); video_stream_.set_video_decoder_config(video_config);
diff --git a/media/mojo/services/mojo_media_client.cc b/media/mojo/services/mojo_media_client.cc index 8ab4198a..d006960c 100644 --- a/media/mojo/services/mojo_media_client.cc +++ b/media/mojo/services/mojo_media_client.cc
@@ -7,7 +7,8 @@ #include "base/single_thread_task_runner.h" #include "media/base/audio_decoder.h" #include "media/base/cdm_factory.h" -#include "media/base/renderer_factory.h" +#include "media/base/media_log.h" +#include "media/base/renderer.h" #include "media/base/video_decoder.h" namespace media { @@ -30,17 +31,10 @@ return nullptr; } -std::unique_ptr<RendererFactory> MojoMediaClient::CreateRendererFactory( - const scoped_refptr<MediaLog>& media_log) { - return nullptr; -} - -AudioRendererSink* MojoMediaClient::CreateAudioRendererSink() { - return nullptr; -} - -VideoRendererSink* MojoMediaClient::CreateVideoRendererSink( - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { +std::unique_ptr<Renderer> MojoMediaClient::CreateRenderer( + scoped_refptr<base::SingleThreadTaskRunner> media_task_runner, + scoped_refptr<MediaLog> media_log, + const std::string& audio_device_id) { return nullptr; }
diff --git a/media/mojo/services/mojo_media_client.h b/media/mojo/services/mojo_media_client.h index 3e3e284..b6d0db7 100644 --- a/media/mojo/services/mojo_media_client.h +++ b/media/mojo/services/mojo_media_client.h
@@ -6,6 +6,7 @@ #define MEDIA_MOJO_SERVICES_MOJO_MEDIA_CLIENT_H_ #include <memory> +#include <string> #include "base/memory/ref_counted.h" #include "media/mojo/services/media_mojo_export.h" @@ -23,12 +24,10 @@ namespace media { class AudioDecoder; -class AudioRendererSink; class CdmFactory; class MediaLog; -class RendererFactory; +class Renderer; class VideoDecoder; -class VideoRendererSink; class MEDIA_MOJO_EXPORT MojoMediaClient { public: @@ -48,20 +47,14 @@ virtual std::unique_ptr<VideoDecoder> CreateVideoDecoder( scoped_refptr<base::SingleThreadTaskRunner> task_runner); - // TODO(xhwang): Consider creating Renderer and CDM directly in the client + // TODO(xhwang): Consider creating CDM directly in the client // instead of creating factories. See http://crbug.com/586211 - // Returns the RendererFactory to be used by MojoRendererService. - virtual std::unique_ptr<RendererFactory> CreateRendererFactory( - const scoped_refptr<MediaLog>& media_log); - - // The output sink used for rendering audio or video respectively. They will - // be used in the CreateRenderer() call on the RendererFactory returned by - // CreateRendererFactory(). May be null if the RendererFactory doesn't need an - // audio or video sink. If not null, the sink must be owned by the client. - virtual AudioRendererSink* CreateAudioRendererSink(); - virtual VideoRendererSink* CreateVideoRendererSink( - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner); + // Creates and returns a Renderer. + virtual std::unique_ptr<Renderer> CreateRenderer( + scoped_refptr<base::SingleThreadTaskRunner> media_task_runner, + scoped_refptr<MediaLog> media_log, + const std::string& audio_device_id); // Returns the CdmFactory to be used by MojoCdmService. virtual std::unique_ptr<CdmFactory> CreateCdmFactory(
diff --git a/media/mojo/services/service_factory_impl.cc b/media/mojo/services/service_factory_impl.cc index 433a8a9b..954568a 100644 --- a/media/mojo/services/service_factory_impl.cc +++ b/media/mojo/services/service_factory_impl.cc
@@ -79,24 +79,16 @@ } void ServiceFactoryImpl::CreateRenderer( + const mojo::String& audio_device_id, mojo::InterfaceRequest<mojom::Renderer> request) { #if defined(ENABLE_MOJO_RENDERER) // The created object is owned by the pipe. // The audio and video sinks are owned by the client. scoped_refptr<base::SingleThreadTaskRunner> task_runner( base::ThreadTaskRunnerHandle::Get()); - AudioRendererSink* audio_renderer_sink = - mojo_media_client_->CreateAudioRendererSink(); - VideoRendererSink* video_renderer_sink = - mojo_media_client_->CreateVideoRendererSink(task_runner); - RendererFactory* renderer_factory = GetRendererFactory(); - if (!renderer_factory) - return; - - std::unique_ptr<Renderer> renderer = renderer_factory->CreateRenderer( - task_runner, task_runner, audio_renderer_sink, video_renderer_sink, - RequestSurfaceCB()); + std::unique_ptr<Renderer> renderer = mojo_media_client_->CreateRenderer( + task_runner, media_log_, audio_device_id); if (!renderer) { LOG(ERROR) << "Renderer creation failed."; return; @@ -120,16 +112,6 @@ #endif // defined(ENABLE_MOJO_CDM) } -#if defined(ENABLE_MOJO_RENDERER) -RendererFactory* ServiceFactoryImpl::GetRendererFactory() { - if (!renderer_factory_) { - renderer_factory_ = mojo_media_client_->CreateRendererFactory(media_log_); - LOG_IF(ERROR, !renderer_factory_) << "RendererFactory not available."; - } - return renderer_factory_.get(); -} -#endif // defined(ENABLE_MOJO_RENDERER) - #if defined(ENABLE_MOJO_CDM) CdmFactory* ServiceFactoryImpl::GetCdmFactory() { if (!cdm_factory_) {
diff --git a/media/mojo/services/service_factory_impl.h b/media/mojo/services/service_factory_impl.h index 19a1e74..4796db6 100644 --- a/media/mojo/services/service_factory_impl.h +++ b/media/mojo/services/service_factory_impl.h
@@ -39,16 +39,11 @@ // mojom::ServiceFactory implementation. void CreateAudioDecoder(mojom::AudioDecoderRequest request) final; void CreateVideoDecoder(mojom::VideoDecoderRequest request) final; - void CreateRenderer(mojom::RendererRequest request) final; + void CreateRenderer(const mojo::String& audio_device_id, + mojom::RendererRequest request) final; void CreateCdm(mojom::ContentDecryptionModuleRequest request) final; private: -#if defined(ENABLE_MOJO_RENDERER) - RendererFactory* GetRendererFactory(); - - std::unique_ptr<RendererFactory> renderer_factory_; -#endif // defined(ENABLE_MOJO_RENDERER) - #if defined(ENABLE_MOJO_CDM) CdmFactory* GetCdmFactory();
diff --git a/media/mojo/services/test_mojo_media_client.cc b/media/mojo/services/test_mojo_media_client.cc index 3b4fbde..313c1f2 100644 --- a/media/mojo/services/test_mojo_media_client.cc +++ b/media/mojo/services/test_mojo_media_client.cc
@@ -5,6 +5,7 @@ #include "media/mojo/services/test_mojo_media_client.h" #include "base/memory/ptr_util.h" +#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/threading/thread_task_runner_handle.h" #include "media/audio/audio_device_description.h" @@ -13,6 +14,7 @@ #include "media/base/audio_hardware_config.h" #include "media/base/cdm_factory.h" #include "media/base/media.h" +#include "media/base/media_log.h" #include "media/base/null_video_sink.h" #include "media/base/renderer_factory.h" #include "media/cdm/default_cdm_factory.h" @@ -50,21 +52,44 @@ base::RunLoop().RunUntilIdle(); } -std::unique_ptr<RendererFactory> TestMojoMediaClient::CreateRendererFactory( - const scoped_refptr<MediaLog>& media_log) { +std::unique_ptr<Renderer> TestMojoMediaClient::CreateRenderer( + scoped_refptr<base::SingleThreadTaskRunner> media_task_runner, + scoped_refptr<MediaLog> media_log, + const std::string& audio_device_id) { DVLOG(1) << __FUNCTION__; - return base::WrapUnique(new DefaultRendererFactory( - media_log, nullptr, DefaultRendererFactory::GetGpuFactoriesCB())); + AudioRendererSink* audio_renderer_sink = GetAudioRendererSink(); + VideoRendererSink* video_renderer_sink = + GetVideoRendererSink(media_task_runner); + + RendererFactory* renderer_factory = GetRendererFactory(std::move(media_log)); + if (!renderer_factory) + return nullptr; + + return renderer_factory->CreateRenderer( + media_task_runner, media_task_runner, audio_renderer_sink, + video_renderer_sink, RequestSurfaceCB()); } -AudioRendererSink* TestMojoMediaClient::CreateAudioRendererSink() { +RendererFactory* TestMojoMediaClient::GetRendererFactory( + scoped_refptr<MediaLog> media_log) { + DVLOG(1) << __FUNCTION__; + if (!renderer_factory_) { + renderer_factory_ = base::MakeUnique<DefaultRendererFactory>( + std::move(media_log), nullptr, + DefaultRendererFactory::GetGpuFactoriesCB()); + } + + return renderer_factory_.get(); +} + +AudioRendererSink* TestMojoMediaClient::GetAudioRendererSink() { if (!audio_renderer_sink_) audio_renderer_sink_ = new AudioOutputStreamSink(); return audio_renderer_sink_.get(); } -VideoRendererSink* TestMojoMediaClient::CreateVideoRendererSink( +VideoRendererSink* TestMojoMediaClient::GetVideoRendererSink( const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { if (!video_renderer_sink_) { video_renderer_sink_ = base::WrapUnique(
diff --git a/media/mojo/services/test_mojo_media_client.h b/media/mojo/services/test_mojo_media_client.h index 90461675..7d9a142 100644 --- a/media/mojo/services/test_mojo_media_client.h +++ b/media/mojo/services/test_mojo_media_client.h
@@ -12,10 +12,16 @@ #include "media/audio/audio_manager.h" #include "media/mojo/services/mojo_media_client.h" +namespace base { +class SingleThreadTaskRunner; +} + namespace media { class AudioHardwareConfig; class AudioRendererSink; +class MediaLog; +class RendererFactory; class VideoRendererSink; // Default MojoMediaClient for MojoMediaApplication. @@ -27,16 +33,21 @@ // MojoMediaClient implementation. void Initialize() final; void WillQuit() final; - std::unique_ptr<RendererFactory> CreateRendererFactory( - const scoped_refptr<MediaLog>& media_log) final; - AudioRendererSink* CreateAudioRendererSink() final; - VideoRendererSink* CreateVideoRendererSink( - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) final; + std::unique_ptr<Renderer> CreateRenderer( + scoped_refptr<base::SingleThreadTaskRunner> media_task_runner, + scoped_refptr<MediaLog> media_log, + const std::string& audio_device_id) final; std::unique_ptr<CdmFactory> CreateCdmFactory( shell::mojom::InterfaceProvider* /* interface_provider */) final; private: + RendererFactory* GetRendererFactory(scoped_refptr<MediaLog> media_log); + AudioRendererSink* GetAudioRendererSink(); + VideoRendererSink* GetVideoRendererSink( + const scoped_refptr<base::SingleThreadTaskRunner>& task_runner); + ScopedAudioManagerPtr audio_manager_; + std::unique_ptr<RendererFactory> renderer_factory_; scoped_refptr<AudioRendererSink> audio_renderer_sink_; std::unique_ptr<VideoRendererSink> video_renderer_sink_;
diff --git a/media/renderers/skcanvas_video_renderer.cc b/media/renderers/skcanvas_video_renderer.cc index 74e72bc..5454967a 100644 --- a/media/renderers/skcanvas_video_renderer.cc +++ b/media/renderers/skcanvas_video_renderer.cc
@@ -429,22 +429,15 @@ -SkFloatToScalar(last_image_->height() * 0.5f)); } - // This is a workaround for crbug.com/524717. SkBitmaps are read back before a - // SkPicture is sent to multiple threads while SkImages are not. The long term - // solution is for Skia to provide a SkPicture filter that makes a picture - // safe for multiple CPU raster threads (skbug.com/4321). We limit the - // workaround to cases where the src frame is a texture and the canvas is - // recording. - if (last_image_.get()->getTexture() && - canvas->imageInfo().colorType() == kUnknown_SkColorType) { - SkBitmap bmp; - GrWrapTextureInBitmap(last_image_.get()->getTexture(), - last_image_.get()->width(), - last_image_.get()->height(), true, &bmp); - // Even though the bitmap is logically immutable we do not mark it as such - // because doing so would defer readback until rasterization, which will be - // on another thread and is therefore unsafe. - canvas->drawBitmap(bmp, 0, 0, &paint); + // This is a workaround for crbug.com/524717. A texture backed image is not + // safe to access on another thread or GL context. So if we're drawing into a + // recording canvas we read the texture back into CPU memory and record that + // sw image into the SkPicture. The long term solution is for Skia to provide + // a SkPicture filter that makes a picture safe for multiple CPU raster + // threads. (skbug.com/4321). + if (canvas->imageInfo().colorType() == kUnknown_SkColorType) { + sk_sp<SkImage> swImage = last_image_->makeNonTextureImage(); + canvas->drawImage(swImage, 0, 0, &paint); } else { canvas->drawImage(last_image_.get(), 0, 0, &paint); }
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc index e244dde2..b3c7349b 100644 --- a/media/test/pipeline_integration_test.cc +++ b/media/test/pipeline_integration_test.cc
@@ -716,7 +716,8 @@ connector()->ConnectToInterface("mojo:media", &media_service_factory_); mojom::RendererPtr mojo_renderer; - media_service_factory_->CreateRenderer(mojo::GetProxy(&mojo_renderer)); + media_service_factory_->CreateRenderer(std::string(), + mojo::GetProxy(&mojo_renderer)); return base::WrapUnique(new MojoRenderer(message_loop_.task_runner(), std::move(mojo_renderer)));
diff --git a/mojo/edk/system/node_channel.cc b/mojo/edk/system/node_channel.cc index eb83f2e..ce094c16 100644 --- a/mojo/edk/system/node_channel.cc +++ b/mojo/edk/system/node_channel.cc
@@ -503,7 +503,7 @@ if (payload_size <= sizeof(Header)) { - delegate_->OnChannelError(remote_node_name_); + delegate_->OnChannelError(remote_node_name_, this); return; } @@ -733,7 +733,7 @@ } DLOG(ERROR) << "Received invalid message. Closing channel."; - delegate_->OnChannelError(remote_node_name_); + delegate_->OnChannelError(remote_node_name_, this); } void NodeChannel::OnChannelError() { @@ -746,7 +746,7 @@ // to the name name after that destruction. So may a copy of // |remote_node_name_| so it can be used if |this| becomes destroyed. ports::NodeName node_name = remote_node_name_; - delegate_->OnChannelError(node_name); + delegate_->OnChannelError(node_name, this); } #if defined(OS_MACOSX) && !defined(OS_IOS)
diff --git a/mojo/edk/system/node_channel.h b/mojo/edk/system/node_channel.h index 658553c..5a5fc8a 100644 --- a/mojo/edk/system/node_channel.h +++ b/mojo/edk/system/node_channel.h
@@ -77,7 +77,8 @@ Channel::MessagePtr message) = 0; #endif - virtual void OnChannelError(const ports::NodeName& node) = 0; + virtual void OnChannelError(const ports::NodeName& node, + NodeChannel* channel) = 0; #if defined(OS_MACOSX) && !defined(OS_IOS) virtual MachPortRelay* GetMachPortRelay() = 0;
diff --git a/mojo/edk/system/node_controller.cc b/mojo/edk/system/node_controller.cc index a7f247a..28343b3a 100644 --- a/mojo/edk/system/node_controller.cc +++ b/mojo/edk/system/node_controller.cc
@@ -310,6 +310,7 @@ } scoped_refptr<NodeChannel> parent; + bool reject_merge = false; { // Hold |pending_port_merges_lock_| while getting |parent|. Otherwise, // there is a race where the parent can be set, and |pending_port_merges_| @@ -317,11 +318,21 @@ // |pending_port_merges_|. base::AutoLock lock(pending_port_merges_lock_); parent = GetParentChannel(); - if (!parent) { + if (reject_pending_merges_) { + reject_merge = true; + } else if (!parent) { pending_port_merges_.push_back(std::make_pair(token, port)); return; } } + if (reject_merge) { + node_->ClosePort(port); + DVLOG(2) << "Rejecting port merge for token " << token + << " due to closed parent channel."; + AcceptIncomingMessages(); + return; + } + parent->RequestPortMerge(port.name(), token); } @@ -495,7 +506,8 @@ } } -void NodeController::DropPeer(const ports::NodeName& name) { +void NodeController::DropPeer(const ports::NodeName& name, + NodeChannel* channel) { DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); { @@ -542,6 +554,23 @@ } } + bool is_parent; + { + base::AutoLock lock(parent_lock_); + is_parent = (name == parent_name_ || channel == bootstrap_parent_channel_); + } + // If the error comes from the parent channel, we also need to cancel any + // port merge requests, so that errors can be propagated to the message + // pipes. + if (is_parent) { + base::AutoLock lock(pending_port_merges_lock_); + reject_pending_merges_ = true; + + for (const auto& port : pending_port_merges_) + ports_to_close.push_back(port.second); + pending_port_merges_.clear(); + } + for (const auto& port : ports_to_close) node_->ClosePort(port); @@ -651,6 +680,16 @@ void NodeController::ProcessIncomingMessages() { RequestContext request_context(RequestContext::Source::SYSTEM); + + { + base::AutoLock lock(messages_lock_); + // Allow a new incoming messages processing task to be posted. This can't be + // done after AcceptIncomingMessages() otherwise a message might be missed. + // Doing it here may result in at most two tasks existing at the same time; + // this running one, and one pending in the task runner. + incoming_messages_task_posted_ = false; + } + AcceptIncomingMessages(); } @@ -708,16 +747,18 @@ // (synchronously) in response to Node's ClosePort, SendMessage, or // AcceptMessage, we flush the queue after calling any of those methods. base::AutoLock lock(messages_lock_); - schedule_pump_task = incoming_messages_.empty(); + // |io_task_runner_| may be null in tests or processes that don't require + // multi-process Mojo. + schedule_pump_task = incoming_messages_.empty() && io_task_runner_ && + !incoming_messages_task_posted_; + incoming_messages_task_posted_ |= schedule_pump_task; incoming_messages_.emplace(std::move(message)); incoming_messages_flag_.Set(true); } else { SendPeerMessage(node, std::move(message)); } - // |io_task_runner_| may be null in tests or processes that don't require - // multi-process Mojo. - if (schedule_pump_task && io_task_runner_) { + if (schedule_pump_task) { // Normally, the queue is processed after the action that added the local // message is done (i.e. SendMessage, ClosePort, etc). However, it's also // possible for a local message to be added as a result of a remote message, @@ -778,7 +819,7 @@ if (!parent) { DLOG(ERROR) << "Unexpected AcceptChild message from " << from_node; - DropPeer(from_node); + DropPeer(from_node, nullptr); return; } @@ -801,7 +842,7 @@ if (it == pending_children_.end() || token != from_node) { DLOG(ERROR) << "Received unexpected AcceptParent message from " << from_node; - DropPeer(from_node); + DropPeer(from_node, nullptr); return; } @@ -858,7 +899,7 @@ if (GetPeerChannel(client_name)) { DLOG(ERROR) << "Ignoring AddBrokerClient for known client."; - DropPeer(from_node); + DropPeer(from_node, nullptr); return; } @@ -989,7 +1030,7 @@ if (!ParsePortsMessage(channel_message.get(), &data, &num_data_bytes, &num_header_bytes, &num_payload_bytes, &num_ports_bytes)) { - DropPeer(from_node); + DropPeer(from_node, nullptr); return; } @@ -1040,7 +1081,7 @@ if (from_node == name || name == ports::kInvalidNodeName || !requestor) { DLOG(ERROR) << "Rejecting invalid OnRequestIntroduction message from " << from_node; - DropPeer(from_node); + DropPeer(from_node, nullptr); return; } @@ -1086,13 +1127,13 @@ if (!ParsePortsMessage(message.get(), &data, &num_data_bytes, &num_header_bytes, &num_payload_bytes, &num_ports_bytes)) { - DropPeer(from_node); + DropPeer(from_node, nullptr); return; } // Broadcast messages must not contain ports. if (num_ports_bytes > 0) { - DropPeer(from_node); + DropPeer(from_node, nullptr); return; } @@ -1117,7 +1158,7 @@ if (GetBrokerChannel()) { // Only the broker should be asked to relay a message. LOG(ERROR) << "Non-broker refusing to relay message."; - DropPeer(from_node); + DropPeer(from_node, nullptr); return; } @@ -1178,7 +1219,7 @@ Channel::MessagePtr message) { if (GetPeerChannel(from_node) != GetBrokerChannel()) { LOG(ERROR) << "Refusing relayed message from non-broker node."; - DropPeer(from_node); + DropPeer(from_node, nullptr); return; } @@ -1186,9 +1227,10 @@ } #endif -void NodeController::OnChannelError(const ports::NodeName& from_node) { +void NodeController::OnChannelError(const ports::NodeName& from_node, + NodeChannel* channel) { if (io_task_runner_->RunsTasksOnCurrentThread()) { - DropPeer(from_node); + DropPeer(from_node, channel); // DropPeer may have caused local port closures, so be sure to process any // pending local messages. AcceptIncomingMessages(); @@ -1196,7 +1238,7 @@ io_task_runner_->PostTask( FROM_HERE, base::Bind(&NodeController::OnChannelError, base::Unretained(this), - from_node)); + from_node, channel)); } }
diff --git a/mojo/edk/system/node_controller.h b/mojo/edk/system/node_controller.h index c96b4f44..2cdcd90 100644 --- a/mojo/edk/system/node_controller.h +++ b/mojo/edk/system/node_controller.h
@@ -153,7 +153,7 @@ void AddPeer(const ports::NodeName& name, scoped_refptr<NodeChannel> channel, bool start_channel); - void DropPeer(const ports::NodeName& name); + void DropPeer(const ports::NodeName& name, NodeChannel* channel); void SendPeerMessage(const ports::NodeName& name, ports::ScopedMessage message); void AcceptIncomingMessages(); @@ -206,7 +206,8 @@ const ports::NodeName& source_node, Channel::MessagePtr message) override; #endif - void OnChannelError(const ports::NodeName& from_node) override; + void OnChannelError(const ports::NodeName& from_node, + NodeChannel* channel) override; #if defined(OS_MACOSX) && !defined(OS_IOS) MachPortRelay* GetMachPortRelay() override; #endif @@ -246,12 +247,16 @@ // have one yet :( std::unordered_map<ports::NodeName, std::string> pending_child_tokens_; - // Guards |pending_port_merges_|. + // Guards |pending_port_merges_| and |reject_pending_merges_|. base::Lock pending_port_merges_lock_; // A set of port merge requests awaiting parent connection. std::vector<std::pair<std::string, ports::PortRef>> pending_port_merges_; + // Indicates that new merge requests should be rejected because the parent has + // disconnected. + bool reject_pending_merges_ = false; + // Guards |parent_name_| and |bootstrap_parent_channel_|. base::Lock parent_lock_; @@ -275,9 +280,12 @@ std::unordered_map<ports::NodeName, OutgoingMessageQueue> pending_relay_messages_; - // Guards |incoming_messages_|. + // Guards |incoming_messages_| and |incoming_messages_task_posted_|. base::Lock messages_lock_; std::queue<ports::ScopedMessage> incoming_messages_; + // Ensures that there is only one incoming messages task posted to the IO + // thread. + bool incoming_messages_task_posted_ = false; // Flag to fast-path checking |incoming_messages_|. AtomicFlag incoming_messages_flag_;
diff --git a/mojo/mojo_public.gyp b/mojo/mojo_public.gyp index c52d21f..005e012 100644 --- a/mojo/mojo_public.gyp +++ b/mojo/mojo_public.gyp
@@ -225,8 +225,10 @@ 'public/cpp/bindings/array_traits_wtf.h', 'public/cpp/bindings/array_traits_wtf_vector.h', 'public/cpp/bindings/lib/string_traits_wtf.cc', + 'public/cpp/bindings/lib/wtf_clone_equals_util.h', 'public/cpp/bindings/lib/wtf_serialization.h', 'public/cpp/bindings/map_traits_wtf.h', + 'public/cpp/bindings/map_traits_wtf_hash_map.h', 'public/cpp/bindings/string_traits_wtf.h', 'public/cpp/bindings/wtf_array.h', 'public/cpp/bindings/wtf_map.h',
diff --git a/mojo/mojo_public.gypi b/mojo/mojo_public.gypi index c24a98bc..b5da143 100644 --- a/mojo/mojo_public.gypi +++ b/mojo/mojo_public.gypi
@@ -36,6 +36,7 @@ 'public/cpp/bindings/lib/bindings_internal.cc', 'public/cpp/bindings/lib/bindings_internal.h', 'public/cpp/bindings/lib/buffer.h', + 'public/cpp/bindings/lib/clone_equals_util.h', 'public/cpp/bindings/lib/connector.cc', 'public/cpp/bindings/lib/control_message_handler.cc', 'public/cpp/bindings/lib/control_message_handler.h',
diff --git a/mojo/mojo_public_tests.gyp b/mojo/mojo_public_tests.gyp index ebe2b6c..c114667 100644 --- a/mojo/mojo_public_tests.gyp +++ b/mojo/mojo_public_tests.gyp
@@ -43,6 +43,7 @@ 'public/cpp/bindings/tests/rect_chromium.typemap', 'public/cpp/bindings/tests/test_native_types_chromium.typemap', ], + 'use_new_wrapper_types': 'true', }, 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], }, @@ -53,6 +54,7 @@ 'mojom_typemaps': [ 'public/cpp/bindings/tests/struct_with_traits.typemap', ], + 'use_new_wrapper_types': 'true', }, 'sources': [ 'public/interfaces/bindings/tests/struct_with_traits.mojom', @@ -87,6 +89,7 @@ 'public/interfaces/bindings/tests/test_associated_interfaces.mojom', 'public/interfaces/bindings/tests/validation_test_associated_interfaces.mojom', ], + 'use_new_wrapper_types': 'true', }, 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], }, @@ -108,6 +111,9 @@ 'sources': [ 'public/interfaces/bindings/tests/test_wtf_types.mojom', ], + 'variables': { + 'use_new_wrapper_types': 'true', + }, 'includes': [ 'mojom_bindings_generator.gypi' ], }, ], @@ -124,6 +130,7 @@ 'public/cpp/bindings/tests/test_native_types_blink.typemap', ], 'mojom_files': '<(mojo_public_test_interfaces_mojom_files)', + 'use_new_wrapper_types': 'true', }, 'includes': [ 'mojom_bindings_generator_explicit.gypi' ], }, @@ -149,6 +156,7 @@ 'type': 'static_library', 'variables': { 'for_blink': 'true', + 'use_new_wrapper_types': 'true', }, 'sources': [ 'public/interfaces/bindings/tests/test_wtf_types.mojom',
diff --git a/mojo/mojom_bindings_generator.gypi b/mojo/mojom_bindings_generator.gypi index dea1169..c8c5f15 100644 --- a/mojo/mojom_bindings_generator.gypi +++ b/mojo/mojom_bindings_generator.gypi
@@ -10,8 +10,10 @@ 'variables': { 'variables': { 'for_blink%': 'false', + 'use_new_wrapper_types%': 'false', }, 'for_blink%': '<(for_blink)', + 'use_new_wrapper_types%': '<(use_new_wrapper_types)', 'conditions': [ ['for_blink=="true"', { 'mojom_output_languages%': 'c++', @@ -29,11 +31,20 @@ 'mojom_generator_wtf_arg%': [], 'wtf_dependencies%': [], }], + ['use_new_wrapper_types=="true"', { + 'mojom_generator_new_wrappers_arg%': [ + '--use_new_wrapper_types', + ], + }, { + 'mojom_generator_new_wrappers_arg%': [], + }], ], }, 'for_blink%': '<(for_blink)', + 'use_new_wrapper_types%': '<(use_new_wrapper_types)', 'mojom_variant%': '<(mojom_variant)', 'mojom_generator_wtf_arg%': '<(mojom_generator_wtf_arg)', + 'mojom_generator_new_wrappers_arg%': '<(mojom_generator_new_wrappers_arg)', 'wtf_dependencies%': '<(wtf_dependencies)', 'mojom_output_languages%': '<(mojom_output_languages)', 'mojom_typemaps%': [], @@ -127,6 +138,7 @@ '--typemap', '<(generated_typemap_file)', '<@(mojom_generator_wtf_arg)', + '<@(mojom_generator_new_wrappers_arg)', '--bytecode_path', '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings', ],
diff --git a/mojo/mojom_bindings_generator_explicit.gypi b/mojo/mojom_bindings_generator_explicit.gypi index 06e8310..51676e9 100644 --- a/mojo/mojom_bindings_generator_explicit.gypi +++ b/mojo/mojom_bindings_generator_explicit.gypi
@@ -10,8 +10,10 @@ 'variables': { 'variables': { 'for_blink%': 'false', + 'use_new_wrapper_types%': 'false', }, 'for_blink%': 'false', + 'use_new_wrapper_types%': 'false', 'conditions': [ ['for_blink=="true"', { 'mojom_output_languages%': 'c++', @@ -29,11 +31,20 @@ 'mojom_generator_wtf_arg%': [], 'wtf_dependencies%': [], }], + ['use_new_wrapper_types=="true"', { + 'mojom_generator_new_wrappers_arg%': [ + '--use_new_wrapper_types', + ], + }, { + 'mojom_generator_new_wrappers_arg%': [], + }], ], }, 'for_blink%': '<(for_blink)', + 'use_new_wrapper_types%': '<(use_new_wrapper_types)', 'mojom_variant%': '<(mojom_variant)', 'mojom_generator_wtf_arg%': '<(mojom_generator_wtf_arg)', + 'mojom_generator_new_wrappers_arg%': '<(mojom_generator_new_wrappers_arg)', 'wtf_dependencies%': '<(wtf_dependencies)', 'mojom_output_languages%': '<(mojom_output_languages)', 'mojom_typemaps%': [], @@ -121,6 +132,7 @@ '--typemap', '<(generated_typemap_file)', '<@(mojom_generator_wtf_arg)', + '<@(mojom_generator_new_wrappers_arg)', '--bytecode_path', '<(SHARED_INTERMEDIATE_DIR)/mojo/public/tools/bindings', ],
diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn index 84f55bec..e18e144 100644 --- a/mojo/public/cpp/bindings/BUILD.gn +++ b/mojo/public/cpp/bindings/BUILD.gn
@@ -36,6 +36,7 @@ "lib/bindings_internal.cc", "lib/bindings_internal.h", "lib/buffer.h", + "lib/clone_equals_util.h", "lib/connector.cc", "lib/control_message_handler.cc", "lib/control_message_handler.h", @@ -147,8 +148,10 @@ "array_traits_wtf.h", "array_traits_wtf_vector.h", "lib/string_traits_wtf.cc", + "lib/wtf_clone_equals_util.h", "lib/wtf_serialization.h", "map_traits_wtf.h", + "map_traits_wtf_hash_map.h", "string_traits_wtf.h", "wtf_array.h", "wtf_map.h",
diff --git a/mojo/public/cpp/bindings/array.h b/mojo/public/cpp/bindings/array.h index ed8bdb59..a253da1 100644 --- a/mojo/public/cpp/bindings/array.h +++ b/mojo/public/cpp/bindings/array.h
@@ -16,6 +16,7 @@ #include "base/macros.h" #include "mojo/public/cpp/bindings/lib/array_internal.h" #include "mojo/public/cpp/bindings/lib/bindings_internal.h" +#include "mojo/public/cpp/bindings/lib/clone_equals_util.h" #include "mojo/public/cpp/bindings/lib/template_util.h" #include "mojo/public/cpp/bindings/type_converter.h" @@ -137,14 +138,13 @@ const std::vector<T>& storage() const { return vec_; } // Passes the underlying storage and resets this array to null. - // - // TODO(yzshen): Consider changing this to a rvalue-ref-qualified conversion - // to std::vector<T> after we move to MSVC 2015. std::vector<T> PassStorage() { is_null_ = true; return std::move(vec_); } + operator const std::vector<T>&() const { return vec_; } + void Swap(Array* other) { std::swap(is_null_, other->is_null_); vec_.swap(other->vec_); @@ -169,10 +169,8 @@ Array Clone() const { Array result; result.is_null_ = is_null_; - result.vec_.reserve(vec_.size()); - for (const auto& element : vec_) - result.vec_.push_back(internal::Clone(element)); - return std::move(result); + result.vec_ = internal::Clone(vec_); + return result; } // Indicates whether the contents of this array are equal to |other|. A null @@ -181,13 +179,7 @@ bool Equals(const Array& other) const { if (is_null() != other.is_null()) return false; - if (size() != other.size()) - return false; - for (size_t i = 0; i < size(); ++i) { - if (!internal::Equals(at(i), other.at(i))) - return false; - } - return true; + return internal::Equals(vec_, other.vec_); } private:
diff --git a/mojo/public/cpp/bindings/array_traits_stl.h b/mojo/public/cpp/bindings/array_traits_stl.h index 51af5ad..9054a92 100644 --- a/mojo/public/cpp/bindings/array_traits_stl.h +++ b/mojo/public/cpp/bindings/array_traits_stl.h
@@ -43,7 +43,16 @@ } static bool Resize(std::vector<T>& input, size_t size) { - input.resize(size); + if (input.size() != size) { + // This is a hack to make compilers for Mac and Android happy. They + // currently don't allow resizing types like + // std::vector<std::vector<MoveOnlyType>>. + // Because the deserialization code doesn't care about the original + // contents of |input|, we discard them directly. + std::vector<T> temp(size); + input.swap(temp); + } + return true; } };
diff --git a/mojo/public/cpp/bindings/lib/bindings_internal.h b/mojo/public/cpp/bindings/lib/bindings_internal.h index b32cf694..b37d8727 100644 --- a/mojo/public/cpp/bindings/lib/bindings_internal.h +++ b/mojo/public/cpp/bindings/lib/bindings_internal.h
@@ -7,6 +7,9 @@ #include <stdint.h> +#include <functional> + +#include "base/template_util.h" #include "mojo/public/cpp/bindings/interface_id.h" #include "mojo/public/cpp/bindings/lib/template_util.h" #include "mojo/public/cpp/system/core.h" @@ -315,6 +318,16 @@ static_cast<uint32_t>(MojomTypeTraits<T>::category & categories) != 0; }; +template <typename T> +struct EnumHashImpl { + static_assert(std::is_enum<T>::value, "Incorrect hash function."); + + size_t operator()(T input) const { + using UnderlyingType = typename base::underlying_type<T>::type; + return std::hash<UnderlyingType>()(static_cast<UnderlyingType>(input)); + } +}; + } // namespace internal } // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/clone_equals_util.h b/mojo/public/cpp/bindings/lib/clone_equals_util.h new file mode 100644 index 0000000..f7bd898c3 --- /dev/null +++ b/mojo/public/cpp/bindings/lib/clone_equals_util.h
@@ -0,0 +1,161 @@ +// 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 MOJO_PUBLIC_CPP_BINDINGS_LIB_CLONE_EQUALS_UTIL_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_LIB_CLONE_EQUALS_UTIL_H_ + +#include <type_traits> +#include <unordered_map> +#include <vector> + +#include "base/optional.h" +#include "mojo/public/cpp/bindings/lib/template_util.h" + +namespace mojo { +namespace internal { + +template <typename T> +struct HasCloneMethod { + template <typename U> + static char Test(decltype(&U::Clone)); + template <typename U> + static int Test(...); + static const bool value = sizeof(Test<T>(0)) == sizeof(char); + + private: + EnsureTypeIsComplete<T> check_t_; +}; + +template <typename T, bool has_clone_method = HasCloneMethod<T>::value> +struct CloneTraits; + +template <typename T> +T Clone(const T& input); + +template <typename T> +struct CloneTraits<T, true> { + static T Clone(const T& input) { return input.Clone(); } +}; + +template <typename T> +struct CloneTraits<T, false> { + static T Clone(const T& input) { return input; } +}; + +template <typename T> +struct CloneTraits<base::Optional<T>, false> { + static base::Optional<T> Clone(const base::Optional<T>& input) { + if (!input) + return base::nullopt; + + return base::Optional<T>(internal::Clone(*input)); + } +}; + +template <typename T> +struct CloneTraits<std::vector<T>, false> { + static std::vector<T> Clone(const std::vector<T>& input) { + std::vector<T> result; + result.reserve(input.size()); + for (const auto& element : input) + result.push_back(internal::Clone(element)); + + return result; + } +}; + +template <typename K, typename V> +struct CloneTraits<std::unordered_map<K, V>, false> { + static std::unordered_map<K, V> Clone(const std::unordered_map<K, V>& input) { + std::unordered_map<K, V> result; + for (const auto& element : input) { + result.insert(std::make_pair(internal::Clone(element.first), + internal::Clone(element.second))); + } + return result; + } +}; + +template <typename T> +T Clone(const T& input) { + return CloneTraits<T>::Clone(input); +}; + +template <typename T> +struct HasEqualsMethod { + template <typename U> + static char Test(decltype(&U::Equals)); + template <typename U> + static int Test(...); + static const bool value = sizeof(Test<T>(0)) == sizeof(char); + + private: + EnsureTypeIsComplete<T> check_t_; +}; + +template <typename T, bool has_equals_method = HasEqualsMethod<T>::value> +struct EqualsTraits; + +template <typename T> +bool Equals(const T& a, const T& b); + +template <typename T> +struct EqualsTraits<T, true> { + static bool Equals(const T& a, const T& b) { return a.Equals(b); } +}; + +template <typename T> +struct EqualsTraits<T, false> { + static bool Equals(const T& a, const T& b) { return a == b; } +}; + +template <typename T> +struct EqualsTraits<base::Optional<T>, false> { + static bool Equals(const base::Optional<T>& a, const base::Optional<T>& b) { + if (!a && !b) + return true; + if (!a || !b) + return false; + + return internal::Equals(*a, *b); + } +}; + +template <typename T> +struct EqualsTraits<std::vector<T>, false> { + static bool Equals(const std::vector<T>& a, const std::vector<T>& b) { + if (a.size() != b.size()) + return false; + for (size_t i = 0; i < a.size(); ++i) { + if (!internal::Equals(a[i], b[i])) + return false; + } + return true; + } +}; + +template <typename K, typename V> +struct EqualsTraits<std::unordered_map<K, V>, false> { + static bool Equals(const std::unordered_map<K, V>& a, + const std::unordered_map<K, V>& b) { + if (a.size() != b.size()) + return false; + for (const auto& element : a) { + auto iter = b.find(element.first); + if (iter == b.end() || !internal::Equals(element.second, iter->second)) + return false; + } + return true; + } +}; + +template <typename T> +bool Equals(const T& a, const T& b) { + return EqualsTraits<T>::Equals(a, b); +} + +} // namespace internal +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_CLONE_EQUALS_UTIL_H_
diff --git a/mojo/public/cpp/bindings/lib/serialization_forward.h b/mojo/public/cpp/bindings/lib/serialization_forward.h index 7f73932..5bed126 100644 --- a/mojo/public/cpp/bindings/lib/serialization_forward.h +++ b/mojo/public/cpp/bindings/lib/serialization_forward.h
@@ -5,8 +5,10 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_FORWARD_H_ #define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_FORWARD_H_ +#include "base/optional.h" #include "mojo/public/cpp/bindings/array_traits.h" #include "mojo/public/cpp/bindings/enum_traits.h" +#include "mojo/public/cpp/bindings/lib/template_util.h" #include "mojo/public/cpp/bindings/map_traits.h" #include "mojo/public/cpp/bindings/string_traits.h" #include "mojo/public/cpp/bindings/struct_traits.h" @@ -22,11 +24,23 @@ template <typename MojomType, typename MaybeConstUserType> struct Serializer; +template <typename T> +struct IsOptionalWrapper { + static const bool value = IsSpecializationOf< + base::Optional, + typename std::remove_const< + typename std::remove_reference<T>::type>::type>::value; +}; + // PrepareToSerialize() must be matched by a Serialize() for the same input // later. Moreover, within the same SerializationContext if PrepareToSerialize() // is called for |input_1|, ..., |input_n|, Serialize() must be called for // those objects in the exact same order. -template <typename MojomType, typename InputUserType, typename... Args> +template <typename MojomType, + typename InputUserType, + typename... Args, + typename std::enable_if< + !IsOptionalWrapper<InputUserType>::value>::type* = nullptr> size_t PrepareToSerialize(InputUserType&& input, Args&&... args) { return Serializer<MojomType, typename std::remove_reference<InputUserType>::type>:: @@ -34,7 +48,11 @@ std::forward<Args>(args)...); } -template <typename MojomType, typename InputUserType, typename... Args> +template <typename MojomType, + typename InputUserType, + typename... Args, + typename std::enable_if< + !IsOptionalWrapper<InputUserType>::value>::type* = nullptr> void Serialize(InputUserType&& input, Args&&... args) { Serializer<MojomType, typename std::remove_reference<InputUserType>::type>:: Serialize(std::forward<InputUserType>(input), @@ -44,12 +62,60 @@ template <typename MojomType, typename DataType, typename InputUserType, - typename... Args> + typename... Args, + typename std::enable_if< + !IsOptionalWrapper<InputUserType>::value>::type* = nullptr> bool Deserialize(DataType&& input, InputUserType* output, Args&&... args) { return Serializer<MojomType, InputUserType>::Deserialize( std::forward<DataType>(input), output, std::forward<Args>(args)...); } +// Specialization that unwraps base::Optional<>. +template <typename MojomType, + typename InputUserType, + typename... Args, + typename std::enable_if< + IsOptionalWrapper<InputUserType>::value>::type* = nullptr> +size_t PrepareToSerialize(InputUserType&& input, Args&&... args) { + if (!input) + return 0; + return PrepareToSerialize<MojomType>(*input, std::forward<Args>(args)...); +} + +template <typename MojomType, + typename InputUserType, + typename DataType, + typename... Args, + typename std::enable_if< + IsOptionalWrapper<InputUserType>::value>::type* = nullptr> +void Serialize(InputUserType&& input, + Buffer* buffer, + DataType** output, + Args&&... args) { + if (!input) { + *output = nullptr; + return; + } + Serialize<MojomType>(*input, buffer, output, std::forward<Args>(args)...); +} + +template <typename MojomType, + typename DataType, + typename InputUserType, + typename... Args, + typename std::enable_if< + IsOptionalWrapper<InputUserType>::value>::type* = nullptr> +bool Deserialize(DataType&& input, InputUserType* output, Args&&... args) { + if (!input) { + *output = base::nullopt; + return true; + } + if (!*output) + output->emplace(); + return Deserialize<MojomType>(std::forward<DataType>(input), &output->value(), + std::forward<Args>(args)...); +} + } // namespace internal } // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/template_util.h b/mojo/public/cpp/bindings/lib/template_util.h index 4e4ce66..5151123 100644 --- a/mojo/public/cpp/bindings/lib/template_util.h +++ b/mojo/public/cpp/bindings/lib/template_util.h
@@ -114,54 +114,6 @@ typedef F type; }; -template <typename T> -struct HasCloneMethod { - template <typename U> - static char Test(decltype(&U::Clone)); - template <typename U> - static int Test(...); - static const bool value = sizeof(Test<T>(0)) == sizeof(char); - - private: - EnsureTypeIsComplete<T> check_t_; -}; - -template <typename T, - typename std::enable_if<HasCloneMethod<T>::value>::type* = nullptr> -T Clone(const T& input) { - return input.Clone(); -}; - -template <typename T, - typename std::enable_if<!HasCloneMethod<T>::value>::type* = nullptr> -T Clone(const T& input) { - return input; -} - -template <typename T> -struct HasEqualsMethod { - template <typename U> - static char Test(decltype(&U::Equals)); - template <typename U> - static int Test(...); - static const bool value = sizeof(Test<T>(0)) == sizeof(char); - - private: - EnsureTypeIsComplete<T> check_t_; -}; - -template <typename T, - typename std::enable_if<HasEqualsMethod<T>::value>::type* = nullptr> -bool Equals(const T& a, const T& b) { - return a.Equals(b); -}; - -template <typename T, - typename std::enable_if<!HasEqualsMethod<T>::value>::type* = nullptr> -bool Equals(const T& a, const T& b) { - return a == b; -} - } // namespace internal } // namespace mojo
diff --git a/mojo/public/cpp/bindings/lib/validation_context.cc b/mojo/public/cpp/bindings/lib/validation_context.cc index e2688c4..a95e07e 100644 --- a/mojo/public/cpp/bindings/lib/validation_context.cc +++ b/mojo/public/cpp/bindings/lib/validation_context.cc
@@ -16,7 +16,7 @@ namespace internal { ValidationContext::ValidationContext(const void* data, - uint32_t data_num_bytes, + size_t data_num_bytes, size_t num_handles, Message* message, const base::StringPiece& description)
diff --git a/mojo/public/cpp/bindings/lib/validation_context.h b/mojo/public/cpp/bindings/lib/validation_context.h index 5b02a59..6045ca82 100644 --- a/mojo/public/cpp/bindings/lib/validation_context.h +++ b/mojo/public/cpp/bindings/lib/validation_context.h
@@ -31,7 +31,7 @@ // provided, the MojoNotifyBadMessage API will be used to notify the system of // such errors. ValidationContext(const void* data, - uint32_t data_num_bytes, + size_t data_num_bytes, size_t num_handles, Message* message = nullptr, const base::StringPiece& description = "");
diff --git a/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h b/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h new file mode 100644 index 0000000..edbf27b --- /dev/null +++ b/mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h
@@ -0,0 +1,76 @@ +// 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 MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_CLONE_EQUALS_UTIL_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_CLONE_EQUALS_UTIL_H_ + +#include <type_traits> + +#include "mojo/public/cpp/bindings/lib/clone_equals_util.h" +#include "third_party/WebKit/Source/wtf/HashMap.h" +#include "third_party/WebKit/Source/wtf/Optional.h" +#include "third_party/WebKit/Source/wtf/Vector.h" +#include "third_party/WebKit/Source/wtf/text/WTFString.h" + +namespace mojo { +namespace internal { + +template <typename T> +struct CloneTraits<WTF::Vector<T>, false> { + static WTF::Vector<T> Clone(const WTF::Vector<T>& input) { + WTF::Vector<T> result; + result.reserveCapacity(input.size()); + for (const auto& element : input) + result.append(internal::Clone(element)); + + return result; + } +}; + +template <typename K, typename V> +struct CloneTraits<WTF::HashMap<K, V>, false> { + static WTF::HashMap<K, V> Clone(const WTF::HashMap<K, V>& input) { + WTF::HashMap<K, V> result; + auto input_end = input.end(); + for (auto it = input.begin(); it != input_end; ++it) + result.add(internal::Clone(it->key), internal::Clone(it->value)); + return result; + } +}; + +template <typename T> +struct EqualsTraits<WTF::Vector<T>, false> { + static bool Equals(const WTF::Vector<T>& a, const WTF::Vector<T>& b) { + if (a.size() != b.size()) + return false; + for (size_t i = 0; i < a.size(); ++i) { + if (!internal::Equals(a[i], b[i])) + return false; + } + return true; + } +}; + +template <typename K, typename V> +struct EqualsTraits<WTF::HashMap<K, V>, false> { + static bool Equals(const WTF::HashMap<K, V>& a, const WTF::HashMap<K, V>& b) { + if (a.size() != b.size()) + return false; + + auto a_end = a.end(); + auto b_end = b.end(); + + for (auto iter = a.begin(); iter != a_end; ++iter) { + auto b_iter = b.find(iter->key); + if (b_iter == b_end || !internal::Equals(iter->value, b_iter->value)) + return false; + } + return true; + } +}; + +} // namespace internal +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_CLONE_EQUALS_UTIL_H_
diff --git a/mojo/public/cpp/bindings/lib/wtf_serialization.h b/mojo/public/cpp/bindings/lib/wtf_serialization.h index 91f24b5..132e19c 100644 --- a/mojo/public/cpp/bindings/lib/wtf_serialization.h +++ b/mojo/public/cpp/bindings/lib/wtf_serialization.h
@@ -8,6 +8,7 @@ #include "mojo/public/cpp/bindings/array_traits_wtf.h" #include "mojo/public/cpp/bindings/array_traits_wtf_vector.h" #include "mojo/public/cpp/bindings/map_traits_wtf.h" +#include "mojo/public/cpp/bindings/map_traits_wtf_hash_map.h" #include "mojo/public/cpp/bindings/string_traits_wtf.h" #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_WTF_SERIALIZATION_H_
diff --git a/mojo/public/cpp/bindings/map.h b/mojo/public/cpp/bindings/map.h index 8fa3d67..d4c7952 100644 --- a/mojo/public/cpp/bindings/map.h +++ b/mojo/public/cpp/bindings/map.h
@@ -7,6 +7,7 @@ #include <stddef.h> #include <map> +#include <unordered_map> #include <utility> #include "base/logging.h" @@ -135,14 +136,13 @@ const std::map<Key, Value>& storage() const { return map_; } // Passes the underlying storage and resets this map to null. - // - // TODO(yzshen): Consider changing this to a rvalue-ref-qualified conversion - // to std::map<Key, Value> after we move to MSVC 2015. std::map<Key, Value> PassStorage() { is_null_ = true; return std::move(map_); } + operator const std::map<Key, Value>&() const { return map_; } + // Swaps the contents of this Map with another Map of the same type (including // nullness). void Swap(Map<Key, Value>* other) {
diff --git a/mojo/public/cpp/bindings/map_traits_stl.h b/mojo/public/cpp/bindings/map_traits_stl.h index 2d5c137..ff79a200 100644 --- a/mojo/public/cpp/bindings/map_traits_stl.h +++ b/mojo/public/cpp/bindings/map_traits_stl.h
@@ -6,6 +6,7 @@ #define MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_STL_H_ #include <map> +#include <unordered_map> #include "mojo/public/cpp/bindings/map_traits.h" @@ -56,6 +57,57 @@ static void SetToEmpty(std::map<K, V>* output) { output->clear(); } }; +template <typename K, typename V> +struct MapTraits<std::unordered_map<K, V>> { + using Key = K; + using Value = V; + using Iterator = typename std::unordered_map<K, V>::iterator; + using ConstIterator = typename std::unordered_map<K, V>::const_iterator; + + static bool IsNull(const std::unordered_map<K, V>& input) { + // std::unordered_map<> is always converted to non-null mojom map. + return false; + } + + static void SetToNull(std::unordered_map<K, V>* output) { + // std::unordered_map<> doesn't support null state. Set it to empty instead. + output->clear(); + } + + static size_t GetSize(const std::unordered_map<K, V>& input) { + return input.size(); + } + + static ConstIterator GetBegin(const std::unordered_map<K, V>& input) { + return input.begin(); + } + static Iterator GetBegin(std::unordered_map<K, V>& input) { + return input.begin(); + } + + static void AdvanceIterator(ConstIterator& iterator) { iterator++; } + static void AdvanceIterator(Iterator& iterator) { iterator++; } + + static const K& GetKey(Iterator& iterator) { return iterator->first; } + static const K& GetKey(ConstIterator& iterator) { return iterator->first; } + + static V& GetValue(Iterator& iterator) { return iterator->second; } + static const V& GetValue(ConstIterator& iterator) { return iterator->second; } + + static bool Insert(std::unordered_map<K, V>& input, const K& key, V&& value) { + input.insert(std::make_pair(key, std::forward<V>(value))); + return true; + } + static bool Insert(std::unordered_map<K, V>& input, + const K& key, + const V& value) { + input.insert(std::make_pair(key, value)); + return true; + } + + static void SetToEmpty(std::unordered_map<K, V>* output) { output->clear(); } +}; + } // namespace mojo #endif // MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_STL_H_
diff --git a/mojo/public/cpp/bindings/map_traits_wtf_hash_map.h b/mojo/public/cpp/bindings/map_traits_wtf_hash_map.h new file mode 100644 index 0000000..43922013 --- /dev/null +++ b/mojo/public/cpp/bindings/map_traits_wtf_hash_map.h
@@ -0,0 +1,71 @@ +// 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 MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_WTF_HASH_MAP_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_WTF_HASH_MAP_H_ + +#include "base/logging.h" +#include "mojo/public/cpp/bindings/map_traits.h" +#include "third_party/WebKit/Source/wtf/HashMap.h" + +namespace mojo { + +template <typename K, typename V> +struct MapTraits<WTF::HashMap<K, V>> { + using Key = K; + using Value = V; + using Iterator = typename WTF::HashMap<K, V>::iterator; + using ConstIterator = typename WTF::HashMap<K, V>::const_iterator; + + static bool IsNull(const WTF::HashMap<K, V>& input) { + // WTF::HashMap<> is always converted to non-null mojom map. + return false; + } + + static void SetToNull(WTF::HashMap<K, V>* output) { + // WTF::HashMap<> doesn't support null state. Set it to empty instead. + output->clear(); + } + + static size_t GetSize(const WTF::HashMap<K, V>& input) { + return input.size(); + } + + static ConstIterator GetBegin(const WTF::HashMap<K, V>& input) { + return input.begin(); + } + static Iterator GetBegin(WTF::HashMap<K, V>& input) { return input.begin(); } + + static void AdvanceIterator(ConstIterator& iterator) { ++iterator; } + static void AdvanceIterator(Iterator& iterator) { ++iterator; } + + static const K& GetKey(Iterator& iterator) { return iterator->key; } + static const K& GetKey(ConstIterator& iterator) { return iterator->key; } + + static V& GetValue(Iterator& iterator) { return iterator->value; } + static const V& GetValue(ConstIterator& iterator) { return iterator->value; } + + static bool Insert(WTF::HashMap<K, V>& input, const K& key, V&& value) { + if (!WTF::HashMap<K, V>::isValidKey(key)) { + LOG(ERROR) << "The key value is disallowed by WTF::HashMap: " << key; + return false; + } + input.add(key, std::forward<V>(value)); + return true; + } + static bool Insert(WTF::HashMap<K, V>& input, const K& key, const V& value) { + if (!WTF::HashMap<K, V>::isValidKey(key)) { + LOG(ERROR) << "The key value is disallowed by WTF::HashMap: " << key; + return false; + } + input.add(key, value); + return true; + } + + static void SetToEmpty(WTF::HashMap<K, V>* output) { output->clear(); } +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_MAP_TRAITS_WTF_HASH_MAP_H_
diff --git a/mojo/public/cpp/bindings/native_enum.h b/mojo/public/cpp/bindings/native_enum.h index 140045e..08b43b7 100644 --- a/mojo/public/cpp/bindings/native_enum.h +++ b/mojo/public/cpp/bindings/native_enum.h
@@ -5,6 +5,9 @@ #ifndef MOJO_PUBLIC_CPP_BINDINGS_NATIVE_ENUM_H_ #define MOJO_PUBLIC_CPP_BINDINGS_NATIVE_ENUM_H_ +#include <functional> + +#include "mojo/public/cpp/bindings/lib/bindings_internal.h" #include "mojo/public/cpp/bindings/lib/native_enum_data.h" namespace mojo { @@ -14,4 +17,12 @@ } // namespace mojo +namespace std { + +template <> +struct hash<mojo::NativeEnum> + : public mojo::internal::EnumHashImpl<mojo::NativeEnum> {}; + +} // namespace std + #endif // MOJO_PUBLIC_CPP_BINDINGS_NATIVE_ENUM_H_
diff --git a/mojo/public/cpp/bindings/tests/binding_callback_unittest.cc b/mojo/public/cpp/bindings/tests/binding_callback_unittest.cc index ff0973e..02b082a 100644 --- a/mojo/public/cpp/bindings/tests/binding_callback_unittest.cc +++ b/mojo/public/cpp/bindings/tests/binding_callback_unittest.cc
@@ -87,13 +87,13 @@ } } - void EchoString(const String& a, + void EchoString(const std::string& a, const EchoStringCallback& callback) override { CHECK(false) << "Not implemented."; } - void EchoStrings(const String& a, - const String& b, + void EchoStrings(const std::string& a, + const std::string& b, const EchoStringsCallback& callback) override { CHECK(false) << "Not implemented."; }
diff --git a/mojo/public/cpp/bindings/tests/e2e_perftest.cc b/mojo/public/cpp/bindings/tests/e2e_perftest.cc index df7f25a..66ac6dc7 100644 --- a/mojo/public/cpp/bindings/tests/e2e_perftest.cc +++ b/mojo/public/cpp/bindings/tests/e2e_perftest.cc
@@ -28,7 +28,7 @@ ~EchoServiceImpl() override; // |EchoService| methods: - void Echo(const mojo::String& test_data, + void Echo(const std::string& test_data, const EchoCallback& callback) override; private: @@ -44,7 +44,7 @@ quit_closure_.Run(); } -void EchoServiceImpl::Echo(const mojo::String& test_data, +void EchoServiceImpl::Echo(const std::string& test_data, const EchoCallback& callback) { callback.Run(test_data); } @@ -57,10 +57,10 @@ private: void DoPing(); - void OnPingDone(mojo::String reply); + void OnPingDone(const std::string& reply); test::EchoServicePtr service_; - const base::Callback<void(mojo::String)> ping_done_callback_; + const base::Callback<void(const std::string&)> ping_done_callback_; int iterations_; int batch_size_; @@ -106,7 +106,7 @@ } } -void PingPongTest::OnPingDone(mojo::String reply) { +void PingPongTest::OnPingDone(const std::string& reply) { DCHECK_GT(calls_outstanding_, 0); calls_outstanding_--;
diff --git a/mojo/public/cpp/bindings/tests/equals_unittest.cc b/mojo/public/cpp/bindings/tests/equals_unittest.cc index 1add5b0..376c2bd 100644 --- a/mojo/public/cpp/bindings/tests/equals_unittest.cc +++ b/mojo/public/cpp/bindings/tests/equals_unittest.cc
@@ -61,32 +61,34 @@ TEST_F(EqualsTest, Array) { NamedRegionPtr n1(NamedRegion::New()); - n1->name = "n1"; - n1->rects.push_back(CreateRect()); + n1->name.emplace("n1"); + n1->rects.emplace(); + n1->rects->push_back(CreateRect()); NamedRegionPtr n2(n1.Clone()); EXPECT_TRUE(n1.Equals(n2)); - n2->rects = nullptr; + n2->rects = base::nullopt; EXPECT_FALSE(n1.Equals(n2)); - n2->rects.resize(0); + n2->rects.emplace(); EXPECT_FALSE(n1.Equals(n2)); - n2->rects.push_back(CreateRect()); - n2->rects.push_back(CreateRect()); + n2->rects->push_back(CreateRect()); + n2->rects->push_back(CreateRect()); EXPECT_FALSE(n1.Equals(n2)); - n2->rects.resize(1); - n2->rects[0]->width = 0; + n2->rects->resize(1); + (*n2->rects)[0]->width = 0; EXPECT_FALSE(n1.Equals(n2)); - n2->rects[0] = CreateRect(); + (*n2->rects)[0] = CreateRect(); EXPECT_TRUE(n1.Equals(n2)); } TEST_F(EqualsTest, Map) { auto n1(NamedRegion::New()); - n1->name = "foo"; - n1->rects.push_back(CreateRect()); + n1->name.emplace("foo"); + n1->rects.emplace(); + n1->rects->push_back(CreateRect()); Map<std::string, NamedRegionPtr> m1; m1.insert("foo", std::move(n1)); @@ -98,15 +100,15 @@ EXPECT_FALSE(m1.Equals(m2)); m2 = m1.Clone(); - m2.at("foo")->name = "monkey"; + m2.at("foo")->name.emplace("monkey"); EXPECT_FALSE(m1.Equals(m2)); m2 = m1.Clone(); - m2.at("foo")->rects.push_back(Rect::New()); + m2.at("foo")->rects->push_back(Rect::New()); EXPECT_FALSE(m1.Equals(m2)); - m2.at("foo")->rects.resize(1); - m2.at("foo")->rects[0]->width = 1; + m2.at("foo")->rects->resize(1); + (*m2.at("foo")->rects)[0]->width = 1; EXPECT_FALSE(m1.Equals(m2)); m2 = m1.Clone();
diff --git a/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc b/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc index 417b857..0bd9b283 100644 --- a/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc +++ b/mojo/public/cpp/bindings/tests/handle_passing_unittest.cc
@@ -22,12 +22,12 @@ void RecordString(std::string* storage, const base::Closure& closure, - String str) { - *storage = str.PassStorage(); + const std::string& str) { + *storage = str; closure.Run(); } -base::Callback<void(mojo::String)> MakeStringRecorder( +base::Callback<void(const std::string&)> MakeStringRecorder( std::string* storage, const base::Closure& closure) { return base::Bind(&RecordString, storage, closure); @@ -58,7 +58,7 @@ public: explicit SampleNamedObjectImpl(InterfaceRequest<sample::NamedObject> request) : binding_(this, std::move(request)) {} - void SetName(const mojo::String& name) override { name_ = name; } + void SetName(const std::string& name) override { name_ = name; } void GetName(const GetNameCallback& callback) override { callback.Run(name_); @@ -167,7 +167,7 @@ std::string* got_text_reply, const base::Closure& closure, sample::ResponsePtr response, - String text_reply) { + const std::string& text_reply) { *got_text_reply = text_reply; if (response->pipe.is_valid()) { @@ -190,9 +190,9 @@ } void DoStuff2(bool* got_response, - std::string* got_text_reply, - const base::Closure& closure, - String text_reply) { + std::string* got_text_reply, + const base::Closure& closure, + const std::string& text_reply) { *got_response = true; *got_text_reply = text_reply; closure.Run(); @@ -304,7 +304,7 @@ MojoHandle handle1_value = extra_pipe.handle1.get().value(); { - Array<ScopedMessagePipeHandle> pipes(2); + std::vector<ScopedMessagePipeHandle> pipes(2); pipes[0] = std::move(extra_pipe.handle0); pipes[1] = std::move(extra_pipe.handle1);
diff --git a/mojo/public/cpp/bindings/tests/pickle_unittest.cc b/mojo/public/cpp/bindings/tests/pickle_unittest.cc index 86ab8d3..bd716cc 100644 --- a/mojo/public/cpp/bindings/tests/pickle_unittest.cc +++ b/mojo/public/cpp/bindings/tests/pickle_unittest.cc
@@ -105,14 +105,15 @@ callback.Run(std::move(container)); } - void PassPickles(Array<PickledStructChromium> pickles, + void PassPickles(const std::vector<PickledStructChromium>& pickles, const PassPicklesCallback& callback) override { - callback.Run(std::move(pickles)); + callback.Run(pickles); } - void PassPickleArrays(Array<Array<PickledStructChromium>> pickle_arrays, - const PassPickleArraysCallback& callback) override { - callback.Run(std::move(pickle_arrays)); + void PassPickleArrays( + const std::vector<std::vector<PickledStructChromium>>& pickle_arrays, + const PassPickleArraysCallback& callback) override { + callback.Run(pickle_arrays); } }; @@ -138,14 +139,15 @@ callback.Run(std::move(container)); } - void PassPickles(WTFArray<PickledStructBlink> pickles, + void PassPickles(const WTF::Vector<PickledStructBlink>& pickles, const PassPicklesCallback& callback) override { - callback.Run(std::move(pickles)); + callback.Run(pickles); } - void PassPickleArrays(WTFArray<WTFArray<PickledStructBlink>> pickle_arrays, - const PassPickleArraysCallback& callback) override { - callback.Run(std::move(pickle_arrays)); + void PassPickleArrays( + const WTF::Vector<WTF::Vector<PickledStructBlink>>& pickle_arrays, + const PassPickleArraysCallback& callback) override { + callback.Run(pickle_arrays); } }; @@ -312,28 +314,28 @@ // deserialized intact. This ensures that the ParamTraits are actually used // rather than doing a byte-for-byte copy of the element data, beacuse the // |baz| field should never be serialized. - proxy->PassPickles(std::move(pickles), - BindSimpleLambda<Array<PickledStructChromium>>( - [&](Array<PickledStructChromium> passed) { - ASSERT_FALSE(passed.is_null()); - ASSERT_EQ(2u, passed.size()); - EXPECT_EQ(1, passed[0].foo()); - EXPECT_EQ(2, passed[0].bar()); - EXPECT_EQ(0, passed[0].baz()); - EXPECT_EQ(3, passed[1].foo()); - EXPECT_EQ(4, passed[1].bar()); - EXPECT_EQ(0, passed[1].baz()); - run_loop.Quit(); - })); + proxy->PassPickles( + std::move(pickles), + BindSimpleLambda<const std::vector<PickledStructChromium>&>( + [&](const std::vector<PickledStructChromium>& passed) { + ASSERT_EQ(2u, passed.size()); + EXPECT_EQ(1, passed[0].foo()); + EXPECT_EQ(2, passed[0].bar()); + EXPECT_EQ(0, passed[0].baz()); + EXPECT_EQ(3, passed[1].foo()); + EXPECT_EQ(4, passed[1].bar()); + EXPECT_EQ(0, passed[1].baz()); + run_loop.Quit(); + })); run_loop.Run(); } } TEST_F(PickleTest, PickleArrayArray) { auto proxy = ConnectToChromiumService(); - auto pickle_arrays = Array<Array<PickledStructChromium>>::New(2); + auto pickle_arrays = std::vector<std::vector<PickledStructChromium>>(2); for (size_t i = 0; i < 2; ++i) - pickle_arrays[i] = Array<PickledStructChromium>::New(2); + pickle_arrays[i] = std::vector<PickledStructChromium>(2); pickle_arrays[0][0].set_foo(1); pickle_arrays[0][0].set_bar(2); @@ -351,10 +353,10 @@ base::RunLoop run_loop; // Verify that the array-of-arrays serializes and deserializes properly. proxy->PassPickleArrays( - std::move(pickle_arrays), - BindSimpleLambda<Array<Array<PickledStructChromium>>>( - [&](Array<Array<PickledStructChromium>> passed) { - ASSERT_FALSE(passed.is_null()); + pickle_arrays, + BindSimpleLambda< + const std::vector<std::vector<PickledStructChromium>>&>( + [&](const std::vector<std::vector<PickledStructChromium>>& passed) { ASSERT_EQ(2u, passed.size()); ASSERT_EQ(2u, passed[0].size()); ASSERT_EQ(2u, passed[1].size());
diff --git a/mojo/public/cpp/bindings/tests/request_response_unittest.cc b/mojo/public/cpp/bindings/tests/request_response_unittest.cc index 3c024ad..5e203a2 100644 --- a/mojo/public/cpp/bindings/tests/request_response_unittest.cc +++ b/mojo/public/cpp/bindings/tests/request_response_unittest.cc
@@ -22,7 +22,7 @@ explicit ProviderImpl(InterfaceRequest<sample::Provider> request) : binding_(this, std::move(request)) {} - void EchoString(const String& a, + void EchoString(const std::string& a, const EchoStringCallback& callback) override { EchoStringCallback callback_copy; // Make sure operator= is used. @@ -30,8 +30,8 @@ callback_copy.Run(a); } - void EchoStrings(const String& a, - const String& b, + void EchoStrings(const std::string& a, + const std::string& b, const EchoStringsCallback& callback) override { callback.Run(a, b); } @@ -55,16 +55,16 @@ void RecordString(std::string* storage, const base::Closure& closure, - String str) { + const std::string& str) { *storage = str; closure.Run(); } void RecordStrings(std::string* storage, const base::Closure& closure, - String a, - String b) { - *storage = a.get() + b.get(); + const std::string& a, + const std::string& b) { + *storage = a + b; closure.Run(); } @@ -99,7 +99,7 @@ std::string buf; base::RunLoop run_loop; - provider->EchoString(String::From("hello"), + provider->EchoString("hello", base::Bind(&RecordString, &buf, run_loop.QuitClosure())); run_loop.Run(); @@ -113,9 +113,8 @@ std::string buf; base::RunLoop run_loop; - provider->EchoStrings( - String::From("hello"), String::From(" world"), - base::Bind(&RecordStrings, &buf, run_loop.QuitClosure())); + provider->EchoStrings("hello", " world", base::Bind(&RecordStrings, &buf, + run_loop.QuitClosure())); run_loop.Run();
diff --git a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc b/mojo/public/cpp/bindings/tests/sample_service_unittest.cc index 609a1dd1..00a8dbf 100644 --- a/mojo/public/cpp/bindings/tests/sample_service_unittest.cc +++ b/mojo/public/cpp/bindings/tests/sample_service_unittest.cc
@@ -36,7 +36,7 @@ // Make a sample |Foo|. FooPtr MakeFoo() { - mojo::String name("foopy"); + std::string name("foopy"); BarPtr bar(Bar::New()); bar->alpha = 20; @@ -44,7 +44,7 @@ bar->gamma = 60; bar->type = Bar::Type::VERTICAL; - mojo::Array<BarPtr> extra_bars(3); + std::vector<BarPtr> extra_bars(3); for (size_t i = 0; i < extra_bars.size(); ++i) { Bar::Type type = i % 2 == 0 ? Bar::Type::VERTICAL : Bar::Type::HORIZONTAL; BarPtr bar(Bar::New()); @@ -56,12 +56,12 @@ extra_bars[i] = std::move(bar); } - mojo::Array<uint8_t> data(10); + std::vector<uint8_t> data(10); for (size_t i = 0; i < data.size(); ++i) data[i] = static_cast<uint8_t>(data.size() - i); - mojo::Array<mojo::ScopedDataPipeConsumerHandle> input_streams(2); - mojo::Array<mojo::ScopedDataPipeProducerHandle> output_streams(2); + std::vector<mojo::ScopedDataPipeConsumerHandle> input_streams(2); + std::vector<mojo::ScopedDataPipeProducerHandle> output_streams(2); for (size_t i = 0; i < input_streams.size(); ++i) { MojoCreateDataPipeOptions options; options.struct_size = sizeof(MojoCreateDataPipeOptions); @@ -75,9 +75,9 @@ output_streams[i] = std::move(producer); } - mojo::Array<mojo::Array<bool>> array_of_array_of_bools(2); + std::vector<std::vector<bool>> array_of_array_of_bools(2); for (size_t i = 0; i < 2; ++i) { - mojo::Array<bool> array_of_bools(2); + std::vector<bool> array_of_bools(2); for (size_t j = 0; j < 2; ++j) array_of_bools[j] = j; array_of_array_of_bools[i] = std::move(array_of_bools); @@ -105,14 +105,13 @@ // Check that the given |Foo| is identical to the one made by |MakeFoo()|. void CheckFoo(const Foo& foo) { const std::string kName("foopy"); - ASSERT_FALSE(foo.name.is_null()); EXPECT_EQ(kName.size(), foo.name.size()); for (size_t i = 0; i < std::min(kName.size(), foo.name.size()); i++) { // Test both |operator[]| and |at|. EXPECT_EQ(kName[i], foo.name.at(i)) << i; EXPECT_EQ(kName[i], foo.name[i]) << i; } - EXPECT_EQ(kName, foo.name.get()); + EXPECT_EQ(kName, foo.name); EXPECT_EQ(1, foo.x); EXPECT_EQ(2, foo.y); @@ -125,32 +124,32 @@ EXPECT_EQ(60, foo.bar->gamma); EXPECT_EQ(Bar::Type::VERTICAL, foo.bar->type); - EXPECT_EQ(3u, foo.extra_bars.size()); - for (size_t i = 0; i < foo.extra_bars.size(); i++) { + EXPECT_EQ(3u, foo.extra_bars->size()); + for (size_t i = 0; i < foo.extra_bars->size(); i++) { uint8_t base = static_cast<uint8_t>(i * 100); Bar::Type type = i % 2 == 0 ? Bar::Type::VERTICAL : Bar::Type::HORIZONTAL; - EXPECT_EQ(base, foo.extra_bars[i]->alpha) << i; - EXPECT_EQ(base + 20, foo.extra_bars[i]->beta) << i; - EXPECT_EQ(base + 40, foo.extra_bars[i]->gamma) << i; - EXPECT_EQ(type, foo.extra_bars[i]->type) << i; + EXPECT_EQ(base, (*foo.extra_bars)[i]->alpha) << i; + EXPECT_EQ(base + 20, (*foo.extra_bars)[i]->beta) << i; + EXPECT_EQ(base + 40, (*foo.extra_bars)[i]->gamma) << i; + EXPECT_EQ(type, (*foo.extra_bars)[i]->type) << i; } - EXPECT_EQ(10u, foo.data.size()); - for (size_t i = 0; i < foo.data.size(); ++i) { - EXPECT_EQ(static_cast<uint8_t>(foo.data.size() - i), foo.data[i]) << i; + EXPECT_EQ(10u, foo.data->size()); + for (size_t i = 0; i < foo.data->size(); ++i) { + EXPECT_EQ(static_cast<uint8_t>(foo.data->size() - i), (*foo.data)[i]) << i; } - EXPECT_FALSE(foo.input_streams.is_null()); - EXPECT_EQ(2u, foo.input_streams.size()); + EXPECT_TRUE(foo.input_streams); + EXPECT_EQ(2u, foo.input_streams->size()); - EXPECT_FALSE(foo.output_streams.is_null()); - EXPECT_EQ(2u, foo.output_streams.size()); + EXPECT_TRUE(foo.output_streams); + EXPECT_EQ(2u, foo.output_streams->size()); - EXPECT_EQ(2u, foo.array_of_array_of_bools.size()); - for (size_t i = 0; i < foo.array_of_array_of_bools.size(); ++i) { - EXPECT_EQ(2u, foo.array_of_array_of_bools[i].size()); - for (size_t j = 0; j < foo.array_of_array_of_bools[i].size(); ++j) { - EXPECT_EQ(bool(j), foo.array_of_array_of_bools[i][j]); + EXPECT_EQ(2u, foo.array_of_array_of_bools->size()); + for (size_t i = 0; i < foo.array_of_array_of_bools->size(); ++i) { + EXPECT_EQ(2u, (*foo.array_of_array_of_bools)[i].size()); + for (size_t j = 0; j < (*foo.array_of_array_of_bools)[i].size(); ++j) { + EXPECT_EQ(bool(j), (*foo.array_of_array_of_bools)[i][j]); } } } @@ -183,9 +182,9 @@ std::cout << name << ": 0x" << std::hex << value.get().value() << std::endl; } -void Print(int depth, const char* name, const mojo::String& str) { +void Print(int depth, const char* name, const std::string& str) { PrintSpacer(depth); - std::cout << name << ": \"" << str.get() << "\"" << std::endl; + std::cout << name << ": \"" << str << "\"" << std::endl; } void Print(int depth, const char* name, const BarPtr& bar) { @@ -202,18 +201,26 @@ } template <typename T> -void Print(int depth, const char* name, const mojo::Array<T>& array) { +void Print(int depth, const char* name, const std::vector<T>& array) { PrintSpacer(depth); std::cout << name << ":" << std::endl; - if (!array.is_null()) { - ++depth; - for (size_t i = 0; i < array.size(); ++i) { - std::stringstream buf; - buf << i; - Print(depth, buf.str().data(), array.at(i)); - } - --depth; + ++depth; + for (size_t i = 0; i < array.size(); ++i) { + std::stringstream buf; + buf << i; + Print(depth, buf.str().data(), array.at(i)); } + --depth; +} + +template <typename T> +void Print(int depth, + const char* name, + const base::Optional<std::vector<T>>& array) { + if (array) + Print(depth, name, *array); + else + Print(depth, name, std::vector<T>()); } void Print(int depth, const char* name, const FooPtr& foo) { @@ -358,8 +365,8 @@ EXPECT_DOUBLE_EQ(1E10, defaults->a15); EXPECT_DOUBLE_EQ(-1.2E+20, defaults->a16); EXPECT_DOUBLE_EQ(1.23E-20, defaults->a17); - EXPECT_TRUE(defaults->a18.is_null()); - EXPECT_TRUE(defaults->a19.is_null()); + EXPECT_TRUE(defaults->a18.empty()); + EXPECT_TRUE(defaults->a19.empty()); EXPECT_EQ(Bar::Type::BOTH, defaults->a20); EXPECT_TRUE(defaults->a21.is_null()); ASSERT_FALSE(defaults->a22.is_null());
diff --git a/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc b/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc index 9eb111b..dcf2967b 100644 --- a/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc +++ b/mojo/public/cpp/bindings/tests/serialization_warning_unittest.cc
@@ -119,12 +119,6 @@ TEST_F(SerializationWarningTest, ArrayOfStructsInStruct) { Struct4Ptr test_struct(Struct4::New()); - EXPECT_TRUE(!test_struct->data); - - TestWarning(std::move(test_struct), - mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER); - - test_struct = Struct4::New(); test_struct->data.resize(1); TestWarning(std::move(test_struct), @@ -144,12 +138,6 @@ TEST_F(SerializationWarningTest, FixedArrayOfStructsInStruct) { Struct5Ptr test_struct(Struct5::New()); - EXPECT_TRUE(!test_struct->pair); - - TestWarning(std::move(test_struct), - mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER); - - test_struct = Struct5::New(); test_struct->pair.resize(1); test_struct->pair[0] = Struct1::New(); @@ -164,19 +152,6 @@ TestWarning(std::move(test_struct), mojo::internal::VALIDATION_ERROR_NONE); } -TEST_F(SerializationWarningTest, StringInStruct) { - Struct6Ptr test_struct(Struct6::New()); - EXPECT_TRUE(!test_struct->str); - - TestWarning(std::move(test_struct), - mojo::internal::VALIDATION_ERROR_UNEXPECTED_NULL_POINTER); - - test_struct = Struct6::New(); - test_struct->str = "hello world"; - - TestWarning(std::move(test_struct), mojo::internal::VALIDATION_ERROR_NONE); -} - TEST_F(SerializationWarningTest, ArrayOfArraysOfHandles) { Array<Array<ScopedHandle>> test_array = CreateTestNestedHandleArray(); test_array[0] = nullptr;
diff --git a/mojo/public/cpp/bindings/tests/stl_converters_unittest.cc b/mojo/public/cpp/bindings/tests/stl_converters_unittest.cc index 282480b1..92a31b35 100644 --- a/mojo/public/cpp/bindings/tests/stl_converters_unittest.cc +++ b/mojo/public/cpp/bindings/tests/stl_converters_unittest.cc
@@ -73,20 +73,20 @@ TEST_F(STLConvertersTest, StopsAtMojoStruct) { Array<NamedRegionPtr> mojo_obj(1); mojo_obj[0] = NamedRegion::New(); - mojo_obj[0]->name = "hello"; - mojo_obj[0]->rects.resize(3); + mojo_obj[0]->name.emplace("hello"); + mojo_obj[0]->rects.emplace(3); std::vector<NamedRegionPtr> stl_obj = UnwrapToSTLType(std::move(mojo_obj)); ASSERT_EQ(1u, stl_obj.size()); - ASSERT_EQ("hello", stl_obj[0]->name); - ASSERT_EQ(3u, stl_obj[0]->rects.size()); + ASSERT_EQ("hello", stl_obj[0]->name.value()); + ASSERT_EQ(3u, stl_obj[0]->rects->size()); Array<NamedRegionPtr> mojo_obj2 = WrapSTLType(std::move(stl_obj)); ASSERT_EQ(1u, mojo_obj2.size()); - ASSERT_EQ("hello", mojo_obj2[0]->name); - ASSERT_EQ(3u, mojo_obj2[0]->rects.size()); + ASSERT_EQ("hello", mojo_obj2[0]->name.value()); + ASSERT_EQ(3u, mojo_obj2[0]->rects->size()); } } // namespace test
diff --git a/mojo/public/cpp/bindings/tests/struct_unittest.cc b/mojo/public/cpp/bindings/tests/struct_unittest.cc index eb6e631a..76b4cce 100644 --- a/mojo/public/cpp/bindings/tests/struct_unittest.cc +++ b/mojo/public/cpp/bindings/tests/struct_unittest.cc
@@ -36,11 +36,11 @@ MultiVersionStructPtr output(MultiVersionStruct::New()); output->f_int32 = 123; output->f_rect = MakeRect(5); - output->f_string = "hello"; - output->f_array = Array<int8_t>(3); - output->f_array[0] = 10; - output->f_array[1] = 9; - output->f_array[2] = 8; + output->f_string.emplace("hello"); + output->f_array.emplace(3); + (*output->f_array)[0] = 10; + (*output->f_array)[1] = 9; + (*output->f_array)[2] = 8; MessagePipe pipe; output->f_message_pipe = std::move(pipe.handle0); output->f_int16 = 42; @@ -107,19 +107,19 @@ region = NamedRegion::New(); clone_region = region.Clone(); - EXPECT_TRUE(clone_region->name.is_null()); - EXPECT_TRUE(clone_region->rects.is_null()); + EXPECT_FALSE(clone_region->name); + EXPECT_FALSE(clone_region->rects); - region->name = "hello world"; + region->name.emplace("hello world"); clone_region = region.Clone(); EXPECT_EQ(region->name, clone_region->name); - region->rects = Array<RectPtr>(2); - region->rects[1] = MakeRect(); + region->rects.emplace(2); + (*region->rects)[1] = MakeRect(); clone_region = region.Clone(); - EXPECT_EQ(2u, clone_region->rects.size()); - EXPECT_TRUE(clone_region->rects[0].is_null()); - CheckRect(*clone_region->rects[1]); + EXPECT_EQ(2u, clone_region->rects->size()); + EXPECT_TRUE((*clone_region->rects)[0].is_null()); + CheckRect(*(*clone_region->rects)[1]); // NoDefaultFieldValues contains handles, so Clone() is not available, but // NoDefaultFieldValuesPtr should still compile. @@ -181,10 +181,10 @@ // Serialization test of a struct with an array member. TEST_F(StructTest, Serialization_ArrayPointers) { NamedRegionPtr region(NamedRegion::New()); - region->name = "region"; - region->rects = Array<RectPtr>::New(4); - for (size_t i = 0; i < region->rects.size(); ++i) - region->rects[i] = MakeRect(static_cast<int32_t>(i) + 1); + region->name.emplace("region"); + region->rects.emplace(4); + for (size_t i = 0; i < region->rects->size(); ++i) + (*region->rects)[i] = MakeRect(static_cast<int32_t>(i) + 1); size_t size = mojo::internal::PrepareToSerialize<NamedRegionPtr>(region, nullptr); @@ -206,18 +206,18 @@ NamedRegionPtr region2; mojo::internal::Deserialize<NamedRegionPtr>(data, ®ion2, nullptr); - EXPECT_EQ(String("region"), region2->name); + EXPECT_EQ("region", *region2->name); - EXPECT_EQ(4U, region2->rects.size()); - for (size_t i = 0; i < region2->rects.size(); ++i) - CheckRect(*region2->rects[i], static_cast<int32_t>(i) + 1); + EXPECT_EQ(4U, region2->rects->size()); + for (size_t i = 0; i < region2->rects->size(); ++i) + CheckRect(*(*region2->rects)[i], static_cast<int32_t>(i) + 1); } // Serialization test of a struct with null array pointers. TEST_F(StructTest, Serialization_NullArrayPointers) { NamedRegionPtr region(NamedRegion::New()); - EXPECT_TRUE(region->name.is_null()); - EXPECT_TRUE(region->rects.is_null()); + EXPECT_FALSE(region->name); + EXPECT_FALSE(region->rects); size_t size = mojo::internal::PrepareToSerialize<NamedRegionPtr>(region, nullptr); @@ -233,8 +233,8 @@ NamedRegionPtr region2; mojo::internal::Deserialize<NamedRegionPtr>(data, ®ion2, nullptr); - EXPECT_TRUE(region2->name.is_null()); - EXPECT_TRUE(region2->rects.is_null()); + EXPECT_FALSE(region2->name); + EXPECT_FALSE(region2->rects); } // Tests deserializing structs as a newer version. @@ -269,11 +269,11 @@ MultiVersionStructV3Ptr input(MultiVersionStructV3::New()); input->f_int32 = 123; input->f_rect = MakeRect(5); - input->f_string = "hello"; + input->f_string.emplace("hello"); MultiVersionStructPtr expected_output(MultiVersionStruct::New()); expected_output->f_int32 = 123; expected_output->f_rect = MakeRect(5); - expected_output->f_string = "hello"; + expected_output->f_string.emplace("hello"); MultiVersionStructPtr output = SerializeAndDeserialize<MultiVersionStructPtr>(std::move(input)); @@ -285,19 +285,19 @@ MultiVersionStructV5Ptr input(MultiVersionStructV5::New()); input->f_int32 = 123; input->f_rect = MakeRect(5); - input->f_string = "hello"; - input->f_array = Array<int8_t>(3); - input->f_array[0] = 10; - input->f_array[1] = 9; - input->f_array[2] = 8; + input->f_string.emplace("hello"); + input->f_array.emplace(3); + (*input->f_array)[0] = 10; + (*input->f_array)[1] = 9; + (*input->f_array)[2] = 8; MultiVersionStructPtr expected_output(MultiVersionStruct::New()); expected_output->f_int32 = 123; expected_output->f_rect = MakeRect(5); - expected_output->f_string = "hello"; - expected_output->f_array = Array<int8_t>(3); - expected_output->f_array[0] = 10; - expected_output->f_array[1] = 9; - expected_output->f_array[2] = 8; + expected_output->f_string.emplace("hello"); + expected_output->f_array.emplace(3); + (*expected_output->f_array)[0] = 10; + (*expected_output->f_array)[1] = 9; + (*expected_output->f_array)[2] = 8; MultiVersionStructPtr output = SerializeAndDeserialize<MultiVersionStructPtr>(std::move(input)); @@ -309,22 +309,22 @@ MultiVersionStructV7Ptr input(MultiVersionStructV7::New()); input->f_int32 = 123; input->f_rect = MakeRect(5); - input->f_string = "hello"; - input->f_array = Array<int8_t>(3); - input->f_array[0] = 10; - input->f_array[1] = 9; - input->f_array[2] = 8; + input->f_string.emplace("hello"); + input->f_array.emplace(3); + (*input->f_array)[0] = 10; + (*input->f_array)[1] = 9; + (*input->f_array)[2] = 8; MessagePipe pipe; input->f_message_pipe = std::move(pipe.handle0); MultiVersionStructPtr expected_output(MultiVersionStruct::New()); expected_output->f_int32 = 123; expected_output->f_rect = MakeRect(5); - expected_output->f_string = "hello"; - expected_output->f_array = Array<int8_t>(3); - expected_output->f_array[0] = 10; - expected_output->f_array[1] = 9; - expected_output->f_array[2] = 8; + expected_output->f_string.emplace("hello"); + expected_output->f_array.emplace(3); + (*expected_output->f_array)[0] = 10; + (*expected_output->f_array)[1] = 9; + (*expected_output->f_array)[2] = 8; // Save the raw handle value separately so that we can compare later. MojoHandle expected_handle = input->f_message_pipe.get().value(); @@ -344,11 +344,11 @@ MultiVersionStructV7Ptr expected_output(MultiVersionStructV7::New()); expected_output->f_int32 = 123; expected_output->f_rect = MakeRect(5); - expected_output->f_string = "hello"; - expected_output->f_array = Array<int8_t>(3); - expected_output->f_array[0] = 10; - expected_output->f_array[1] = 9; - expected_output->f_array[2] = 8; + expected_output->f_string.emplace("hello"); + expected_output->f_array.emplace(3); + (*expected_output->f_array)[0] = 10; + (*expected_output->f_array)[1] = 9; + (*expected_output->f_array)[2] = 8; // Save the raw handle value separately so that we can compare later. MojoHandle expected_handle = input->f_message_pipe.get().value(); @@ -365,11 +365,11 @@ MultiVersionStructV5Ptr expected_output(MultiVersionStructV5::New()); expected_output->f_int32 = 123; expected_output->f_rect = MakeRect(5); - expected_output->f_string = "hello"; - expected_output->f_array = Array<int8_t>(3); - expected_output->f_array[0] = 10; - expected_output->f_array[1] = 9; - expected_output->f_array[2] = 8; + expected_output->f_string.emplace("hello"); + expected_output->f_array.emplace(3); + (*expected_output->f_array)[0] = 10; + (*expected_output->f_array)[1] = 9; + (*expected_output->f_array)[2] = 8; MultiVersionStructV5Ptr output = SerializeAndDeserialize<MultiVersionStructV5Ptr>(std::move(input)); @@ -382,7 +382,7 @@ MultiVersionStructV3Ptr expected_output(MultiVersionStructV3::New()); expected_output->f_int32 = 123; expected_output->f_rect = MakeRect(5); - expected_output->f_string = "hello"; + expected_output->f_string.emplace("hello"); MultiVersionStructV3Ptr output = SerializeAndDeserialize<MultiVersionStructV3Ptr>(std::move(input)); @@ -520,10 +520,10 @@ { // A struct containing other objects. NamedRegionPtr region(NamedRegion::New()); - region->name = "region"; - region->rects = Array<RectPtr>::New(4); - for (size_t i = 0; i < region->rects.size(); ++i) - region->rects[i] = MakeRect(static_cast<int32_t>(i) + 1); + region->name.emplace("region"); + region->rects.emplace(3); + for (size_t i = 0; i < region->rects->size(); ++i) + (*region->rects)[i] = MakeRect(static_cast<int32_t>(i) + 1); NamedRegionPtr cloned_region = region.Clone(); mojo::Array<uint8_t> data = NamedRegion::Serialize(®ion);
diff --git a/mojo/public/cpp/bindings/tests/struct_with_traits.typemap b/mojo/public/cpp/bindings/tests/struct_with_traits.typemap index fb9d01d3..da061deb 100644 --- a/mojo/public/cpp/bindings/tests/struct_with_traits.typemap +++ b/mojo/public/cpp/bindings/tests/struct_with_traits.typemap
@@ -19,6 +19,6 @@ "mojo.test.EnumWithTraits=mojo::test::EnumWithTraitsImpl", "mojo.test.StructWithTraits=mojo::test::StructWithTraitsImpl", "mojo.test.NestedStructWithTraits=mojo::test::NestedStructWithTraitsImpl", - "mojo.test.PassByValueStructWithTraits=mojo::test::PassByValueStructWithTraitsImpl[pass_by_value]", - "mojo.test.StructWithTraitsForUniquePtrTest=std::unique_ptr<int>[pass_by_value]", + "mojo.test.PassByValueStructWithTraits=mojo::test::PassByValueStructWithTraitsImpl[move_only]", + "mojo.test.StructWithTraitsForUniquePtrTest=std::unique_ptr<int>[move_only]", ]
diff --git a/mojo/public/cpp/bindings/tests/type_conversion_unittest.cc b/mojo/public/cpp/bindings/tests/type_conversion_unittest.cc index a2692a06..7eb24ea 100644 --- a/mojo/public/cpp/bindings/tests/type_conversion_unittest.cc +++ b/mojo/public/cpp/bindings/tests/type_conversion_unittest.cc
@@ -69,8 +69,8 @@ struct TypeConverter<test::NamedRegionPtr, RedmondNamedRegion> { static test::NamedRegionPtr Convert(const RedmondNamedRegion& input) { test::NamedRegionPtr region(test::NamedRegion::New()); - region->name = input.name; - region->rects = Array<test::RectPtr>::From(input.rects); + region->name.emplace(input.name); + region->rects = Array<test::RectPtr>::From(input.rects).PassStorage(); return region; } }; @@ -79,8 +79,13 @@ struct TypeConverter<RedmondNamedRegion, test::NamedRegionPtr> { static RedmondNamedRegion Convert(const test::NamedRegionPtr& input) { RedmondNamedRegion region; - region.name = input->name; - region.rects = input->rects.To<std::vector<RedmondRect>>(); + if (input->name) + region.name = input->name.value(); + if (input->rects) { + region.rects.reserve(input->rects->size()); + for (const auto& element : *input->rects) + region.rects.push_back(element.To<RedmondRect>()); + } return region; } };
diff --git a/mojo/public/cpp/bindings/tests/union_unittest.cc b/mojo/public/cpp/bindings/tests/union_unittest.cc index 938b2a0..d65a348 100644 --- a/mojo/public/cpp/bindings/tests/union_unittest.cc +++ b/mojo/public/cpp/bindings/tests/union_unittest.cc
@@ -413,15 +413,15 @@ // Array tests TEST(UnionTest, PodUnionInArray) { SmallStructPtr small_struct(SmallStruct::New()); - small_struct->pod_union_array = Array<PodUnionPtr>(2); - small_struct->pod_union_array[0] = PodUnion::New(); - small_struct->pod_union_array[1] = PodUnion::New(); + small_struct->pod_union_array.emplace(2); + small_struct->pod_union_array.value()[0] = PodUnion::New(); + small_struct->pod_union_array.value()[1] = PodUnion::New(); - small_struct->pod_union_array[0]->set_f_int8(10); - small_struct->pod_union_array[1]->set_f_int16(12); + small_struct->pod_union_array.value()[0]->set_f_int8(10); + small_struct->pod_union_array.value()[1]->set_f_int16(12); - EXPECT_EQ(10, small_struct->pod_union_array[0]->get_f_int8()); - EXPECT_EQ(12, small_struct->pod_union_array[1]->get_f_int16()); + EXPECT_EQ(10, small_struct->pod_union_array.value()[0]->get_f_int8()); + EXPECT_EQ(12, small_struct->pod_union_array.value()[1]->get_f_int16()); } TEST(UnionTest, PodUnionInArraySerialization) { @@ -669,15 +669,15 @@ // Map Tests TEST(UnionTest, PodUnionInMap) { SmallStructPtr small_struct(SmallStruct::New()); - small_struct->pod_union_map = Map<String, PodUnionPtr>(); - small_struct->pod_union_map.insert("one", PodUnion::New()); - small_struct->pod_union_map.insert("two", PodUnion::New()); + small_struct->pod_union_map.emplace(); + small_struct->pod_union_map.value()["one"] = PodUnion::New(); + small_struct->pod_union_map.value()["two"] = PodUnion::New(); - small_struct->pod_union_map["one"]->set_f_int8(8); - small_struct->pod_union_map["two"]->set_f_int16(16); + small_struct->pod_union_map.value()["one"]->set_f_int8(8); + small_struct->pod_union_map.value()["two"]->set_f_int16(16); - EXPECT_EQ(8, small_struct->pod_union_map["one"]->get_f_int8()); - EXPECT_EQ(16, small_struct->pod_union_map["two"]->get_f_int16()); + EXPECT_EQ(8, small_struct->pod_union_map.value()["one"]->get_f_int8()); + EXPECT_EQ(16, small_struct->pod_union_map.value()["two"]->get_f_int16()); } TEST(UnionTest, PodUnionInMapSerialization) { @@ -892,9 +892,9 @@ } TEST(UnionTest, MapInUnionGetterSetter) { - Map<String, int8_t> map; - map.insert("one", 1); - map.insert("two", 2); + std::unordered_map<std::string, int8_t> map; + map.insert({"one", 1}); + map.insert({"two", 2}); ObjectUnionPtr obj(ObjectUnion::New()); obj->set_f_map_int8(std::move(map)); @@ -904,9 +904,9 @@ } TEST(UnionTest, MapInUnionSerialization) { - Map<String, int8_t> map; - map.insert("one", 1); - map.insert("two", 2); + std::unordered_map<std::string, int8_t> map; + map.insert({"one", 1}); + map.insert({"two", 2}); ObjectUnionPtr obj(ObjectUnion::New()); obj->set_f_map_int8(std::move(map)); @@ -928,9 +928,9 @@ } TEST(UnionTest, MapInUnionValidation) { - Map<String, int8_t> map; - map.insert("one", 1); - map.insert("two", 2); + std::unordered_map<std::string, int8_t> map; + map.insert({"one", 1}); + map.insert({"two", 2}); ObjectUnionPtr obj(ObjectUnion::New()); obj->set_f_map_int8(std::move(map));
diff --git a/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc b/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc index 4ebf158..97392d4 100644 --- a/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc +++ b/mojo/public/cpp/bindings/tests/wtf_types_unittest.cc
@@ -30,18 +30,22 @@ : binding_(this, std::move(request)) {} // mojo::test::TestWTF implementation: - void EchoString(const String& str, + void EchoString(const base::Optional<std::string>& str, const EchoStringCallback& callback) override { callback.Run(str); } - void EchoStringArray(Array<String> arr, - const EchoStringArrayCallback& callback) override { + void EchoStringArray( + const base::Optional<std::vector<base::Optional<std::string>>>& arr, + const EchoStringArrayCallback& callback) override { callback.Run(std::move(arr)); } - void EchoStringMap(Map<String, String> str_map, - const EchoStringMapCallback& callback) override { + void EchoStringMap( + const base::Optional< + std::unordered_map<std::string, base::Optional<std::string>>>& + str_map, + const EchoStringMapCallback& callback) override { callback.Run(std::move(str_map)); } @@ -57,8 +61,8 @@ base::MessageLoop loop_; }; -WTFArray<WTF::String> ConstructStringArray() { - WTFArray<WTF::String> strs(4); +WTF::Vector<WTF::String> ConstructStringArray() { + WTF::Vector<WTF::String> strs(4); // strs[0] is null. // strs[1] is empty. strs[1] = ""; @@ -68,12 +72,12 @@ return strs; } -WTFMap<WTF::String, WTF::String> ConstructStringMap() { - WTFMap<WTF::String, WTF::String> str_map; +WTF::HashMap<WTF::String, WTF::String> ConstructStringMap() { + WTF::HashMap<WTF::String, WTF::String> str_map; // A null string as value. - str_map.insert("0", WTF::String()); - str_map.insert("1", kHelloWorld); - str_map.insert("2", WTF::String::fromUTF8(kUTF8HelloWorld)); + str_map.add("0", WTF::String()); + str_map.add("1", kHelloWorld); + str_map.add("2", WTF::String::fromUTF8(kUTF8HelloWorld)); return str_map; } @@ -85,17 +89,18 @@ closure.Run(); } -void ExpectStringArray(WTFArray<WTF::String> expected_arr, +void ExpectStringArray(WTF::Optional<WTF::Vector<WTF::String>>* expected_arr, const base::Closure& closure, - WTFArray<WTF::String> arr) { - EXPECT_TRUE(expected_arr.Equals(arr)); + const WTF::Optional<WTF::Vector<WTF::String>>& arr) { + EXPECT_EQ(*expected_arr, arr); closure.Run(); } -void ExpectStringMap(WTFMap<WTF::String, WTF::String> expected_map, - const base::Closure& closure, - WTFMap<WTF::String, WTF::String> map) { - EXPECT_TRUE(expected_map.Equals(map)); +void ExpectStringMap( + WTF::Optional<WTF::HashMap<WTF::String, WTF::String>>* expected_map, + const base::Closure& closure, + const WTF::Optional<WTF::HashMap<WTF::String, WTF::String>>& map) { + EXPECT_EQ(*expected_map, map); closure.Run(); } @@ -103,7 +108,7 @@ TEST_F(WTFTypesTest, Serialization_WTFArrayToWTFArray) { WTFArray<WTF::String> strs = ConstructStringArray(); - WTFArray<WTF::String> cloned_strs = strs.Clone(); + auto cloned_strs = strs.Clone(); mojo::internal::SerializationContext context; size_t size = mojo::internal::PrepareToSerialize<Array<mojo::String>>( @@ -123,8 +128,8 @@ } TEST_F(WTFTypesTest, Serialization_WTFVectorToWTFVector) { - WTF::Vector<WTF::String> strs = ConstructStringArray().PassStorage(); - WTF::Vector<WTF::String> cloned_strs = strs; + WTF::Vector<WTF::String> strs = ConstructStringArray(); + auto cloned_strs = strs; mojo::internal::SerializationContext context; size_t size = mojo::internal::PrepareToSerialize<Array<mojo::String>>( @@ -245,13 +250,13 @@ blink::TestWTFPtr ptr; TestWTFImpl impl(ConvertInterfaceRequest<TestWTF>(GetProxy(&ptr))); - WTFArray<WTF::String> strs = ConstructStringArray(); + WTF::Vector<WTF::String> strs = ConstructStringArray(); for (size_t i = 0; i < strs.size(); ++i) { base::RunLoop loop; // Test that a WTF::String is unchanged after the following conversion: // - serialized; - // - deserialized as mojo::String; + // - deserialized as base::Optional<std::string>; // - serialized; // - deserialized as WTF::String. ptr->EchoString(strs[i], @@ -264,25 +269,24 @@ blink::TestWTFPtr ptr; TestWTFImpl impl(ConvertInterfaceRequest<TestWTF>(GetProxy(&ptr))); - WTFArray<WTF::String> arrs[3]; + WTF::Optional<WTF::Vector<WTF::String>> arrs[3]; // arrs[0] is empty. + arrs[0].emplace(); // arrs[1] is null. - arrs[1] = nullptr; arrs[2] = ConstructStringArray(); for (size_t i = 0; i < arraysize(arrs); ++i) { - WTFArray<WTF::String> expected_arr = arrs[i].Clone(); base::RunLoop loop; - // Test that a mojo::WTFArray<WTF::String> is unchanged after the following - // conversion: + // Test that a WTF::Optional<WTF::Vector<WTF::String>> is unchanged after + // the following conversion: // - serialized; - // - deserialized as mojo::Array<mojo::String>; + // - deserialized as + // base::Optional<std::vector<base::Optional<std::string>>>; // - serialized; - // - deserialized as mojo::WTFArray<WTF::String>. + // - deserialized as WTF::Optional<WTF::Vector<WTF::String>>. ptr->EchoStringArray( - std::move(arrs[i]), - base::Bind(&ExpectStringArray, base::Passed(&expected_arr), - loop.QuitClosure())); + arrs[i], base::Bind(&ExpectStringArray, base::Unretained(&arrs[i]), + loop.QuitClosure())); loop.Run(); } } @@ -291,25 +295,25 @@ blink::TestWTFPtr ptr; TestWTFImpl impl(ConvertInterfaceRequest<TestWTF>(GetProxy(&ptr))); - WTFMap<WTF::String, WTF::String> maps[3]; + WTF::Optional<WTF::HashMap<WTF::String, WTF::String>> maps[3]; // maps[0] is empty. + maps[0].emplace(); // maps[1] is null. - maps[1] = nullptr; maps[2] = ConstructStringMap(); for (size_t i = 0; i < arraysize(maps); ++i) { - WTFMap<WTF::String, WTF::String> expected_map = maps[i].Clone(); base::RunLoop loop; - // Test that a mojo::WTFMap<WTF::String, WTF::String> is unchanged after the - // following conversion: + // Test that a WTF::Optional<WTF::HashMap<WTF::String, WTF::String>> is + // unchanged after the following conversion: // - serialized; - // - deserialized as mojo::Map<mojo::String, mojo::String>; + // - deserialized as base::Optional< + // std::unordered_map<std::string, base::Optional<std::string>>>; // - serialized; - // - deserialized as mojo::WTFMap<WTF::String, WTF::String>. - ptr->EchoStringMap( - std::move(maps[i]), - base::Bind(&ExpectStringMap, base::Passed(&expected_map), - loop.QuitClosure())); + // - deserialized as WTF::Optional<WTF::HashMap<WTF::String, + // WTF::String>>. + ptr->EchoStringMap(maps[i], + base::Bind(&ExpectStringMap, base::Unretained(&maps[i]), + loop.QuitClosure())); loop.Run(); } }
diff --git a/mojo/public/cpp/bindings/wtf_array.h b/mojo/public/cpp/bindings/wtf_array.h index 116d1b9..46d9a69 100644 --- a/mojo/public/cpp/bindings/wtf_array.h +++ b/mojo/public/cpp/bindings/wtf_array.h
@@ -12,6 +12,7 @@ #include "mojo/public/cpp/bindings/lib/array_internal.h" #include "mojo/public/cpp/bindings/lib/bindings_internal.h" #include "mojo/public/cpp/bindings/lib/template_util.h" +#include "mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h" #include "mojo/public/cpp/bindings/type_converter.h" #include "third_party/WebKit/Source/wtf/Vector.h" @@ -147,9 +148,7 @@ WTFArray Clone() const { WTFArray result; result.is_null_ = is_null_; - result.vec_.reserveCapacity(vec_.size()); - for (const auto& element : vec_) - result.vec_.append(internal::Clone(element)); + result.vec_ = internal::Clone(vec_); return result; } @@ -159,13 +158,7 @@ bool Equals(const WTFArray& other) const { if (is_null() != other.is_null()) return false; - if (size() != other.size()) - return false; - for (size_t i = 0; i < size(); ++i) { - if (!internal::Equals(at(i), other.at(i))) - return false; - } - return true; + return internal::Equals(vec_, other.vec_); } private:
diff --git a/mojo/public/cpp/bindings/wtf_map.h b/mojo/public/cpp/bindings/wtf_map.h index 18d0c42..0aba959 100644 --- a/mojo/public/cpp/bindings/wtf_map.h +++ b/mojo/public/cpp/bindings/wtf_map.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "mojo/public/cpp/bindings/lib/template_util.h" +#include "mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h" #include "mojo/public/cpp/bindings/type_converter.h" #include "third_party/WebKit/Source/wtf/HashMap.h" #include "third_party/WebKit/Source/wtf/text/StringHash.h" @@ -156,9 +157,7 @@ WTFMap Clone() const { WTFMap result; result.is_null_ = is_null_; - auto map_end = map_.end(); - for (auto it = map_.begin(); it != map_end; ++it) - result.map_.add(internal::Clone(it->key), internal::Clone(it->value)); + result.map_ = internal::Clone(map_); return result; } @@ -168,20 +167,7 @@ bool Equals(const WTFMap& other) const { if (is_null() != other.is_null()) return false; - if (size() != other.size()) - return false; - - auto this_end = map_.end(); - auto other_end = other.map_.end(); - - for (auto iter = map_.begin(); iter != this_end; ++iter) { - auto other_iter = other.map_.find(iter->key); - if (other_iter == other_end || - !internal::Equals(iter->value, other_iter->value)) { - return false; - } - } - return true; + return internal::Equals(map_, other.map_); } ConstIterator begin() const { return map_.begin(); }
diff --git a/mojo/public/interfaces/bindings/tests/BUILD.gn b/mojo/public/interfaces/bindings/tests/BUILD.gn index 635b615..0a48076 100644 --- a/mojo/public/interfaces/bindings/tests/BUILD.gn +++ b/mojo/public/interfaces/bindings/tests/BUILD.gn
@@ -27,6 +27,8 @@ ":test_mojom_import", ":test_mojom_import2", ] + + use_new_wrapper_types = true } mojom("test_mojom_import") { @@ -34,6 +36,7 @@ sources = [ "sample_import.mojom", ] + use_new_wrapper_types = true } mojom("test_mojom_import_wrapper") { @@ -59,6 +62,7 @@ ":test_mojom_import", ":test_mojom_import_wrapper_wrapper", ] + use_new_wrapper_types = true } mojom("test_struct_traits_interfaces") { @@ -66,6 +70,7 @@ sources = [ "struct_with_traits.mojom", ] + use_new_wrapper_types = true } mojom("test_interfaces_experimental") { @@ -73,6 +78,7 @@ sources = [ "test_unions.mojom", ] + use_new_wrapper_types = true } mojom("test_associated_interfaces") { @@ -83,6 +89,7 @@ "test_associated_interfaces.mojom", "validation_test_associated_interfaces.mojom", ] + use_new_wrapper_types = true } mojom("versioning_test_service_interfaces") { @@ -90,6 +97,7 @@ sources = [ "versioning_test_service.mojom", ] + use_new_wrapper_types = true } mojom("versioning_test_client_interfaces") { @@ -97,6 +105,7 @@ sources = [ "versioning_test_client.mojom", ] + use_new_wrapper_types = true } mojom("test_wtf_types") { @@ -105,6 +114,7 @@ sources = [ "test_wtf_types.mojom", ] + use_new_wrapper_types = true } mojom("test_no_sources") {
diff --git a/mojo/public/tools/bindings/generate_type_mappings.py b/mojo/public/tools/bindings/generate_type_mappings.py index 77915892..e2fbf31 100755 --- a/mojo/public/tools/bindings/generate_type_mappings.py +++ b/mojo/public/tools/bindings/generate_type_mappings.py
@@ -97,9 +97,8 @@ mojom_type = match_result.group(1) native_type = match_result.group(2) - # The only attribute supported currently is "pass_by_value". - pass_by_value = (match_result.group(3) and - match_result.group(3) == "pass_by_value") + # The only attribute supported currently is "move_only". + move_only = match_result.group(3) and match_result.group(3) == "move_only" assert mojom_type not in result, ( "Cannot map multiple native types (%s, %s) to the same mojom type: %s" % @@ -107,7 +106,7 @@ result[mojom_type] = { 'typename': native_type, - 'pass_by_value': pass_by_value, + 'move_only': move_only, 'public_headers': values['public_headers'], 'traits_headers': values['traits_headers'], }
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl index 36856e8..0a446a7 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/enum_macros.tmpl
@@ -75,3 +75,9 @@ static_cast<int32_t>(value)); } {%- endmacro %} + +{%- macro enum_hash(enum) %} +template <> +struct hash<{{enum|get_qualified_name_for_kind}}> + : public mojo::internal::EnumHashImpl<{{enum|get_qualified_name_for_kind}}> {}; +{%- endmacro %}
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl index b5f8e16..0249ef3 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl
@@ -54,7 +54,8 @@ virtual bool {{method.name}}({{interface_macros.declare_sync_method_params("", method)}}); {%- endif %} - using {{method.name}}Callback = {{interface_macros.declare_callback(method, for_blink)}}; + using {{method.name}}Callback = {{interface_macros.declare_callback(method, + for_blink, use_new_wrapper_types)}}; {%- endif %} virtual void {{method.name}}({{interface_macros.declare_request_params("", method)}}) = 0; {%- endfor %}
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl index b3c6423..4017fc51 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
@@ -265,7 +265,8 @@ void Run( {{interface_macros.declare_responder_params( - "in_", method.response_parameters, for_blink)}}); + "in_", method.response_parameters, for_blink, + use_new_wrapper_types)}}); uint64_t request_id_; bool is_sync_; @@ -278,7 +279,8 @@ void {{class_name}}_{{method.name}}_ProxyToResponder::Run( {{interface_macros.declare_responder_params( - "in_", method.response_parameters, for_blink)}}) { + "in_", method.response_parameters, for_blink, + use_new_wrapper_types)}}) { {{struct_macros.get_serialized_size(response_params_struct, "in_%s", "&serialization_context_")}} mojo::internal::ResponseMessageBuilder builder(
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl index c996adc..4bec4c6 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl
@@ -5,9 +5,10 @@ {%- endfor %} {%- endmacro %} -{%- macro declare_responder_params(prefix, parameters, for_blink) %} +{%- macro declare_responder_params(prefix, parameters, for_blink, use_new_wrapper_types) %} {%- for param in parameters -%} -{%- if (not param.kind|is_string_kind) or for_blink -%} +{%- if (not param.kind|is_string_kind) or for_blink or + use_new_wrapper_types -%} {{param.kind|cpp_wrapper_param_type}} {{prefix}}{{param.name}} {%- else %} mojo::String {{prefix}}{{param.name}} @@ -16,17 +17,18 @@ {%- endfor %} {%- endmacro %} -{%- macro declare_callback(method, for_blink) -%} +{%- macro declare_callback(method, for_blink, use_new_wrapper_types) -%} base::Callback<void( {%- for param in method.response_parameters -%} {#- TODO(yzshen): For historical reasons, we use mojo::String here (instead of const mojo::String&) inconsistently. Preserve the behavior temporarily. #} -{%- if (not param.kind|is_string_kind) or for_blink -%} +{%- if (not param.kind|is_string_kind) or for_blink or + use_new_wrapper_types -%} {{param.kind|cpp_wrapper_param_type}} -{%- else -%} +{%- else -%} mojo::String -{%- endif %} -{%- if not loop.last %}, {% endif %} +{%- endif %} +{%- if not loop.last %}, {% endif %} {%- endfor -%} )> {%- endmacro -%}
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl index 97f8e3a0..c4f3e07 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/module.h.tmpl
@@ -12,15 +12,41 @@ variant_path|upper|replace("/","_")|replace(".","_")| replace("-", "_")) %} +{%- from "enum_macros.tmpl" import enum_decl %} +{%- from "enum_macros.tmpl" import enum_stream_operator %} +{%- from "enum_macros.tmpl" import is_known_enum_value %} +{%- from "enum_macros.tmpl" import enum_hash %} + +{%- macro namespace_begin() %} +{%- for namespace in namespaces_as_array %} +namespace {{namespace}} { +{%- endfor %} +{%- if variant %} +namespace {{variant}} { +{%- endif %} +{%- endmacro %} + +{%- macro namespace_end() %} +{%- if variant %} +} // namespace {{variant}} +{%- endif %} +{%- for namespace in namespaces_as_array|reverse %} +} // namespace {{namespace}} +{%- endfor %} +{%- endmacro %} + #ifndef {{header_guard}} #define {{header_guard}} #include <stdint.h> + +#include <functional> #include <ostream> #include <type_traits> #include <utility> #include "base/callback.h" +#include "base/optional.h" #include "base/strings/string_piece.h" #include "mojo/public/cpp/bindings/associated_interface_ptr.h" #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" @@ -51,6 +77,7 @@ {%- else %} #include "mojo/public/cpp/bindings/wtf_array.h" #include "mojo/public/cpp/bindings/wtf_map.h" +#include "third_party/WebKit/Source/wtf/Optional.h" #include "third_party/WebKit/Source/wtf/text/WTFString.h" {%- endif %} @@ -58,26 +85,32 @@ #include "{{header}}" {%- endfor %} -{%- for namespace in namespaces_as_array %} -namespace {{namespace}} { -{%- endfor %} -{%- if variant %} -namespace {{variant}} { -{%- endif %} - {#--- Enums #} -{% from "enum_macros.tmpl" import enum_decl -%} -{% from "enum_macros.tmpl" import enum_stream_operator -%} -{% from "enum_macros.tmpl" import is_known_enum_value -%} -{%- for enum in enums %} -{%- if enum|is_native_only_kind %} +{%- if enums %} +{{namespace_begin()}} +{%- for enum in enums %} +{%- if enum|is_native_only_kind %} using {{enum.name}} = mojo::NativeEnum; -{%- else %} +{%- else %} {{enum_decl(enum)}} {{enum_stream_operator(enum)}} {{is_known_enum_value(enum)}} -{%- endif %} -{%- endfor %} +{%- endif %} +{%- endfor %} +{{namespace_end()}} + +namespace std { + +{%- for enum in enums %} +{%- if not enum|is_native_only_kind %} +{{enum_hash(enum)}} +{%- endif %} +{%- endfor %} + +} // namespace std +{%- endif %} + +{{namespace_begin()}} {#--- Constants #} {%- for constant in module.constants %} @@ -133,6 +166,27 @@ {#--- Interfaces -#} {% for interface in interfaces %} {% include "interface_declaration.tmpl" %} + +{%- if interface.enums %} +{{namespace_end()}} +namespace std { + +{%- for enum in interface.enums %} +{%- if not enum|is_native_only_kind %} +{{enum_hash(enum)}} +{%- endif %} +{%- endfor %} + +} // namespace std +{{namespace_begin()}} +{%- endif %} + +{%- for enum in interface.enums %} +{%- if not enum|is_native_only_kind %} +{{enum_stream_operator(enum)}} +{{is_known_enum_value(enum)}} +{%- endif %} +{%- endfor %} {%- endfor %} {#--- Interface Proxies -#} @@ -190,6 +244,20 @@ {% include "wrapper_class_template_definition.tmpl" %} {%- endif %} +{%- if struct.enums %} +{{namespace_end()}} +namespace std { + +{%- for enum in struct.enums %} +{%- if not enum|is_native_only_kind %} +{{enum_hash(enum)}} +{%- endif %} +{%- endfor %} + +} // namespace std +{{namespace_begin()}} +{%- endif %} + {%- for enum in struct.enums %} {%- if not enum|is_native_only_kind %} {{enum_stream_operator(enum)}} @@ -198,21 +266,7 @@ {%- endfor %} {%- endfor %} -{%- for interface in interfaces %} -{%- for enum in interface.enums %} -{%- if not enum|is_native_only_kind %} -{{enum_stream_operator(enum)}} -{{is_known_enum_value(enum)}} -{%- endif %} -{%- endfor %} -{%- endfor %} - -{%- if variant %} -} // namespace {{variant}} -{%- endif %} -{%- for namespace in namespaces_as_array|reverse %} -} // namespace {{namespace}} -{%- endfor %} +{{namespace_end()}} namespace mojo {
diff --git a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py index 85d4a1d..38b219c6 100644 --- a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py +++ b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -36,6 +36,7 @@ # generator library code so that filters can use the generator as context. _current_typemap = {} _for_blink = False +_use_new_wrapper_types = False # TODO(rockot, yzshen): The variant handling is kind of a hack currently. Make # it right. _variant = None @@ -106,16 +107,20 @@ def ConstantValue(constant): return ExpressionToText(constant.value, kind=constant.kind) +# TODO(yzshen): Revisit the default value feature. It was designed prior to +# custom type mapping. def DefaultValue(field): if field.default: if mojom.IsStructKind(field.kind): assert field.default == "default" - return "%s::New()" % GetNameForKind(field.kind) + if not IsTypemappedKind(field.kind): + return "%s::New()" % GetNameForKind(field.kind) return ExpressionToText(field.default, kind=field.kind) - if mojom.IsArrayKind(field.kind) or mojom.IsMapKind(field.kind): - return "nullptr"; - if mojom.IsStringKind(field.kind): - return "" if _for_blink else "nullptr" + if not _use_new_wrapper_types: + if mojom.IsArrayKind(field.kind) or mojom.IsMapKind(field.kind): + return "nullptr"; + if mojom.IsStringKind(field.kind): + return "" if _for_blink else "nullptr" return "" def NamespaceToArray(namespace): @@ -155,10 +160,27 @@ if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): return "%sPtr" % GetNameForKind(kind) if mojom.IsArrayKind(kind): - pattern = "mojo::WTFArray<%s>" if _for_blink else "mojo::Array<%s>" + pattern = None + if _use_new_wrapper_types: + if mojom.IsNullableKind(kind): + pattern = ("WTF::Optional<WTF::Vector<%s>>" if _for_blink else + "base::Optional<std::vector<%s>>") + else: + pattern = "WTF::Vector<%s>" if _for_blink else "std::vector<%s>" + else: + pattern = "mojo::WTFArray<%s>" if _for_blink else "mojo::Array<%s>" return pattern % GetCppWrapperType(kind.kind) if mojom.IsMapKind(kind): - pattern = "mojo::WTFMap<%s, %s>" if _for_blink else "mojo::Map<%s, %s>" + pattern = None + if _use_new_wrapper_types: + if mojom.IsNullableKind(kind): + pattern = ("WTF::Optional<WTF::HashMap<%s, %s>>" if _for_blink else + "base::Optional<std::unordered_map<%s, %s>>") + else: + pattern = ("WTF::HashMap<%s, %s>" if _for_blink else + "std::unordered_map<%s, %s>") + else: + pattern = "mojo::WTFMap<%s, %s>" if _for_blink else "mojo::Map<%s, %s>" return pattern % (GetCppWrapperType(kind.key_kind), GetCppWrapperType(kind.value_kind)) if mojom.IsInterfaceKind(kind): @@ -170,7 +192,12 @@ if mojom.IsAssociatedInterfaceRequestKind(kind): return "%sAssociatedRequest" % GetNameForKind(kind.kind) if mojom.IsStringKind(kind): - return "WTF::String" if _for_blink else "mojo::String" + if _for_blink: + return "WTF::String" + if not _use_new_wrapper_types: + return "mojo::String" + return ("base::Optional<std::string>" if mojom.IsNullableKind(kind) else + "std::string") if mojom.IsGenericHandleKind(kind): return "mojo::ScopedHandle" if mojom.IsDataPipeConsumerKind(kind): @@ -185,12 +212,23 @@ raise Exception("Unrecognized kind %s" % kind.spec) return _kind_to_cpp_type[kind] -def ShouldPassParamByValue(kind): +def IsMoveOnlyKind(kind): if IsTypemappedKind(kind): if mojom.IsEnumKind(kind): - return True - return _current_typemap[GetFullMojomNameForKind(kind)]["pass_by_value"] - return not mojom.IsStringKind(kind) + return False + return _current_typemap[GetFullMojomNameForKind(kind)]["move_only"] + if mojom.IsStructKind(kind) or mojom.IsUnionKind(kind): + return True + if mojom.IsArrayKind(kind): + return IsMoveOnlyKind(kind.kind) if _use_new_wrapper_types else True + if mojom.IsMapKind(kind): + return IsMoveOnlyKind(kind.value_kind) if _use_new_wrapper_types else True + if mojom.IsAnyHandleOrInterfaceKind(kind): + return True + return False + +def ShouldPassParamByValue(kind): + return (not mojom.IsReferenceKind(kind)) or IsMoveOnlyKind(kind) def GetCppWrapperParamType(kind): cpp_wrapper_type = GetCppWrapperType(kind) @@ -309,12 +347,14 @@ if len(struct.fields) > 4: return False for field in struct.fields: - if mojom.IsMoveOnlyKind(field.kind): + if mojom.IsReferenceKind(field.kind) and not mojom.IsStringKind(field.kind): return False return True def ShouldInlineUnion(union): - return not any(mojom.IsMoveOnlyKind(field.kind) for field in union.fields) + return not any( + mojom.IsReferenceKind(field.kind) and not mojom.IsStringKind(field.kind) + for field in union.fields) def GetContainerValidateParamsCtorArgs(kind): if mojom.IsStringKind(kind): @@ -428,6 +468,7 @@ "extra_traits_headers": self.GetExtraTraitsHeaders(), "extra_public_headers": self.GetExtraPublicHeaders(), "for_blink": self.for_blink, + "use_new_wrapper_types": self.use_new_wrapper_types, } @staticmethod @@ -455,6 +496,8 @@ _current_typemap = self.typemap global _for_blink _for_blink = self.for_blink + global _use_new_wrapper_types + _use_new_wrapper_types = self.use_new_wrapper_types global _variant _variant = self.variant suffix = "-%s" % self.variant if self.variant else ""
diff --git a/mojo/public/tools/bindings/mojom.gni b/mojo/public/tools/bindings/mojom.gni index 0caaabf..d6f4f17 100644 --- a/mojo/public/tools/bindings/mojom.gni +++ b/mojo/public/tools/bindings/mojom.gni
@@ -69,6 +69,16 @@ # testonly (optional) # # visibility (optional) +# +# use_new_wrapper_types (optional) +# If set to true, mojom array/map/string will be mapped to STL (for +# chromium variant) or WTF (for blink) types. Otherwise, they will be +# mapped to mojo::Array/Map/String/etc. +# Default value is false. +# TODO(yzshen): +# - flip the flag and make use_new_wrapper_types=true the default; +# - convert all users to use the new mode; +# - remove support for the old mode. template("mojom") { assert( defined(invoker.sources) || defined(invoker.deps) || @@ -219,6 +229,11 @@ bindings_configuration.for_blink) { args += [ "--for_blink" ] } + + if (defined(invoker.use_new_wrapper_types) && + invoker.use_new_wrapper_types) { + args += [ "--use_new_wrapper_types" ] + } } }
diff --git a/mojo/public/tools/bindings/mojom_bindings_generator.py b/mojo/public/tools/bindings/mojom_bindings_generator.py index 130e730..5240dd7 100755 --- a/mojo/public/tools/bindings/mojom_bindings_generator.py +++ b/mojo/public/tools/bindings/mojom_bindings_generator.py
@@ -144,7 +144,8 @@ generator = generator_module.Generator( module, args.output_dir, typemap=self._typemap.get(language, {}), variant=args.variant, bytecode_path=args.bytecode_path, - for_blink=args.for_blink) + for_blink=args.for_blink, + use_new_wrapper_types=args.use_new_wrapper_types) filtered_args = [] if hasattr(generator_module, 'GENERATOR_PREFIX'): prefix = '--' + generator_module.GENERATOR_PREFIX + '_' @@ -256,6 +257,10 @@ generate_parser.add_argument("--for_blink", action="store_true", help="Use WTF types as generated types for mojo " "string/array/map.") + generate_parser.add_argument( + "--use_new_wrapper_types", action="store_true", + help="Map mojom array/map/string to STL (for chromium variant) or WTF " + "(for blink variant) types directly.") generate_parser.set_defaults(func=_Generate) precompile_parser = subparsers.add_parser("precompile",
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/generator.py b/mojo/public/tools/bindings/pylib/mojom/generate/generator.py index a97d2eac..ccb8363b 100644 --- a/mojo/public/tools/bindings/pylib/mojom/generate/generator.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
@@ -37,13 +37,15 @@ # Pass |output_dir| to emit files to disk. Omit |output_dir| to echo all # files to stdout. def __init__(self, module, output_dir=None, typemap=None, variant=None, - bytecode_path=None, for_blink=False): + bytecode_path=None, for_blink=False, + use_new_wrapper_types=False): self.module = module self.output_dir = output_dir self.typemap = typemap or {} self.variant = variant self.bytecode_path = bytecode_path self.for_blink = for_blink + self.use_new_wrapper_types = use_new_wrapper_types def GetStructsFromMethods(self): result = []
diff --git a/mojo/public/tools/bindings/pylib/mojom/generate/module.py b/mojo/public/tools/bindings/pylib/mojom/generate/module.py index 97f1f0ef..2775b6c5 100644 --- a/mojo/public/tools/bindings/pylib/mojom/generate/module.py +++ b/mojo/public/tools/bindings/pylib/mojom/generate/module.py
@@ -792,11 +792,6 @@ IsAssociatedInterfaceRequestKind(kind)) -def IsMoveOnlyKind(kind): - return (not IsStringKind(kind) and IsObjectKind(kind)) or \ - IsAnyHandleKind(kind) or IsInterfaceKind(kind) or IsAssociatedKind(kind) - - def HasCallbacks(interface): for method in interface.methods: if method.response_parameters != None:
diff --git a/native_client_sdk/PRESUBMIT.py b/native_client_sdk/PRESUBMIT.py index 9e551bb..fd02d58 100644 --- a/native_client_sdk/PRESUBMIT.py +++ b/native_client_sdk/PRESUBMIT.py
@@ -41,15 +41,15 @@ def GetPreferredTryMasters(project, change): return { - 'tryserver.chromium.linux': { + 'master.tryserver.chromium.linux': { 'linux_nacl_sdk': set(['defaulttests']), 'linux_nacl_sdk_build': set(['defaulttests']), }, - 'tryserver.chromium.win': { + 'master.ryserver.chromium.win': { 'win_nacl_sdk': set(['defaulttests']), 'win_nacl_sdk_build': set(['defaulttests']), }, - 'tryserver.chromium.mac': { + 'master.tryserver.chromium.mac': { 'mac_nacl_sdk': set(['defaulttests']), 'mac_nacl_sdk_build': set(['defaulttests']), }
diff --git a/net/BUILD.gn b/net/BUILD.gn index 2623fc4..2ba91279 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -819,6 +819,8 @@ "tools/cert_verify_tool/cert_verify_tool_util.h", "tools/cert_verify_tool/verify_using_cert_verify_proc.cc", "tools/cert_verify_tool/verify_using_cert_verify_proc.h", + "tools/cert_verify_tool/verify_using_path_builder.cc", + "tools/cert_verify_tool/verify_using_path_builder.h", ] # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h index df55033f..ba17ac1 100644 --- a/net/base/net_error_list.h +++ b/net/base/net_error_list.h
@@ -674,11 +674,6 @@ // The PAC script terminated fatally and must be reloaded. NET_ERROR(PAC_SCRIPT_TERMINATED, -367) -// The certificate offered by the alternative server is not valid for the -// origin, a violation of HTTP Alternative Services specification Section 2.1, -// https://tools.ietf.org/id/draft-ietf-httpbis-alt-svc-06.html#host_auth. -NET_ERROR(ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN, -368) - // Request is throttled because of a Backoff header. // See: crbug.com/486891. NET_ERROR(TEMPORARY_BACKOFF, -369)
diff --git a/net/cert/internal/parse_ocsp.cc b/net/cert/internal/parse_ocsp.cc index 0243d95..21ce878b 100644 --- a/net/cert/internal/parse_ocsp.cc +++ b/net/cert/internal/parse_ocsp.cc
@@ -7,6 +7,7 @@ #include "base/sha1.h" #include "crypto/sha2.h" #include "net/cert/internal/parse_ocsp.h" +#include "net/der/encode_values.h" namespace net { @@ -529,4 +530,28 @@ return found; } +bool CheckOCSPDateValid(const OCSPSingleResponse& response, + const base::Time& verify_time, + const base::TimeDelta& max_age) { + der::GeneralizedTime verify_time_der; + if (!der::EncodeTimeAsGeneralizedTime(verify_time, &verify_time_der)) + return false; + + if (response.this_update > verify_time_der) + return false; // Response is not yet valid. + + if (response.has_next_update && (response.next_update <= verify_time_der)) + return false; // Response is no longer valid. + + der::GeneralizedTime earliest_this_update; + if (!der::EncodeTimeAsGeneralizedTime(verify_time - max_age, + &earliest_this_update)) { + return false; + } + if (response.this_update < earliest_this_update) + return false; // Response is too old. + + return true; +} + } // namespace net
diff --git a/net/cert/internal/parse_ocsp.h b/net/cert/internal/parse_ocsp.h index b9052ae..af5541d 100644 --- a/net/cert/internal/parse_ocsp.h +++ b/net/cert/internal/parse_ocsp.h
@@ -17,6 +17,10 @@ #include "net/der/parser.h" #include "net/der/tag.h" +namespace base { +class Time; +} + namespace net { // OCSPCertID contains a representation of a DER-encoded RFC 6960 "CertID". @@ -278,6 +282,15 @@ const der::Input& cert_tbs_certificate_tlv, OCSPCertStatus* out); +// Returns true if |response|, a valid OCSP response with a thisUpdate field and +// potentially a nextUpdate field, is valid at |verify_time| and not older than +// |max_age|. Expressed differently, returns true if |response.thisUpdate| <= +// |verify_time| < response.nextUpdate, and |response.thisUpdate| >= +// |verify_time| - |max_age|. +NET_EXPORT_PRIVATE bool CheckOCSPDateValid(const OCSPSingleResponse& response, + const base::Time& verify_time, + const base::TimeDelta& max_age); + } // namespace net #endif // NET_CERT_INTERNAL_PARSE_OCSP_H_
diff --git a/net/cert/internal/parse_ocsp_unittest.cc b/net/cert/internal/parse_ocsp_unittest.cc index c0fc061b..bc4e1e1e 100644 --- a/net/cert/internal/parse_ocsp_unittest.cc +++ b/net/cert/internal/parse_ocsp_unittest.cc
@@ -8,6 +8,7 @@ #include "base/logging.h" #include "net/cert/internal/test_helpers.h" #include "net/cert/x509_certificate.h" +#include "net/der/encode_values.h" #include "net/test/test_data_directory.h" #include "testing/gtest/include/gtest/gtest.h" @@ -15,6 +16,8 @@ namespace { +const base::TimeDelta kOCSPAgeOneWeek = base::TimeDelta::FromDays(7); + std::string GetFilePath(const std::string& file_name) { return std::string("net/data/parse_ocsp_unittest/") + file_name; } @@ -182,4 +185,131 @@ ASSERT_EQ(PARSE_OCSP_SINGLE_RESPONSE, ParseOCSP("missing_response.pem")); } +TEST(OCSPDateTest, Valid) { + OCSPSingleResponse response; + + base::Time now = base::Time::Now(); + base::Time this_update = now - base::TimeDelta::FromHours(1); + ASSERT_TRUE( + der::EncodeTimeAsGeneralizedTime(this_update, &response.this_update)); + response.has_next_update = false; + EXPECT_TRUE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek)); + + base::Time next_update = this_update + base::TimeDelta::FromDays(7); + ASSERT_TRUE( + der::EncodeTimeAsGeneralizedTime(next_update, &response.next_update)); + response.has_next_update = true; + EXPECT_TRUE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek)); +} + +TEST(OCSPDateTest, ThisUpdateInTheFuture) { + OCSPSingleResponse response; + + base::Time now = base::Time::Now(); + base::Time this_update = now + base::TimeDelta::FromHours(1); + ASSERT_TRUE( + der::EncodeTimeAsGeneralizedTime(this_update, &response.this_update)); + response.has_next_update = false; + EXPECT_FALSE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek)); + + base::Time next_update = this_update + base::TimeDelta::FromDays(7); + ASSERT_TRUE( + der::EncodeTimeAsGeneralizedTime(next_update, &response.next_update)); + response.has_next_update = true; + EXPECT_FALSE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek)); +} + +TEST(OCSPDateTest, NextUpdatePassed) { + OCSPSingleResponse response; + + base::Time now = base::Time::Now(); + base::Time this_update = now - base::TimeDelta::FromDays(6); + ASSERT_TRUE( + der::EncodeTimeAsGeneralizedTime(this_update, &response.this_update)); + response.has_next_update = false; + EXPECT_TRUE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek)); + + base::Time next_update = now - base::TimeDelta::FromHours(1); + ASSERT_TRUE( + der::EncodeTimeAsGeneralizedTime(next_update, &response.next_update)); + response.has_next_update = true; + EXPECT_FALSE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek)); +} + +TEST(OCSPDateTest, NextUpdateBeforeThisUpdate) { + OCSPSingleResponse response; + + base::Time now = base::Time::Now(); + base::Time this_update = now - base::TimeDelta::FromDays(1); + ASSERT_TRUE( + der::EncodeTimeAsGeneralizedTime(this_update, &response.this_update)); + response.has_next_update = false; + EXPECT_TRUE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek)); + + base::Time next_update = this_update - base::TimeDelta::FromDays(1); + ASSERT_TRUE( + der::EncodeTimeAsGeneralizedTime(next_update, &response.next_update)); + response.has_next_update = true; + EXPECT_FALSE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek)); +} + +TEST(OCSPDateTest, ThisUpdateOlderThanMaxAge) { + OCSPSingleResponse response; + + base::Time now = base::Time::Now(); + base::Time this_update = now - kOCSPAgeOneWeek; + ASSERT_TRUE( + der::EncodeTimeAsGeneralizedTime(this_update, &response.this_update)); + response.has_next_update = false; + EXPECT_TRUE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek)); + + base::Time next_update = now + base::TimeDelta::FromHours(1); + ASSERT_TRUE( + der::EncodeTimeAsGeneralizedTime(next_update, &response.next_update)); + response.has_next_update = true; + EXPECT_TRUE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek)); + + ASSERT_TRUE(der::EncodeTimeAsGeneralizedTime( + this_update - base::TimeDelta::FromSeconds(1), &response.this_update)); + response.has_next_update = false; + EXPECT_FALSE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek)); + response.has_next_update = true; + EXPECT_FALSE(CheckOCSPDateValid(response, now, kOCSPAgeOneWeek)); +} + +TEST(OCSPDateTest, VerifyTimeFromBeforeWindowsEpoch) { + OCSPSingleResponse response; + base::Time windows_epoch; + base::Time verify_time = windows_epoch - base::TimeDelta::FromDays(1); + + base::Time now = base::Time::Now(); + base::Time this_update = now - base::TimeDelta::FromHours(1); + ASSERT_TRUE( + der::EncodeTimeAsGeneralizedTime(this_update, &response.this_update)); + response.has_next_update = false; + EXPECT_FALSE(CheckOCSPDateValid(response, verify_time, kOCSPAgeOneWeek)); + + base::Time next_update = this_update + kOCSPAgeOneWeek; + ASSERT_TRUE( + der::EncodeTimeAsGeneralizedTime(next_update, &response.next_update)); + response.has_next_update = true; + EXPECT_FALSE(CheckOCSPDateValid(response, verify_time, kOCSPAgeOneWeek)); +} + +TEST(OCSPDateTest, VerifyTimeMinusAgeFromBeforeWindowsEpoch) { + OCSPSingleResponse response; + base::Time windows_epoch; + base::Time verify_time = windows_epoch + base::TimeDelta::FromDays(1); + + base::Time this_update = windows_epoch; + ASSERT_TRUE( + der::EncodeTimeAsGeneralizedTime(this_update, &response.this_update)); + response.has_next_update = false; +#ifdef OS_WIN + EXPECT_FALSE(CheckOCSPDateValid(response, verify_time, kOCSPAgeOneWeek)); +#else + EXPECT_TRUE(CheckOCSPDateValid(response, verify_time, kOCSPAgeOneWeek)); +#endif +} + } // namespace net
diff --git a/net/der/encode_values.cc b/net/der/encode_values.cc new file mode 100644 index 0000000..af7098a --- /dev/null +++ b/net/der/encode_values.cc
@@ -0,0 +1,30 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/time/time.h" +#include "net/der/encode_values.h" + +namespace net { + +namespace der { + +bool EncodeTimeAsGeneralizedTime(const base::Time& time, + der::GeneralizedTime* generalized_time) { + base::Time::Exploded exploded; + time.UTCExplode(&exploded); + if (!exploded.HasValidValues()) + return false; + + generalized_time->year = exploded.year; + generalized_time->month = exploded.month; + generalized_time->day = exploded.day_of_month; + generalized_time->hours = exploded.hour; + generalized_time->minutes = exploded.minute; + generalized_time->seconds = exploded.second; + return true; +} + +} // namespace der + +} // namespace net
diff --git a/net/der/encode_values.h b/net/der/encode_values.h new file mode 100644 index 0000000..e0b04423 --- /dev/null +++ b/net/der/encode_values.h
@@ -0,0 +1,29 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_DER_ENCODE_VALUES_H_ +#define NET_DER_ENCODE_VALUES_H_ + +#include "net/base/net_export.h" +#include "net/der/parse_values.h" + +namespace base { +class Time; +} + +namespace net { + +namespace der { + +// Encodes |time|, a UTC-based time, to DER |generalized_time|, for comparing +// against other GeneralizedTime objects. +NET_EXPORT bool EncodeTimeAsGeneralizedTime( + const base::Time& time, + der::GeneralizedTime* generalized_time); + +} // namespace der + +} // namespace net + +#endif // NET_DER_ENCODE_VALUES_H
diff --git a/net/der/encode_values_unittest.cc b/net/der/encode_values_unittest.cc new file mode 100644 index 0000000..52672cf --- /dev/null +++ b/net/der/encode_values_unittest.cc
@@ -0,0 +1,96 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/time/time.h" +#include "net/der/encode_values.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { +namespace der { +namespace test { + +TEST(EncodeValuesTest, EncodeTimeAsGeneralizedTime) { + // Fri, 24 Jun 2016 17:04:54 GMT + base::Time time = + base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(1466787894); + GeneralizedTime generalized_time; + ASSERT_TRUE(EncodeTimeAsGeneralizedTime(time, &generalized_time)); + EXPECT_EQ(2016, generalized_time.year); + EXPECT_EQ(6, generalized_time.month); + EXPECT_EQ(24, generalized_time.day); + EXPECT_EQ(17, generalized_time.hours); + EXPECT_EQ(4, generalized_time.minutes); + EXPECT_EQ(54, generalized_time.seconds); +} + +// ASN.1 GeneralizedTime can represent dates from year 0000 to 9999, and +// although base::Time can represent times from before the Windows epoch and +// after the 32-bit time_t maximum, the conversion between base::Time and +// der::GeneralizedTime goes through the time representation of the underlying +// platform, which might not be able to handle the full GeneralizedTime date +// range. Out-of-range times should not be converted to der::GeneralizedTime. In +// tests, possibly-out-of-range test times are specified as a +// base::Time::Exploded, and then converted to a base::Time. If the conversion +// fails, this signals the underlying platform cannot handle the time, and the +// test aborts early. If the underlying platform can represent the time, then +// the conversion is successful, and the encoded GeneralizedTime can should +// match the test time. +// +// Thu, 1 Jan 1570 00:00:00 GMT. This time is unrepresentable by the Windows +// native time libraries. +TEST(EncodeValuesTest, EncodeTimeFromBeforeWindowsEpoch) { + base::Time::Exploded exploded; + exploded.year = 1570; + exploded.month = 1; + exploded.day_of_week = 5; + exploded.hour = 0; + exploded.minute = 0; + exploded.second = 0; + exploded.millisecond = 0; + + base::Time time; + if (!base::Time::FromUTCExploded(exploded, &time)) + return; + + GeneralizedTime generalized_time; + ASSERT_TRUE(EncodeTimeAsGeneralizedTime(time, &generalized_time)); + EXPECT_EQ(1570, generalized_time.year); + EXPECT_EQ(1, generalized_time.month); + EXPECT_EQ(1, generalized_time.day); + EXPECT_EQ(0, generalized_time.hours); + EXPECT_EQ(0, generalized_time.minutes); + EXPECT_EQ(0, generalized_time.seconds); +} + +// Sat, 1 Jan 2039 00:00:00 GMT. See above comment. This time may be +// unrepresentable on 32-bit systems. +TEST(EncodeValuesTest, EncodeTimeAfterTimeTMax) { + base::Time::Exploded exploded; + exploded.year = 2039; + exploded.month = 1; + exploded.day_of_week = 7; + exploded.hour = 0; + exploded.minute = 0; + exploded.second = 0; + exploded.millisecond = 0; + + base::Time time; + if (!base::Time::FromUTCExploded(exploded, &time)) + return; + + GeneralizedTime generalized_time; + ASSERT_TRUE(EncodeTimeAsGeneralizedTime(time, &generalized_time)); + EXPECT_EQ(2039, generalized_time.year); + EXPECT_EQ(1, generalized_time.month); + EXPECT_EQ(1, generalized_time.day); + EXPECT_EQ(0, generalized_time.hours); + EXPECT_EQ(0, generalized_time.minutes); + EXPECT_EQ(0, generalized_time.seconds); +} + +} // namespace test + +} // namespace der + +} // namespace net
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index 06651e96..0661daf 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -127,6 +127,7 @@ quic_disable_preconnect_if_0rtt(false), quic_migrate_sessions_on_network_change(false), quic_migrate_sessions_early(false), + quic_allow_server_migration(false), quic_disable_bidirectional_streams(false), quic_force_hol_blocking(false), proxy_delegate(NULL), @@ -187,6 +188,7 @@ params.quic_idle_connection_timeout_seconds, params.quic_migrate_sessions_on_network_change, params.quic_migrate_sessions_early, + params.quic_allow_server_migration, params.quic_force_hol_blocking, params.quic_connection_options, params.enable_token_binding),
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index b4a72ea..c3de445 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h
@@ -176,6 +176,9 @@ // If true, active QUIC sessions experiencing poor connectivity may be // migrated onto a new network. bool quic_migrate_sessions_early; + // If true, allows migration of QUIC connections to a server-specified + // alternate server address. + bool quic_allow_server_migration; // If true, bidirectional streams over QUIC will be disabled. bool quic_disable_bidirectional_streams; // If true, enable force HOL blocking. For measurement purposes.
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 9254739..414300e5 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -1653,83 +1653,6 @@ arraysize(data_reads)); EXPECT_THAT(out.rv, IsError(ERR_EMPTY_RESPONSE)); } -// -//// Test that network access can be deferred and resumed. -// TEST_P(HttpNetworkTransactionTest, ThrottleBeforeNetworkStart) { -// HttpRequestInfo request; -// request.method = "GET"; -// request.url = GURL("http://www.example.org/"); -// request.load_flags = 0; -// -// std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); -// std::unique_ptr<HttpTransaction> trans( -// new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); -// -// // Defer on OnBeforeNetworkStart. -// BeforeNetworkStartHandler net_start_handler(true); // defer -// trans->SetBeforeNetworkStartCallback( -// base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart, -// base::Unretained(&net_start_handler))); -// -// MockRead data_reads[] = { -// MockRead("HTTP/1.0 200 OK\r\n"), -// MockRead("Content-Length: 5\r\n\r\n"), -// MockRead("hello"), -// MockRead(SYNCHRONOUS, 0), -// }; -// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0); -// session_deps_.socket_factory->AddSocketDataProvider(&data); -// -// TestCompletionCallback callback; -// -// int rv = trans->Start(&request, callback.callback(), BoundNetLog()); -// EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); -// base::RunLoop().RunUntilIdle(); -// -// // Should have deferred for network start. -// EXPECT_TRUE(net_start_handler.observed_before_network_start()); -// EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState()); -// -// trans->ResumeNetworkStart(); -// rv = callback.WaitForResult(); -// EXPECT_THAT(rv, IsOk()); -// EXPECT_TRUE(trans->GetResponseInfo()); -// -// scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(100)); -// rv = trans->Read(io_buf.get(), io_buf->size(), callback.callback()); -// if (rv == ERR_IO_PENDING) -// rv = callback.WaitForResult(); -// EXPECT_EQ(5, rv); -// trans.reset(); -//} -// -//// Test that network use can be deferred and canceled. -// TEST_P(HttpNetworkTransactionTest, ThrottleAndCancelBeforeNetworkStart) { -// HttpRequestInfo request; -// request.method = "GET"; -// request.url = GURL("http://www.example.org/"); -// request.load_flags = 0; -// -// std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); -// std::unique_ptr<HttpTransaction> trans( -// new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); -// -// // Defer on OnBeforeNetworkStart. -// BeforeNetworkStartHandler net_start_handler(true); // defer -// trans->SetBeforeNetworkStartCallback( -// base::Bind(&BeforeNetworkStartHandler::OnBeforeNetworkStart, -// base::Unretained(&net_start_handler))); -// -// TestCompletionCallback callback; -// -// int rv = trans->Start(&request, callback.callback(), BoundNetLog()); -// EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); -// base::RunLoop().RunUntilIdle(); -// -// // Should have deferred for network start. -// EXPECT_TRUE(net_start_handler.observed_before_network_start()); -// EXPECT_EQ(LOAD_STATE_WAITING_FOR_DELEGATE, trans->GetLoadState()); -//} // Next 2 cases (KeepAliveEarlyClose and KeepAliveEarlyClose2) are regression // tests. There was a bug causing HttpNetworkTransaction to hang in the @@ -13172,166 +13095,6 @@ EXPECT_FALSE(trans2.GetResponseInfo()->was_fetched_via_spdy); } -class AltSvcCertificateVerificationTest : public HttpNetworkTransactionTest { - public: - void Run(bool pooling, bool valid) { - url::SchemeHostPort server(GURL(valid ? "https://mail.example.org:443" - : "https://invalid.example.org:443")); - HostPortPair alternative("www.example.org", 443); - - base::FilePath certs_dir = GetTestCertsDirectory(); - scoped_refptr<X509Certificate> cert( - ImportCertFromFile(certs_dir, "spdy_pooling.pem")); - ASSERT_TRUE(cert); - bool common_name_fallback_used; - EXPECT_EQ(valid, - cert->VerifyNameMatch(server.host(), &common_name_fallback_used)); - EXPECT_TRUE( - cert->VerifyNameMatch(alternative.host(), &common_name_fallback_used)); - SSLSocketDataProvider ssl(ASYNC, OK); - ssl.SetNextProto(kProtoHTTP2); - ssl.cert = cert; - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - - // If pooling, then start a request to alternative first to create a - // SpdySession. - std::string url0 = "https://www.example.org:443"; - // Second request to server, which has an alternative service, and could - // open a connection to the alternative host or pool to the existing one. - std::string url1("https://"); - url1.append(server.host()); - url1.append(":443"); - - std::unique_ptr<SpdySerializedFrame> req0; - std::unique_ptr<SpdySerializedFrame> req1; - std::unique_ptr<SpdySerializedFrame> resp0; - std::unique_ptr<SpdySerializedFrame> body0; - std::unique_ptr<SpdySerializedFrame> resp1; - std::unique_ptr<SpdySerializedFrame> body1; - std::vector<MockWrite> writes; - std::vector<MockRead> reads; - - if (pooling) { - req0.reset(spdy_util_.ConstructSpdyGet(url0.c_str(), 1, LOWEST)); - spdy_util_.UpdateWithStreamDestruction(1); - req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), 3, LOWEST)); - - writes.push_back(CreateMockWrite(*req0, 0)); - writes.push_back(CreateMockWrite(*req1, 3)); - - resp0.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); - body0.reset(spdy_util_.ConstructSpdyBodyFrame(1, true)); - resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3)); - body1.reset(spdy_util_.ConstructSpdyBodyFrame(3, true)); - - reads.push_back(CreateMockRead(*resp0, 1)); - reads.push_back(CreateMockRead(*body0, 2)); - reads.push_back(MockRead(ASYNC, ERR_IO_PENDING, 4)); - reads.push_back(CreateMockRead(*resp1, 5)); - reads.push_back(CreateMockRead(*body1, 6)); - reads.push_back(MockRead(ASYNC, OK, 7)); - } else { - req1.reset(spdy_util_.ConstructSpdyGet(url1.c_str(), 1, LOWEST)); - - writes.push_back(CreateMockWrite(*req1, 0)); - - resp1.reset(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); - body1.reset(spdy_util_.ConstructSpdyBodyFrame(1, true)); - - reads.push_back(CreateMockRead(*resp1, 1)); - reads.push_back(CreateMockRead(*body1, 2)); - reads.push_back(MockRead(ASYNC, OK, 3)); - } - - SequencedSocketData data(reads.data(), reads.size(), writes.data(), - writes.size()); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - // Connection to the server fails. - MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); - StaticSocketDataProvider data_refused; - data_refused.set_connect_data(mock_connect); - session_deps_.socket_factory->AddSocketDataProvider(&data_refused); - - std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); - HttpServerProperties* http_server_properties = - session->http_server_properties(); - AlternativeService alternative_service( - AlternateProtocolFromNextProto(kProtoHTTP2), alternative); - base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1); - http_server_properties->SetAlternativeService(server, alternative_service, - expiration); - - // First request to alternative. - if (pooling) { - std::unique_ptr<HttpTransaction> trans0( - new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); - HttpRequestInfo request0; - request0.method = "GET"; - request0.url = GURL(url0); - request0.load_flags = 0; - TestCompletionCallback callback0; - - int rv = trans0->Start(&request0, callback0.callback(), BoundNetLog()); - EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); - rv = callback0.WaitForResult(); - EXPECT_THAT(rv, IsOk()); - } - - // Second request to origin. - std::unique_ptr<HttpTransaction> trans1( - new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); - HttpRequestInfo request1; - request1.method = "GET"; - request1.url = GURL(url1); - request1.load_flags = 0; - TestCompletionCallback callback1; - - int rv = trans1->Start(&request1, callback1.callback(), BoundNetLog()); - EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); - base::RunLoop().RunUntilIdle(); - if (data.IsPaused()) - data.Resume(); - rv = callback1.WaitForResult(); - if (valid) { - EXPECT_THAT(rv, IsOk()); - } else { - if (pooling) { - EXPECT_THAT(rv, IsError(ERR_CONNECTION_REFUSED)); - } else { - EXPECT_THAT(rv, IsError(ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN)); - } - } - } -}; - -INSTANTIATE_TEST_CASE_P(ProtoPlusDepend, - AltSvcCertificateVerificationTest, - testing::Values(kTestCaseNoPriorityDependencies, - kTestCasePriorityDependencies)); - -// The alternative service host must exhibit a certificate that is valid for the -// origin host. Test that this is enforced when pooling to an existing -// connection. -TEST_P(AltSvcCertificateVerificationTest, PoolingValid) { - Run(true, true); -} - -TEST_P(AltSvcCertificateVerificationTest, PoolingInvalid) { - Run(true, false); -} - -// The alternative service host must exhibit a certificate that is valid for the -// origin host. Test that this is enforced when opening a new connection. -TEST_P(AltSvcCertificateVerificationTest, NewConnectionValid) { - Run(false, true); -} - -// TODO(bnc): Re-enable when https://crbug.com/615413 is fixed. -TEST_P(AltSvcCertificateVerificationTest, DISABLED_NewConnectionInvalid) { - Run(false, false); -} - // Alternative service requires HTTP/2 (or SPDY), but HTTP/1.1 is negotiated // with the alternative server. That connection should not be used. TEST_P(HttpNetworkTransactionTest, AlternativeServiceNotOnHttp11) {
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc index a779d7f..3ba3c914 100644 --- a/net/http/http_stream_factory_impl_job.cc +++ b/net/http/http_stream_factory_impl_job.cc
@@ -654,14 +654,9 @@ return ERR_IO_PENDING; default: - DCHECK(result != ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN || - IsSpdyAlternative() || IsQuicAlternative()); if (job_status_ != STATUS_BROKEN) { DCHECK_EQ(STATUS_RUNNING, job_status_); job_status_ = STATUS_FAILED; - // TODO(bnc): If (result == ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN), - // then instead of marking alternative service broken, mark (origin, - // alternative service) couple as invalid. MaybeMarkAlternativeServiceBroken(); } base::ThreadTaskRunnerHandle::Get()->PostTask( @@ -738,8 +733,6 @@ } int HttpStreamFactoryImpl::Job::DoStart() { - valid_spdy_session_pool_.reset(new ValidSpdySessionPool( - session_->spdy_session_pool(), origin_url_, IsSpdyAlternative())); const BoundNetLog* net_log = delegate_->GetNetLog(this); if (net_log) { @@ -978,11 +971,9 @@ // Check first if we have a spdy session for this group. If so, then go // straight to using that. if (CanUseExistingSpdySession()) { - base::WeakPtr<SpdySession> spdy_session; - int result = valid_spdy_session_pool_->FindAvailableSession( - spdy_session_key, net_log_, &spdy_session); - if (result != OK) - return result; + base::WeakPtr<SpdySession> spdy_session = + session_->spdy_session_pool()->FindAvailableSession( + spdy_session_key, origin_url_, net_log_); if (spdy_session) { // If we're preconnecting, but we already have a SpdySession, we don't // actually need to preconnect any sockets, so we're done. @@ -1175,9 +1166,6 @@ if (!ssl_started && result < 0 && (IsSpdyAlternative() || IsQuicAlternative())) { job_status_ = STATUS_BROKEN; - // TODO(bnc): if (result == ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN), then - // instead of marking alternative service broken, mark (origin, alternative - // service) couple as invalid. MaybeMarkAlternativeServiceBroken(); return result; } @@ -1321,22 +1309,17 @@ } SpdySessionKey spdy_session_key = GetSpdySessionKey(); - base::WeakPtr<SpdySession> spdy_session; - int result = valid_spdy_session_pool_->FindAvailableSession( - spdy_session_key, net_log_, &spdy_session); - if (result != OK) { - return result; - } + base::WeakPtr<SpdySession> spdy_session = + session_->spdy_session_pool()->FindAvailableSession( + spdy_session_key, origin_url_, net_log_); if (spdy_session) { return SetSpdyHttpStreamOrBidirectionalStreamImpl(spdy_session, direct); } - result = valid_spdy_session_pool_->CreateAvailableSessionFromSocket( - spdy_session_key, std::move(connection_), net_log_, - spdy_certificate_error_, using_ssl_, &spdy_session); - if (result != OK) { - return result; - } + spdy_session = + session_->spdy_session_pool()->CreateAvailableSessionFromSocket( + spdy_session_key, std::move(connection_), net_log_, + spdy_certificate_error_, using_ssl_); if (!spdy_session->HasAcceptableTransportSecurity()) { spdy_session->CloseSessionOnError( @@ -1657,52 +1640,6 @@ } } -HttpStreamFactoryImpl::Job::ValidSpdySessionPool::ValidSpdySessionPool( - SpdySessionPool* spdy_session_pool, - GURL& origin_url, - bool is_spdy_alternative) - : spdy_session_pool_(spdy_session_pool), - origin_url_(origin_url), - is_spdy_alternative_(is_spdy_alternative) { -} - -int HttpStreamFactoryImpl::Job::ValidSpdySessionPool::FindAvailableSession( - const SpdySessionKey& key, - const BoundNetLog& net_log, - base::WeakPtr<SpdySession>* spdy_session) { - *spdy_session = - spdy_session_pool_->FindAvailableSession(key, origin_url_, net_log); - return CheckAlternativeServiceValidityForOrigin(*spdy_session); -} - -int HttpStreamFactoryImpl::Job::ValidSpdySessionPool:: - CreateAvailableSessionFromSocket( - const SpdySessionKey& key, - std::unique_ptr<ClientSocketHandle> connection, - const BoundNetLog& net_log, - int certificate_error_code, - bool is_secure, - base::WeakPtr<SpdySession>* spdy_session) { - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("net"), - "HttpStreamFactoryImpl::Job::CreateAvailableSessionFromSocket"); - *spdy_session = spdy_session_pool_->CreateAvailableSessionFromSocket( - key, std::move(connection), net_log, certificate_error_code, is_secure); - return CheckAlternativeServiceValidityForOrigin(*spdy_session); -} - -int HttpStreamFactoryImpl::Job::ValidSpdySessionPool:: - CheckAlternativeServiceValidityForOrigin( - base::WeakPtr<SpdySession> spdy_session) { - // For an alternative Job, destination_.host() might be different than - // origin_url_.host(), therefore it needs to be verified that the former - // provides a certificate that is valid for the latter. - if (!is_spdy_alternative_ || !spdy_session || - spdy_session->VerifyDomainAuthentication(origin_url_.host())) { - return OK; - } - return ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN; -} - ClientSocketPoolManager::SocketGroupType HttpStreamFactoryImpl::Job::GetSocketGroup() const { std::string scheme = origin_url_.scheme();
diff --git a/net/http/http_stream_factory_impl_job.h b/net/http/http_stream_factory_impl_job.h index 0f7b177..e24f1bae 100644 --- a/net/http/http_stream_factory_impl_job.h +++ b/net/http/http_stream_factory_impl_job.h
@@ -265,51 +265,6 @@ STATUS_SUCCEEDED }; - // Wrapper class for SpdySessionPool methods to enforce certificate - // requirements for SpdySessions. - class ValidSpdySessionPool { - public: - ValidSpdySessionPool(SpdySessionPool* spdy_session_pool, - GURL& origin_url, - bool is_spdy_alternative); - - // Returns OK if a SpdySession was not found (in which case |spdy_session| - // is set to nullptr), or if one was found (in which case |spdy_session| is - // set to it) and it has an associated SSL certificate with is valid for - // |origin_url_|, or if this requirement does not apply because the Job is - // not a SPDY alternative job. Returns the appropriate error code - // otherwise, - // in which case |spdy_session| should not be used. - int FindAvailableSession(const SpdySessionKey& key, - const BoundNetLog& net_log, - base::WeakPtr<SpdySession>* spdy_session); - - // Creates a SpdySession and sets |spdy_session| to point to it. Returns OK - // if the associated SSL certificate is valid for |origin_url_|, or if this - // requirement does not apply because the Job is not a SPDY alternative job. - // Returns the appropriate error code otherwise, in which case - // |spdy_session| should not be used. - int CreateAvailableSessionFromSocket( - const SpdySessionKey& key, - std::unique_ptr<ClientSocketHandle> connection, - const BoundNetLog& net_log, - int certificate_error_code, - bool is_secure, - base::WeakPtr<SpdySession>* spdy_session); - - private: - // Returns OK if |spdy_session| has an associated SSL certificate with is - // valid for |origin_url_|, or if this requirement does not apply because - // the Job is not a SPDY alternative job, or if |spdy_session| is null. - // Returns appropriate error code otherwise. - int CheckAlternativeServiceValidityForOrigin( - base::WeakPtr<SpdySession> spdy_session); - - SpdySessionPool* const spdy_session_pool_; - const GURL origin_url_; - const bool is_spdy_alternative_; - }; - // Resume the |this| job after the specified |wait_time_|. void ResumeAfterDelay(); @@ -507,8 +462,6 @@ // preconnect. int num_streams_; - std::unique_ptr<ValidSpdySessionPool> valid_spdy_session_pool_; - // Initialized when we create a new SpdySession. base::WeakPtr<SpdySession> new_spdy_session_;
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc index b673689..e71a07a 100644 --- a/net/http/http_stream_parser.cc +++ b/net/http/http_stream_parser.cc
@@ -333,6 +333,7 @@ DCHECK(callback_.is_null()); DCHECK(!callback.is_null()); DCHECK_EQ(0, read_buf_unused_offset_); + DCHECK(SendRequestBuffersEmpty()); // This function can be called with io_state_ == STATE_DONE if the // connection is closed after seeing just a 1xx response code. @@ -369,6 +370,7 @@ DCHECK(callback_.is_null()); DCHECK(!callback.is_null()); DCHECK_LE(buf_len, kMaxBufSize); + DCHECK(SendRequestBuffersEmpty()); // Added to investigate crbug.com/499663. CHECK(buf); @@ -409,19 +411,27 @@ case STATE_SEND_HEADERS: DCHECK_EQ(OK, result); result = DoSendHeaders(); + DCHECK_NE(STATE_NONE, io_state_); break; case STATE_SEND_HEADERS_COMPLETE: result = DoSendHeadersComplete(result); + DCHECK_NE(STATE_NONE, io_state_); break; case STATE_SEND_BODY: DCHECK_EQ(OK, result); result = DoSendBody(); + DCHECK_NE(STATE_NONE, io_state_); break; case STATE_SEND_BODY_COMPLETE: result = DoSendBodyComplete(result); + DCHECK_NE(STATE_NONE, io_state_); break; case STATE_SEND_REQUEST_READ_BODY_COMPLETE: result = DoSendRequestReadBodyComplete(result); + DCHECK_NE(STATE_NONE, io_state_); + break; + case STATE_SEND_REQUEST_COMPLETE: + result = DoSendRequestComplete(result); break; case STATE_READ_HEADERS: net_log_.BeginEvent(NetLog::TYPE_HTTP_STREAM_PARSER_READ_HEADERS); @@ -475,6 +485,7 @@ // the headers were sent, but not all of the body way, and |result| is // an error that this should try reading after, stash the error for now and // act like the request was successfully sent. + io_state_ = STATE_SEND_REQUEST_COMPLETE; if (request_headers_->BytesConsumed() >= request_headers_length_ && ShouldTryReadingOnUploadError(result)) { upload_error_ = result; @@ -506,6 +517,7 @@ } // Finished sending the request. + io_state_ = STATE_SEND_REQUEST_COMPLETE; return OK; } @@ -520,6 +532,7 @@ if (request_->upload_data_stream->is_chunked() && sent_last_chunk_) { // Finished sending the request. + io_state_ = STATE_SEND_REQUEST_COMPLETE; return OK; } @@ -534,6 +547,7 @@ if (result < 0) { // If |result| is an error that this should try reading after, stash the // error for now and act like the request was successfully sent. + io_state_ = STATE_SEND_REQUEST_COMPLETE; if (ShouldTryReadingOnUploadError(result)) { upload_error_ = result; return OK; @@ -551,8 +565,10 @@ int HttpStreamParser::DoSendRequestReadBodyComplete(int result) { // |result| is the result of read from the request body from the last call to // DoSendBody(). - if (result < 0) + if (result < 0) { + io_state_ = STATE_SEND_REQUEST_COMPLETE; return result; + } // Chunked data needs to be encoded. if (request_->upload_data_stream->is_chunked()) { @@ -574,6 +590,7 @@ DCHECK(request_->upload_data_stream->IsEOF()); DCHECK(!request_->upload_data_stream->is_chunked()); // Finished sending the request. + io_state_ = STATE_SEND_REQUEST_COMPLETE; } else if (result > 0) { request_body_send_buf_->DidAppend(result); result = 0; @@ -582,6 +599,15 @@ return result; } +int HttpStreamParser::DoSendRequestComplete(int result) { + DCHECK_NE(result, ERR_IO_PENDING); + request_headers_ = nullptr; + request_body_send_buf_ = nullptr; + request_body_read_buf_ = nullptr; + + return result; +} + int HttpStreamParser::DoReadHeaders() { io_state_ = STATE_READ_HEADERS_COMPLETE; @@ -1194,4 +1220,9 @@ HttpStatusLineValidator::STATUS_LINE_MAX); } +bool HttpStreamParser::SendRequestBuffersEmpty() { + return request_headers_ == nullptr && request_body_send_buf_ == nullptr && + request_body_send_buf_ == nullptr; +} + } // namespace net
diff --git a/net/http/http_stream_parser.h b/net/http/http_stream_parser.h index 3a4258e..a70af65 100644 --- a/net/http/http_stream_parser.h +++ b/net/http/http_stream_parser.h
@@ -135,6 +135,7 @@ STATE_SEND_BODY, STATE_SEND_BODY_COMPLETE, STATE_SEND_REQUEST_READ_BODY_COMPLETE, + STATE_SEND_REQUEST_COMPLETE, STATE_READ_HEADERS, STATE_READ_HEADERS_COMPLETE, STATE_READ_BODY, @@ -167,6 +168,7 @@ int DoSendBody(); int DoSendBodyComplete(int result); int DoSendRequestReadBodyComplete(int result); + int DoSendRequestComplete(int result); int DoReadHeaders(); int DoReadHeadersComplete(int result); int DoReadBody(); @@ -191,6 +193,9 @@ // Uploads statistics about status line compliance with RFC 7230. void ValidateStatusLine(const std::string& status_line); + // Check if buffers used to send the request are empty. + bool SendRequestBuffersEmpty(); + // Next state of the request, when the current one completes. State io_state_;
diff --git a/net/http/http_util.cc b/net/http/http_util.cc index 1f1ef91..313da11 100644 --- a/net/http/http_util.cc +++ b/net/http/http_util.cc
@@ -347,9 +347,8 @@ // static bool HttpUtil::IsValidHeaderValue(const std::string& value) { - // Just a sanity check: disallow NUL and CRLF. - return value.find('\0') == std::string::npos && - value.find("\r\n") == std::string::npos; + // Just a sanity check: disallow NUL, CR and LF. + return value.find_first_of("\0\r\n", 0, 3) == std::string::npos; } // static
diff --git a/net/http/http_util_unittest.cc b/net/http/http_util_unittest.cc index 7162d7a0..94fde66 100644 --- a/net/http/http_util_unittest.cc +++ b/net/http/http_util_unittest.cc
@@ -1367,4 +1367,29 @@ EXPECT_TRUE(HttpUtil::HasValidators(v1_1, kEtagEmpty, kLastModifiedInvalid)); } +TEST(HttpUtilTest, IsValidHeaderValue) { + const char* const invalid_values[] = { + "X-Requested-With: chrome${NUL}Sec-Unsafe: injected", + "X-Requested-With: chrome\r\nSec-Unsafe: injected", + "X-Requested-With: chrome\nSec-Unsafe: injected", + "X-Requested-With: chrome\rSec-Unsafe: injected", + }; + for (const std::string& value : invalid_values) { + std::string replaced = value; + base::ReplaceSubstringsAfterOffset(&replaced, 0, "${NUL}", + std::string(1, '\0')); + EXPECT_FALSE(HttpUtil::IsValidHeaderValue(replaced)) << replaced; + } + + // Check that all characters permitted by RFC7230 3.2.6 are allowed. + std::string allowed = "\t"; + for (char c = '\x20'; c < '\x7F'; ++c) { + allowed.append(1, c); + } + for (int c = 0x80; c <= 0xFF; ++c) { + allowed.append(1, static_cast<char>(c)); + } + EXPECT_TRUE(HttpUtil::IsValidHeaderValue(allowed)); +} + } // namespace net
diff --git a/net/net.gyp b/net/net.gyp index d033f73..74a1deab 100644 --- a/net/net.gyp +++ b/net/net.gyp
@@ -1016,6 +1016,8 @@ 'tools/cert_verify_tool/cert_verify_tool_util.h', 'tools/cert_verify_tool/verify_using_cert_verify_proc.cc', 'tools/cert_verify_tool/verify_using_cert_verify_proc.h', + 'tools/cert_verify_tool/verify_using_path_builder.cc', + 'tools/cert_verify_tool/verify_using_path_builder.h', ], # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. 'msvs_disabled_warnings': [4267, ],
diff --git a/net/net.gypi b/net/net.gypi index 744f6e8..9bac24b 100644 --- a/net/net.gypi +++ b/net/net.gypi
@@ -142,6 +142,8 @@ 'cert/x509_util_openssl.h', 'der/input.cc', 'der/input.h', + 'der/encode_values.cc', + 'der/encode_values.h', 'der/parse_values.cc', 'der/parse_values.h', 'der/parser.cc', @@ -922,14 +924,6 @@ 'quic/iovector.h', 'quic/network_connection.cc', 'quic/network_connection.h', - 'quic/p2p/quic_p2p_crypto_config.cc', - 'quic/p2p/quic_p2p_crypto_config.h', - 'quic/p2p/quic_p2p_crypto_stream.cc', - 'quic/p2p/quic_p2p_crypto_stream.h', - 'quic/p2p/quic_p2p_session.cc', - 'quic/p2p/quic_p2p_session.h', - 'quic/p2p/quic_p2p_stream.cc', - 'quic/p2p/quic_p2p_stream.h', 'quic/port_suggester.cc', 'quic/port_suggester.h', 'quic/quic_address_mismatch.cc', @@ -1442,6 +1436,7 @@ 'cookies/cookie_util_unittest.cc', 'cookies/parsed_cookie_unittest.cc', 'der/input_unittest.cc', + 'der/encode_values_unittest.cc', 'der/parse_values_unittest.cc', 'der/parser_unittest.cc', 'disk_cache/backend_unittest.cc', @@ -1627,7 +1622,6 @@ 'quic/interval_test.cc', 'quic/iovector_test.cc', 'quic/network_connection_unittest.cc', - 'quic/p2p/quic_p2p_session_test.cc', 'quic/port_suggester_unittest.cc', 'quic/quic_address_mismatch_test.cc', 'quic/quic_alarm_test.cc',
diff --git a/net/quic/congestion_control/general_loss_algorithm.cc b/net/quic/congestion_control/general_loss_algorithm.cc index 05491b1b..9dfc7ce9 100644 --- a/net/quic/congestion_control/general_loss_algorithm.cc +++ b/net/quic/congestion_control/general_loss_algorithm.cc
@@ -64,10 +64,10 @@ } loss_detection_timeout_ = QuicTime::Zero(); QuicTime::Delta max_rtt = - QuicTime::Delta::Max(rtt_stats.previous_srtt(), rtt_stats.latest_rtt()); + std::max(rtt_stats.previous_srtt(), rtt_stats.latest_rtt()); QuicTime::Delta loss_delay = - QuicTime::Delta::Max(QuicTime::Delta::FromMilliseconds(kMinLossDelayMs), - max_rtt + (max_rtt >> reordering_shift_)); + std::max(QuicTime::Delta::FromMilliseconds(kMinLossDelayMs), + max_rtt + (max_rtt >> reordering_shift_)); QuicPacketNumber packet_number = unacked_packets.GetLeastUnacked(); for (QuicUnackedPacketMap::const_iterator it = unacked_packets.begin(); it != unacked_packets.end() && packet_number <= largest_observed; @@ -133,7 +133,7 @@ unacked_packets.GetTransmissionInfo(spurious_retransmission).sent_time; // Increase the reordering fraction until enough time would be allowed. QuicTime::Delta max_rtt = - QuicTime::Delta::Max(rtt_stats.previous_srtt(), rtt_stats.latest_rtt()); + std::max(rtt_stats.previous_srtt(), rtt_stats.latest_rtt()); QuicTime::Delta proposed_extra_time(QuicTime::Delta::Zero()); do { proposed_extra_time = max_rtt >> reordering_shift_;
diff --git a/net/quic/congestion_control/pacing_sender.cc b/net/quic/congestion_control/pacing_sender.cc index 7f366c9..d98dacf 100644 --- a/net/quic/congestion_control/pacing_sender.cc +++ b/net/quic/congestion_control/pacing_sender.cc
@@ -48,7 +48,7 @@ QuicByteCount bytes_in_flight, const CongestionVector& acked_packets, const CongestionVector& lost_packets) { - if (FLAGS_quic_allow_noprr && !lost_packets.empty()) { + if (!lost_packets.empty()) { // Clear any burst tokens when entering recovery. burst_tokens_ = 0; } @@ -110,7 +110,7 @@ } } else { ideal_next_packet_send_time_ = - QuicTime::Max(ideal_next_packet_send_time_ + delay, sent_time + delay); + std::max(ideal_next_packet_send_time_ + delay, sent_time + delay); } return in_flight; }
diff --git a/net/quic/congestion_control/pacing_sender_test.cc b/net/quic/congestion_control/pacing_sender_test.cc index c531a59a..3277cacd 100644 --- a/net/quic/congestion_control/pacing_sender_test.cc +++ b/net/quic/congestion_control/pacing_sender_test.cc
@@ -299,7 +299,6 @@ } TEST_F(PacingSenderTest, NoBurstEnteringRecovery) { - ValueRestore<bool> old_flag(&FLAGS_quic_allow_noprr, true); // Configure pacing rate of 1 packet per 1 ms with no burst tokens. InitPacingRate(0, QuicBandwidth::FromBytesAndTimeDelta( kMaxPacketSize, QuicTime::Delta::FromMilliseconds(1)));
diff --git a/net/quic/congestion_control/send_algorithm_simulator.cc b/net/quic/congestion_control/send_algorithm_simulator.cc index bb1316f..d1eac0c 100644 --- a/net/quic/congestion_control/send_algorithm_simulator.cc +++ b/net/quic/congestion_control/send_algorithm_simulator.cc
@@ -380,7 +380,7 @@ ? QuicTime::Zero() : sent_packets_.back().ack_time + bandwidth_.TransferTime(kPacketSize); - ack_time = QuicTime::Max(ack_time, queue_ack_time); + ack_time = std::max(ack_time, queue_ack_time); sent_packets_.push_back(SentPacket(sender->last_sent, clock_->Now(), ack_time, packet_lost, transfer)); } else {
diff --git a/net/quic/congestion_control/tcp_cubic_sender_base.cc b/net/quic/congestion_control/tcp_cubic_sender_base.cc index 539eadc..8fb7b711 100644 --- a/net/quic/congestion_control/tcp_cubic_sender_base.cc +++ b/net/quic/congestion_control/tcp_cubic_sender_base.cc
@@ -87,7 +87,7 @@ // Slow Start Fast Exit experiment. slow_start_large_reduction_ = true; } - if (FLAGS_quic_allow_noprr && config.HasReceivedConnectionOptions() && + if (config.HasReceivedConnectionOptions() && ContainsQuicTag(config.ReceivedConnectionOptions(), kNPRR)) { // Use unity pacing instead of PRR. no_prr_ = true; @@ -224,10 +224,9 @@ if (rate_based_sending_ && bytes_in_flight > GetCongestionWindow()) { // Rate based sending allows sending more than CWND, but reduces the pacing // rate when the bytes in flight is more than the CWND to 75% of bandwidth. - return bandwidth.Scale(0.75); + return 0.75 * bandwidth; } - return bandwidth.Scale(InSlowStart() ? 2 - : (no_prr_ && InRecovery() ? 1 : 1.25)); + return bandwidth * (InSlowStart() ? 2 : (no_prr_ && InRecovery() ? 1 : 1.25)); } QuicBandwidth TcpCubicSenderBase::BandwidthEstimate() const {
diff --git a/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc b/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc index 6415172f..21fcd17a 100644 --- a/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc +++ b/net/quic/congestion_control/tcp_cubic_sender_bytes_test.cc
@@ -779,7 +779,6 @@ } TEST_F(TcpCubicSenderBytesTest, NoPRR) { - ValueRestore<bool> old_flag(&FLAGS_quic_allow_noprr, true); QuicTime::Delta rtt = QuicTime::Delta::FromMilliseconds(100); sender_->rtt_stats_.UpdateRtt(rtt, QuicTime::Delta::Zero(), QuicTime::Zero()); @@ -828,15 +827,15 @@ EXPECT_TRUE( sender_->TimeUntilSend(QuicTime::Zero(), kDefaultTCPMSS).IsZero()); - EXPECT_EQ(sender_->PacingRate(kDefaultTCPMSS), - QuicBandwidth::FromBytesAndTimeDelta(7 * kDefaultTCPMSS, rtt) - .Scale(1.25)); + EXPECT_EQ( + sender_->PacingRate(kDefaultTCPMSS), + QuicBandwidth::FromBytesAndTimeDelta(7 * kDefaultTCPMSS, rtt) * 1.25); for (QuicPacketCount i = cwnd + 1; i < 1.5 * cwnd; ++i) { EXPECT_TRUE( sender_->TimeUntilSend(QuicTime::Zero(), i * kDefaultTCPMSS).IsZero()); EXPECT_EQ(sender_->PacingRate(i * kDefaultTCPMSS), - QuicBandwidth::FromBytesAndTimeDelta(cwnd * kDefaultTCPMSS, rtt) - .Scale(0.75)); + QuicBandwidth::FromBytesAndTimeDelta(cwnd * kDefaultTCPMSS, rtt) * + 0.75); } EXPECT_FALSE( sender_->TimeUntilSend(QuicTime::Zero(), 11 * kDefaultTCPMSS).IsZero());
diff --git a/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc b/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc index 57cda3f..ae277d8a 100644 --- a/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc +++ b/net/quic/congestion_control/tcp_cubic_sender_packets_test.cc
@@ -928,7 +928,6 @@ } TEST_F(TcpCubicSenderPacketsTest, NoPRR) { - ValueRestore<bool> old_flag(&FLAGS_quic_allow_noprr, true); QuicTime::Delta rtt = QuicTime::Delta::FromMilliseconds(100); sender_->rtt_stats_.UpdateRtt(rtt, QuicTime::Delta::Zero(), QuicTime::Zero()); @@ -977,15 +976,15 @@ EXPECT_TRUE( sender_->TimeUntilSend(QuicTime::Zero(), kDefaultTCPMSS).IsZero()); - EXPECT_EQ(sender_->PacingRate(kDefaultTCPMSS), - QuicBandwidth::FromBytesAndTimeDelta(7 * kDefaultTCPMSS, rtt) - .Scale(1.25)); + EXPECT_EQ( + sender_->PacingRate(kDefaultTCPMSS), + QuicBandwidth::FromBytesAndTimeDelta(7 * kDefaultTCPMSS, rtt) * 1.25); for (QuicPacketCount i = cwnd + 1; i < 1.5 * cwnd; ++i) { EXPECT_TRUE( sender_->TimeUntilSend(QuicTime::Zero(), i * kDefaultTCPMSS).IsZero()); EXPECT_EQ(sender_->PacingRate(i * kDefaultTCPMSS), - QuicBandwidth::FromBytesAndTimeDelta(cwnd * kDefaultTCPMSS, rtt) - .Scale(0.75)); + QuicBandwidth::FromBytesAndTimeDelta(cwnd * kDefaultTCPMSS, rtt) * + 0.75); } EXPECT_FALSE( sender_->TimeUntilSend(QuicTime::Zero(), 11 * kDefaultTCPMSS).IsZero());
diff --git a/net/quic/congestion_control/windowed_filter_test.cc b/net/quic/congestion_control/windowed_filter_test.cc index fd540d0c..c6bf279f 100644 --- a/net/quic/congestion_control/windowed_filter_test.cc +++ b/net/quic/congestion_control/windowed_filter_test.cc
@@ -65,7 +65,7 @@ << windowed_max_bw_.GetSecondBest().ToBitsPerSecond() << " " << windowed_max_bw_.GetThirdBest().ToBitsPerSecond(); now = now + QuicTime::Delta::FromMilliseconds(25); - bw_sample = bw_sample.Subtract(QuicBandwidth::FromBitsPerSecond(100)); + bw_sample = bw_sample - QuicBandwidth::FromBitsPerSecond(100); } EXPECT_EQ(QuicBandwidth::FromBitsPerSecond(900), windowed_max_bw_.GetBest()); @@ -150,7 +150,7 @@ // decreasing. for (int i = 0; i < 6; ++i) { now = now + QuicTime::Delta::FromMilliseconds(25); - bw_sample = bw_sample.Subtract(QuicBandwidth::FromBitsPerSecond(100)); + bw_sample = bw_sample - QuicBandwidth::FromBitsPerSecond(100); windowed_max_bw_.Update(bw_sample, now); VLOG(1) << "i: " << i << " sample: " << bw_sample.ToBitsPerSecond() << " maxs: " @@ -193,7 +193,7 @@ InitializeMaxFilter(); // BW sample higher than the third-choice max sets that, but nothing else. QuicBandwidth bw_sample = - windowed_max_bw_.GetThirdBest().Add(QuicBandwidth::FromBitsPerSecond(50)); + windowed_max_bw_.GetThirdBest() + QuicBandwidth::FromBitsPerSecond(50); // Latest sample was recorded at 100ms. QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(101); windowed_max_bw_.Update(bw_sample, now); @@ -225,8 +225,8 @@ InitializeMaxFilter(); // BW sample higher than the second-choice max sets that and also // the third-choice max. - QuicBandwidth bw_sample = windowed_max_bw_.GetSecondBest().Add( - QuicBandwidth::FromBitsPerSecond(50)); + QuicBandwidth bw_sample = + windowed_max_bw_.GetSecondBest() + QuicBandwidth::FromBitsPerSecond(50); // Latest sample was recorded at 100ms. QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(101); windowed_max_bw_.Update(bw_sample, now); @@ -257,7 +257,7 @@ // BW sample higher than the first-choice max sets that and also // the second and third-choice maxs. QuicBandwidth bw_sample = - windowed_max_bw_.GetBest().Add(QuicBandwidth::FromBitsPerSecond(50)); + windowed_max_bw_.GetBest() + QuicBandwidth::FromBitsPerSecond(50); // Latest sample was recorded at 100ms. QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(101); windowed_max_bw_.Update(bw_sample, now); @@ -285,7 +285,7 @@ QuicBandwidth old_third_best = windowed_max_bw_.GetThirdBest(); QuicBandwidth old_second_best = windowed_max_bw_.GetSecondBest(); QuicBandwidth bw_sample = - old_third_best.Subtract(QuicBandwidth::FromBitsPerSecond(50)); + old_third_best - QuicBandwidth::FromBitsPerSecond(50); // Best max sample was recorded at 25ms, so expiry time is 124ms. QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(125); windowed_max_bw_.Update(bw_sample, now); @@ -311,7 +311,7 @@ InitializeMaxFilter(); QuicBandwidth old_third_best = windowed_max_bw_.GetThirdBest(); QuicBandwidth bw_sample = - old_third_best.Subtract(QuicBandwidth::FromBitsPerSecond(50)); + old_third_best - QuicBandwidth::FromBitsPerSecond(50); // Second best max sample was recorded at 75ms, so expiry time is 174ms. QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(175); windowed_max_bw_.Update(bw_sample, now); @@ -339,8 +339,8 @@ TEST_F(WindowedFilterTest, ExpireAllMaxs) { InitializeMaxFilter(); - QuicBandwidth bw_sample = windowed_max_bw_.GetThirdBest().Subtract( - QuicBandwidth::FromBitsPerSecond(50)); + QuicBandwidth bw_sample = + windowed_max_bw_.GetThirdBest() - QuicBandwidth::FromBitsPerSecond(50); // Third best max sample was recorded at 100ms, so expiry time is 199ms. QuicTime now = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(200); windowed_max_bw_.Update(bw_sample, now);
diff --git a/net/quic/crypto/crypto_handshake_message.cc b/net/quic/crypto/crypto_handshake_message.cc index aef8dbf..b07eac8 100644 --- a/net/quic/crypto/crypto_handshake_message.cc +++ b/net/quic/crypto/crypto_handshake_message.cc
@@ -28,23 +28,29 @@ : tag_(other.tag_), tag_value_map_(other.tag_value_map_), minimum_size_(other.minimum_size_) { - // Don't copy serialized_. scoped_ptr doesn't have a copy constructor. + // Don't copy serialized_. unique_ptr doesn't have a copy constructor. // The new object can lazily reconstruct serialized_. } +CryptoHandshakeMessage::CryptoHandshakeMessage(CryptoHandshakeMessage&& other) = + default; + CryptoHandshakeMessage::~CryptoHandshakeMessage() {} CryptoHandshakeMessage& CryptoHandshakeMessage::operator=( const CryptoHandshakeMessage& other) { tag_ = other.tag_; tag_value_map_ = other.tag_value_map_; - // Don't copy serialized_. scoped_ptr doesn't have an assignment operator. + // Don't copy serialized_. unique_ptr doesn't have an assignment operator. // However, invalidate serialized_. serialized_.reset(); minimum_size_ = other.minimum_size_; return *this; } +CryptoHandshakeMessage& CryptoHandshakeMessage::operator=( + CryptoHandshakeMessage&& other) = default; + void CryptoHandshakeMessage::Clear() { tag_ = 0; tag_value_map_.clear();
diff --git a/net/quic/crypto/crypto_handshake_message.h b/net/quic/crypto/crypto_handshake_message.h index 6e4da16..fc98754 100644 --- a/net/quic/crypto/crypto_handshake_message.h +++ b/net/quic/crypto/crypto_handshake_message.h
@@ -25,9 +25,11 @@ public: CryptoHandshakeMessage(); CryptoHandshakeMessage(const CryptoHandshakeMessage& other); + CryptoHandshakeMessage(CryptoHandshakeMessage&& other); ~CryptoHandshakeMessage(); CryptoHandshakeMessage& operator=(const CryptoHandshakeMessage& other); + CryptoHandshakeMessage& operator=(CryptoHandshakeMessage&& other); // Clears state. void Clear();
diff --git a/net/quic/crypto/crypto_handshake_message_test.cc b/net/quic/crypto/crypto_handshake_message_test.cc index e8a5e4f9..7197174 100644 --- a/net/quic/crypto/crypto_handshake_message_test.cc +++ b/net/quic/crypto/crypto_handshake_message_test.cc
@@ -13,37 +13,108 @@ namespace { TEST(CryptoHandshakeMessageTest, DebugString) { + const char* str = "SHLO<\n>"; + CryptoHandshakeMessage message; message.set_tag(kSHLO); - EXPECT_EQ("SHLO<\n>", message.DebugString()); + EXPECT_EQ(str, message.DebugString()); + + // Test copy + CryptoHandshakeMessage message2(message); + EXPECT_EQ(str, message2.DebugString()); + + // Test move + CryptoHandshakeMessage message3(std::move(message)); + EXPECT_EQ(str, message3.DebugString()); + + // Test assign + CryptoHandshakeMessage message4 = message3; + EXPECT_EQ(str, message4.DebugString()); + + // Test move-assign + CryptoHandshakeMessage message5 = std::move(message3); + EXPECT_EQ(str, message5.DebugString()); } TEST(CryptoHandshakeMessageTest, DebugStringWithUintVector) { + const char* str = + "REJ <\n RREJ: " + "SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE," + "CLIENT_NONCE_NOT_UNIQUE_FAILURE\n>"; + CryptoHandshakeMessage message; message.set_tag(kREJ); std::vector<uint32_t> reasons = { SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE, CLIENT_NONCE_NOT_UNIQUE_FAILURE}; message.SetVector(kRREJ, reasons); - EXPECT_EQ( - "REJ <\n RREJ: " - "SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE," - "CLIENT_NONCE_NOT_UNIQUE_FAILURE\n>", - message.DebugString()); + EXPECT_EQ(str, message.DebugString()); + + // Test copy + CryptoHandshakeMessage message2(message); + EXPECT_EQ(str, message2.DebugString()); + + // Test move + CryptoHandshakeMessage message3(std::move(message)); + EXPECT_EQ(str, message3.DebugString()); + + // Test assign + CryptoHandshakeMessage message4 = message3; + EXPECT_EQ(str, message4.DebugString()); + + // Test move-assign + CryptoHandshakeMessage message5 = std::move(message3); + EXPECT_EQ(str, message5.DebugString()); } TEST(CryptoHandshakeMessageTest, DebugStringWithTagVector) { + const char* str = "CHLO<\n COPT: 'TBBR','PAD ','BYTE'\n>"; + CryptoHandshakeMessage message; message.set_tag(kCHLO); message.SetVector(kCOPT, QuicTagVector{kTBBR, kPAD, kBYTE}); - EXPECT_EQ("CHLO<\n COPT: 'TBBR','PAD ','BYTE'\n>", message.DebugString()); + EXPECT_EQ(str, message.DebugString()); + + // Test copy + CryptoHandshakeMessage message2(message); + EXPECT_EQ(str, message2.DebugString()); + + // Test move + CryptoHandshakeMessage message3(std::move(message)); + EXPECT_EQ(str, message3.DebugString()); + + // Test assign + CryptoHandshakeMessage message4 = message3; + EXPECT_EQ(str, message4.DebugString()); + + // Test move-assign + CryptoHandshakeMessage message5 = std::move(message3); + EXPECT_EQ(str, message5.DebugString()); } TEST(CryptoHandshakeMessageTest, ServerDesignatedConnectionId) { + const char* str = "SREJ<\n RCID: 18364758544493064720\n>"; + CryptoHandshakeMessage message; message.set_tag(kSREJ); message.SetValue(kRCID, UINT64_C(18364758544493064720)); - EXPECT_EQ("SREJ<\n RCID: 18364758544493064720\n>", message.DebugString()); + EXPECT_EQ(str, message.DebugString()); + + // Test copy + CryptoHandshakeMessage message2(message); + EXPECT_EQ(str, message2.DebugString()); + + // Test move + CryptoHandshakeMessage message3(std::move(message)); + EXPECT_EQ(str, message3.DebugString()); + + // Test assign + CryptoHandshakeMessage message4 = message3; + EXPECT_EQ(str, message4.DebugString()); + + // Test move-assign + CryptoHandshakeMessage message5 = std::move(message3); + EXPECT_EQ(str, message5.DebugString()); } } // namespace
diff --git a/net/quic/crypto/proof_test.cc b/net/quic/crypto/proof_test.cc index a343cf66..d2669a84 100644 --- a/net/quic/crypto/proof_test.cc +++ b/net/quic/crypto/proof_test.cc
@@ -239,7 +239,7 @@ } TEST_P(ProofTest, UseAfterFree) { - ProofSource* source = CryptoTestUtils::ProofSourceForTesting(); + std::unique_ptr<ProofSource> source(CryptoTestUtils::ProofSourceForTesting()); const string server_config = "server config bytes"; const string hostname = "test.example.com"; @@ -254,7 +254,7 @@ // Make sure we can safely access results after deleting where they came from. EXPECT_FALSE(chain->HasOneRef()); - delete source; + source = nullptr; EXPECT_TRUE(chain->HasOneRef()); EXPECT_FALSE(chain->certs.empty());
diff --git a/net/quic/crypto/quic_crypto_client_config.cc b/net/quic/crypto/quic_crypto_client_config.cc index b31a737..50eed98 100644 --- a/net/quic/crypto/quic_crypto_client_config.cc +++ b/net/quic/crypto/quic_crypto_client_config.cc
@@ -54,8 +54,9 @@ } // namespace -QuicCryptoClientConfig::QuicCryptoClientConfig(ProofVerifier* proof_verifier) - : proof_verifier_(proof_verifier), disable_ecdsa_(false) { +QuicCryptoClientConfig::QuicCryptoClientConfig( + std::unique_ptr<ProofVerifier> proof_verifier) + : proof_verifier_(std::move(proof_verifier)), disable_ecdsa_(false) { DCHECK(proof_verifier_.get()); SetDefaults(); }
diff --git a/net/quic/crypto/quic_crypto_client_config.h b/net/quic/crypto/quic_crypto_client_config.h index 6a7a5c99..f4662872 100644 --- a/net/quic/crypto/quic_crypto_client_config.h +++ b/net/quic/crypto/quic_crypto_client_config.h
@@ -194,7 +194,8 @@ DISALLOW_COPY_AND_ASSIGN(CachedState); }; - explicit QuicCryptoClientConfig(ProofVerifier* proof_verifier); + explicit QuicCryptoClientConfig( + std::unique_ptr<ProofVerifier> proof_verifier); ~QuicCryptoClientConfig(); // LookupOrCreate returns a CachedState for the given |server_id|. If no such
diff --git a/net/quic/crypto/quic_crypto_server_config.cc b/net/quic/crypto/quic_crypto_server_config.cc index 4f0e1144..11b96ffd 100644 --- a/net/quic/crypto/quic_crypto_server_config.cc +++ b/net/quic/crypto/quic_crypto_server_config.cc
@@ -211,14 +211,14 @@ QuicCryptoServerConfig::QuicCryptoServerConfig( StringPiece source_address_token_secret, QuicRandom* server_nonce_entropy, - ProofSource* proof_source) + std::unique_ptr<ProofSource> proof_source) : replay_protection_(true), chlo_multiplier_(kMultiplier), configs_lock_(), primary_config_(nullptr), next_config_promotion_time_(QuicWallTime::Zero()), server_nonce_strike_register_lock_(), - proof_source_(proof_source), + proof_source_(std::move(proof_source)), strike_register_no_startup_period_(false), strike_register_max_entries_(1 << 10), strike_register_window_secs_(600), @@ -531,6 +531,13 @@ } if (result->error_code == QUIC_NO_ERROR) { + if (FLAGS_quic_refresh_proof && version > QUIC_VERSION_30) { + // QUIC v31 and above require a new proof for each CHLO so clear the + // existing proof, if any. + crypto_proof->chain = nullptr; + crypto_proof->signature = ""; + crypto_proof->cert_sct = ""; + } EvaluateClientHello(server_ip, version, primary_orbit, requested_config, primary_config, crypto_proof, result, done_cb); } else { @@ -611,6 +618,7 @@ DCHECK(proof_source_.get()); string chlo_hash; CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash); + // No need to get a new proof if one was already generated. if (!crypto_proof->chain && !proof_source_->GetProof( server_ip, info.sni.as_string(), primary_config->serialized, version, @@ -1062,7 +1070,13 @@ string serialized_config = primary_config->serialized; string chlo_hash; CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash); - if (!proof_source_->GetProof( + bool need_proof = true; + if (FLAGS_quic_refresh_proof) { + need_proof = !crypto_proof->chain; + } + // No need to get a new proof if one was already generated. + if (need_proof && + !proof_source_->GetProof( server_ip, info->sni.as_string(), serialized_config, version, chlo_hash, x509_ecdsa_supported, &crypto_proof->chain, &crypto_proof->signature, &crypto_proof->cert_sct)) { @@ -1219,6 +1233,121 @@ return true; } +void QuicCryptoServerConfig::BuildServerConfigUpdateMessage( + QuicVersion version, + StringPiece chlo_hash, + const SourceAddressTokens& previous_source_address_tokens, + const IPAddress& server_ip, + const IPAddress& client_ip, + const QuicClock* clock, + QuicRandom* rand, + QuicCompressedCertsCache* compressed_certs_cache, + const QuicCryptoNegotiatedParameters& params, + const CachedNetworkParameters* cached_network_params, + std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const { + string serialized; + string source_address_token; + const CommonCertSets* common_cert_sets; + { + base::AutoLock locked(configs_lock_); + serialized = primary_config_->serialized; + common_cert_sets = primary_config_->common_cert_sets; + source_address_token = NewSourceAddressToken( + *primary_config_, previous_source_address_tokens, client_ip, rand, + clock->WallNow(), cached_network_params); + } + + CryptoHandshakeMessage message; + message.set_tag(kSCUP); + message.SetStringPiece(kSCFG, serialized); + message.SetStringPiece(kSourceAddressTokenTag, source_address_token); + + std::unique_ptr<BuildServerConfigUpdateMessageProofSourceCallback> + proof_source_cb(new BuildServerConfigUpdateMessageProofSourceCallback( + this, version, compressed_certs_cache, common_cert_sets, params, + std::move(message), std::move(cb))); + + if (FLAGS_quic_use_hash_in_scup) { + proof_source_->GetProof(server_ip, params.sni, serialized, version, + chlo_hash, params.x509_ecdsa_supported, + std::move(proof_source_cb)); + } else { + proof_source_->GetProof(server_ip, params.sni, serialized, version, + params.client_nonce, params.x509_ecdsa_supported, + std::move(proof_source_cb)); + } +} + +QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback:: + ~BuildServerConfigUpdateMessageProofSourceCallback() {} + +QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback:: + BuildServerConfigUpdateMessageProofSourceCallback( + const QuicCryptoServerConfig* config, + QuicVersion version, + QuicCompressedCertsCache* compressed_certs_cache, + const CommonCertSets* common_cert_sets, + const QuicCryptoNegotiatedParameters& params, + CryptoHandshakeMessage message, + std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) + : config_(config), + version_(version), + compressed_certs_cache_(compressed_certs_cache), + common_cert_sets_(common_cert_sets), + client_common_set_hashes_(params.client_common_set_hashes), + client_cached_cert_hashes_(params.client_cached_cert_hashes), + sct_supported_by_client_(params.sct_supported_by_client), + message_(std::move(message)), + cb_(std::move(cb)) {} + +void QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback:: + Run(bool ok, + const scoped_refptr<ProofSource::Chain>& chain, + const string& signature, + const string& leaf_cert_sct) { + config_->FinishBuildServerConfigUpdateMessage( + version_, compressed_certs_cache_, common_cert_sets_, + client_common_set_hashes_, client_cached_cert_hashes_, + sct_supported_by_client_, ok, chain, signature, leaf_cert_sct, + std::move(message_), std::move(cb_)); +} + +void QuicCryptoServerConfig::FinishBuildServerConfigUpdateMessage( + QuicVersion version, + QuicCompressedCertsCache* compressed_certs_cache, + const CommonCertSets* common_cert_sets, + const string& client_common_set_hashes, + const string& client_cached_cert_hashes, + bool sct_supported_by_client, + bool ok, + const scoped_refptr<ProofSource::Chain>& chain, + const string& signature, + const string& leaf_cert_sct, + CryptoHandshakeMessage message, + std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const { + if (!ok) { + cb->Run(false, message); + return; + } + + const string compressed = + CompressChain(compressed_certs_cache, chain, client_common_set_hashes, + client_cached_cert_hashes, common_cert_sets); + + message.SetStringPiece(kCertificateTag, compressed); + message.SetStringPiece(kPROF, signature); + if (sct_supported_by_client && version > QUIC_VERSION_29 && + enable_serving_sct_) { + if (leaf_cert_sct.empty()) { + DLOG(WARNING) << "SCT is expected but it is empty."; + } else { + message.SetStringPiece(kCertificateSCTTag, leaf_cert_sct); + } + } + + cb->Run(true, message); +} + void QuicCryptoServerConfig::BuildRejection( QuicVersion version, const Config& config, @@ -1311,12 +1440,12 @@ } } -const string QuicCryptoServerConfig::CompressChain( +string QuicCryptoServerConfig::CompressChain( QuicCompressedCertsCache* compressed_certs_cache, const scoped_refptr<ProofSource::Chain>& chain, const string& client_common_set_hashes, const string& client_cached_cert_hashes, - const CommonCertSets* common_sets) const { + const CommonCertSets* common_sets) { // Check whether the compressed certs is available in the cache. DCHECK(compressed_certs_cache); const string* cached_value = compressed_certs_cache->GetCompressedCert(
diff --git a/net/quic/crypto/quic_crypto_server_config.h b/net/quic/crypto/quic_crypto_server_config.h index a43bd78..4b7985f 100644 --- a/net/quic/crypto/quic_crypto_server_config.h +++ b/net/quic/crypto/quic_crypto_server_config.h
@@ -115,6 +115,18 @@ DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloResultCallback); }; +// Callback used to receive the results of a call to +// BuildServerConfigUpdateMessage. +class BuildServerConfigUpdateMessageResultCallback { + public: + BuildServerConfigUpdateMessageResultCallback() = default; + virtual ~BuildServerConfigUpdateMessageResultCallback() {} + virtual void Run(bool ok, const CryptoHandshakeMessage& message) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(BuildServerConfigUpdateMessageResultCallback); +}; + // QuicCryptoServerConfig contains the crypto configuration of a QUIC server. // Unlike a client, a QUIC server can have multiple configurations active in // order to support clients resuming with a previous configuration. @@ -159,7 +171,7 @@ // takes ownership of |proof_source|. QuicCryptoServerConfig(base::StringPiece source_address_token_secret, QuicRandom* server_nonce_entropy, - ProofSource* proof_source); + std::unique_ptr<ProofSource> proof_source); ~QuicCryptoServerConfig(); // TESTING is a magic parameter for passing to the constructor in tests. @@ -297,6 +309,8 @@ // filled |out|. // // |cached_network_params| is optional, and can be nullptr. + // + // TODO(gredner): remove this when --FLAGS_enable_async_get_proof is removed. bool BuildServerConfigUpdateMessage( QuicVersion version, base::StringPiece chlo_hash, @@ -310,6 +324,29 @@ const CachedNetworkParameters* cached_network_params, CryptoHandshakeMessage* out) const; + // BuildServerConfigUpdateMessage invokes |cb| with a SCUP message containing + // the current primary config, an up to date source-address token, and cert + // chain and proof in the case of secure QUIC. Passes true to |cb| if the + // message was generated successfully, and false otherwise. This method + // assumes ownership of |cb|. + // + // |cached_network_params| is optional, and can be nullptr. + // + // TODO(gredner): This method is an async version of the above. The + // synchronous version will eventually be removed. + void BuildServerConfigUpdateMessage( + QuicVersion version, + base::StringPiece chlo_hash, + const SourceAddressTokens& previous_source_address_tokens, + const IPAddress& server_ip, + const IPAddress& client_ip, + const QuicClock* clock, + QuicRandom* rand, + QuicCompressedCertsCache* compressed_certs_cache, + const QuicCryptoNegotiatedParameters& params, + const CachedNetworkParameters* cached_network_params, + std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const; + // SetEphemeralKeySource installs an object that can cache ephemeral keys for // a short period of time. This object takes ownership of // |ephemeral_key_source|. If not set then ephemeral keys will be generated @@ -497,12 +534,12 @@ // sets known locally and |client_common_set_hashes| contains the hashes of // the common sets known to the peer. |client_cached_cert_hashes| contains // 64-bit, FNV-1a hashes of certificates that the peer already possesses. - const std::string CompressChain( + static std::string CompressChain( QuicCompressedCertsCache* compressed_certs_cache, const scoped_refptr<ProofSource::Chain>& chain, const std::string& client_common_set_hashes, const std::string& client_cached_cert_hashes, - const CommonCertSets* common_sets) const; + const CommonCertSets* common_sets); // ParseConfigProtobuf parses the given config protobuf and returns a // scoped_refptr<Config> if successful. The caller adopts the reference to the @@ -583,6 +620,61 @@ bool* x509_supported, bool* x509_ecdsa_supported) const; + // Callback to receive the results of ProofSource::GetProof. Note: this + // callback has no cancellation support, since the lifetime of the ProofSource + // is controlled by this object via unique ownership. If that ownership + // stricture changes, this decision may need to be revisited. + class BuildServerConfigUpdateMessageProofSourceCallback + : public ProofSource::Callback { + public: + BuildServerConfigUpdateMessageProofSourceCallback( + const BuildServerConfigUpdateMessageProofSourceCallback&) = delete; + ~BuildServerConfigUpdateMessageProofSourceCallback() override; + void operator=(const BuildServerConfigUpdateMessageProofSourceCallback&) = + delete; + BuildServerConfigUpdateMessageProofSourceCallback( + const QuicCryptoServerConfig* config, + QuicVersion version, + QuicCompressedCertsCache* compressed_certs_cache, + const CommonCertSets* common_cert_sets, + const QuicCryptoNegotiatedParameters& params, + CryptoHandshakeMessage message, + std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb); + + void Run(bool ok, + const scoped_refptr<ProofSource::Chain>& chain, + const std::string& signature, + const std::string& leaf_cert_sct) override; + + private: + const QuicCryptoServerConfig* config_; + const QuicVersion version_; + QuicCompressedCertsCache* compressed_certs_cache_; + const CommonCertSets* common_cert_sets_; + const std::string client_common_set_hashes_; + const std::string client_cached_cert_hashes_; + const bool sct_supported_by_client_; + CryptoHandshakeMessage message_; + std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb_; + }; + + // Invoked by BuildServerConfigUpdateMessageProofSourceCallback::RunImpl once + // the proof has been acquired. Finishes building the server config update + // message and invokes |cb|. + void FinishBuildServerConfigUpdateMessage( + QuicVersion version, + QuicCompressedCertsCache* compressed_certs_cache, + const CommonCertSets* common_cert_sets, + const std::string& client_common_set_hashes, + const std::string& client_cached_cert_hashes, + bool sct_supported_by_client, + bool ok, + const scoped_refptr<ProofSource::Chain>& chain, + const std::string& signature, + const std::string& leaf_cert_sct, + CryptoHandshakeMessage message, + std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const; + // replay_protection_ controls whether the server enforces that handshakes // aren't replays. bool replay_protection_;
diff --git a/net/quic/crypto/quic_crypto_server_config_test.cc b/net/quic/crypto/quic_crypto_server_config_test.cc index f1dab3a..f6bda82a 100644 --- a/net/quic/crypto/quic_crypto_server_config_test.cc +++ b/net/quic/crypto/quic_crypto_server_config_test.cc
@@ -113,8 +113,8 @@ vector<string> certs = {"testcert"}; scoped_refptr<ProofSource::Chain> chain(new ProofSource::Chain(certs)); - string compressed = - peer.CompressChain(&compressed_certs_cache, chain, "", "", nullptr); + string compressed = QuicCryptoServerConfigPeer::CompressChain( + &compressed_certs_cache, chain, "", "", nullptr); EXPECT_EQ(compressed_certs_cache.Size(), 1u); } @@ -134,13 +134,13 @@ string common_certs = ""; string cached_certs = ""; - string compressed = peer.CompressChain(&compressed_certs_cache, chain, - common_certs, cached_certs, nullptr); + string compressed = QuicCryptoServerConfigPeer::CompressChain( + &compressed_certs_cache, chain, common_certs, cached_certs, nullptr); EXPECT_EQ(compressed_certs_cache.Size(), 1u); // Compress the same certs, should use cache if available. - string compressed2 = peer.CompressChain(&compressed_certs_cache, chain, - common_certs, cached_certs, nullptr); + string compressed2 = QuicCryptoServerConfigPeer::CompressChain( + &compressed_certs_cache, chain, common_certs, cached_certs, nullptr); EXPECT_EQ(compressed, compressed2); EXPECT_EQ(compressed_certs_cache.Size(), 1u); } @@ -161,15 +161,15 @@ string common_certs = ""; string cached_certs = ""; - string compressed = peer.CompressChain(&compressed_certs_cache, chain, - common_certs, cached_certs, nullptr); + string compressed = QuicCryptoServerConfigPeer::CompressChain( + &compressed_certs_cache, chain, common_certs, cached_certs, nullptr); EXPECT_EQ(compressed_certs_cache.Size(), 1u); // Compress a similar certs which only differs in the chain. scoped_refptr<ProofSource::Chain> chain2(new ProofSource::Chain(certs)); - string compressed2 = peer.CompressChain(&compressed_certs_cache, chain2, - common_certs, cached_certs, nullptr); + string compressed2 = QuicCryptoServerConfigPeer::CompressChain( + &compressed_certs_cache, chain2, common_certs, cached_certs, nullptr); EXPECT_EQ(compressed_certs_cache.Size(), 2u); // Compress a similar certs which only differs in common certs field. @@ -178,9 +178,9 @@ CryptoTestUtils::MockCommonCertSets(certs[0], set_hash, 1)); StringPiece different_common_certs(reinterpret_cast<const char*>(&set_hash), sizeof(set_hash)); - string compressed3 = peer.CompressChain(&compressed_certs_cache, chain, - different_common_certs.as_string(), - cached_certs, common_sets.get()); + string compressed3 = QuicCryptoServerConfigPeer::CompressChain( + &compressed_certs_cache, chain, different_common_certs.as_string(), + cached_certs, common_sets.get()); EXPECT_EQ(compressed_certs_cache.Size(), 3u); }
diff --git a/net/quic/p2p/quic_p2p_crypto_config.cc b/net/quic/p2p/quic_p2p_crypto_config.cc deleted file mode 100644 index 6f32056..0000000 --- a/net/quic/p2p/quic_p2p_crypto_config.cc +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/quic/p2p/quic_p2p_crypto_config.h" - -#include "net/quic/crypto/crypto_handshake.h" -#include "net/quic/crypto/crypto_utils.h" - -namespace net { - -QuicP2PCryptoConfig::QuicP2PCryptoConfig(const std::string& shared_key) - : shared_key_(shared_key) {} - -QuicP2PCryptoConfig::~QuicP2PCryptoConfig() {} - -bool QuicP2PCryptoConfig::GetNegotiatedParameters( - Perspective perspective, - QuicCryptoNegotiatedParameters* out_params) { - out_params->forward_secure_premaster_secret = shared_key_; - out_params->aead = aead_; - out_params->hkdf_input_suffix = hkdf_input_suffix_; - - std::string hkdf_input; - const size_t label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1; - hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size()); - hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel, label_len); - hkdf_input.append(out_params->hkdf_input_suffix); - - if (!CryptoUtils::DeriveKeys( - out_params->forward_secure_premaster_secret, out_params->aead, - out_params->client_nonce, out_params->server_nonce, hkdf_input, - perspective, CryptoUtils::Diversification::Never(), - &out_params->forward_secure_crypters, &out_params->subkey_secret)) { - return false; - } - - return true; -} - -} // namespace net
diff --git a/net/quic/p2p/quic_p2p_crypto_config.h b/net/quic/p2p/quic_p2p_crypto_config.h deleted file mode 100644 index 786a7e11..0000000 --- a/net/quic/p2p/quic_p2p_crypto_config.h +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_QUIC_P2P_QUIC_P2P_CRYPTO_CONFIG_H_ -#define NET_QUIC_P2P_QUIC_P2P_CRYPTO_CONFIG_H_ - -#include <string> - -#include "net/quic/crypto/crypto_protocol.h" - -namespace net { - -struct QuicCryptoNegotiatedParameters; - -// Crypto configuration for P2P sessions. -class NET_EXPORT QuicP2PCryptoConfig { - public: - // |shared_key| specifies a key that's used to generate crypto keys. The key - // must be exchanged out-of-bound when the P2P transport is negotiated. - explicit QuicP2PCryptoConfig(const std::string& shared_key); - ~QuicP2PCryptoConfig(); - - void set_aead(QuicTag aead) { aead_ = aead; } - - // Sets suffix for HKDF. E.g. can be channel name to make sure different - // channels use different encryption keys derived from the same |shared_key|. - // Empty by default. - void set_hkdf_input_suffix(const std::string& hkdf_input_suffix) { - hkdf_input_suffix_ = hkdf_input_suffix; - } - - bool GetNegotiatedParameters(Perspective perspective, - QuicCryptoNegotiatedParameters* out_params); - - private: - QuicTag aead_ = kAESG; - std::string shared_key_; - std::string hkdf_input_suffix_; -}; - -} // namespace net - -#endif // NET_QUIC_P2P_QUIC_P2P_CRYPTO_CONFIG_H_
diff --git a/net/quic/p2p/quic_p2p_crypto_stream.cc b/net/quic/p2p/quic_p2p_crypto_stream.cc deleted file mode 100644 index f5acb98b..0000000 --- a/net/quic/p2p/quic_p2p_crypto_stream.cc +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/quic/p2p/quic_p2p_crypto_stream.h" - -#include "crypto/hkdf.h" -#include "net/quic/crypto/crypto_handshake_message.h" -#include "net/quic/crypto/quic_decrypter.h" -#include "net/quic/crypto/quic_encrypter.h" -#include "net/quic/quic_session.h" - -namespace net { - -QuicP2PCryptoStream::QuicP2PCryptoStream(QuicSession* session, - const QuicP2PCryptoConfig& config) - : QuicCryptoStream(session), config_(config) {} - -QuicP2PCryptoStream::~QuicP2PCryptoStream() {} - -bool QuicP2PCryptoStream::Connect() { - if (!config_.GetNegotiatedParameters(session()->connection()->perspective(), - &crypto_negotiated_params_)) { - return false; - } - - CrypterPair* crypters = &crypto_negotiated_params_.forward_secure_crypters; - - session()->connection()->SetEncrypter(ENCRYPTION_FORWARD_SECURE, - crypters->encrypter.release()); - session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE); - session()->connection()->SetAlternativeDecrypter( - ENCRYPTION_FORWARD_SECURE, crypters->decrypter.release(), - false /* don't latch */); - encryption_established_ = true; - session()->OnCryptoHandshakeEvent(QuicSession::ENCRYPTION_FIRST_ESTABLISHED); - session()->OnConfigNegotiated(); - session()->connection()->OnHandshakeComplete(); - handshake_confirmed_ = true; - session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED); - if (session()->connection()->perspective() == Perspective::IS_CLIENT) { - // Send a ping from the client to the server to satisfy QUIC's version - // negotiation. - session()->connection()->SendPing(); - } - return true; -} - -} // namespace net
diff --git a/net/quic/p2p/quic_p2p_crypto_stream.h b/net/quic/p2p/quic_p2p_crypto_stream.h deleted file mode 100644 index 185a8f8..0000000 --- a/net/quic/p2p/quic_p2p_crypto_stream.h +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_QUIC_P2P_QUIC_P2P_CRYPTO_STREAM_H_ -#define NET_QUIC_P2P_QUIC_P2P_CRYPTO_STREAM_H_ - -#include "base/macros.h" -#include "net/quic/p2p/quic_p2p_crypto_config.h" -#include "net/quic/quic_crypto_stream.h" - -namespace net { - -class QuicSession; - -class NET_EXPORT_PRIVATE QuicP2PCryptoStream : public QuicCryptoStream { - public: - QuicP2PCryptoStream(QuicSession* session, const QuicP2PCryptoConfig& config); - ~QuicP2PCryptoStream() override; - - bool Connect(); - - private: - QuicP2PCryptoConfig config_; - - DISALLOW_COPY_AND_ASSIGN(QuicP2PCryptoStream); -}; - -} // namespace net - -#endif // NET_QUIC_P2P_QUIC_P2P_CRYPTO_STREAM_H_
diff --git a/net/quic/p2p/quic_p2p_session.cc b/net/quic/p2p/quic_p2p_session.cc deleted file mode 100644 index ca38851c..0000000 --- a/net/quic/p2p/quic_p2p_session.cc +++ /dev/null
@@ -1,132 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/quic/p2p/quic_p2p_session.h" - -#include <utility> - -#include "base/callback_helpers.h" -#include "net/base/io_buffer.h" -#include "net/base/ip_address.h" -#include "net/base/net_errors.h" -#include "net/quic/p2p/quic_p2p_crypto_stream.h" -#include "net/quic/quic_connection.h" -#include "net/socket/socket.h" - -namespace net { - -QuicP2PSession::QuicP2PSession(const QuicConfig& config, - const QuicP2PCryptoConfig& crypto_config, - std::unique_ptr<QuicConnection> connection, - std::unique_ptr<Socket> socket) - : QuicSession(connection.release(), config), - socket_(std::move(socket)), - crypto_stream_(new QuicP2PCryptoStream(this, crypto_config)), - read_buffer_(new IOBuffer(static_cast<size_t>(kMaxPacketSize))) { - DCHECK(config.negotiated()); -} - -QuicP2PSession::~QuicP2PSession() {} - -void QuicP2PSession::Initialize() { - QuicSession::Initialize(); - crypto_stream_->Connect(); - DoReadLoop(OK); -} - -void QuicP2PSession::SetDelegate(Delegate* delegate) { - delegate_ = delegate; -} - -int QuicP2PSession::OnWriteError(int error_code, - scoped_refptr<StringIOBuffer> packet) { - return error_code; -} - -QuicCryptoStream* QuicP2PSession::GetCryptoStream() { - return crypto_stream_.get(); -} - -QuicP2PStream* QuicP2PSession::CreateIncomingDynamicStream(QuicStreamId id) { - QuicP2PStream* stream = new QuicP2PStream(id, this); - if (delegate_) { - delegate_->OnIncomingStream(stream); - } - ActivateStream(stream); - return stream; -} - -QuicP2PStream* QuicP2PSession::CreateOutgoingDynamicStream( - SpdyPriority priority) { - QuicP2PStream* stream = new QuicP2PStream(GetNextOutgoingStreamId(), this); - if (stream) { - ActivateStream(stream); - } - return stream; -} - -void QuicP2PSession::OnConnectionClosed(QuicErrorCode error, - const std::string& error_details, - ConnectionCloseSource source) { - QuicSession::OnConnectionClosed(error, error_details, source); - - socket_.reset(); - - if (delegate_) { - Delegate* delegate = delegate_; - delegate_ = nullptr; - delegate->OnConnectionClosed(error); - } -} - -void QuicP2PSession::DoReadLoop(int result) { - while (error() == QUIC_NO_ERROR) { - switch (read_state_) { - case READ_STATE_DO_READ: - CHECK_EQ(result, OK); - result = DoRead(); - break; - case READ_STATE_DO_READ_COMPLETE: - result = DoReadComplete(result); - break; - default: - NOTREACHED() << "read_state_: " << read_state_; - break; - } - - if (result < 0) - break; - } -} - -int QuicP2PSession::DoRead() { - DCHECK_EQ(read_state_, READ_STATE_DO_READ); - read_state_ = READ_STATE_DO_READ_COMPLETE; - - if (!socket_) { - return ERR_SOCKET_NOT_CONNECTED; - } - - return socket_->Read( - read_buffer_.get(), kMaxPacketSize, - base::Bind(&QuicP2PSession::DoReadLoop, base::Unretained(this))); -} - -int QuicP2PSession::DoReadComplete(int result) { - DCHECK_EQ(read_state_, READ_STATE_DO_READ_COMPLETE); - read_state_ = READ_STATE_DO_READ; - - if (result <= 0) { - connection()->CloseConnection(QUIC_PACKET_READ_ERROR, "packet read error", - ConnectionCloseBehavior::SILENT_CLOSE); - return result; - } - - QuicReceivedPacket packet(read_buffer_->data(), result, clock_.Now()); - connection()->ProcessUdpPacket(connection()->self_address(), - connection()->peer_address(), packet); - return OK; -} - -} // namespace net
diff --git a/net/quic/p2p/quic_p2p_session.h b/net/quic/p2p/quic_p2p_session.h deleted file mode 100644 index 66c1050a..0000000 --- a/net/quic/p2p/quic_p2p_session.h +++ /dev/null
@@ -1,105 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_QUIC_P2P_QUIC_P2P_SESSION_H_ -#define NET_QUIC_P2P_QUIC_P2P_SESSION_H_ - -#include <memory> -#include <string> - -#include "base/macros.h" -#include "base/strings/string_piece.h" -#include "net/base/io_buffer.h" -#include "net/quic/p2p/quic_p2p_stream.h" -#include "net/quic/quic_chromium_packet_writer.h" -#include "net/quic/quic_client_session_base.h" -#include "net/quic/quic_clock.h" -#include "net/quic/quic_protocol.h" - -namespace net { - -class QuicConfig; -class QuicConnection; -class QuicP2PCryptoStream; -class QuicP2PCryptoConfig; -class Socket; -class IOBuffer; - -// QuicP2PSession represents a QUIC session over peer-to-peer transport -// specified by |socket|. There is no handshake performed by this class, i.e. -// the handshake is expected to happen out-of-bound before QuicP2PSession is -// created. The out-of-bound handshake should generate the following parameters -// passed to the constructor: -// 1. Negotiated QuicConfig. -// 2. Secret key exchanged with the peer on the other end of the |socket|. -// This key is passed to the constructor as part of the |crypto_config|. -class NET_EXPORT QuicP2PSession - : public QuicSession, - public QuicChromiumPacketWriter::WriteErrorObserver { - public: - class Delegate { - public: - virtual void OnIncomingStream(QuicP2PStream* stream) = 0; - - virtual void OnConnectionClosed(QuicErrorCode error) = 0; - }; - - // |config| must be already negotiated. |crypto_config| contains a secret key - // shared with the peer. - QuicP2PSession(const QuicConfig& config, - const QuicP2PCryptoConfig& crypto_config, - std::unique_ptr<QuicConnection> connection, - std::unique_ptr<Socket> socket); - ~QuicP2PSession() override; - - // QuicChromiumPacketWriter::WriteErrorObserver override. - int OnWriteError(int error_code, - scoped_refptr<StringIOBuffer> last_packet) override; - - // QuicSession overrides. - void Initialize() override; - QuicP2PStream* CreateOutgoingDynamicStream( - net::SpdyPriority priority) override; - - // QuicConnectionVisitorInterface overrides. - void OnConnectionClosed(QuicErrorCode error, - const std::string& error_details, - ConnectionCloseSource source) override; - - void SetDelegate(Delegate* delegate); - - protected: - // QuicSession overrides. - QuicCryptoStream* GetCryptoStream() override; - QuicP2PStream* CreateIncomingDynamicStream(QuicStreamId id) override; - - QuicP2PSession* CreateDataStream(QuicStreamId id); - - private: - enum ReadState { - READ_STATE_DO_READ, - READ_STATE_DO_READ_COMPLETE, - }; - - void DoReadLoop(int result); - int DoRead(); - int DoReadComplete(int result); - - std::unique_ptr<Socket> socket_; - std::unique_ptr<QuicP2PCryptoStream> crypto_stream_; - - Delegate* delegate_ = nullptr; - - ReadState read_state_ = READ_STATE_DO_READ; - scoped_refptr<IOBuffer> read_buffer_; - - // For recording receipt time - QuicClock clock_; - - DISALLOW_COPY_AND_ASSIGN(QuicP2PSession); -}; - -} // namespace net - -#endif // NET_QUIC_P2P_QUIC_P2P_SESSION_H_
diff --git a/net/quic/p2p/quic_p2p_session_test.cc b/net/quic/p2p/quic_p2p_session_test.cc deleted file mode 100644 index e3335ba..0000000 --- a/net/quic/p2p/quic_p2p_session_test.cc +++ /dev/null
@@ -1,409 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/quic/p2p/quic_p2p_session.h" - -#include <algorithm> -#include <deque> -#include <utility> -#include <vector> - -#include "base/callback_helpers.h" -#include "base/location.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" -#include "net/quic/crypto/quic_random.h" -#include "net/quic/p2p/quic_p2p_crypto_config.h" -#include "net/quic/p2p/quic_p2p_stream.h" -#include "net/quic/quic_chromium_alarm_factory.h" -#include "net/quic/quic_chromium_connection_helper.h" -#include "net/quic/quic_chromium_packet_writer.h" -#include "net/quic/test_tools/quic_session_peer.h" -#include "net/socket/socket.h" -#include "net/test/gtest_util.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using net::test::IsOk; - -namespace net { - -namespace { - -const char kTestSharedKey[] = "Shared key exchanged out of bound."; - -class FakeP2PDatagramSocket : public Socket { - public: - FakeP2PDatagramSocket() : weak_factory_(this) {} - ~FakeP2PDatagramSocket() override {} - - base::WeakPtr<FakeP2PDatagramSocket> GetWeakPtr() { - return weak_factory_.GetWeakPtr(); - } - - void ConnectWith(FakeP2PDatagramSocket* peer_socket) { - peer_socket_ = peer_socket->GetWeakPtr(); - peer_socket->peer_socket_ = GetWeakPtr(); - } - - void SetReadError(int error) { - read_error_ = error; - if (!read_callback_.is_null()) { - base::ResetAndReturn(&read_callback_).Run(error); - } - } - - void SetWriteError(int error) { write_error_ = error; } - - void AppendInputPacket(const std::vector<char>& data) { - if (!read_callback_.is_null()) { - int size = std::min(read_buffer_size_, static_cast<int>(data.size())); - memcpy(read_buffer_->data(), &data[0], data.size()); - read_buffer_ = nullptr; - base::ResetAndReturn(&read_callback_).Run(size); - } else { - incoming_packets_.push_back(data); - } - } - - // Socket interface. - int Read(IOBuffer* buf, - int buf_len, - const CompletionCallback& callback) override { - DCHECK(read_callback_.is_null()); - - if (read_error_ != OK) { - return read_error_; - } - - if (!incoming_packets_.empty()) { - scoped_refptr<IOBuffer> buffer(buf); - int size = - std::min(static_cast<int>(incoming_packets_.front().size()), buf_len); - memcpy(buffer->data(), &*incoming_packets_.front().begin(), size); - incoming_packets_.pop_front(); - return size; - } else { - read_callback_ = callback; - read_buffer_ = buf; - read_buffer_size_ = buf_len; - return ERR_IO_PENDING; - } - } - - int Write(IOBuffer* buf, - int buf_len, - const CompletionCallback& callback) override { - if (write_error_ != OK) { - return write_error_; - } - - if (peer_socket_) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&FakeP2PDatagramSocket::AppendInputPacket, peer_socket_, - std::vector<char>(buf->data(), buf->data() + buf_len))); - } - - return buf_len; - } - - int SetReceiveBufferSize(int32_t size) override { - NOTIMPLEMENTED(); - return ERR_NOT_IMPLEMENTED; - } - int SetSendBufferSize(int32_t size) override { - NOTIMPLEMENTED(); - return ERR_NOT_IMPLEMENTED; - } - - private: - int read_error_ = OK; - int write_error_ = OK; - - scoped_refptr<IOBuffer> read_buffer_; - int read_buffer_size_; - CompletionCallback read_callback_; - - std::deque<std::vector<char>> incoming_packets_; - - base::WeakPtr<FakeP2PDatagramSocket> peer_socket_; - - base::WeakPtrFactory<FakeP2PDatagramSocket> weak_factory_; -}; - -class TestP2PStreamDelegate : public QuicP2PStream::Delegate { - public: - TestP2PStreamDelegate() {} - ~TestP2PStreamDelegate() override {} - - void OnDataReceived(const char* data, int length) override { - received_data_.append(data, length); - } - void OnClose(QuicErrorCode error) override { - is_closed_ = true; - error_ = error; - } - - const std::string& received_data() { return received_data_; } - bool is_closed() { return is_closed_; } - QuicErrorCode error() { return error_; } - - private: - std::string received_data_; - bool is_closed_ = false; - QuicErrorCode error_ = QUIC_NO_ERROR; - - DISALLOW_COPY_AND_ASSIGN(TestP2PStreamDelegate); -}; - -class TestP2PSessionDelegate : public QuicP2PSession::Delegate { - public: - void OnIncomingStream(QuicP2PStream* stream) override { - last_incoming_stream_ = stream; - stream->SetDelegate(next_incoming_stream_delegate_); - next_incoming_stream_delegate_ = nullptr; - if (!on_incoming_stream_callback_.is_null()) - base::ResetAndReturn(&on_incoming_stream_callback_).Run(); - } - - void OnConnectionClosed(QuicErrorCode error) override { - is_closed_ = true; - error_ = error; - } - - void set_next_incoming_stream_delegate(QuicP2PStream::Delegate* delegate) { - next_incoming_stream_delegate_ = delegate; - } - void set_on_incoming_stream_callback(const base::Closure& callback) { - on_incoming_stream_callback_ = callback; - } - QuicP2PStream* last_incoming_stream() { return last_incoming_stream_; } - bool is_closed() { return is_closed_; } - QuicErrorCode error() { return error_; } - - private: - QuicP2PStream::Delegate* next_incoming_stream_delegate_ = nullptr; - base::Closure on_incoming_stream_callback_; - QuicP2PStream* last_incoming_stream_ = nullptr; - bool is_closed_ = false; - QuicErrorCode error_ = QUIC_NO_ERROR; -}; - -} // namespace - -class QuicP2PSessionTest : public ::testing::Test { - public: - void OnWriteResult(int result); - - protected: - QuicP2PSessionTest() - : quic_helper_(&quic_clock_, QuicRandom::GetInstance()), - alarm_factory_(base::ThreadTaskRunnerHandle::Get().get(), - &quic_clock_) { - // Simulate out-of-bound config handshake. - CryptoHandshakeMessage hello_message; - config_.ToHandshakeMessage(&hello_message); - std::string error_detail; - EXPECT_EQ(QUIC_NO_ERROR, - config_.ProcessPeerHello(hello_message, CLIENT, &error_detail)); - } - - void CreateSessions() { - std::unique_ptr<FakeP2PDatagramSocket> socket1(new FakeP2PDatagramSocket()); - std::unique_ptr<FakeP2PDatagramSocket> socket2(new FakeP2PDatagramSocket()); - socket1->ConnectWith(socket2.get()); - - socket1_ = socket1->GetWeakPtr(); - socket2_ = socket2->GetWeakPtr(); - - QuicP2PCryptoConfig crypto_config(kTestSharedKey); - - session1_ = CreateP2PSession(std::move(socket1), crypto_config, - Perspective::IS_SERVER); - session2_ = CreateP2PSession(std::move(socket2), crypto_config, - Perspective::IS_CLIENT); - } - - std::unique_ptr<QuicP2PSession> CreateP2PSession( - std::unique_ptr<Socket> socket, - QuicP2PCryptoConfig crypto_config, - Perspective perspective) { - QuicChromiumPacketWriter* writer = - new QuicChromiumPacketWriter(socket.get()); - std::unique_ptr<QuicConnection> quic_connection1(new QuicConnection( - 0, IPEndPoint(IPAddress::IPv4AllZeros(), 0), &quic_helper_, - &alarm_factory_, writer, true /* owns_writer */, perspective, - QuicSupportedVersions())); - - std::unique_ptr<QuicP2PSession> result( - new QuicP2PSession(config_, crypto_config, std::move(quic_connection1), - std::move(socket))); - writer->Initialize(result.get(), quic_connection1.get()); - result->Initialize(); - return result; - } - - void TestStreamConnection(QuicP2PSession* from_session, - QuicP2PSession* to_session, - QuicStreamId expected_stream_id); - - QuicClock quic_clock_; - QuicChromiumConnectionHelper quic_helper_; - QuicChromiumAlarmFactory alarm_factory_; - QuicConfig config_; - - base::WeakPtr<FakeP2PDatagramSocket> socket1_; - std::unique_ptr<QuicP2PSession> session1_; - - base::WeakPtr<FakeP2PDatagramSocket> socket2_; - std::unique_ptr<QuicP2PSession> session2_; -}; - -void QuicP2PSessionTest::OnWriteResult(int result) { - EXPECT_THAT(result, IsOk()); -} - -void QuicP2PSessionTest::TestStreamConnection(QuicP2PSession* from_session, - QuicP2PSession* to_session, - QuicStreamId expected_stream_id) { - QuicP2PStream* outgoing_stream = - from_session->CreateOutgoingDynamicStream(kDefaultPriority); - EXPECT_TRUE(outgoing_stream); - TestP2PStreamDelegate outgoing_stream_delegate; - outgoing_stream->SetDelegate(&outgoing_stream_delegate); - EXPECT_EQ(expected_stream_id, outgoing_stream->id()); - - // Add streams to write_blocked_lists of both QuicSession objects. - QuicWriteBlockedList* write_blocked_list1 = - test::QuicSessionPeer::GetWriteBlockedStreams(from_session); - write_blocked_list1->RegisterStream(expected_stream_id, kV3HighestPriority); - QuicWriteBlockedList* write_blocked_list2 = - test::QuicSessionPeer::GetWriteBlockedStreams(to_session); - write_blocked_list2->RegisterStream(expected_stream_id, kV3HighestPriority); - - // Send a test message to the client. - const char kTestMessage[] = "Hi"; - const char kTestResponse[] = "Response"; - outgoing_stream->Write( - std::string(kTestMessage), - base::Bind(&QuicP2PSessionTest::OnWriteResult, base::Unretained(this))); - - // Wait for the incoming stream to be created. - TestP2PStreamDelegate incoming_stream_delegate; - base::RunLoop run_loop; - TestP2PSessionDelegate session_delegate; - session_delegate.set_next_incoming_stream_delegate(&incoming_stream_delegate); - session_delegate.set_on_incoming_stream_callback( - base::Bind(&base::RunLoop::Quit, base::Unretained(&run_loop))); - to_session->SetDelegate(&session_delegate); - run_loop.Run(); - to_session->SetDelegate(nullptr); - - QuicP2PStream* incoming_stream = session_delegate.last_incoming_stream(); - ASSERT_TRUE(incoming_stream); - EXPECT_EQ(expected_stream_id, incoming_stream->id()); - EXPECT_EQ(kTestMessage, incoming_stream_delegate.received_data()); - - incoming_stream->Write( - std::string(kTestResponse), - base::Bind(&QuicP2PSessionTest::OnWriteResult, base::Unretained(this))); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(kTestResponse, outgoing_stream_delegate.received_data()); - - from_session->CloseStream(outgoing_stream->id()); - base::RunLoop().RunUntilIdle(); - - EXPECT_TRUE(outgoing_stream_delegate.is_closed()); - EXPECT_TRUE(incoming_stream_delegate.is_closed()); -} - -TEST_F(QuicP2PSessionTest, ClientToServer) { - CreateSessions(); - TestStreamConnection(session2_.get(), session1_.get(), 3); -} - -TEST_F(QuicP2PSessionTest, ServerToClient) { - CreateSessions(); - TestStreamConnection(session1_.get(), session2_.get(), 2); -} - -TEST_F(QuicP2PSessionTest, DestroySocketWhenClosed) { - CreateSessions(); - - // The socket must be destroyed when connection is closed. - EXPECT_TRUE(socket1_); - session1_->connection()->CloseConnection( - QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE); - EXPECT_FALSE(socket1_); -} - -TEST_F(QuicP2PSessionTest, TransportWriteError) { - CreateSessions(); - - TestP2PSessionDelegate session_delegate; - session1_->SetDelegate(&session_delegate); - - QuicP2PStream* stream = - session1_->CreateOutgoingDynamicStream(kDefaultPriority); - EXPECT_TRUE(stream); - TestP2PStreamDelegate stream_delegate; - stream->SetDelegate(&stream_delegate); - EXPECT_EQ(2U, stream->id()); - - // Add stream to write_blocked_list. - QuicWriteBlockedList* write_blocked_list = - test::QuicSessionPeer::GetWriteBlockedStreams(session1_.get()); - write_blocked_list->RegisterStream(stream->id(), kV3HighestPriority); - - socket1_->SetWriteError(ERR_INTERNET_DISCONNECTED); - - const char kTestMessage[] = "Hi"; - stream->Write( - std::string(kTestMessage), - base::Bind(&QuicP2PSessionTest::OnWriteResult, base::Unretained(this))); - - base::RunLoop().RunUntilIdle(); - - EXPECT_TRUE(stream_delegate.is_closed()); - EXPECT_EQ(QUIC_PACKET_WRITE_ERROR, stream_delegate.error()); - EXPECT_TRUE(session_delegate.is_closed()); - EXPECT_EQ(QUIC_PACKET_WRITE_ERROR, session_delegate.error()); - - // Verify that the socket was destroyed. - EXPECT_FALSE(socket1_); -} - -TEST_F(QuicP2PSessionTest, TransportReceiveError) { - CreateSessions(); - - TestP2PSessionDelegate session_delegate; - session1_->SetDelegate(&session_delegate); - - QuicP2PStream* stream = - session1_->CreateOutgoingDynamicStream(kDefaultPriority); - EXPECT_TRUE(stream); - TestP2PStreamDelegate stream_delegate; - stream->SetDelegate(&stream_delegate); - EXPECT_EQ(2U, stream->id()); - - socket1_->SetReadError(ERR_INTERNET_DISCONNECTED); - - base::RunLoop().RunUntilIdle(); - - EXPECT_TRUE(stream_delegate.is_closed()); - EXPECT_EQ(QUIC_PACKET_READ_ERROR, stream_delegate.error()); - EXPECT_TRUE(session_delegate.is_closed()); - EXPECT_EQ(QUIC_PACKET_READ_ERROR, session_delegate.error()); - - // Verify that the socket was destroyed. - EXPECT_FALSE(socket1_); -} - -} // namespace net
diff --git a/net/quic/p2p/quic_p2p_stream.cc b/net/quic/p2p/quic_p2p_stream.cc deleted file mode 100644 index da01019..0000000 --- a/net/quic/p2p/quic_p2p_stream.cc +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/quic/p2p/quic_p2p_stream.h" - -#include "base/callback_helpers.h" -#include "net/base/net_errors.h" -#include "net/quic/quic_session.h" -#include "net/quic/quic_write_blocked_list.h" - -namespace net { - -QuicP2PStream::QuicP2PStream(QuicStreamId id, QuicSession* session) - : ReliableQuicStream(id, session) {} - -QuicP2PStream::~QuicP2PStream() {} - -void QuicP2PStream::OnDataAvailable() { - DCHECK(delegate_); - - struct iovec iov; - while (true) { - if (sequencer()->GetReadableRegions(&iov, 1) != 1) { - // No more data to read. - break; - } - delegate_->OnDataReceived(reinterpret_cast<const char*>(iov.iov_base), - iov.iov_len); - sequencer()->MarkConsumed(iov.iov_len); - } -} - -void QuicP2PStream::OnClose() { - ReliableQuicStream::OnClose(); - - if (delegate_) { - Delegate* delegate = delegate_; - delegate_ = nullptr; - delegate->OnClose(connection_error()); - } -} - -void QuicP2PStream::OnCanWrite() { - ReliableQuicStream::OnCanWrite(); - - if (!HasBufferedData() && !write_callback_.is_null()) { - base::ResetAndReturn(&write_callback_).Run(last_write_size_); - } -} - -void QuicP2PStream::WriteHeader(base::StringPiece data) { - WriteOrBufferData(data, false, nullptr); -} - -int QuicP2PStream::Write(base::StringPiece data, - const CompletionCallback& callback) { - DCHECK(write_callback_.is_null()); - - // Writes the data, or buffers it. - WriteOrBufferData(data, false, nullptr); - if (!HasBufferedData()) { - return data.size(); - } - - write_callback_ = callback; - last_write_size_ = data.size(); - return ERR_IO_PENDING; -} - -void QuicP2PStream::SetDelegate(QuicP2PStream::Delegate* delegate) { - DCHECK(!(delegate_ && delegate)); - delegate_ = delegate; -} - -} // namespace net
diff --git a/net/quic/p2p/quic_p2p_stream.h b/net/quic/p2p/quic_p2p_stream.h deleted file mode 100644 index 4e456b2..0000000 --- a/net/quic/p2p/quic_p2p_stream.h +++ /dev/null
@@ -1,63 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_QUIC_P2P_QUIC_P2P_STREAM_H_ -#define NET_QUIC_P2P_QUIC_P2P_STREAM_H_ - -#include "base/macros.h" -#include "net/base/completion_callback.h" -#include "net/base/net_export.h" -#include "net/quic/reliable_quic_stream.h" - -namespace net { - -// Streams created by QuicP2PSession. -class NET_EXPORT QuicP2PStream : public ReliableQuicStream { - public: - // Delegate handles protocol specific behavior of a quic stream. - class NET_EXPORT Delegate { - public: - Delegate() {} - - // Called when data is received. - virtual void OnDataReceived(const char* data, int length) = 0; - - // Called when the stream is closed by the peer. - virtual void OnClose(QuicErrorCode error) = 0; - - protected: - virtual ~Delegate() {} - - private: - DISALLOW_COPY_AND_ASSIGN(Delegate); - }; - - QuicP2PStream(QuicStreamId id, QuicSession* session); - - ~QuicP2PStream() override; - - // ReliableQuicStream overrides. - void OnDataAvailable() override; - void OnClose() override; - void OnCanWrite() override; - - void WriteHeader(base::StringPiece data); - - int Write(base::StringPiece data, const CompletionCallback& callback); - - void SetDelegate(Delegate* delegate); - Delegate* GetDelegate() { return delegate_; } - - private: - Delegate* delegate_ = nullptr; - - CompletionCallback write_callback_; - int last_write_size_ = 0; - - DISALLOW_COPY_AND_ASSIGN(QuicP2PStream); -}; - -} // namespace net - -#endif // NET_QUIC_P2P_QUIC_P2P_STREAM_H_
diff --git a/net/quic/quic_bandwidth.cc b/net/quic/quic_bandwidth.cc index 734858d5..9e25ba0e 100644 --- a/net/quic/quic_bandwidth.cc +++ b/net/quic/quic_bandwidth.cc
@@ -95,18 +95,6 @@ return (bits_per_second_ == 0); } -QuicBandwidth QuicBandwidth::Add(QuicBandwidth delta) const { - return QuicBandwidth(bits_per_second_ + delta.bits_per_second_); -} - -QuicBandwidth QuicBandwidth::Subtract(QuicBandwidth delta) const { - return QuicBandwidth(bits_per_second_ - delta.bits_per_second_); -} - -QuicBandwidth QuicBandwidth::Scale(float scale_factor) const { - return QuicBandwidth(static_cast<int64_t>(bits_per_second_ * scale_factor)); -} - QuicTime::Delta QuicBandwidth::TransferTime(QuicByteCount bytes) const { if (bits_per_second_ == 0) { return QuicTime::Delta::Zero();
diff --git a/net/quic/quic_bandwidth.h b/net/quic/quic_bandwidth.h index 215ee25..1aa2c9a2 100644 --- a/net/quic/quic_bandwidth.h +++ b/net/quic/quic_bandwidth.h
@@ -52,17 +52,15 @@ bool IsZero() const; - QuicBandwidth Add(QuicBandwidth delta) const WARN_UNUSED_RESULT; - - QuicBandwidth Subtract(QuicBandwidth delta) const WARN_UNUSED_RESULT; - - QuicBandwidth Scale(float scale_factor) const WARN_UNUSED_RESULT; - QuicTime::Delta TransferTime(QuicByteCount bytes) const; private: explicit QuicBandwidth(int64_t bits_per_second); int64_t bits_per_second_; + + friend QuicBandwidth operator+(QuicBandwidth lhs, QuicBandwidth rhs); + friend QuicBandwidth operator-(QuicBandwidth lhs, QuicBandwidth rhs); + friend QuicBandwidth operator*(QuicBandwidth lhs, float factor); }; // Non-member relational operators for QuicBandwidth. @@ -85,5 +83,19 @@ return !(lhs < rhs); } +// Non-member arithmetic operators for QuicBandwidth. +inline QuicBandwidth operator+(QuicBandwidth lhs, QuicBandwidth rhs) { + return QuicBandwidth(lhs.bits_per_second_ + rhs.bits_per_second_); +} +inline QuicBandwidth operator-(QuicBandwidth lhs, QuicBandwidth rhs) { + return QuicBandwidth(lhs.bits_per_second_ - rhs.bits_per_second_); +} +inline QuicBandwidth operator*(QuicBandwidth lhs, float rhs) { + return QuicBandwidth(static_cast<int64_t>(lhs.bits_per_second_ * rhs)); +} +inline QuicBandwidth operator*(float lhs, QuicBandwidth rhs) { + return rhs * lhs; +} + } // namespace net #endif // NET_QUIC_QUIC_BANDWIDTH_H_
diff --git a/net/quic/quic_bandwidth_test.cc b/net/quic/quic_bandwidth_test.cc index 191405c..ebfe005 100644 --- a/net/quic/quic_bandwidth_test.cc +++ b/net/quic/quic_bandwidth_test.cc
@@ -35,15 +35,15 @@ QuicBandwidth bandwidht_1 = QuicBandwidth::FromKBitsPerSecond(1); QuicBandwidth bandwidht_2 = QuicBandwidth::FromKBytesPerSecond(1); - EXPECT_EQ(9000, bandwidht_1.Add(bandwidht_2).ToBitsPerSecond()); - EXPECT_EQ(9000, bandwidht_2.Add(bandwidht_1).ToBitsPerSecond()); + EXPECT_EQ(9000, (bandwidht_1 + bandwidht_2).ToBitsPerSecond()); + EXPECT_EQ(9000, (bandwidht_2 + bandwidht_1).ToBitsPerSecond()); } TEST_F(QuicBandwidthTest, Subtract) { QuicBandwidth bandwidht_1 = QuicBandwidth::FromKBitsPerSecond(1); QuicBandwidth bandwidht_2 = QuicBandwidth::FromKBytesPerSecond(1); - EXPECT_EQ(7000, bandwidht_2.Subtract(bandwidht_1).ToBitsPerSecond()); + EXPECT_EQ(7000, (bandwidht_2 - bandwidht_1).ToBitsPerSecond()); } TEST_F(QuicBandwidthTest, TimeDelta) { @@ -58,11 +58,11 @@ TEST_F(QuicBandwidthTest, Scale) { EXPECT_EQ(QuicBandwidth::FromKBytesPerSecond(500), - QuicBandwidth::FromKBytesPerSecond(1000).Scale(0.5f)); + QuicBandwidth::FromKBytesPerSecond(1000) * 0.5f); EXPECT_EQ(QuicBandwidth::FromKBytesPerSecond(750), - QuicBandwidth::FromKBytesPerSecond(1000).Scale(0.75f)); + 0.75f * QuicBandwidth::FromKBytesPerSecond(1000)); EXPECT_EQ(QuicBandwidth::FromKBytesPerSecond(1250), - QuicBandwidth::FromKBytesPerSecond(1000).Scale(1.25f)); + QuicBandwidth::FromKBytesPerSecond(1000) * 1.25f); } TEST_F(QuicBandwidthTest, BytesPerPeriod) {
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index f18ff5bc..a5769e9 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -737,6 +737,15 @@ } } +void QuicChromiumClientSession::OnConfigNegotiated() { + QuicClientSessionBase::OnConfigNegotiated(); + if (stream_factory_ && config()->HasReceivedAlternateServerAddress()) { + // Server has sent an alternate address to connect to. + stream_factory_->MigrateSessionToNewPeerAddress( + this, config()->ReceivedAlternateServerAddress(), net_log_); + } +} + void QuicChromiumClientSession::OnCryptoHandshakeEvent( CryptoHandshakeEvent event) { if (stream_factory_ && event == HANDSHAKE_CONFIRMED &&
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h index c7b25ba0..25e18f30 100644 --- a/net/quic/quic_chromium_client_session.h +++ b/net/quic/quic_chromium_client_session.h
@@ -183,6 +183,7 @@ void OnRstStream(const QuicRstStreamFrame& frame) override; // QuicClientSessionBase methods: + void OnConfigNegotiated() override; void OnProofValid(const QuicCryptoClientConfig::CachedState& cached) override; void OnProofVerifyDetailsAvailable( const ProofVerifyDetails& verify_details) override;
diff --git a/net/quic/quic_client_session_base.cc b/net/quic/quic_client_session_base.cc index 1d83ee39..7875c67 100644 --- a/net/quic/quic_client_session_base.cc +++ b/net/quic/quic_client_session_base.cc
@@ -29,6 +29,10 @@ } } +void QuicClientSessionBase::OnConfigNegotiated() { + QuicSpdySession::OnConfigNegotiated(); +} + void QuicClientSessionBase::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { QuicSession::OnCryptoHandshakeEvent(event); }
diff --git a/net/quic/quic_client_session_base.h b/net/quic/quic_client_session_base.h index 58c7d65b..7814d2e 100644 --- a/net/quic/quic_client_session_base.h +++ b/net/quic/quic_client_session_base.h
@@ -42,6 +42,8 @@ ~QuicClientSessionBase() override; + void OnConfigNegotiated() override; + // Override base class to set FEC policy before any data is sent by client. void OnCryptoHandshakeEvent(CryptoHandshakeEvent event) override;
diff --git a/net/quic/quic_config.h b/net/quic/quic_config.h index 5baeb33..c79f9ef 100644 --- a/net/quic/quic_config.h +++ b/net/quic/quic_config.h
@@ -216,7 +216,7 @@ }; // Stores IPEndPoint from CHLO or SHLO messages that are not negotiated. -class QuicFixedIPEndPoint : public QuicConfigValue { +class NET_EXPORT_PRIVATE QuicFixedIPEndPoint : public QuicConfigValue { public: QuicFixedIPEndPoint(QuicTag tag, QuicConfigPresence presence); ~QuicFixedIPEndPoint() override;
diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc index 957cc399..96dabd7 100644 --- a/net/quic/quic_connection.cc +++ b/net/quic/quic_connection.cc
@@ -681,8 +681,12 @@ PeerAddressChangeType peer_migration_type = QuicUtils::DetermineAddressChangeType(peer_address_, last_packet_source_address_); + // Do not migrate connection if the changed address packet is a reordered + // packet. if (active_peer_migration_type_ == NO_CHANGE && - peer_migration_type != NO_CHANGE) { + peer_migration_type != NO_CHANGE && + (!FLAGS_quic_do_not_migrate_on_old_packet || + header.packet_number > received_packet_manager_.GetLargestObserved())) { StartPeerMigration(header.path_id, peer_migration_type); } @@ -1064,7 +1068,7 @@ ack_queued_ = true; } else if (!ack_alarm_->IsSet()) { // Wait the minimum of a quarter min_rtt and the delayed ack time. - QuicTime::Delta ack_delay = QuicTime::Delta::Min( + QuicTime::Delta ack_delay = std::min( DelayedAckTime(), sent_packet_manager_->GetRttStats()->min_rtt() * ack_decimation_delay_); ack_alarm_->Set(clock_->ApproximateNow() + ack_delay); @@ -1212,8 +1216,7 @@ ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING); // The optimized path may be used for data only packets which fit into a // standard buffer and don't need padding. - if (FLAGS_quic_use_optimized_write_path && id != kCryptoStreamId && - !packet_generator_.HasQueuedFrames() && + if (id != kCryptoStreamId && !packet_generator_.HasQueuedFrames() && iov.total_length > kMaxPacketSize) { // Use the fast path to send full data packets. return packet_generator_.ConsumeDataFastPath(id, iov, offset, fin,
diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc index c604b4d..0673c26 100644 --- a/net/quic/quic_connection_test.cc +++ b/net/quic/quic_connection_test.cc
@@ -1113,6 +1113,34 @@ EXPECT_FALSE(connection_.connected()); } +TEST_P(QuicConnectionTest, ClientAddressChangeAndPacketReordered) { + EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); + set_perspective(Perspective::IS_SERVER); + QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false); + // Clear peer address. + QuicConnectionPeer::SetPeerAddress(&connection_, IPEndPoint()); + + QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 5); + QuicStreamFrame stream_frame(1u, false, 0u, StringPiece()); + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber()); + const IPEndPoint kNewPeerAddress = IPEndPoint(Loopback6(), + /*port=*/23456); + ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress, + kNewPeerAddress); + + // Decrease packet number to simulate out-of-order packets. + QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 4); + if (FLAGS_quic_do_not_migrate_on_old_packet) { + // This is an old packet, do not migrate. + EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0); + } else { + // A connection migration is observed. + EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)); + } + ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress, + kPeerAddress); +} + TEST_P(QuicConnectionTest, MaxPacketSize) { EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective()); EXPECT_EQ(1350u, connection_.max_packet_length());
diff --git a/net/quic/quic_crypto_server_stream.cc b/net/quic/quic_crypto_server_stream.cc index 452cd37..d222fe3 100644 --- a/net/quic/quic_crypto_server_stream.cc +++ b/net/quic/quic_crypto_server_stream.cc
@@ -85,6 +85,7 @@ validate_client_hello_cb_(nullptr), num_handshake_messages_(0), num_handshake_messages_with_server_nonces_(0), + send_server_config_update_cb_(nullptr), num_server_config_update_messages_sent_(0), use_stateless_rejects_if_peer_supported_( use_stateless_rejects_if_peer_supported), @@ -102,6 +103,10 @@ validate_client_hello_cb_->Cancel(); validate_client_hello_cb_ = nullptr; } + if (send_server_config_update_cb_ != nullptr) { + send_server_config_update_cb_->Cancel(); + send_server_config_update_cb_ = nullptr; + } } void QuicCryptoServerStream::OnHandshakeMessage( @@ -109,8 +114,11 @@ QuicCryptoServerStreamBase::OnHandshakeMessage(message); ++num_handshake_messages_; - // This block should be removed with support for QUIC_VERSION_25. - if (FLAGS_quic_require_fix && !HasFixedTag(message)) { + // It's only safe to deprecate kFIXD where we have deprecated v25 + bool require_kfixd = + !FLAGS_quic_deprecate_kfixd || !FLAGS_quic_disable_pre_30; + + if (require_kfixd && !HasFixedTag(message)) { CloseConnectionWithDetails(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND, "Missing kFIXD"); return; @@ -262,6 +270,27 @@ return; } + if (FLAGS_enable_async_get_proof) { + if (send_server_config_update_cb_ != nullptr) { + DVLOG(1) + << "Skipped server config update since one is already in progress"; + return; + } + + std::unique_ptr<SendServerConfigUpdateCallback> cb( + new SendServerConfigUpdateCallback(this)); + send_server_config_update_cb_ = cb.get(); + crypto_config_->BuildServerConfigUpdateMessage( + session()->connection()->version(), chlo_hash_, + previous_source_address_tokens_, + session()->connection()->self_address().address(), + session()->connection()->peer_address().address(), + session()->connection()->clock(), + session()->connection()->random_generator(), compressed_certs_cache_, + crypto_negotiated_params_, cached_network_params, std::move(cb)); + return; + } + CryptoHandshakeMessage server_config_update_message; if (!crypto_config_->BuildServerConfigUpdateMessage( session()->connection()->version(), chlo_hash_, @@ -284,6 +313,43 @@ ++num_server_config_update_messages_sent_; } +QuicCryptoServerStream::SendServerConfigUpdateCallback:: + SendServerConfigUpdateCallback(QuicCryptoServerStream* parent) + : parent_(parent) {} + +void QuicCryptoServerStream::SendServerConfigUpdateCallback::Cancel() { + parent_ = nullptr; +} + +// From BuildServerConfigUpdateMessageResultCallback +void QuicCryptoServerStream::SendServerConfigUpdateCallback::Run( + bool ok, + const CryptoHandshakeMessage& message) { + if (parent_ == nullptr) { + return; + } + parent_->FinishSendServerConfigUpdate(ok, message); +} + +void QuicCryptoServerStream::FinishSendServerConfigUpdate( + bool ok, + const CryptoHandshakeMessage& message) { + // Clear the callback that got us here. + DCHECK(send_server_config_update_cb_ != nullptr); + send_server_config_update_cb_ = nullptr; + + if (!ok) { + DVLOG(1) << "Server: Failed to build server config update (SCUP)!"; + return; + } + + DVLOG(1) << "Server: Sending server config update: " << message.DebugString(); + const QuicData& data = message.GetSerialized(); + WriteOrBufferData(StringPiece(data.data(), data.length()), false, nullptr); + + ++num_server_config_update_messages_sent_; +} + void QuicCryptoServerStream::OnServerHelloAcked() { session()->connection()->OnHandshakeComplete(); }
diff --git a/net/quic/quic_crypto_server_stream.h b/net/quic/quic_crypto_server_stream.h index f3900847..77711b8 100644 --- a/net/quic/quic_crypto_server_stream.h +++ b/net/quic/quic_crypto_server_stream.h
@@ -157,6 +157,24 @@ DISALLOW_COPY_AND_ASSIGN(ValidateCallback); }; + class SendServerConfigUpdateCallback + : public BuildServerConfigUpdateMessageResultCallback { + public: + explicit SendServerConfigUpdateCallback(QuicCryptoServerStream* parent); + SendServerConfigUpdateCallback(const SendServerConfigUpdateCallback&) = + delete; + void operator=(const SendServerConfigUpdateCallback&) = delete; + + // To allow the parent to detach itself from the callback before deletion. + void Cancel(); + + // From BuildServerConfigUpdateMessageResultCallback + void Run(bool ok, const CryptoHandshakeMessage& message) override; + + private: + QuicCryptoServerStream* parent_; + }; + // Invoked by ValidateCallback::RunImpl once initial validation of // the client hello is complete. Finishes processing of the client // hello message and handles handshake success/failure. @@ -164,6 +182,13 @@ const CryptoHandshakeMessage& message, const ValidateClientHelloResultCallback::Result& result); + // Invoked by SendServerConfigUpdateCallback::RunImpl once the proof has been + // received. |ok| indicates whether or not the proof was successfully + // acquired, and |message| holds the partially-constructed message from + // SendServerConfigUpdate. + void FinishSendServerConfigUpdate(bool ok, + const CryptoHandshakeMessage& message); + // crypto_config_ contains crypto parameters for the handshake. const QuicCryptoServerConfig* crypto_config_; @@ -193,6 +218,12 @@ // attempt). uint8_t num_handshake_messages_with_server_nonces_; + // Pointer to the active callback that will receive the result of + // BuildServerConfigUpdateMessage and forward it to + // FinishSendServerConfigUpdate. nullptr if no update message is currently + // being built. + SendServerConfigUpdateCallback* send_server_config_update_cb_; + // Number of server config update (SCUP) messages sent by this stream. int num_server_config_update_messages_sent_;
diff --git a/net/quic/quic_crypto_server_stream_test.cc b/net/quic/quic_crypto_server_stream_test.cc index 1cf2d5c..fc5583b2 100644 --- a/net/quic/quic_crypto_server_stream_test.cc +++ b/net/quic/quic_crypto_server_stream_test.cc
@@ -428,7 +428,8 @@ TEST_P(QuicCryptoServerStreamTest, FailByPolicy) { FLAGS_quic_enable_chlo_policy = true; - FLAGS_quic_require_fix = false; + FLAGS_quic_disable_pre_30 = true; + FLAGS_quic_deprecate_kfixd = true; Initialize(); InitializeFakeClient(/* supports_stateless_rejects= */ false); @@ -441,7 +442,8 @@ } TEST_P(QuicCryptoServerStreamTest, MessageAfterHandshake) { - FLAGS_quic_require_fix = false; + FLAGS_quic_disable_pre_30 = true; + FLAGS_quic_deprecate_kfixd = true; Initialize(); CompleteCryptoHandshake(); EXPECT_CALL( @@ -455,7 +457,8 @@ } TEST_P(QuicCryptoServerStreamTest, BadMessageType) { - FLAGS_quic_require_fix = false; + FLAGS_quic_disable_pre_30 = true; + FLAGS_quic_deprecate_kfixd = true; Initialize(); message_.set_tag(kSHLO);
diff --git a/net/quic/quic_crypto_stream.cc b/net/quic/quic_crypto_stream.cc index f904871..271af57a2 100644 --- a/net/quic/quic_crypto_stream.cc +++ b/net/quic/quic_crypto_stream.cc
@@ -10,6 +10,7 @@ #include "net/quic/crypto/crypto_handshake.h" #include "net/quic/crypto/crypto_utils.h" #include "net/quic/quic_connection.h" +#include "net/quic/quic_flags.h" #include "net/quic/quic_session.h" #include "net/quic/quic_utils.h" @@ -69,6 +70,9 @@ const CryptoHandshakeMessage& message, QuicAckListenerInterface* listener) { DVLOG(1) << ENDPOINT << "Sending " << message.DebugString(); + if (FLAGS_quic_neuter_unencrypted_when_sending) { + session()->connection()->NeuterUnencryptedPackets(); + } session()->OnCryptoHandshakeMessageSent(message); const QuicData& data = message.GetSerialized(); // TODO(wtc): check the return value.
diff --git a/net/quic/quic_flags.cc b/net/quic/quic_flags.cc index cd92ea6..06a30f0 100644 --- a/net/quic/quic_flags.cc +++ b/net/quic/quic_flags.cc
@@ -60,9 +60,6 @@ // If true, Close the connection instead of writing unencrypted stream data. bool FLAGS_quic_never_write_unencrypted_data = true; -// If true, reject any incoming QUIC which does not have the FIXD tag. -bool FLAGS_quic_require_fix = true; - // If true, headers stream will support receiving PUSH_PROMISE frames. bool FLAGS_quic_supports_push_promise = true; @@ -92,13 +89,6 @@ // flags. bool FLAGS_quic_use_old_public_reset_packets = true; -// Allow the NPRR connection option which reduces QUIC\'s pacing rate during -// recovery instead of PRR. -bool FLAGS_quic_allow_noprr = true; - -// Use a write path optimized for StreamFrames. -bool FLAGS_quic_use_optimized_write_path = true; - // If true, the dispatcher is responsible for generating server designated // connection IDs. bool FLAGS_quic_dispatcher_creates_id = true; @@ -155,3 +145,21 @@ // If true, requires support for X509 certificates in QUIC CHLO PDMDs. bool FLAGS_quic_require_x509 = false; + +// If true, deprecate safeguards for b/26023400. +bool FLAGS_quic_deprecate_kfixd = false; + +// If true, QUIC will refresh the proof for versions 31 and beyond on subsequent +// CHLOs. +bool FLAGS_quic_refresh_proof = true; + +// If true, a connection does not migrate on an old packet even the peer address +// changes. +bool FLAGS_quic_do_not_migrate_on_old_packet = true; + +// If true, use async codepaths to invoke ProofSource::GetProof. +bool FLAGS_enable_async_get_proof = false; + +// If true, neuter null encrypted packets before sending the next handshake +// message. +bool FLAGS_quic_neuter_unencrypted_when_sending = false;
diff --git a/net/quic/quic_flags.h b/net/quic/quic_flags.h index 0a54c7b..59c9f9e8 100644 --- a/net/quic/quic_flags.h +++ b/net/quic/quic_flags.h
@@ -22,7 +22,6 @@ NET_EXPORT_PRIVATE extern bool FLAGS_quic_measure_headers_hol_blocking_time; NET_EXPORT_PRIVATE extern bool FLAGS_quic_disable_pacing_for_perf_tests; NET_EXPORT_PRIVATE extern bool FLAGS_quic_never_write_unencrypted_data; -NET_EXPORT_PRIVATE extern bool FLAGS_quic_require_fix; NET_EXPORT_PRIVATE extern bool FLAGS_quic_supports_push_promise; NET_EXPORT_PRIVATE extern bool FLAGS_quic_supports_push_promise; NET_EXPORT_PRIVATE extern bool FLAGS_quic_no_lower_bw_resumption_limit; @@ -32,8 +31,6 @@ NET_EXPORT_PRIVATE extern bool FLAGS_quic_only_one_sending_alarm; NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_hash_in_scup; NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_old_public_reset_packets; -NET_EXPORT_PRIVATE extern bool FLAGS_quic_allow_noprr; -NET_EXPORT_PRIVATE extern bool FLAGS_quic_use_optimized_write_path; NET_EXPORT_PRIVATE extern bool FLAGS_quic_dispatcher_creates_id; NET_EXPORT_PRIVATE extern bool FLAGS_quic_enable_chlo_policy; NET_EXPORT_PRIVATE extern bool FLAGS_quic_ignore_zero_length_frames; @@ -50,5 +47,10 @@ NET_EXPORT_PRIVATE extern bool FLAGS_quic_enable_version_35; NET_EXPORT_PRIVATE extern bool FLAGS_quic_enable_version_36; NET_EXPORT_PRIVATE extern bool FLAGS_quic_require_x509; +NET_EXPORT_PRIVATE extern bool FLAGS_quic_deprecate_kfixd; +NET_EXPORT_PRIVATE extern bool FLAGS_quic_refresh_proof; +NET_EXPORT_PRIVATE extern bool FLAGS_quic_do_not_migrate_on_old_packet; +NET_EXPORT_PRIVATE extern bool FLAGS_enable_async_get_proof; +NET_EXPORT_PRIVATE extern bool FLAGS_quic_neuter_unencrypted_when_sending; #endif // NET_QUIC_QUIC_FLAGS_H_
diff --git a/net/quic/quic_headers_stream.cc b/net/quic/quic_headers_stream.cc index bdf9c9e..c9f3529 100644 --- a/net/quic/quic_headers_stream.cc +++ b/net/quic/quic_headers_stream.cc
@@ -446,7 +446,7 @@ break; } DCHECK(timestamp.IsInitialized()); - cur_max_timestamp_ = QuicTime::Max(timestamp, cur_max_timestamp_); + cur_max_timestamp_ = std::max(timestamp, cur_max_timestamp_); } else { if (sequencer()->GetReadableRegions(&iov, 1) != 1) { // No more data to read.
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc index 5009a2e..1097fee 100644 --- a/net/quic/quic_http_stream.cc +++ b/net/quic/quic_http_stream.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "base/auto_reset.h" #include "base/callback_helpers.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string_split.h" @@ -62,12 +63,14 @@ port_migration_detected_(false), found_promise_(false), push_handle_(nullptr), + in_loop_(false), weak_factory_(this) { DCHECK(session_); session_->AddObserver(this); } QuicHttpStream::~QuicHttpStream() { + CHECK(!in_loop_); Close(false); if (session_) session_->RemoveObserver(this); @@ -555,6 +558,7 @@ void QuicHttpStream::DoCallback(int rv) { CHECK_NE(rv, ERR_IO_PENDING); CHECK(!callback_.is_null()); + CHECK(!in_loop_); // The client callback can do anything, including destroying this class, // so any pending callback must be issued after everything else is done. @@ -562,6 +566,8 @@ } int QuicHttpStream::DoLoop(int rv) { + CHECK(!in_loop_); + base::AutoReset<bool> auto_reset_in_loop(&in_loop_, true); do { State state = next_state_; next_state_ = STATE_NONE;
diff --git a/net/quic/quic_http_stream.h b/net/quic/quic_http_stream.h index 25eb334..e46ed0a 100644 --- a/net/quic/quic_http_stream.h +++ b/net/quic/quic_http_stream.h
@@ -207,6 +207,9 @@ // invoked. QuicClientPushPromiseIndex::TryHandle* push_handle_; + // Set to true when DoLoop() is being executed, false otherwise. + bool in_loop_; + base::WeakPtrFactory<QuicHttpStream> weak_factory_; DISALLOW_COPY_AND_ASSIGN(QuicHttpStream);
diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc index b940c99..e60e2c80 100644 --- a/net/quic/quic_packet_creator.cc +++ b/net/quic/quic_packet_creator.cc
@@ -276,7 +276,7 @@ const char* src = static_cast<char*>(iov.iov[iovnum].iov_base) + iov_offset; while (true) { - memcpy(buffer, src, copy_len); + memmove(buffer, src, copy_len); length -= copy_len; buffer += copy_len; if (length == 0 || ++iovnum >= iov.iov_count) {
diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc index 9829ab46..fe387f08 100644 --- a/net/quic/quic_protocol.cc +++ b/net/quic/quic_protocol.cc
@@ -504,6 +504,13 @@ return Empty() || old_min != Min(); } +void PacketNumberQueue::Complement() { + if (Empty()) { + return; + } + packet_number_intervals_.Complement(Min(), Max() + 1); +} + bool PacketNumberQueue::Contains(QuicPacketNumber packet_number) const { return packet_number_intervals_.Contains(packet_number); }
diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h index c3089f7..d7325c5 100644 --- a/net/quic/quic_protocol.h +++ b/net/quic/quic_protocol.h
@@ -956,6 +956,11 @@ // the queue. Returns true if packets were removed. bool RemoveUpTo(QuicPacketNumber higher); + // Mutates packet number set so that it contains only those packet numbers + // from minimum to maximum packet number not currently in the set. Do nothing + // if packet number set is empty. + void Complement(); + // Returns true if the queue contains |packet_number|. bool Contains(QuicPacketNumber packet_number) const;
diff --git a/net/quic/quic_protocol_test.cc b/net/quic/quic_protocol_test.cc index 126f610..b50e60ec 100644 --- a/net/quic/quic_protocol_test.cc +++ b/net/quic/quic_protocol_test.cc
@@ -400,6 +400,19 @@ EXPECT_FALSE(queue.Contains(20)); } +TEST(PacketNumberQueueTest, Complement) { + PacketNumberQueue queue; + queue.Add(1, 10); + queue.Add(12, 20); + queue.Add(22, 30); + queue.Complement(); + EXPECT_EQ(2u, queue.NumIntervals()); + EXPECT_TRUE(queue.Contains(10)); + EXPECT_TRUE(queue.Contains(11)); + EXPECT_TRUE(queue.Contains(20)); + EXPECT_TRUE(queue.Contains(21)); +} + } // namespace } // namespace test } // namespace net
diff --git a/net/quic/quic_received_packet_manager.cc b/net/quic/quic_received_packet_manager.cc index 4ce6945..199fe7f 100644 --- a/net/quic/quic_received_packet_manager.cc +++ b/net/quic/quic_received_packet_manager.cc
@@ -319,4 +319,8 @@ return ack_frame_updated_; } +QuicPacketNumber QuicReceivedPacketManager::GetLargestObserved() const { + return ack_frame_.largest_observed; +} + } // namespace net
diff --git a/net/quic/quic_received_packet_manager.h b/net/quic/quic_received_packet_manager.h index 44a770b..013bde17 100644 --- a/net/quic/quic_received_packet_manager.h +++ b/net/quic/quic_received_packet_manager.h
@@ -149,6 +149,8 @@ virtual bool ack_frame_updated() const; + QuicPacketNumber GetLargestObserved() const; + // For logging purposes. const QuicAckFrame& ack_frame() const { return ack_frame_; }
diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc index 7ec63fc..7a26504c 100644 --- a/net/quic/quic_sent_packet_manager.cc +++ b/net/quic/quic_sent_packet_manager.cc
@@ -816,7 +816,7 @@ const QuicTime sent_time = unacked_packets_.GetLastPacketSentTime(); const QuicTime tlp_time = sent_time + GetTailLossProbeDelay(); // Ensure the TLP timer never gets set to a time in the past. - return QuicTime::Max(clock_->ApproximateNow(), tlp_time); + return std::max(clock_->ApproximateNow(), tlp_time); } case RTO_MODE: { // The RTO is based on the first outstanding packet. @@ -825,7 +825,7 @@ // Wait for TLP packets to be acked before an RTO fires. QuicTime tlp_time = unacked_packets_.GetLastPacketSentTime() + GetTailLossProbeDelay(); - return QuicTime::Max(tlp_time, rto_time); + return std::max(tlp_time, rto_time); } } DCHECK(false); @@ -857,9 +857,8 @@ static_cast<int64_t>(0.5 * srtt.ToMilliseconds()))); } if (!unacked_packets_.HasMultipleInFlightPackets()) { - return QuicTime::Delta::Max(2 * srtt, - 1.5 * srtt + QuicTime::Delta::FromMilliseconds( - kMinRetransmissionTimeMs / 2)); + return std::max(2 * srtt, 1.5 * srtt + QuicTime::Delta::FromMilliseconds( + kMinRetransmissionTimeMs / 2)); } return QuicTime::Delta::FromMilliseconds( max(kMinTailLossProbeTimeoutMs,
diff --git a/net/quic/quic_spdy_stream.h b/net/quic/quic_spdy_stream.h index 01f7a29..d8d8d714 100644 --- a/net/quic/quic_spdy_stream.h +++ b/net/quic/quic_spdy_stream.h
@@ -193,6 +193,10 @@ // use of the spdy_session_ member. void ClearSession(); + // Returns true if the sequencer has delivered the FIN, and no more body bytes + // will be available. + bool IsClosed() { return sequencer()->IsClosed(); } + protected: // Called by OnStreamHeadersComplete depending on which type (initial or // trailing) headers are expected next.
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index 91e442d..6836f9d 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc
@@ -632,6 +632,7 @@ int idle_connection_timeout_seconds, bool migrate_sessions_on_network_change, bool migrate_sessions_early, + bool allow_server_migration, bool force_hol_blocking, const QuicTagVector& connection_options, bool enable_token_binding) @@ -649,10 +650,11 @@ socket_performance_watcher_factory_(socket_performance_watcher_factory), config_(InitializeQuicConfig(connection_options, idle_connection_timeout_seconds)), - crypto_config_(new ProofVerifierChromium(cert_verifier, - ct_policy_enforcer, - transport_security_state, - cert_transparency_verifier)), + crypto_config_(base::WrapUnique( + new ProofVerifierChromium(cert_verifier, + ct_policy_enforcer, + transport_security_state, + cert_transparency_verifier))), supported_versions_(supported_versions), enable_port_selection_(enable_port_selection), always_require_handshake_confirmation_( @@ -686,6 +688,7 @@ NetworkChangeNotifier::AreNetworkHandlesSupported()), migrate_sessions_early_(migrate_sessions_early && migrate_sessions_on_network_change_), + allow_server_migration_(allow_server_migration), force_hol_blocking_(force_hol_blocking), port_seed_(random_generator_->RandUint64()), check_persisted_supports_quic_(true), @@ -1445,7 +1448,7 @@ continue; } - MigrateSessionToNetwork(session, new_network, bound_net_log, nullptr); + MigrateSessionToNewNetwork(session, new_network, bound_net_log, nullptr); } } @@ -1477,15 +1480,37 @@ return; } OnSessionGoingAway(session); - MigrateSessionToNetwork(session, new_network, scoped_event_log.net_log(), - packet); + MigrateSessionToNewNetwork(session, new_network, scoped_event_log.net_log(), + packet); } -void QuicStreamFactory::MigrateSessionToNetwork( +void QuicStreamFactory::MigrateSessionToNewPeerAddress( QuicChromiumClientSession* session, - NetworkHandle new_network, + IPEndPoint peer_address, + const BoundNetLog& bound_net_log) { + if (!allow_server_migration_) + return; + // Specifying kInvalidNetworkHandle for the |network| parameter + // causes the session to use the default network for the new socket. + MigrateSession(session, peer_address, + NetworkChangeNotifier::kInvalidNetworkHandle, bound_net_log, + nullptr); +} + +void QuicStreamFactory::MigrateSessionToNewNetwork( + QuicChromiumClientSession* session, + NetworkHandle network, const BoundNetLog& bound_net_log, scoped_refptr<StringIOBuffer> packet) { + MigrateSession(session, session->connection()->peer_address(), network, + bound_net_log, packet); +} + +void QuicStreamFactory::MigrateSession(QuicChromiumClientSession* session, + IPEndPoint peer_address, + NetworkHandle network, + const BoundNetLog& bound_net_log, + scoped_refptr<StringIOBuffer> packet) { // Use OS-specified port for socket (DEFAULT_BIND) instead of // using the PortSuggester since the connection is being migrated // and not being newly created. @@ -1493,9 +1518,7 @@ client_socket_factory_->CreateDatagramClientSocket( DatagramSocket::DEFAULT_BIND, RandIntCallback(), session->net_log().net_log(), session->net_log().source())); - QuicConnection* connection = session->connection(); - if (ConfigureSocket(socket.get(), connection->peer_address(), new_network) != - OK) { + if (ConfigureSocket(socket.get(), peer_address, network) != OK) { session->CloseSessionOnError(ERR_NETWORK_CHANGED, QUIC_INTERNAL_ERROR); HistogramAndLogMigrationFailure( bound_net_log, MIGRATION_STATUS_INTERNAL_ERROR,
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h index fbb91ab..45af9632 100644 --- a/net/quic/quic_stream_factory.h +++ b/net/quic/quic_stream_factory.h
@@ -192,6 +192,7 @@ int idle_connection_timeout_seconds, bool migrate_sessions_on_network_change, bool migrate_sessions_early, + bool allow_server_migration, bool force_hol_blocking, const QuicTagVector& connection_options, bool enable_token_binding); @@ -297,13 +298,20 @@ MigrationCause migration_cause, scoped_refptr<StringIOBuffer> packet); - // Method that migrates |session| over to using |new_network|. If - // not null, |packet| is sent on the new network, else a PING frame - // is sent. Returns ERR_QUIC_PROTOCOL_ERROR if migration fails. - void MigrateSessionToNetwork(QuicChromiumClientSession* session, - NetworkChangeNotifier::NetworkHandle new_network, - const BoundNetLog& bound_net_log, - scoped_refptr<StringIOBuffer> packet); + // Migrates |session| over to using |network|. If |network| is + // kInvalidNetworkHandle, default network is used. If |packet| is + // not null, it is sent on the new network, else a PING frame is + // sent. + void MigrateSessionToNewNetwork(QuicChromiumClientSession* session, + NetworkChangeNotifier::NetworkHandle network, + const BoundNetLog& bound_net_log, + scoped_refptr<StringIOBuffer> packet); + + // Migrates |session| over to using |peer_address|. Causes a PING frame + // to be sent to the new peer address. + void MigrateSessionToNewPeerAddress(QuicChromiumClientSession* session, + IPEndPoint peer_address, + const BoundNetLog& bound_net_log); // NetworkChangeNotifier::IPAddressObserver methods: @@ -447,6 +455,16 @@ void MaybeDisableQuic(uint16_t port); + // Internal method that migrates |session| over to using + // |peer_address| and |network|. If |network| is kInvalidNetworkHandle, + // default network is used. If |packet| is not null, it is sent + // on the new network, else a PING frame is sent. + void MigrateSession(QuicChromiumClientSession* session, + IPEndPoint peer_address, + NetworkChangeNotifier::NetworkHandle network, + const BoundNetLog& bound_net_log, + scoped_refptr<StringIOBuffer> packet); + bool require_confirmation_; NetLog* net_log_; HostResolver* host_resolver_; @@ -573,6 +591,10 @@ // experiences poor connectivity. const bool migrate_sessions_early_; + // If set, allows migration of connection to server-specified alternate + // server address. + const bool allow_server_migration_; + // If set, force HOL blocking. For measurement purposes. const bool force_hol_blocking_;
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc index cb159de8..11021a92 100644 --- a/net/quic/quic_stream_factory_test.cc +++ b/net/quic/quic_stream_factory_test.cc
@@ -321,6 +321,7 @@ idle_connection_timeout_seconds_(kIdleConnectionTimeoutSeconds), migrate_sessions_on_network_change_(false), migrate_sessions_early_(false), + allow_server_migration_(false), force_hol_blocking_(false) { clock_->AdvanceTime(QuicTime::Delta::FromSeconds(1)); } @@ -353,8 +354,8 @@ close_sessions_on_ip_change_, disable_quic_on_timeout_with_open_streams_, idle_connection_timeout_seconds_, migrate_sessions_on_network_change_, - migrate_sessions_early_, force_hol_blocking_, QuicTagVector(), - /*enable_token_binding*/ false)); + migrate_sessions_early_, allow_server_migration_, force_hol_blocking_, + QuicTagVector(), /*enable_token_binding*/ false)); factory_->set_require_confirmation(false); EXPECT_FALSE(factory_->has_quic_server_info_factory()); factory_->set_quic_server_info_factory(new MockQuicServerInfoFactory()); @@ -546,6 +547,7 @@ int idle_connection_timeout_seconds_; bool migrate_sessions_on_network_change_; bool migrate_sessions_early_; + bool allow_server_migration_; bool force_hol_blocking_; }; @@ -2655,6 +2657,107 @@ EXPECT_TRUE(socket_data.AllWriteDataConsumed()); } +TEST_P(QuicStreamFactoryTest, ServerMigration) { + allow_server_migration_ = true; + Initialize(); + + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + std::unique_ptr<QuicEncryptedPacket> request_packet( + ConstructGetRequestPacket(1, kClientDataStreamId1, true, true)); + MockWrite writes1[] = {MockWrite(SYNCHRONOUS, request_packet->data(), + request_packet->length(), 1)}; + MockRead reads1[] = {MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)}; + SequencedSocketData socket_data1(reads1, arraysize(reads1), writes1, + arraysize(writes1)); + socket_factory_.AddSocketDataProvider(&socket_data1); + + // Create request and QuicHttpStream. + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request(host_port_pair_, privacy_mode_, + /*cert_verify_flags=*/0, url_, "GET", net_log_, + callback_.callback())); + EXPECT_EQ(OK, callback_.WaitForResult()); + std::unique_ptr<QuicHttpStream> stream = request.CreateStream(); + EXPECT_TRUE(stream.get()); + + // Cause QUIC stream to be created. + HttpRequestInfo request_info; + request_info.method = "GET"; + request_info.url = GURL("https://www.example.org/"); + EXPECT_EQ(OK, stream->InitializeStream(&request_info, DEFAULT_PRIORITY, + net_log_, CompletionCallback())); + + // Ensure that session is alive and active. + QuicChromiumClientSession* session = GetActiveSession(host_port_pair_); + EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + + // Send GET request on stream. + HttpResponseInfo response; + HttpRequestHeaders request_headers; + EXPECT_EQ(OK, stream->SendRequest(request_headers, &response, + callback_.callback())); + + IPEndPoint ip; + session->GetDefaultSocket()->GetPeerAddress(&ip); + DVLOG(1) << "Socket connected to: " << ip.address().ToString() << " " + << ip.port(); + + // Set up second socket data provider that is used after + // migration. The request is rewritten to this new socket, and the + // response to the request is read on this new socket. + std::unique_ptr<QuicEncryptedPacket> ping( + client_maker_.MakePingPacket(2, /*include_version=*/true)); + std::unique_ptr<QuicEncryptedPacket> client_rst( + client_maker_.MakeAckAndRstPacket(3, false, kClientDataStreamId1, + QUIC_STREAM_CANCELLED, 1, 1, 1, true)); + MockWrite writes2[] = { + MockWrite(SYNCHRONOUS, ping->data(), ping->length(), 0), + MockWrite(SYNCHRONOUS, client_rst->data(), client_rst->length(), 3)}; + std::unique_ptr<QuicEncryptedPacket> response_headers_packet( + ConstructOkResponsePacket(1, kClientDataStreamId1, false, false)); + MockRead reads2[] = {MockRead(ASYNC, response_headers_packet->data(), + response_headers_packet->length(), 1), + MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2)}; + SequencedSocketData socket_data2(reads2, arraysize(reads2), writes2, + arraysize(writes2)); + socket_factory_.AddSocketDataProvider(&socket_data2); + + const uint8_t kTestIpAddress[] = {1, 2, 3, 4}; + const uint16_t kTestPort = 123; + factory_->MigrateSessionToNewPeerAddress( + session, IPEndPoint(IPAddress(kTestIpAddress), kTestPort), net_log_); + + session->GetDefaultSocket()->GetPeerAddress(&ip); + DVLOG(1) << "Socket migrated to: " << ip.address().ToString() << " " + << ip.port(); + + // The session should be alive and active. + EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session)); + EXPECT_TRUE(HasActiveSession(host_port_pair_)); + EXPECT_EQ(1u, session->GetNumActiveStreams()); + + // Run the message loop so that data queued in the new socket is read by the + // packet reader. + base::RunLoop().RunUntilIdle(); + + // Verify that response headers on the migrated socket were delivered to the + // stream. + EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback())); + EXPECT_EQ(200, response.headers->response_code()); + + stream.reset(); + + EXPECT_TRUE(socket_data1.AllReadDataConsumed()); + EXPECT_TRUE(socket_data1.AllWriteDataConsumed()); + EXPECT_TRUE(socket_data2.AllReadDataConsumed()); + EXPECT_TRUE(socket_data2.AllWriteDataConsumed()); +} + TEST_P(QuicStreamFactoryTest, OnSSLConfigChanged) { Initialize(); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
diff --git a/net/quic/quic_time.h b/net/quic/quic_time.h index 3c5a670..ffdbb80 100644 --- a/net/quic/quic_time.h +++ b/net/quic/quic_time.h
@@ -70,16 +70,6 @@ // Converts the time offset to a rounded number of microseconds. inline int64_t ToMicroseconds() const { return time_offset_; } - // Returns the larger delta of time1 and time2. - static inline Delta Max(Delta delta1, Delta delta2) { - return delta1 < delta2 ? delta2 : delta1; - } - - // Returns the smaller delta of time1 and time2. - static inline Delta Min(Delta delta1, Delta delta2) { - return delta1 < delta2 ? delta1 : delta2; - } - inline bool IsZero() const { return time_offset_ == 0; } inline bool IsInfinite() const { @@ -126,11 +116,6 @@ return QuicTime(Delta::kQuicInfiniteTimeUs); } - // Returns the later time of time1 and time2. - static inline QuicTime Max(QuicTime time1, QuicTime time2) { - return time1 < time2 ? time2 : time1; - } - // Produce the internal value to be used when logging. This value // represents the number of microseconds since some epoch. It may // be the UNIX epoch on some platforms. On others, it may
diff --git a/net/quic/quic_time_test.cc b/net/quic/quic_time_test.cc index 9bdba53..be760d7 100644 --- a/net/quic/quic_time_test.cc +++ b/net/quic/quic_time_test.cc
@@ -63,8 +63,8 @@ TEST(QuicTimeDeltaTest, Max) { EXPECT_EQ(QuicTime::Delta::FromMicroseconds(2000), - QuicTime::Delta::Max(QuicTime::Delta::FromMicroseconds(1000), - QuicTime::Delta::FromMicroseconds(2000))); + std::max(QuicTime::Delta::FromMicroseconds(1000), + QuicTime::Delta::FromMicroseconds(2000))); } TEST(QuicTimeDeltaTest, NotEqual) { @@ -113,7 +113,7 @@ QuicTime time_1 = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1); QuicTime time_2 = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(2); - EXPECT_EQ(time_2, QuicTime::Max(time_1, time_2)); + EXPECT_EQ(time_2, std::max(time_1, time_2)); } TEST_F(QuicTimeTest, MockClock) {
diff --git a/net/quic/test_tools/crypto_test_utils.h b/net/quic/test_tools/crypto_test_utils.h index b453cec..176d6878 100644 --- a/net/quic/test_tools/crypto_test_utils.h +++ b/net/quic/test_tools/crypto_test_utils.h
@@ -142,14 +142,14 @@ static std::string GetValueForTag(const CryptoHandshakeMessage& message, QuicTag tag); - // Returns a |ProofSource| that serves up test certificates. - static ProofSource* ProofSourceForTesting(); + // Returns a new |ProofSource| that serves up test certificates. + static std::unique_ptr<ProofSource> ProofSourceForTesting(); // Returns a |ProofVerifier| that uses the QUIC testing root CA. - static ProofVerifier* ProofVerifierForTesting(); + static std::unique_ptr<ProofVerifier> ProofVerifierForTesting(); // Returns a real ProofVerifier (not a fake proof verifier) for testing. - static ProofVerifier* RealProofVerifierForTesting(); + static std::unique_ptr<ProofVerifier> RealProofVerifierForTesting(); // Returns a hash of the leaf test certificate. static uint64_t LeafCertHashForTesting();
diff --git a/net/quic/test_tools/crypto_test_utils_chromium.cc b/net/quic/test_tools/crypto_test_utils_chromium.cc index 1e944e0..ec2be57 100644 --- a/net/quic/test_tools/crypto_test_utils_chromium.cc +++ b/net/quic/test_tools/crypto_test_utils_chromium.cc
@@ -82,18 +82,19 @@ } // namespace // static -ProofSource* CryptoTestUtils::ProofSourceForTesting() { - ProofSourceChromium* source = new ProofSourceChromium(); +std::unique_ptr<ProofSource> CryptoTestUtils::ProofSourceForTesting() { + std::unique_ptr<ProofSourceChromium> source(new ProofSourceChromium()); base::FilePath certs_dir = GetTestCertsDirectory(); CHECK(source->Initialize( certs_dir.AppendASCII("quic_chain.crt"), certs_dir.AppendASCII("quic_test.example.com.key.pkcs8"), certs_dir.AppendASCII("quic_test.example.com.key.sct"))); - return source; + return std::move(source); } // static -ProofVerifier* ProofVerifierForTestingInternal(bool use_real_proof_verifier) { +std::unique_ptr<ProofVerifier> ProofVerifierForTestingInternal( + bool use_real_proof_verifier) { // TODO(rch): use a real cert verifier? std::unique_ptr<MockCertVerifier> cert_verifier(new MockCertVerifier()); net::CertVerifyResult verify_result; @@ -106,24 +107,24 @@ cert_verifier->AddResultForCertAndHost(verify_result.verified_cert.get(), "test.example.com", verify_result, OK); if (use_real_proof_verifier) { - return new TestProofVerifierChromium( + return base::WrapUnique(new TestProofVerifierChromium( std::move(cert_verifier), base::WrapUnique(new TransportSecurityState), base::WrapUnique(new MultiLogCTVerifier), - base::WrapUnique(new CTPolicyEnforcer), "quic_root.crt"); + base::WrapUnique(new CTPolicyEnforcer), "quic_root.crt")); } - return new TestProofVerifierChromium( + return base::WrapUnique(new TestProofVerifierChromium( std::move(cert_verifier), base::WrapUnique(new TransportSecurityState), base::WrapUnique(new MultiLogCTVerifier), - base::WrapUnique(new CTPolicyEnforcer), "quic_root.crt"); + base::WrapUnique(new CTPolicyEnforcer), "quic_root.crt")); } // static -ProofVerifier* CryptoTestUtils::ProofVerifierForTesting() { +std::unique_ptr<ProofVerifier> CryptoTestUtils::ProofVerifierForTesting() { return ProofVerifierForTestingInternal(/*use_real_proof_verifier=*/false); } // static -ProofVerifier* CryptoTestUtils::RealProofVerifierForTesting() { +std::unique_ptr<ProofVerifier> CryptoTestUtils::RealProofVerifierForTesting() { return ProofVerifierForTestingInternal(/*use_real_proof_verifier=*/true); }
diff --git a/net/quic/test_tools/quic_config_peer.cc b/net/quic/test_tools/quic_config_peer.cc index f272e9ad..e9e4a95 100644 --- a/net/quic/test_tools/quic_config_peer.cc +++ b/net/quic/test_tools/quic_config_peer.cc
@@ -59,15 +59,21 @@ } // static - void QuicConfigPeer::SetConnectionOptionsToSend(QuicConfig* config, const QuicTagVector& options) { config->SetConnectionOptionsToSend(options); } +// static void QuicConfigPeer::SetReceivedForceHolBlocking(QuicConfig* config) { config->force_hol_blocking_.SetReceivedValue(1); } +// static +void QuicConfigPeer::SetReceivedAlternateServerAddress(QuicConfig* config, + IPEndPoint addr) { + config->alternate_server_address_.SetReceivedValue(addr); +} + } // namespace test } // namespace net
diff --git a/net/quic/test_tools/quic_config_peer.h b/net/quic/test_tools/quic_config_peer.h index 4c9f3cb..470c6a8 100644 --- a/net/quic/test_tools/quic_config_peer.h +++ b/net/quic/test_tools/quic_config_peer.h
@@ -43,6 +43,9 @@ static void SetReceivedForceHolBlocking(QuicConfig* config); + static void SetReceivedAlternateServerAddress(QuicConfig* config, + IPEndPoint addr); + private: DISALLOW_COPY_AND_ASSIGN(QuicConfigPeer); };
diff --git a/net/quic/test_tools/quic_crypto_server_config_peer.cc b/net/quic/test_tools/quic_crypto_server_config_peer.cc index 28c67306..12ff38f 100644 --- a/net/quic/test_tools/quic_crypto_server_config_peer.cc +++ b/net/quic/test_tools/quic_crypto_server_config_peer.cc
@@ -175,15 +175,15 @@ QuicWallTime::FromUNIXSeconds(seconds)); } -const string QuicCryptoServerConfigPeer::CompressChain( +string QuicCryptoServerConfigPeer::CompressChain( QuicCompressedCertsCache* compressed_certs_cache, const scoped_refptr<ProofSource::Chain>& chain, const string& client_common_set_hashes, const string& client_cached_cert_hashes, const CommonCertSets* common_sets) { - return server_config_->CompressChain(compressed_certs_cache, chain, - client_common_set_hashes, - client_cached_cert_hashes, common_sets); + return QuicCryptoServerConfig::CompressChain( + compressed_certs_cache, chain, client_common_set_hashes, + client_cached_cert_hashes, common_sets); } uint32_t QuicCryptoServerConfigPeer::source_address_token_future_secs() {
diff --git a/net/quic/test_tools/quic_crypto_server_config_peer.h b/net/quic/test_tools/quic_crypto_server_config_peer.h index 1341a49..995d64e7 100644 --- a/net/quic/test_tools/quic_crypto_server_config_peer.h +++ b/net/quic/test_tools/quic_crypto_server_config_peer.h
@@ -81,7 +81,7 @@ void SelectNewPrimaryConfig(int seconds); - const std::string CompressChain( + static std::string CompressChain( QuicCompressedCertsCache* compressed_certs_cache, const scoped_refptr<ProofSource::Chain>& chain, const std::string& client_common_set_hashes,
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc index 97a3997..5cb4fbb 100644 --- a/net/socket/ssl_client_socket_impl.cc +++ b/net/socket/ssl_client_socket_impl.cc
@@ -81,7 +81,7 @@ // Token Binding ProtocolVersions supported. const uint8_t kTbProtocolVersionMajor = 0; -const uint8_t kTbProtocolVersionMinor = 6; +const uint8_t kTbProtocolVersionMinor = 8; const uint8_t kTbMinProtocolVersionMajor = 0; const uint8_t kTbMinProtocolVersionMinor = 6;
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc index ad14934..d390c1b 100644 --- a/net/socket/ssl_server_socket_unittest.cc +++ b/net/socket/ssl_server_socket_unittest.cc
@@ -455,8 +455,9 @@ ReadTestKey(private_key_file_name); ASSERT_TRUE(key); - client_ssl_config_.client_private_key = WrapOpenSSLPrivateKey( - crypto::ScopedEVP_PKEY(EVP_PKEY_up_ref(key->key()))); + EVP_PKEY_up_ref(key->key()); + client_ssl_config_.client_private_key = + WrapOpenSSLPrivateKey(crypto::ScopedEVP_PKEY(key->key())); } void ConfigureClientCertsForServer() {
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc index 461d0184..ffa5dad2 100644 --- a/net/spdy/spdy_framer.cc +++ b/net/spdy/spdy_framer.cc
@@ -90,6 +90,17 @@ *parent_stream_id = packed & 0x7fffffff; } +// Creates a SpdyFramerDecoderAdapter if flags indicate that one should be +// used. This code is isolated to hopefully make merging into Chromium easier. +std::unique_ptr<SpdyFramerDecoderAdapter> DecoderAdapterFactory( + SpdyFramer* outer) { + if (FLAGS_use_nested_spdy_framer_decoder) { + DVLOG(1) << "Creating NestedSpdyFramerDecoder."; + return CreateNestedSpdyFramerDecoder(outer); + } + return nullptr; +} + struct DictionaryIds { DictionaryIds() : v3_dictionary_id( @@ -172,7 +183,8 @@ return true; } -SpdyFramer::SpdyFramer(SpdyMajorVersion version, bool choose_decoder) +SpdyFramer::SpdyFramer(SpdyMajorVersion version, + SpdyFramer::DecoderAdapterFactoryFn adapter_factory) : current_frame_buffer_(kControlFrameBufferSize), expect_continuation_(0), visitor_(NULL), @@ -192,16 +204,13 @@ "Our send limit should be at most our receive limit"); Reset(); - if (choose_decoder && version == HTTP2) { - // Another case will be added, hence the nested if blocks... - if (FLAGS_use_nested_spdy_framer_decoder) { - DVLOG(1) << "Creating NestedSpdyFramerDecoder."; - decoder_adapter_.reset(CreateNestedSpdyFramerDecoder(this)); - } + if (version == HTTP2 && adapter_factory != nullptr) { + decoder_adapter_ = adapter_factory(this); } } -SpdyFramer::SpdyFramer(SpdyMajorVersion version) : SpdyFramer(version, true) {} +SpdyFramer::SpdyFramer(SpdyMajorVersion version) + : SpdyFramer(version, &DecoderAdapterFactory) {} SpdyFramer::~SpdyFramer() { if (header_compressor_.get()) {
diff --git a/net/spdy/spdy_framer.h b/net/spdy/spdy_framer.h index b5293e7..d9219b4 100644 --- a/net/spdy/spdy_framer.h +++ b/net/spdy/spdy_framer.h
@@ -355,6 +355,11 @@ LAST_ERROR, // Must be the last entry in the enum. }; + // Typedef for a function used to create SpdyFramerDecoderAdapter's. + // Defined in support of evaluating an alternate HTTP/2 decoder. + typedef std::unique_ptr<SpdyFramerDecoderAdapter> (*DecoderAdapterFactoryFn)( + SpdyFramer* outer); + // Constant for invalid (or unknown) stream IDs. static const SpdyStreamId kInvalidStream; @@ -377,8 +382,9 @@ explicit SpdyFramer(SpdyMajorVersion version); // Used recursively from the above constructor in order to support - // instantiating a SpdyFramerDecoderAdapter selected via flags. - SpdyFramer(SpdyMajorVersion version, bool choose_decoder); + // instantiating a SpdyFramerDecoderAdapter selected via flags or some other + // means. + SpdyFramer(SpdyMajorVersion version, DecoderAdapterFactoryFn adapter_factory); virtual ~SpdyFramer();
diff --git a/net/spdy/spdy_framer_decoder_adapter.cc b/net/spdy/spdy_framer_decoder_adapter.cc index 5e7ddb35..52057e2 100644 --- a/net/spdy/spdy_framer_decoder_adapter.cc +++ b/net/spdy/spdy_framer_decoder_adapter.cc
@@ -197,7 +197,7 @@ public: explicit NestedSpdyFramerDecoder(SpdyFramer* outer) - : framer_(HTTP2, false), outer_(outer) { + : framer_(HTTP2, nullptr), outer_(outer) { DVLOG(1) << PRETTY_THIS; } ~NestedSpdyFramerDecoder() override { DVLOG(1) << PRETTY_THIS; } @@ -254,8 +254,10 @@ std::unique_ptr<SpdyFramerVisitorAdapter> visitor_adapter_; }; -SpdyFramerDecoderAdapter* CreateNestedSpdyFramerDecoder(SpdyFramer* outer) { - return new NestedSpdyFramerDecoder(outer); +std::unique_ptr<SpdyFramerDecoderAdapter> CreateNestedSpdyFramerDecoder( + SpdyFramer* outer) { + return std::unique_ptr<SpdyFramerDecoderAdapter>( + new NestedSpdyFramerDecoder(outer)); } } // namespace net
diff --git a/net/spdy/spdy_framer_decoder_adapter.h b/net/spdy/spdy_framer_decoder_adapter.h index 1e07264..c20bb8d 100644 --- a/net/spdy/spdy_framer_decoder_adapter.h +++ b/net/spdy/spdy_framer_decoder_adapter.h
@@ -7,7 +7,10 @@ #include <stddef.h> +#include <memory> + #include "base/strings/string_piece.h" +#include "net/spdy/hpack/hpack_header_table.h" #include "net/spdy/spdy_alt_svc_wire_format.h" #include "net/spdy/spdy_framer.h" #include "net/spdy/spdy_headers_handler_interface.h" @@ -78,8 +81,11 @@ // Create an instance of NestedSpdyFramerDecoder, which implements // SpdyFramerDecoderAdapter, delegating to a SpdyFramer instance that will -// actually perform the decoding (when requested via ProcessInput). -SpdyFramerDecoderAdapter* CreateNestedSpdyFramerDecoder(SpdyFramer* outer); +// actually perform the decoding (when requested via ProcessInput). This allows +// us to test the SpdyFramerDecoderAdapter mechanism without changing the type +// of decoder that is used. +std::unique_ptr<SpdyFramerDecoderAdapter> CreateNestedSpdyFramerDecoder( + SpdyFramer* outer); // SpdyFramerVisitorInterface::OnError needs the original SpdyFramer* to // pass to the visitor (really a listener). This implementation takes care of
diff --git a/net/ssl/openssl_client_key_store.cc b/net/ssl/openssl_client_key_store.cc index 9b1b876..fb1b172a 100644 --- a/net/ssl/openssl_client_key_store.cc +++ b/net/ssl/openssl_client_key_store.cc
@@ -39,16 +39,18 @@ } OpenSSLClientKeyStore::KeyPair::KeyPair(EVP_PKEY* pub_key, EVP_PKEY* priv_key) - : public_key(EVP_PKEY_up_ref(pub_key)), - private_key(EVP_PKEY_up_ref(priv_key)) { + : public_key(pub_key), private_key(priv_key) { + EVP_PKEY_up_ref(pub_key); + EVP_PKEY_up_ref(priv_key); } OpenSSLClientKeyStore::KeyPair::~KeyPair() { } OpenSSLClientKeyStore::KeyPair::KeyPair(const KeyPair& other) - : public_key(EVP_PKEY_up_ref(other.public_key.get())), - private_key(EVP_PKEY_up_ref(other.private_key.get())) { + : public_key(other.public_key.get()), private_key(other.private_key.get()) { + EVP_PKEY_up_ref(public_key.get()); + EVP_PKEY_up_ref(private_key.get()); } void OpenSSLClientKeyStore::KeyPair::operator=(KeyPair other) { @@ -109,8 +111,8 @@ if (index < 0) return crypto::ScopedEVP_PKEY(); - return crypto::ScopedEVP_PKEY( - EVP_PKEY_up_ref(pairs_[index].private_key.get())); + EVP_PKEY_up_ref(pairs_[index].private_key.get()); + return crypto::ScopedEVP_PKEY(pairs_[index].private_key.get()); } void OpenSSLClientKeyStore::Flush() {
diff --git a/net/ssl/token_binding.cc b/net/ssl/token_binding.cc index 0c6dd81..63fc9db 100644 --- a/net/ssl/token_binding.cc +++ b/net/ssl/token_binding.cc
@@ -6,6 +6,7 @@ #include <openssl/bytestring.h> #include <openssl/ec.h> +#include <openssl/ec_key.h> #include <openssl/evp.h> #include <openssl/mem.h> @@ -18,16 +19,23 @@ namespace { +const size_t kUncompressedPointLen = 65; + bool BuildTokenBindingID(crypto::ECPrivateKey* key, CBB* out) { EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key->key()); DCHECK(ec_key); + uint8_t point_buf[kUncompressedPointLen]; + if (EC_POINT_point2oct( + EC_KEY_get0_group(ec_key), EC_KEY_get0_public_key(ec_key), + POINT_CONVERSION_UNCOMPRESSED, point_buf, kUncompressedPointLen, + NULL) != kUncompressedPointLen) { + return false; + } CBB ec_point; return CBB_add_u8(out, TB_PARAM_ECDSAP256) && CBB_add_u8_length_prefixed(out, &ec_point) && - EC_POINT_point2cbb(&ec_point, EC_KEY_get0_group(ec_key), - EC_KEY_get0_public_key(ec_key), - POINT_CONVERSION_UNCOMPRESSED, nullptr) && + CBB_add_bytes(&ec_point, point_buf + 1, kUncompressedPointLen - 1) && CBB_flush(out); } @@ -162,12 +170,20 @@ bool VerifyEKMSignature(base::StringPiece ec_point, base::StringPiece signature, base::StringPiece ekm) { + if (ec_point.size() != kUncompressedPointLen - 1) + return false; + uint8_t x9_62_ec_point[kUncompressedPointLen]; + x9_62_ec_point[0] = 4; + memcpy(x9_62_ec_point + 1, ec_point.data(), kUncompressedPointLen - 1); crypto::ScopedEC_Key key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); EC_KEY* keyp = key.get(); - const uint8_t* ec_point_data = - reinterpret_cast<const uint8_t*>(ec_point.data()); - if (o2i_ECPublicKey(&keyp, &ec_point_data, ec_point.size()) != key.get()) + crypto::ScopedEC_POINT pub_key(EC_POINT_new(EC_KEY_get0_group(keyp))); + if (!EC_POINT_oct2point(EC_KEY_get0_group(keyp), pub_key.get(), + x9_62_ec_point, kUncompressedPointLen, nullptr) || + !EC_KEY_set_public_key(keyp, pub_key.get())) { return false; + } + crypto::ScopedECDSA_SIG sig(RawToECDSA_SIG(keyp, signature)); if (!sig) return false;
diff --git a/net/tools/cachetool/cachetool.cc b/net/tools/cachetool/cachetool.cc index fde1ffc..c5ac94f 100644 --- a/net/tools/cachetool/cachetool.cc +++ b/net/tools/cachetool/cachetool.cc
@@ -9,6 +9,7 @@ #include "base/command_line.h" #include "base/files/file_path.h" #include "base/logging.h" +#include "base/macros.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" @@ -24,48 +25,295 @@ namespace { -int kResponseInfoIndex = 0; +constexpr int kResponseInfoIndex = 0; -// Get the cache's size. -bool GetSize(Backend* cache_backend) { - net::TestCompletionCallback cb; - int rv = cache_backend->CalculateSizeOfAllEntries(cb.callback()); - rv = cb.GetResult(rv); - if (rv < 0) { - std::cerr << "Couldn't get cache size." << std::endl; - return false; - } - std::cout << rv << std::endl; - return true; +const char* const kCommandNames[] = { + "stop", "get_size", "list_keys", "get_stream_for_key", + "delete_stream", "delete_key", "update_raw_headers", +}; + +// Prints the command line help. +void PrintHelp() { + std::cout << "cachetool <cache_path> <cache_backend_type> <subcommand> " + << std::endl + << std::endl; + std::cout << "Available cache backend types: simple, blockfile" << std::endl; + std::cout << "Available subcommands:" << std::endl; + std::cout << " batch: Starts cachetool to process serialized commands " + << "passed down by the standard input and return commands output " + << "in the stdout until the stop command is received." << std::endl; + std::cout << " delete_key <key>: Delete key from cache." << std::endl; + std::cout << " delete_stream <key> <index>: Delete a particular stream of a" + << " given key." << std::endl; + std::cout << " get_size: Calculate the total size of the cache in bytes." + << std::endl; + std::cout << " get_stream <key> <index>: Print a particular stream for a" + << " given key." << std::endl; + std::cout << " list_keys: List all keys in the cache." << std::endl; + std::cout << " update_raw_headers <key>: Update stdin as the key's raw " + << "response headers." << std::endl; + std::cout << " stop: Verify that the cache can be opened and return, " + << "confirming the cache exists and is of the right type." + << std::endl; + std::cout << "Expected values of <index> are:" << std::endl; + std::cout << " 0 (HTTP response headers)" << std::endl; + std::cout << " 1 (transport encoded content)" << std::endl; + std::cout << " 2 (compiled content)" << std::endl; } -// Print all of a cache's keys to stdout. -bool ListKeys(Backend* cache_backend) { +// Generic command input/output. +class CommandMarshal { + public: + CommandMarshal(Backend* cache_backend) + : command_failed_(false), cache_backend_(cache_backend){}; + virtual ~CommandMarshal(){}; + + // Reads the next command's name to execute. + virtual std::string ReadCommandName() = 0; + + // Reads the next parameter as an integer. + virtual int ReadInt() = 0; + + // Reads the next parameter as stream index. + int ReadStreamIndex() { + if (has_failed()) + return -1; + int index = ReadInt(); + if (index < 0 || index > 2) { + ReturnFailure("Invalid stream index."); + return -1; + } + return index; + } + + // Reads the next parameter as an string. + virtual std::string ReadString() = 0; + + // Reads the next parameter from stdin as string. + virtual std::string ReadBufferedString() = 0; + + // Communicates back an integer. + virtual void ReturnInt(int integer) = 0; + + // Communicates back a string. + virtual void ReturnString(const std::string& string) = 0; + + // Communicates back a buffer. + virtual void ReturnBuffer(net::GrowableIOBuffer* buffer) = 0; + + // Communicates back command failure. + virtual void ReturnFailure(const std::string& error_msg) = 0; + + // Communicates back command success. + virtual void ReturnSuccess() { DCHECK(!command_failed_); }; + + // Returns whether the command has failed. + inline bool has_failed() { return command_failed_; } + + // Returns the opened cache backend. + Backend* cache_backend() { return cache_backend_; } + + protected: + bool command_failed_; + Backend* const cache_backend_; +}; + +// Command line input/output that is user readable. +class ProgramArgumentCommandMarshal final : public CommandMarshal { + public: + ProgramArgumentCommandMarshal(Backend* cache_backend, + base::CommandLine::StringVector args) + : CommandMarshal(cache_backend), command_line_args_(args), args_id_(0) {} + + // Implements CommandMarshal. + std::string ReadCommandName() override { + if (args_id_ == 0) + return ReadString(); + else if (args_id_ == command_line_args_.size()) + return "stop"; + else if (!has_failed()) + ReturnFailure("Command line arguments to long."); + return ""; + } + + // Implements CommandMarshal. + int ReadInt() override { + std::string interger_str = ReadString(); + int interger = -1; + if (!base::StringToInt(interger_str, &interger)) { + ReturnFailure("Couldn't parse integer."); + return 0; + } + return interger; + } + + // Implements CommandMarshal. + std::string ReadString() override { + if (args_id_ < command_line_args_.size()) + return command_line_args_[args_id_++]; + if (!has_failed()) + ReturnFailure("Command line arguments to short."); + return ""; + } + + // Implements CommandMarshal. + std::string ReadBufferedString() override { + std::ostringstream raw_headers_stream; + for (std::string line; std::getline(std::cin, line);) + raw_headers_stream << line << std::endl; + return raw_headers_stream.str(); + } + + // Implements CommandMarshal. + void ReturnInt(int integer) override { + DCHECK(!has_failed()); + std::cout << integer << std::endl; + } + + // Implements CommandMarshal. + void ReturnString(const std::string& string) override { + DCHECK(!has_failed()); + std::cout << string << std::endl; + } + + // Implements CommandMarshal. + void ReturnBuffer(net::GrowableIOBuffer* buffer) override { + DCHECK(!has_failed()); + std::cout.write(buffer->data(), buffer->offset()); + } + + // Implements CommandMarshal. + void ReturnFailure(const std::string& error_msg) override { + DCHECK(!has_failed()); + std::cerr << error_msg << std::endl; + command_failed_ = true; + } + + private: + const base::CommandLine::StringVector command_line_args_; + size_t args_id_; +}; + +// Online command input/output that receives pickled commands from stdin and +// returns their results back in stdout. Send the stop command to properly exit +// cachetool's main loop. +class StreamCommandMarshal final : public CommandMarshal { + public: + StreamCommandMarshal(Backend* cache_backend) + : CommandMarshal(cache_backend) {} + + // Implements CommandMarshal. + std::string ReadCommandName() override { + if (has_failed()) + return ""; + std::cout.flush(); + size_t command_id = static_cast<size_t>(std::cin.get()); + if (command_id >= arraysize(kCommandNames)) { + ReturnFailure("Unknown command."); + return ""; + } + return kCommandNames[command_id]; + } + + // Implements CommandMarshal. + int ReadInt() override { + if (has_failed()) + return -1; + int integer = -1; + std::cin.read(reinterpret_cast<char*>(&integer), sizeof(integer)); + return integer; + } + + // Implements CommandMarshal. + std::string ReadString() override { + if (has_failed()) + return ""; + int string_size = ReadInt(); + if (string_size <= 0) { + if (string_size < 0) + ReturnFailure("Size of string is negative."); + return ""; + } + std::vector<char> tmp_buffer(string_size + 1); + std::cin.read(&tmp_buffer[0], string_size); + tmp_buffer[string_size] = 0; + return std::string(&tmp_buffer[0], string_size); + } + + // Implements CommandMarshal. + std::string ReadBufferedString() override { return ReadString(); } + + // Implements CommandMarshal. + void ReturnInt(int integer) override { + DCHECK(!command_failed_); + std::cout.write(reinterpret_cast<char*>(&integer), sizeof(integer)); + } + + // Implements CommandMarshal. + void ReturnString(const std::string& string) override { + ReturnInt(string.size()); + std::cout.write(string.c_str(), string.size()); + } + + // Implements CommandMarshal. + void ReturnBuffer(net::GrowableIOBuffer* buffer) override { + ReturnInt(buffer->offset()); + std::cout.write(buffer->StartOfBuffer(), buffer->offset()); + } + + // Implements CommandMarshal. + void ReturnFailure(const std::string& error_msg) override { + ReturnString(error_msg); + command_failed_ = true; + } + + // Implements CommandMarshal. + void ReturnSuccess() override { ReturnInt(0); } +}; + +// Gets the cache's size. +void GetSize(CommandMarshal* command_marshal) { + net::TestCompletionCallback cb; + int rv = command_marshal->cache_backend()->CalculateSizeOfAllEntries( + cb.callback()); + rv = cb.GetResult(rv); + if (rv < 0) + return command_marshal->ReturnFailure("Couldn't get cache size."); + command_marshal->ReturnSuccess(); + command_marshal->ReturnInt(rv); +} + +// Prints all of a cache's keys to stdout. +bool ListKeys(CommandMarshal* command_marshal) { std::unique_ptr<Backend::Iterator> entry_iterator = - cache_backend->CreateIterator(); + command_marshal->cache_backend()->CreateIterator(); Entry* entry = nullptr; net::TestCompletionCallback cb; int rv = entry_iterator->OpenNextEntry(&entry, cb.callback()); + command_marshal->ReturnSuccess(); while (cb.GetResult(rv) == net::OK) { std::string url = entry->GetKey(); - std::cout << url << std::endl; + command_marshal->ReturnString(url); entry->Close(); entry = nullptr; rv = entry_iterator->OpenNextEntry(&entry, cb.callback()); } + command_marshal->ReturnString(""); return true; } -// Get a key's stream to a buffer. +// Gets a key's stream to a buffer. scoped_refptr<net::GrowableIOBuffer> GetStreamForKeyBuffer( - Backend* cache_backend, + CommandMarshal* command_marshal, const std::string& key, int index) { + DCHECK(!command_marshal->has_failed()); Entry* cache_entry; net::TestCompletionCallback cb; - int rv = cache_backend->OpenEntry(key, &cache_entry, cb.callback()); + int rv = command_marshal->cache_backend()->OpenEntry(key, &cache_entry, + cb.callback()); if (cb.GetResult(rv) != net::OK) { - std::cerr << "Couldn't find key's entry." << std::endl; + command_marshal->ReturnFailure("Couldn't find key's entry."); return nullptr; } @@ -79,7 +327,7 @@ rv = cb.GetResult(rv); if (rv < 0) { cache_entry->Close(); - std::cerr << "Stream read error." << std::endl; + command_marshal->ReturnFailure("Stream read error."); return nullptr; } buffer->set_offset(buffer->offset() + rv); @@ -91,138 +339,134 @@ return buffer; } -// Print a key's stream to stdout. -bool GetStreamForKey(Backend* cache_backend, - const std::string& key, - int index) { +// Prints a key's stream to stdout. +void GetStreamForKey(CommandMarshal* command_marshal) { + std::string key = command_marshal->ReadString(); + int index = command_marshal->ReadInt(); + if (command_marshal->has_failed()) + return; scoped_refptr<net::GrowableIOBuffer> buffer( - GetStreamForKeyBuffer(cache_backend, key, index)); - if (!buffer) - return false; + GetStreamForKeyBuffer(command_marshal, key, index)); + if (command_marshal->has_failed()) + return; if (index == kResponseInfoIndex) { net::HttpResponseInfo response_info; bool truncated_response_info = false; net::HttpCache::ParseResponseInfo(buffer->StartOfBuffer(), buffer->offset(), &response_info, &truncated_response_info); - if (truncated_response_info) { - std::cerr << "Truncated HTTP response." << std::endl; - return false; - } - std::cout << net::HttpUtil::ConvertHeadersBackToHTTPResponse( - response_info.headers->raw_headers()); + if (truncated_response_info) + return command_marshal->ReturnFailure("Truncated HTTP response."); + command_marshal->ReturnSuccess(); + command_marshal->ReturnString( + net::HttpUtil::ConvertHeadersBackToHTTPResponse( + response_info.headers->raw_headers())); } else { - std::cout.write(buffer->StartOfBuffer(), buffer->offset()); + command_marshal->ReturnSuccess(); + command_marshal->ReturnBuffer(buffer.get()); } - return true; } -// Set stdin as the key's raw response headers. -bool UpdateRawResponseHeaders(Backend* cache_backend, const std::string& key) { +// Sets stdin as the key's raw response headers. +void UpdateRawResponseHeaders(CommandMarshal* command_marshal) { + std::string key = command_marshal->ReadString(); + std::string raw_headers = command_marshal->ReadBufferedString(); + if (command_marshal->has_failed()) + return; scoped_refptr<net::GrowableIOBuffer> buffer( - GetStreamForKeyBuffer(cache_backend, key, kResponseInfoIndex)); - if (!buffer) - return false; + GetStreamForKeyBuffer(command_marshal, key, kResponseInfoIndex)); + if (command_marshal->has_failed()) + return; net::HttpResponseInfo response_info; bool truncated_response_info = false; net::HttpCache::ParseResponseInfo(buffer->StartOfBuffer(), buffer->offset(), &response_info, &truncated_response_info); - if (truncated_response_info) { - std::cerr << "Truncated HTTP response." << std::endl; - return false; - } - std::ostringstream raw_headers_stream; - for (std::string line; std::getline(std::cin, line);) - raw_headers_stream << line << std::endl; - response_info.headers = - new net::HttpResponseHeaders(raw_headers_stream.str()); + if (truncated_response_info) + return command_marshal->ReturnFailure("Truncated HTTP response."); + + response_info.headers = new net::HttpResponseHeaders(raw_headers); scoped_refptr<net::PickledIOBuffer> data(new net::PickledIOBuffer()); response_info.Persist(data->pickle(), false, false); data->Done(); Entry* cache_entry; net::TestCompletionCallback cb; - int rv = cache_backend->OpenEntry(key, &cache_entry, cb.callback()); + int rv = command_marshal->cache_backend()->OpenEntry(key, &cache_entry, + cb.callback()); CHECK(cb.GetResult(rv) == net::OK); int data_len = data->pickle()->size(); rv = cache_entry->WriteData(kResponseInfoIndex, 0, data.get(), data_len, cb.callback(), true); - if (cb.GetResult(rv) != data_len) { - std::cerr << "Couldn't write headers." << std::endl; - return false; - } + if (cb.GetResult(rv) != data_len) + return command_marshal->ReturnFailure("Couldn't write headers."); + command_marshal->ReturnSuccess(); cache_entry->Close(); - return true; } -// Delete a specified key stream from the cache. -bool DeleteStreamForKey(Backend* cache_backend, - const std::string& key, - int index) { +// Deletes a specified key stream from the cache. +void DeleteStreamForKey(CommandMarshal* command_marshal) { + std::string key = command_marshal->ReadString(); + int index = command_marshal->ReadInt(); + if (command_marshal->has_failed()) + return; Entry* cache_entry; net::TestCompletionCallback cb; - int rv = cache_backend->OpenEntry(key, &cache_entry, cb.callback()); - if (cb.GetResult(rv) != net::OK) { - std::cerr << "Couldn't find key's entry." << std::endl; - return false; - } + int rv = command_marshal->cache_backend()->OpenEntry(key, &cache_entry, + cb.callback()); + if (cb.GetResult(rv) != net::OK) + return command_marshal->ReturnFailure("Couldn't find key's entry."); scoped_refptr<net::StringIOBuffer> buffer(new net::StringIOBuffer("")); rv = cache_entry->WriteData(index, 0, buffer.get(), 0, cb.callback(), true); - if (cb.GetResult(rv) != 0) { - std::cerr << "Couldn't delete key stream." << std::endl; - return false; - } + if (cb.GetResult(rv) != net::OK) + return command_marshal->ReturnFailure("Couldn't delete key stream."); + command_marshal->ReturnSuccess(); cache_entry->Close(); - return true; } -// Delete a specified key from the cache. -bool DeleteKey(Backend* cache_backend, const std::string& key) { +// Deletes a specified key from the cache. +void DeleteKey(CommandMarshal* command_marshal) { + std::string key = command_marshal->ReadString(); + if (command_marshal->has_failed()) + return; net::TestCompletionCallback cb; - int rv = cache_backend->DoomEntry(key, cb.callback()); - if (cb.GetResult(rv) != net::OK) { - std::cerr << "Couldn't delete key." << std::endl; - return false; - } - return true; + int rv = command_marshal->cache_backend()->DoomEntry(key, cb.callback()); + if (cb.GetResult(rv) != net::OK) + command_marshal->ReturnFailure("Couldn't delete key."); + else + command_marshal->ReturnSuccess(); } -// Parse stream index from command line argument string. -int ParseStreamIndex(const std::string& index_arg) { - int index = -1; - if (!base::StringToInt(index_arg, &index)) { - std::cerr << "<index> must be an integer." << std::endl; - return -1; - } else if (index < 0 || index > 2) { - std::cerr << "Invalid stream index." << std::endl; - return -1; +// Executes all command from the |command_marshal|. +bool ExecuteCommands(CommandMarshal* command_marshal) { + while (!command_marshal->has_failed()) { + std::string subcommand(command_marshal->ReadCommandName()); + if (command_marshal->has_failed()) + break; + if (subcommand == "stop") { + command_marshal->ReturnSuccess(); + return true; + } else if (subcommand == "batch") { + StreamCommandMarshal stream_command_marshal( + command_marshal->cache_backend()); + return ExecuteCommands(&stream_command_marshal); + } else if (subcommand == "delete_key") { + DeleteKey(command_marshal); + } else if (subcommand == "delete_stream") { + DeleteStreamForKey(command_marshal); + } else if (subcommand == "get_size") { + GetSize(command_marshal); + } else if (subcommand == "get_stream") { + GetStreamForKey(command_marshal); + } else if (subcommand == "list_keys") { + ListKeys(command_marshal); + } else if (subcommand == "update_raw_headers") { + UpdateRawResponseHeaders(command_marshal); + } else { + // The wrong subcommand is originated from the command line. + command_marshal->ReturnFailure("Unknown command."); + PrintHelp(); + } } - return index; -} - -// Print the command line help. -void PrintHelp() { - std::cout << "cachetool <cache_path> <cache_backend_type> <subcommand> ..." - << std::endl - << std::endl; - std::cout << "Available cache backend types: simple, blockfile" << std::endl; - std::cout << "Available subcommands:" << std::endl; - std::cout << " delete_key <key>: Delete key from cache." << std::endl; - std::cout << " delete_stream <key> <index>: Delete a particular stream of a" - << " given key." << std::endl; - std::cout << " get_size: Calculate the total size of the cache in bytes." - << std::endl; - std::cout << " get_stream <key> <index>: Print a particular stream for a" - << " given key." << std::endl; - std::cout << " list_keys: List all keys in the cache." << std::endl; - std::cout << " update_raw_headers <key>: Update stdin as the key's raw " - << "response headers." << std::endl; - std::cout << " validate: Verify that the cache can be opened and return, " - << "confirming the cache exists and is of the right type." - << std::endl; - std::cout << "Expected values of <index> are:" << std::endl; - std::cout << " 0 (HTTP response headers)" << std::endl; - std::cout << " 1 (transport encoded content)" << std::endl; - std::cout << " 2 (compiled content)" << std::endl; + return false; } } // namespace @@ -242,7 +486,6 @@ base::FilePath cache_path(args[0]); std::string cache_backend_type(args[1]); - std::string subcommand(args[2]); net::BackendType backend_type; if (cache_backend_type == "simple") { @@ -265,34 +508,13 @@ return 1; } - bool successful_command; - if (subcommand == "delete_key" && args.size() == 4) { - successful_command = DeleteKey(cache_backend.get(), args[3]); - } else if (subcommand == "delete_stream" && args.size() == 5) { - int index = ParseStreamIndex(args[4]); - if (index < 0) - return 1; - successful_command = - DeleteStreamForKey(cache_backend.get(), args[3], index); - } else if (subcommand == "get_size" && args.size() == 3) { - successful_command = GetSize(cache_backend.get()); - } else if (subcommand == "get_stream" && args.size() == 5) { - int index = ParseStreamIndex(args[4]); - if (index < 0) - return 1; - successful_command = GetStreamForKey(cache_backend.get(), args[3], index); - } else if (subcommand == "list_keys" && args.size() == 3) { - successful_command = ListKeys(cache_backend.get()); - } else if (subcommand == "update_raw_headers" && args.size() == 4) { - successful_command = UpdateRawResponseHeaders(cache_backend.get(), args[3]); - } else if (subcommand == "validate" && args.size() == 3) { - successful_command = true; - } else { - successful_command = false; - PrintHelp(); - } + ProgramArgumentCommandMarshal program_argument_marshal( + cache_backend.get(), + base::CommandLine::StringVector(args.begin() + 2, args.end())); + bool successful_commands = ExecuteCommands(&program_argument_marshal); + base::RunLoop().RunUntilIdle(); cache_backend = nullptr; base::RunLoop().RunUntilIdle(); - return !successful_command; + return !successful_commands; }
diff --git a/net/tools/cert_verify_tool/cert_verify_tool.cc b/net/tools/cert_verify_tool/cert_verify_tool.cc index 794fb5e..210f310 100644 --- a/net/tools/cert_verify_tool/cert_verify_tool.cc +++ b/net/tools/cert_verify_tool/cert_verify_tool.cc
@@ -11,6 +11,7 @@ #include "base/time/time.h" #include "net/tools/cert_verify_tool/cert_verify_tool_util.h" #include "net/tools/cert_verify_tool/verify_using_cert_verify_proc.h" +#include "net/tools/cert_verify_tool/verify_using_path_builder.h" namespace { @@ -24,6 +25,13 @@ std::cerr << " --intermediates=<certs path>\n"; std::cerr << " <certs path> should be a file containing a single DER cert or " "one or more PEM CERTIFICATE blocks.\n"; + std::cerr << " --time=<time>\n"; + std::cerr << " Use <time> instead of the current system time. <time> is " + "interpreted in local time if a timezone is not specified.\n"; + std::cerr << " Many common formats are supported, such as:\n"; + std::cerr << " 1994-11-15 12:45:26 GMT\n"; + std::cerr << " Tue, 15 Nov 1994 12:45:26 GMT\n"; + std::cerr << " Nov 15 12:45:26 1994 GMT\n"; std::cerr << " --dump=<file prefix>\n"; std::cerr << " Dumps the verified chain to PEM files starting with <file " "prefix>.\n"; @@ -59,6 +67,17 @@ return 1; } + base::Time verify_time; + std::string time_flag = command_line.GetSwitchValueASCII("time"); + if (!time_flag.empty()) { + if (!base::Time::FromString(time_flag.c_str(), &verify_time)) { + std::cerr << "Error parsing --time flag\n"; + return 1; + } + } else { + verify_time = base::Time::Now(); + } + base::FilePath roots_path = command_line.GetSwitchValuePath("roots"); base::FilePath intermediates_path = command_line.GetSwitchValuePath("intermediates"); @@ -82,9 +101,20 @@ } std::cout << "CertVerifyProc:\n"; - bool verify_ok = VerifyUsingCertVerifyProc(target_der_cert, hostname, - intermediate_der_certs, - root_der_certs, dump_prefix_path); + bool cert_verify_proc_ok = true; + if (!time_flag.empty()) { + std::cerr << "ERROR: --time is not supported with CertVerifyProc, " + "skipping.\n"; + } else { + cert_verify_proc_ok = VerifyUsingCertVerifyProc( + target_der_cert, hostname, intermediate_der_certs, root_der_certs, + dump_prefix_path); + } - return verify_ok ? 0 : 1; + std::cout << "\nCertPathBuilder:\n"; + bool path_builder_ok = + VerifyUsingPathBuilder(target_der_cert, intermediate_der_certs, + root_der_certs, verify_time, dump_prefix_path); + + return (cert_verify_proc_ok && path_builder_ok) ? 0 : 1; }
diff --git a/net/tools/cert_verify_tool/verify_using_path_builder.cc b/net/tools/cert_verify_tool/verify_using_path_builder.cc new file mode 100644 index 0000000..2520e6d0 --- /dev/null +++ b/net/tools/cert_verify_tool/verify_using_path_builder.cc
@@ -0,0 +1,192 @@ +// 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 "net/tools/cert_verify_tool/verify_using_path_builder.h" + +#include <iostream> + +#include "base/memory/ptr_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "crypto/sha2.h" +#include "net/base/net_errors.h" +#include "net/base/test_completion_callback.h" +#include "net/cert/internal/cert_issuer_source_aia.h" +#include "net/cert/internal/cert_issuer_source_static.h" +#include "net/cert/internal/parse_name.h" +#include "net/cert/internal/parsed_certificate.h" +#include "net/cert/internal/path_builder.h" +#include "net/cert/internal/signature_policy.h" +#include "net/cert/internal/trust_store.h" +#include "net/cert_net/cert_net_fetcher_impl.h" +#include "net/tools/cert_verify_tool/cert_verify_tool_util.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_context_builder.h" + +#if defined(OS_LINUX) +#include "net/proxy/proxy_config.h" +#include "net/proxy/proxy_config_service_fixed.h" +#endif + +namespace { + +std::string GetUserAgent() { + return "cert_verify_tool/0.1"; +} + +// Converts a base::Time::Exploded to a net::der::GeneralizedTime. +// TODO(mattm): This function exists in cast_cert_validator.cc also. Dedupe it? +net::der::GeneralizedTime ConvertExplodedTime( + const base::Time::Exploded& exploded) { + net::der::GeneralizedTime result; + result.year = exploded.year; + result.month = exploded.month; + result.day = exploded.day_of_month; + result.hours = exploded.hour; + result.minutes = exploded.minute; + result.seconds = exploded.second; + return result; +} + +// Dumps a chain of ParsedCertificate objects to a PEM file. +bool DumpParsedCertificateChain( + const base::FilePath& file_path, + const std::vector<scoped_refptr<net::ParsedCertificate>>& chain) { + std::vector<std::string> pem_encoded_chain; + for (const auto& cert : chain) { + std::string der_cert; + cert->der_cert().AsStringPiece().CopyToString(&der_cert); + std::string pem; + if (!net::X509Certificate::GetPEMEncodedFromDER(der_cert, &pem)) { + std::cerr << "ERROR: GetPEMEncodedFromDER failed\n"; + return false; + } + pem_encoded_chain.push_back(pem); + } + return WriteToFile(file_path, base::JoinString(pem_encoded_chain, "")); +} + +// Returns a hex-encoded sha256 of the DER-encoding of |cert|. +std::string FingerPrintParsedCertificate(const net::ParsedCertificate* cert) { + std::string hash = crypto::SHA256HashString(cert->der_cert().AsStringPiece()); + return base::HexEncode(hash.data(), hash.size()); +} + +// Returns a textual representation of the Subject of |cert|. +std::string SubjectFromParsedCertificate(const net::ParsedCertificate* cert) { + net::RDNSequence subject, issuer; + if (!net::ParseName(cert->tbs().subject_tlv, &subject)) + return std::string(); + std::string subject_str; + if (!net::ConvertToRFC2253(subject, &subject_str)) + return std::string(); + return subject_str; +} + +} // namespace + +// Verifies |target_der_cert| using CertPathBuilder. +bool VerifyUsingPathBuilder( + const CertInput& target_der_cert, + const std::vector<CertInput>& intermediate_der_certs, + const std::vector<CertInput>& root_der_certs, + const base::Time at_time, + const base::FilePath& dump_prefix_path) { + std::cout << "NOTE: CertPathBuilder does not currently use OS trust settings " + "(--roots must be specified).\n"; + std::cerr << "WARNING: --hostname is not yet verified with CertPathBuilder\n"; + + base::Time::Exploded exploded_time; + at_time.UTCExplode(&exploded_time); + net::der::GeneralizedTime time = ConvertExplodedTime(exploded_time); + + net::TrustStore trust_store; + for (const auto& der_cert : root_der_certs) { + scoped_refptr<net::ParsedCertificate> cert = + net::ParsedCertificate::CreateFromCertificateCopy(der_cert.der_cert, + {}); + if (!cert) + PrintCertError("ERROR: ParsedCertificate failed:", der_cert); + else + trust_store.AddTrustedCertificate(cert); + } + + net::CertIssuerSourceStatic intermediate_cert_issuer_source; + for (const auto& der_cert : intermediate_der_certs) { + scoped_refptr<net::ParsedCertificate> cert = + net::ParsedCertificate::CreateFromCertificateCopy(der_cert.der_cert, + {}); + if (!cert) + PrintCertError("ERROR: ParsedCertificate failed:", der_cert); + else + intermediate_cert_issuer_source.AddCert(cert); + } + + scoped_refptr<net::ParsedCertificate> target_cert = + net::ParsedCertificate::CreateFromCertificateCopy( + target_der_cert.der_cert, {}); + if (!target_cert) { + PrintCertError("ERROR: ParsedCertificate failed:", target_der_cert); + return false; + } + + // Verify the chain. + net::SimpleSignaturePolicy signature_policy(2048); + net::CertPathBuilder::Result result; + net::CertPathBuilder path_builder(target_cert, &trust_store, + &signature_policy, time, &result); + path_builder.AddCertIssuerSource(&intermediate_cert_issuer_source); + + // TODO(mattm): add command line flags to configure using CertIssuerSourceAia + // (similar to VERIFY_CERT_IO_ENABLED flag for CertVerifyProc). + net::URLRequestContextBuilder url_request_context_builder; + url_request_context_builder.set_user_agent(GetUserAgent()); +#if defined(OS_LINUX) + // On Linux, use a fixed ProxyConfigService, since the default one + // depends on glib. + // + // TODO(akalin): Remove this once http://crbug.com/146421 is fixed. + url_request_context_builder.set_proxy_config_service( + base::WrapUnique(new net::ProxyConfigServiceFixed(net::ProxyConfig()))); +#endif + std::unique_ptr<net::URLRequestContext> url_request_context = + url_request_context_builder.Build(); + net::CertNetFetcherImpl cert_net_fetcher(url_request_context.get()); + net::CertIssuerSourceAia aia_cert_issuer_source(&cert_net_fetcher); + path_builder.AddCertIssuerSource(&aia_cert_issuer_source); + + net::TestClosure callback; + net::CompletionStatus rv = path_builder.Run(callback.closure()); + + if (rv == net::CompletionStatus::ASYNC) { + DVLOG(1) << "waiting for async completion..."; + callback.WaitForResult(); + DVLOG(1) << "async completed."; + } + + std::cout << "CertPathBuilder best result: " + << net::ErrorToShortString(result.error()) << "\n"; + + for (size_t i = 0; i < result.paths.size(); ++i) { + std::cout << "path " << i << " " + << net::ErrorToShortString(result.paths[i]->error) + << ((result.best_result_index == i) ? " (best)" : "") << "\n"; + for (const auto& cert : result.paths[i]->path) { + std::cout << " " << FingerPrintParsedCertificate(cert.get()) << " " + << SubjectFromParsedCertificate(cert.get()) << "\n"; + } + } + + // TODO(mattm): add flag to dump all paths, not just the final one? + if (!dump_prefix_path.empty() && result.paths.size()) { + if (!DumpParsedCertificateChain( + dump_prefix_path.AddExtension( + FILE_PATH_LITERAL(".CertPathBuilder.pem")), + result.paths[result.best_result_index]->path)) { + return false; + } + } + + return result.error() == net::OK; +}
diff --git a/net/tools/cert_verify_tool/verify_using_path_builder.h b/net/tools/cert_verify_tool/verify_using_path_builder.h new file mode 100644 index 0000000..56980a98 --- /dev/null +++ b/net/tools/cert_verify_tool/verify_using_path_builder.h
@@ -0,0 +1,29 @@ +// 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 NET_TOOLS_CERT_VERIFY_TOOL_VERIFY_USING_PATH_BUILDER_H_ +#define NET_TOOLS_CERT_VERIFY_TOOL_VERIFY_USING_PATH_BUILDER_H_ + +#include <string> +#include <vector> + +namespace base { +class FilePath; +class Time; +} + +struct CertInput; + +// Verifies |target_der_cert| using CertPathBuilder. Returns true if the +// certificate verified successfully, false if it failed to verify or there was +// some other error. +// Informational messages will be printed to stdout/stderr as appropriate. +bool VerifyUsingPathBuilder( + const CertInput& target_der_cert, + const std::vector<CertInput>& intermediate_der_certs, + const std::vector<CertInput>& root_der_certs, + const base::Time at_time, + const base::FilePath& dump_prefix_path); + +#endif // NET_TOOLS_CERT_VERIFY_TOOL_VERIFY_USING_PATH_BUILDER_H_
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc index 381ebabd..38d2ed1 100644 --- a/net/tools/quic/end_to_end_test.cc +++ b/net/tools/quic/end_to_end_test.cc
@@ -153,26 +153,30 @@ // to do 0-RTT across incompatible versions. Chromium only supports // a single version at a time anyway. :) QuicVersionVector all_supported_versions = QuicSupportedVersions(); - QuicVersionVector version_buckets[4]; + QuicVersionVector version_buckets[5]; for (const QuicVersion version : all_supported_versions) { if (version <= QUIC_VERSION_25) { + // Versions: 25 // SPDY/4 version_buckets[0].push_back(version); - } else if (version <= QUIC_VERSION_32) { - // QUIC_VERSION_26 changes the kdf in a way that is incompatible with - // version negotiation across the version 26 boundary. + } else if (version <= QUIC_VERSION_30) { + // Versions: 26-30 + // v26 adds a hash of the expected leaf cert in the XLCT tag. version_buckets[1].push_back(version); - } else if (version <= QUIC_VERSION_33) { - // QUIC_VERSION_33 changes the kdf in a way that is incompatible with - // version negotiation across the version 33 boundary, by using the - // diversification nonce. + } else if (version <= QUIC_VERSION_32) { + // Versions: 31-32 + // v31 adds a hash of the CHLO into the proof signature. version_buckets[2].push_back(version); - } else { - // QUIC_VERSION_34 deprecates entropy and uses new ack and stop waiting - // wire formats, so it is incompatible with version negotiation across the - // version 34 boundary. + } else if (version <= QUIC_VERSION_33) { + // Versions: 33 + // v33 adds a diversification nonce into the hkdf. version_buckets[3].push_back(version); + } else { + // Versions: 34+ + // QUIC_VERSION_34 deprecates entropy and uses new ack and stop waiting + // wire formats. + version_buckets[4].push_back(version); } } @@ -299,7 +303,7 @@ EndToEndTest() : initialized_(false), server_address_(IPEndPoint(Loopback4(), 0)), - server_hostname_("example.com"), + server_hostname_("test.example.com"), server_started_(false), strike_register_no_startup_period_(false), chlo_multiplier_(0), @@ -341,9 +345,9 @@ } QuicTestClient* CreateQuicClient(QuicPacketWriterWrapper* writer) { - QuicTestClient* client = - new QuicTestClient(server_address_, server_hostname_, client_config_, - client_supported_versions_); + QuicTestClient* client = new QuicTestClient( + server_address_, server_hostname_, client_config_, + client_supported_versions_, CryptoTestUtils::ProofVerifierForTesting()); client->UseWriter(writer); client->Connect(); return client; @@ -491,7 +495,7 @@ } void AddToCache(StringPiece path, int response_code, StringPiece body) { - QuicInMemoryCache::GetInstance()->AddSimpleResponse("www.google.com", path, + QuicInMemoryCache::GetInstance()->AddSimpleResponse(server_hostname_, path, response_code, body); } @@ -2466,7 +2470,7 @@ trailers["some-trailing-header"] = "trailing-header-value"; QuicInMemoryCache::GetInstance()->AddResponse( - "www.google.com", "/trailer_url", std::move(headers), kBody, + server_hostname_, "/trailer_url", std::move(headers), kBody, trailers.Clone()); EXPECT_EQ(kBody, client_->SendSynchronousRequest("/trailer_url"));
diff --git a/net/tools/quic/quic_client.cc b/net/tools/quic/quic_client.cc index 224859e..651776f 100644 --- a/net/tools/quic/quic_client.cc +++ b/net/tools/quic/quic_client.cc
@@ -51,27 +51,27 @@ const QuicServerId& server_id, const QuicVersionVector& supported_versions, EpollServer* epoll_server, - ProofVerifier* proof_verifier) + std::unique_ptr<ProofVerifier> proof_verifier) : QuicClient(server_address, server_id, supported_versions, QuicConfig(), epoll_server, - proof_verifier) {} + std::move(proof_verifier)) {} QuicClient::QuicClient(IPEndPoint server_address, const QuicServerId& server_id, const QuicVersionVector& supported_versions, const QuicConfig& config, EpollServer* epoll_server, - ProofVerifier* proof_verifier) + std::unique_ptr<ProofVerifier> proof_verifier) : QuicClientBase( server_id, supported_versions, config, new QuicEpollConnectionHelper(epoll_server, QuicAllocator::SIMPLE), new QuicEpollAlarmFactory(epoll_server), - proof_verifier), + std::move(proof_verifier)), server_address_(server_address), local_port_(0), epoll_server_(epoll_server),
diff --git a/net/tools/quic/quic_client.h b/net/tools/quic/quic_client.h index 0beccc1..cec0d884 100644 --- a/net/tools/quic/quic_client.h +++ b/net/tools/quic/quic_client.h
@@ -86,13 +86,13 @@ const QuicServerId& server_id, const QuicVersionVector& supported_versions, EpollServer* epoll_server, - ProofVerifier* proof_verifier); + std::unique_ptr<ProofVerifier> proof_verifier); QuicClient(IPEndPoint server_address, const QuicServerId& server_id, const QuicVersionVector& supported_versions, const QuicConfig& config, EpollServer* epoll_server, - ProofVerifier* proof_verifier); + std::unique_ptr<ProofVerifier> proof_verifier); ~QuicClient() override;
diff --git a/net/tools/quic/quic_client_base.cc b/net/tools/quic/quic_client_base.cc index 211c54d8e..848d17d 100644 --- a/net/tools/quic/quic_client_base.cc +++ b/net/tools/quic/quic_client_base.cc
@@ -14,10 +14,10 @@ const QuicConfig& config, QuicConnectionHelperInterface* helper, QuicAlarmFactory* alarm_factory, - ProofVerifier* proof_verifier) + std::unique_ptr<ProofVerifier> proof_verifier) : server_id_(server_id), config_(config), - crypto_config_(proof_verifier), + crypto_config_(std::move(proof_verifier)), helper_(helper), alarm_factory_(alarm_factory), supported_versions_(supported_versions),
diff --git a/net/tools/quic/quic_client_base.h b/net/tools/quic/quic_client_base.h index 3f9e514..d49f8aad 100644 --- a/net/tools/quic/quic_client_base.h +++ b/net/tools/quic/quic_client_base.h
@@ -38,7 +38,7 @@ const QuicConfig& config, QuicConnectionHelperInterface* helper, QuicAlarmFactory* alarm_factory, - ProofVerifier* proof_verifier); + std::unique_ptr<ProofVerifier> proof_verifier); ~QuicClientBase();
diff --git a/net/tools/quic/quic_client_bin.cc b/net/tools/quic/quic_client_bin.cc index 1d6d6ec..f2a4b44 100644 --- a/net/tools/quic/quic_client_bin.cc +++ b/net/tools/quic/quic_client_bin.cc
@@ -254,11 +254,12 @@ transport_security_state.reset(new TransportSecurityState); std::unique_ptr<CTVerifier> ct_verifier(new MultiLogCTVerifier()); std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer(new CTPolicyEnforcer()); - ProofVerifierChromium* proof_verifier = new ProofVerifierChromium( - cert_verifier.get(), ct_policy_enforcer.get(), - transport_security_state.get(), ct_verifier.get()); + std::unique_ptr<net::ProofVerifierChromium> proof_verifier( + new ProofVerifierChromium(cert_verifier.get(), ct_policy_enforcer.get(), + transport_security_state.get(), + ct_verifier.get())); net::QuicClient client(net::IPEndPoint(ip_addr, FLAGS_port), server_id, - versions, &epoll_server, proof_verifier); + versions, &epoll_server, std::move(proof_verifier)); client.set_initial_max_packet_length( FLAGS_initial_mtu != 0 ? FLAGS_initial_mtu : net::kDefaultMaxPacketSize); if (!client.Initialize()) {
diff --git a/net/tools/quic/quic_client_test.cc b/net/tools/quic/quic_client_test.cc index dca06bd..74910aca 100644 --- a/net/tools/quic/quic_client_test.cc +++ b/net/tools/quic/quic_client_test.cc
@@ -54,7 +54,7 @@ TEST(QuicClientTest, DoNotLeakFDs) { // Create a ProofVerifier before counting the number of open FDs to work // around some ASAN weirdness. - delete CryptoTestUtils::ProofVerifierForTesting(); + CryptoTestUtils::ProofVerifierForTesting().reset(); // Make sure that the QuicClient doesn't leak FDs. Doing so could cause port // exhaustion in long running processes which repeatedly create clients. @@ -81,7 +81,7 @@ TEST(QuicClientTest, CreateAndCleanUpUDPSockets) { // Create a ProofVerifier before counting the number of open FDs to work // around some ASAN weirdness. - delete CryptoTestUtils::ProofVerifierForTesting(); + CryptoTestUtils::ProofVerifierForTesting().reset(); EpollServer eps; int number_of_open_fds = NumOpenFDs();
diff --git a/net/tools/quic/quic_server.cc b/net/tools/quic/quic_server.cc index 94fdfda..dc53bf0d 100644 --- a/net/tools/quic/quic_server.cc +++ b/net/tools/quic/quic_server.cc
@@ -47,14 +47,14 @@ } // namespace -QuicServer::QuicServer(ProofSource* proof_source) - : QuicServer(proof_source, +QuicServer::QuicServer(std::unique_ptr<ProofSource> proof_source) + : QuicServer(std::move(proof_source), QuicConfig(), QuicCryptoServerConfig::ConfigOptions(), QuicSupportedVersions()) {} QuicServer::QuicServer( - ProofSource* proof_source, + std::unique_ptr<ProofSource> proof_source, const QuicConfig& config, const QuicCryptoServerConfig::ConfigOptions& crypto_config_options, const QuicVersionVector& supported_versions) @@ -65,7 +65,7 @@ config_(config), crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance(), - proof_source), + std::move(proof_source)), crypto_config_options_(crypto_config_options), supported_versions_(supported_versions), packet_reader_(new QuicPacketReader()) {
diff --git a/net/tools/quic/quic_server.h b/net/tools/quic/quic_server.h index 76ff17a4..17c80b4 100644 --- a/net/tools/quic/quic_server.h +++ b/net/tools/quic/quic_server.h
@@ -35,8 +35,8 @@ class QuicServer : public EpollCallbackInterface { public: - explicit QuicServer(ProofSource* proof_source); - QuicServer(ProofSource* proof_source, + explicit QuicServer(std::unique_ptr<ProofSource> proof_source); + QuicServer(std::unique_ptr<ProofSource> proof_source, const QuicConfig& config, const QuicCryptoServerConfig::ConfigOptions& server_config_options, const QuicVersionVector& supported_versions);
diff --git a/net/tools/quic/quic_server_bin.cc b/net/tools/quic/quic_server_bin.cc index 983c584..a6119698 100644 --- a/net/tools/quic/quic_server_bin.cc +++ b/net/tools/quic/quic_server_bin.cc
@@ -22,11 +22,13 @@ // The port the quic server will listen on. int32_t FLAGS_port = 6121; -net::ProofSource* CreateProofSource(const base::FilePath& cert_path, - const base::FilePath& key_path) { - net::ProofSourceChromium* proof_source = new net::ProofSourceChromium(); +std::unique_ptr<net::ProofSource> CreateProofSource( + const base::FilePath& cert_path, + const base::FilePath& key_path) { + std::unique_ptr<net::ProofSourceChromium> proof_source( + new net::ProofSourceChromium()); CHECK(proof_source->Initialize(cert_path, key_path, base::FilePath())); - return proof_source; + return std::move(proof_source); } int main(int argc, char* argv[]) {
diff --git a/net/tools/quic/quic_simple_client.cc b/net/tools/quic/quic_simple_client.cc index d179b37..68ed15d 100644 --- a/net/tools/quic/quic_simple_client.cc +++ b/net/tools/quic/quic_simple_client.cc
@@ -37,33 +37,35 @@ headers_ = nullptr; } -QuicSimpleClient::QuicSimpleClient(IPEndPoint server_address, - const QuicServerId& server_id, - const QuicVersionVector& supported_versions, - ProofVerifier* proof_verifier) +QuicSimpleClient::QuicSimpleClient( + IPEndPoint server_address, + const QuicServerId& server_id, + const QuicVersionVector& supported_versions, + std::unique_ptr<ProofVerifier> proof_verifier) : QuicClientBase(server_id, supported_versions, QuicConfig(), CreateQuicConnectionHelper(), CreateQuicAlarmFactory(), - proof_verifier), + std::move(proof_verifier)), server_address_(server_address), local_port_(0), initialized_(false), packet_reader_started_(false), weak_factory_(this) {} -QuicSimpleClient::QuicSimpleClient(IPEndPoint server_address, - const QuicServerId& server_id, - const QuicVersionVector& supported_versions, - const QuicConfig& config, - ProofVerifier* proof_verifier) +QuicSimpleClient::QuicSimpleClient( + IPEndPoint server_address, + const QuicServerId& server_id, + const QuicVersionVector& supported_versions, + const QuicConfig& config, + std::unique_ptr<ProofVerifier> proof_verifier) : QuicClientBase(server_id, supported_versions, config, CreateQuicConnectionHelper(), CreateQuicAlarmFactory(), - proof_verifier), + std::move(proof_verifier)), server_address_(server_address), local_port_(0), initialized_(false),
diff --git a/net/tools/quic/quic_simple_client.h b/net/tools/quic/quic_simple_client.h index b94399c..aa3c731 100644 --- a/net/tools/quic/quic_simple_client.h +++ b/net/tools/quic/quic_simple_client.h
@@ -85,12 +85,12 @@ QuicSimpleClient(IPEndPoint server_address, const QuicServerId& server_id, const QuicVersionVector& supported_versions, - ProofVerifier* proof_verifier); + std::unique_ptr<ProofVerifier> proof_verifier); QuicSimpleClient(IPEndPoint server_address, const QuicServerId& server_id, const QuicVersionVector& supported_versions, const QuicConfig& config, - ProofVerifier* proof_verifier); + std::unique_ptr<ProofVerifier> proof_verifier); ~QuicSimpleClient() override;
diff --git a/net/tools/quic/quic_simple_client_bin.cc b/net/tools/quic/quic_simple_client_bin.cc index 75dca39..25b688c 100644 --- a/net/tools/quic/quic_simple_client_bin.cc +++ b/net/tools/quic/quic_simple_client_bin.cc
@@ -254,11 +254,12 @@ new TransportSecurityState); std::unique_ptr<CTVerifier> ct_verifier(new MultiLogCTVerifier()); std::unique_ptr<CTPolicyEnforcer> ct_policy_enforcer(new CTPolicyEnforcer()); - ProofVerifierChromium* proof_verifier = new ProofVerifierChromium( - cert_verifier.get(), ct_policy_enforcer.get(), - transport_security_state.get(), ct_verifier.get()); + std::unique_ptr<ProofVerifierChromium> proof_verifier( + new ProofVerifierChromium(cert_verifier.get(), ct_policy_enforcer.get(), + transport_security_state.get(), + ct_verifier.get())); net::QuicSimpleClient client(net::IPEndPoint(ip_addr, port), server_id, - versions, proof_verifier); + versions, std::move(proof_verifier)); client.set_initial_max_packet_length( FLAGS_initial_mtu != 0 ? FLAGS_initial_mtu : net::kDefaultMaxPacketSize); if (!client.Initialize()) {
diff --git a/net/tools/quic/quic_simple_server.cc b/net/tools/quic/quic_simple_server.cc index 814feab..d2cc113 100644 --- a/net/tools/quic/quic_simple_server.cc +++ b/net/tools/quic/quic_simple_server.cc
@@ -68,7 +68,7 @@ } // namespace -QuicSimpleServer::QuicSimpleServer(ProofSource* proof_source, +QuicSimpleServer::QuicSimpleServer(std::unique_ptr<ProofSource> proof_source, const QuicConfig& config, const QuicVersionVector& supported_versions) : helper_( @@ -79,7 +79,7 @@ config_(config), crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance(), - proof_source), + std::move(proof_source)), supported_versions_(supported_versions), read_pending_(false), synchronous_read_count_(0),
diff --git a/net/tools/quic/quic_simple_server.h b/net/tools/quic/quic_simple_server.h index 7fe28a4..238393b 100644 --- a/net/tools/quic/quic_simple_server.h +++ b/net/tools/quic/quic_simple_server.h
@@ -33,7 +33,7 @@ class QuicSimpleServer { public: - QuicSimpleServer(ProofSource* proof_source, + QuicSimpleServer(std::unique_ptr<ProofSource> proof_source, const QuicConfig& config, const QuicVersionVector& supported_versions);
diff --git a/net/tools/quic/quic_simple_server_bin.cc b/net/tools/quic/quic_simple_server_bin.cc index b04bf15..b1db0bb 100644 --- a/net/tools/quic/quic_simple_server_bin.cc +++ b/net/tools/quic/quic_simple_server_bin.cc
@@ -22,11 +22,13 @@ // The port the quic server will listen on. int32_t FLAGS_port = 6121; -net::ProofSource* CreateProofSource(const base::FilePath& cert_path, - const base::FilePath& key_path) { - net::ProofSourceChromium* proof_source = new net::ProofSourceChromium(); +std::unique_ptr<net::ProofSource> CreateProofSource( + const base::FilePath& cert_path, + const base::FilePath& key_path) { + std::unique_ptr<net::ProofSourceChromium> proof_source( + new net::ProofSourceChromium()); CHECK(proof_source->Initialize(cert_path, key_path, base::FilePath())); - return proof_source; + return std::move(proof_source); } int main(int argc, char* argv[]) {
diff --git a/net/tools/quic/quic_socket_utils.cc b/net/tools/quic/quic_socket_utils.cc index 7fcc964..49c213a 100644 --- a/net/tools/quic/quic_socket_utils.cc +++ b/net/tools/quic/quic_socket_utils.cc
@@ -71,7 +71,7 @@ for (cmsg = CMSG_FIRSTHDR(hdr); cmsg != nullptr; cmsg = CMSG_NXTHDR(hdr, cmsg)) { if (cmsg->cmsg_type == SO_RXQ_OVFL) { - *dropped_packets = *(reinterpret_cast<int*> CMSG_DATA(cmsg)); + *dropped_packets = *(reinterpret_cast<uint32_t*> CMSG_DATA(cmsg)); return true; } }
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc index ad5748d..19744575 100644 --- a/net/tools/quic/test_tools/quic_test_client.cc +++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -7,6 +7,7 @@ #include <memory> #include <utility> +#include "base/memory/ptr_util.h" #include "base/time/time.h" #include "net/base/completion_callback.h" #include "net/base/net_errors.h" @@ -15,6 +16,8 @@ #include "net/quic/crypto/proof_verifier.h" #include "net/quic/quic_flags.h" #include "net/quic/quic_server_id.h" +#include "net/quic/quic_utils.h" +#include "net/quic/test_tools/crypto_test_utils.h" #include "net/quic/test_tools/quic_connection_peer.h" #include "net/quic/test_tools/quic_spdy_session_peer.h" #include "net/quic/test_tools/quic_test_utils.h" @@ -41,9 +44,14 @@ namespace { // RecordingProofVerifier accepts any certificate chain and records the common -// name of the leaf. +// name of the leaf and then delegates the actual verfication to an actual +// verifier. If no optional verifier is provided, then VerifyProof will return +// success. class RecordingProofVerifier : public ProofVerifier { public: + explicit RecordingProofVerifier(std::unique_ptr<ProofVerifier> verifier) + : verifier_(std::move(verifier)) {} + // ProofVerifier interface. QuicAsyncStatus VerifyProof( const string& hostname, @@ -80,7 +88,13 @@ // common_name_ = cert->subject().GetDisplayName(); cert_sct_ = cert_sct; - return QUIC_SUCCESS; + if (!verifier_) { + return QUIC_SUCCESS; + } + + return verifier_->VerifyProof( + hostname, port, server_config, quic_version, chlo_hash, certs, cert_sct, + signature, context, error_details, details, std::move(callback)); } const string& common_name() const { return common_name_; } @@ -88,6 +102,7 @@ const string& cert_sct() const { return cert_sct_; } private: + std::unique_ptr<ProofVerifier> verifier_; string common_name_; string cert_sct_; }; @@ -106,7 +121,7 @@ headers->CopyFrom(*const_headers); if (!uri.starts_with("https://") && !uri.starts_with("http://")) { // If we have a relative URL, set some defaults. - string full_uri = "https://www.google.com"; + string full_uri = "https://test.example.com"; full_uri.append(uri.as_string()); headers->SetRequestUri(full_uri); } @@ -130,12 +145,27 @@ const QuicConfig& config, const QuicVersionVector& supported_versions, EpollServer* epoll_server) + : MockableQuicClient(server_address, + server_id, + config, + supported_versions, + epoll_server, + nullptr) {} + +MockableQuicClient::MockableQuicClient( + IPEndPoint server_address, + const QuicServerId& server_id, + const QuicConfig& config, + const QuicVersionVector& supported_versions, + EpollServer* epoll_server, + std::unique_ptr<ProofVerifier> proof_verifier) : QuicClient(server_address, server_id, supported_versions, config, epoll_server, - new RecordingProofVerifier()), + base::WrapUnique( + new RecordingProofVerifier(std::move(proof_verifier)))), override_connection_id_(0), test_writer_(nullptr) {} @@ -192,6 +222,23 @@ Initialize(); } +QuicTestClient::QuicTestClient(IPEndPoint server_address, + const string& server_hostname, + const QuicConfig& config, + const QuicVersionVector& supported_versions, + std::unique_ptr<ProofVerifier> proof_verifier) + : client_(new MockableQuicClient(server_address, + QuicServerId(server_hostname, + server_address.port(), + PRIVACY_MODE_DISABLED), + config, + supported_versions, + &epoll_server_, + std::move(proof_verifier))), + allow_bidirectional_data_(false) { + Initialize(); +} + QuicTestClient::QuicTestClient() : allow_bidirectional_data_(false) {} QuicTestClient::~QuicTestClient() {
diff --git a/net/tools/quic/test_tools/quic_test_client.h b/net/tools/quic/test_tools/quic_test_client.h index 47e20621..4a5f6b7a 100644 --- a/net/tools/quic/test_tools/quic_test_client.h +++ b/net/tools/quic/test_tools/quic_test_client.h
@@ -30,6 +30,7 @@ class ProofVerifier; +class ProofVerifier; class QuicPacketWriterWrapper; namespace test { @@ -51,6 +52,13 @@ const QuicVersionVector& supported_versions, EpollServer* epoll_server); + MockableQuicClient(IPEndPoint server_address, + const QuicServerId& server_id, + const QuicConfig& config, + const QuicVersionVector& supported_versions, + EpollServer* epoll_server, + std::unique_ptr<ProofVerifier> proof_verifier); + ~MockableQuicClient() override; QuicPacketWriter* CreateQuicPacketWriter() override; QuicConnectionId GenerateNewConnectionId() override; @@ -81,6 +89,11 @@ const std::string& server_hostname, const QuicConfig& config, const QuicVersionVector& supported_versions); + QuicTestClient(IPEndPoint server_address, + const std::string& server_hostname, + const QuicConfig& config, + const QuicVersionVector& supported_versions, + std::unique_ptr<ProofVerifier> proof_verifier); ~QuicTestClient() override;
diff --git a/net/tools/quic/test_tools/quic_test_server.cc b/net/tools/quic/test_tools/quic_test_server.cc index 1edf41a..0f72c417 100644 --- a/net/tools/quic/test_tools/quic_test_server.cc +++ b/net/tools/quic/test_tools/quic_test_server.cc
@@ -149,13 +149,13 @@ QuicTestServer::CryptoStreamFactory* crypto_stream_factory_; // Not owned. }; -QuicTestServer::QuicTestServer(ProofSource* proof_source) - : QuicServer(proof_source) {} +QuicTestServer::QuicTestServer(std::unique_ptr<ProofSource> proof_source) + : QuicServer(std::move(proof_source)) {} -QuicTestServer::QuicTestServer(ProofSource* proof_source, +QuicTestServer::QuicTestServer(std::unique_ptr<ProofSource> proof_source, const QuicConfig& config, const QuicVersionVector& supported_versions) - : QuicServer(proof_source, + : QuicServer(std::move(proof_source), config, QuicCryptoServerConfig::ConfigOptions(), supported_versions) {}
diff --git a/net/tools/quic/test_tools/quic_test_server.h b/net/tools/quic/test_tools/quic_test_server.h index 0714668..963c43df 100644 --- a/net/tools/quic/test_tools/quic_test_server.h +++ b/net/tools/quic/test_tools/quic_test_server.h
@@ -60,8 +60,8 @@ QuicServerSessionBase* session) = 0; }; - explicit QuicTestServer(ProofSource* proof_source); - QuicTestServer(ProofSource* proof_source, + explicit QuicTestServer(std::unique_ptr<ProofSource> proof_source); + QuicTestServer(std::unique_ptr<ProofSource> proof_source, const QuicConfig& config, const QuicVersionVector& supported_versions);
diff --git a/net/tools/testserver/testserver.py b/net/tools/testserver/testserver.py index ba130af..7950f35 100755 --- a/net/tools/testserver/testserver.py +++ b/net/tools/testserver/testserver.py
@@ -1534,7 +1534,7 @@ return True def ForwardTokenBindingHeader(self): - """Send a redirect that sets the Include-Referer-Token-Binding-ID + """Send a redirect that sets the Include-Referred-Token-Binding-ID header.""" test_name = '/forward-tokbind' @@ -1549,7 +1549,7 @@ self.send_response(302) self.send_header('Location', dest) - self.send_header('Include-Referer-Token-Binding-ID', 'true') + self.send_header('Include-Referred-Token-Binding-ID', 'true') self.end_headers() return True
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc index cfa0aee6..b80c0b3 100644 --- a/net/url_request/url_request_job.cc +++ b/net/url_request/url_request_job.cc
@@ -1013,7 +1013,7 @@ .spec(); std::string include_referer; - request_->GetResponseHeaderByName("include-referer-token-binding-id", + request_->GetResponseHeaderByName("include-referred-token-binding-id", &include_referer); if (include_referer == "true" && request_->ssl_info().token_binding_negotiated) {
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 38289f7..2bd432c4 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -3514,7 +3514,7 @@ } // Test that if a server supporting Token Binding redirects (with -// Include-Referer-Token-Binding-ID) to an https url on a server that does not +// Include-Referred-Token-Binding-ID) to an https url on a server that does not // support Token Binding, then we do not send a Sec-Token-Binding when following // the redirect. TEST_F(TokenBindingURLRequestTest, ForwardWithoutTokenBinding) {
diff --git a/net/websockets/websocket_channel.cc b/net/websockets/websocket_channel.cc index ba100ece..a12d4f9 100644 --- a/net/websockets/websocket_channel.cc +++ b/net/websockets/websocket_channel.cc
@@ -338,11 +338,12 @@ const GURL& socket_url, const std::vector<std::string>& requested_subprotocols, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& additional_headers) { // Delegate to the tested version. SendAddChannelRequestWithSuppliedCreator( - socket_url, requested_subprotocols, origin, additional_headers, - base::Bind(&WebSocketStream::CreateAndConnectStream)); + socket_url, requested_subprotocols, origin, first_party_for_cookies, + additional_headers, base::Bind(&WebSocketStream::CreateAndConnectStream)); } void WebSocketChannel::SetState(State new_state) { @@ -544,10 +545,12 @@ const GURL& socket_url, const std::vector<std::string>& requested_subprotocols, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& additional_headers, const WebSocketStreamCreator& creator) { SendAddChannelRequestWithSuppliedCreator(socket_url, requested_subprotocols, - origin, additional_headers, creator); + origin, first_party_for_cookies, + additional_headers, creator); } void WebSocketChannel::SetClosingHandshakeTimeoutForTesting( @@ -564,6 +567,7 @@ const GURL& socket_url, const std::vector<std::string>& requested_subprotocols, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& additional_headers, const WebSocketStreamCreator& creator) { DCHECK_EQ(FRESHLY_CONSTRUCTED, state_); @@ -578,8 +582,9 @@ std::unique_ptr<WebSocketStream::ConnectDelegate> connect_delegate( new ConnectDelegate(this)); stream_request_ = creator.Run(socket_url_, requested_subprotocols, origin, - additional_headers, url_request_context_, - BoundNetLog(), std::move(connect_delegate)); + first_party_for_cookies, additional_headers, + url_request_context_, BoundNetLog(), + std::move(connect_delegate)); SetState(CONNECTING); }
diff --git a/net/websockets/websocket_channel.h b/net/websockets/websocket_channel.h index 8e7e8c36..ce46388 100644 --- a/net/websockets/websocket_channel.h +++ b/net/websockets/websocket_channel.h
@@ -50,6 +50,7 @@ const GURL&, const std::vector<std::string>&, const url::Origin&, + const GURL&, const std::string&, URLRequestContext*, const BoundNetLog&, @@ -73,6 +74,7 @@ const GURL& socket_url, const std::vector<std::string>& requested_protocols, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& additional_headers); // Sends a data frame to the remote side. It is the responsibility of the @@ -123,6 +125,7 @@ const GURL& socket_url, const std::vector<std::string>& requested_protocols, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& additional_headers, const WebSocketStreamCreator& creator); @@ -216,6 +219,7 @@ const GURL& socket_url, const std::vector<std::string>& requested_protocols, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& additional_headers, const WebSocketStreamCreator& creator);
diff --git a/net/websockets/websocket_channel_test.cc b/net/websockets/websocket_channel_test.cc index 84f8fb97..5fe3c800 100644 --- a/net/websockets/websocket_channel_test.cc +++ b/net/websockets/websocket_channel_test.cc
@@ -700,6 +700,7 @@ const GURL& socket_url, const std::vector<std::string>& requested_subprotocols, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& additional_headers, URLRequestContext* url_request_context, const BoundNetLog& net_log, @@ -707,6 +708,7 @@ this->socket_url = socket_url; this->requested_subprotocols = requested_subprotocols; this->origin = origin; + this->first_party_for_cookies = first_party_for_cookies; this->url_request_context = url_request_context; this->net_log = net_log; this->connect_delegate = std::move(connect_delegate); @@ -715,6 +717,7 @@ GURL socket_url; url::Origin origin; + GURL first_party_for_cookies; std::vector<std::string> requested_subprotocols; URLRequestContext* url_request_context; BoundNetLog net_log; @@ -747,7 +750,7 @@ &connect_data_.url_request_context)); channel_->SendAddChannelRequestForTesting( connect_data_.socket_url, connect_data_.requested_subprotocols, - connect_data_.origin, "", + connect_data_.origin, connect_data_.first_party_for_cookies, "", base::Bind(&ArgumentCopyingWebSocketStreamCreator::Create, base::Unretained(&connect_data_.creator))); } @@ -780,7 +783,10 @@ // A struct containing the data that will be used to connect the channel. // Grouped for readability. struct ConnectData { - ConnectData() : socket_url("ws://ws/"), origin(GURL("http://ws")) {} + ConnectData() + : socket_url("ws://ws/"), + origin(GURL("http://ws")), + first_party_for_cookies("http://ws/") {} // URLRequestContext object. URLRequestContext url_request_context; @@ -791,6 +797,8 @@ std::vector<std::string> requested_subprotocols; // Origin of the request url::Origin origin; + // First party for cookies for the request. + GURL first_party_for_cookies; // A fake WebSocketStreamCreator that just records its arguments. ArgumentCopyingWebSocketStreamCreator creator; @@ -1005,6 +1013,7 @@ TEST_F(WebSocketChannelTest, EverythingIsPassedToTheCreatorFunction) { connect_data_.socket_url = GURL("ws://example.com/test"); connect_data_.origin = url::Origin(GURL("http://example.com")); + connect_data_.first_party_for_cookies = GURL("http://example.com/"); connect_data_.requested_subprotocols.push_back("Sinbad"); CreateChannelAndConnect(); @@ -1017,6 +1026,8 @@ EXPECT_EQ(connect_data_.requested_subprotocols, actual.requested_subprotocols); EXPECT_EQ(connect_data_.origin.Serialize(), actual.origin.Serialize()); + EXPECT_EQ(connect_data_.first_party_for_cookies, + actual.first_party_for_cookies); } // Verify that calling SendFlowControl before the connection is established does
diff --git a/net/websockets/websocket_end_to_end_test.cc b/net/websockets/websocket_end_to_end_test.cc index 18e79b3..be464f6e 100644 --- a/net/websockets/websocket_end_to_end_test.cc +++ b/net/websockets/websocket_end_to_end_test.cc
@@ -265,11 +265,12 @@ InitialiseContext(); } url::Origin origin(GURL("http://localhost")); + GURL first_party_for_cookies("http://localhost/"); event_interface_ = new ConnectTestingEventInterface; channel_.reset( new WebSocketChannel(base::WrapUnique(event_interface_), &context_)); channel_->SendAddChannelRequest(GURL(socket_url), sub_protocols_, origin, - ""); + first_party_for_cookies, ""); event_interface_->WaitForResponse(); return !event_interface_->failed(); }
diff --git a/net/websockets/websocket_stream.cc b/net/websockets/websocket_stream.cc index d1698ae..d621f39 100644 --- a/net/websockets/websocket_stream.cc +++ b/net/websockets/websocket_stream.cc
@@ -86,6 +86,7 @@ const GURL& url, const URLRequestContext* context, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& additional_headers, std::unique_ptr<WebSocketStream::ConnectDelegate> connect_delegate, std::unique_ptr<WebSocketHandshakeStreamCreateHelper> create_helper) @@ -105,6 +106,8 @@ headers.AddHeadersFromString(additional_headers); url_request_->SetExtraRequestHeaders(headers); + url_request_->set_initiator(origin); + url_request_->set_first_party_for_cookies(first_party_for_cookies); // This passes the ownership of |create_helper_| to |url_request_|. url_request_->SetUserData( @@ -336,6 +339,7 @@ const GURL& socket_url, const std::vector<std::string>& requested_subprotocols, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& additional_headers, URLRequestContext* url_request_context, const BoundNetLog& net_log, @@ -344,8 +348,9 @@ new WebSocketHandshakeStreamCreateHelper(connect_delegate.get(), requested_subprotocols)); std::unique_ptr<StreamRequestImpl> request(new StreamRequestImpl( - socket_url, url_request_context, origin, additional_headers, - std::move(connect_delegate), std::move(create_helper))); + socket_url, url_request_context, origin, first_party_for_cookies, + additional_headers, std::move(connect_delegate), + std::move(create_helper))); request->Start(std::unique_ptr<base::Timer>(new base::Timer(false, false))); return std::move(request); } @@ -355,14 +360,16 @@ const GURL& socket_url, std::unique_ptr<WebSocketHandshakeStreamCreateHelper> create_helper, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& additional_headers, URLRequestContext* url_request_context, const BoundNetLog& net_log, std::unique_ptr<WebSocketStream::ConnectDelegate> connect_delegate, std::unique_ptr<base::Timer> timer) { std::unique_ptr<StreamRequestImpl> request(new StreamRequestImpl( - socket_url, url_request_context, origin, additional_headers, - std::move(connect_delegate), std::move(create_helper))); + socket_url, url_request_context, origin, first_party_for_cookies, + additional_headers, std::move(connect_delegate), + std::move(create_helper))); request->Start(std::move(timer)); return std::move(request); }
diff --git a/net/websockets/websocket_stream.h b/net/websockets/websocket_stream.h index 28c90851..002c21a 100644 --- a/net/websockets/websocket_stream.h +++ b/net/websockets/websocket_stream.h
@@ -108,6 +108,7 @@ const GURL& socket_url, const std::vector<std::string>& requested_subprotocols, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& additional_headers, URLRequestContext* url_request_context, const BoundNetLog& net_log, @@ -224,6 +225,7 @@ const GURL& socket_url, std::unique_ptr<WebSocketHandshakeStreamCreateHelper> create_helper, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& additional_headers, URLRequestContext* url_request_context, const BoundNetLog& net_log,
diff --git a/net/websockets/websocket_stream_cookie_test.cc b/net/websockets/websocket_stream_cookie_test.cc index c3ae3a9a..585e03d1 100644 --- a/net/websockets/websocket_stream_cookie_test.cc +++ b/net/websockets/websocket_stream_cookie_test.cc
@@ -32,6 +32,7 @@ public: void CreateAndConnect(const GURL& url, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& cookie_header, const std::string& response_body) { // We assume cookie_header ends with CRLF if not empty, as @@ -45,7 +46,8 @@ cookie_header, std::string(), std::string()), response_body); - CreateAndConnectStream(url.spec(), NoSubProtocols(), origin, "", nullptr); + CreateAndConnectStream(url, NoSubProtocols(), origin, + first_party_for_cookies, "", nullptr); } std::string AddCRLFIfNotEmpty(const std::string& s) { @@ -128,6 +130,7 @@ const GURL url(GetParam().url); const GURL cookie_url(GetParam().cookie_url); const url::Origin origin(GURL("http://www.example.com")); + const GURL first_party_for_cookies("http://www.example.com/"); const std::string cookie_line(GetParam().cookie_line); const std::string cookie_header(AddCRLFIfNotEmpty(GetParam().cookie_header)); @@ -146,7 +149,8 @@ ASSERT_TRUE(is_called); ASSERT_TRUE(set_cookie_result); - CreateAndConnect(url, origin, cookie_header, WebSocketStandardResponse("")); + CreateAndConnect(url, origin, first_party_for_cookies, cookie_header, + WebSocketStandardResponse("")); WaitUntilConnectDone(); EXPECT_FALSE(has_failed()); } @@ -158,6 +162,7 @@ const GURL url(GetParam().url); const GURL cookie_url(GetParam().cookie_url); const url::Origin origin(GURL("http://www.example.com")); + const GURL first_party_for_cookies("http://www.example.com/"); const std::string cookie_line(GetParam().cookie_line); const std::string cookie_header(AddCRLFIfNotEmpty(GetParam().cookie_header)); @@ -173,7 +178,7 @@ CookieStore* store = url_request_context_host_.GetURLRequestContext()->cookie_store(); - CreateAndConnect(url, origin, "", response); + CreateAndConnect(url, origin, first_party_for_cookies, "", response); WaitUntilConnectDone(); EXPECT_FALSE(has_failed());
diff --git a/net/websockets/websocket_stream_create_test_base.cc b/net/websockets/websocket_stream_create_test_base.cc index 0d68b62..354c5d7 100644 --- a/net/websockets/websocket_stream_create_test_base.cc +++ b/net/websockets/websocket_stream_create_test_base.cc
@@ -98,9 +98,10 @@ } void WebSocketStreamCreateTestBase::CreateAndConnectStream( - const std::string& socket_url, + const GURL& socket_url, const std::vector<std::string>& sub_protocols, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& additional_headers, std::unique_ptr<base::Timer> timer) { for (size_t i = 0; i < ssl_data_.size(); ++i) { @@ -114,9 +115,9 @@ new DeterministicKeyWebSocketHandshakeStreamCreateHelper(delegate, sub_protocols)); stream_request_ = CreateAndConnectStreamForTesting( - GURL(socket_url), std::move(create_helper), origin, additional_headers, - url_request_context_host_.GetURLRequestContext(), BoundNetLog(), - std::move(connect_delegate), + socket_url, std::move(create_helper), origin, first_party_for_cookies, + additional_headers, url_request_context_host_.GetURLRequestContext(), + BoundNetLog(), std::move(connect_delegate), timer ? std::move(timer) : std::unique_ptr<base::Timer>(new base::Timer(false, false))); }
diff --git a/net/websockets/websocket_stream_create_test_base.h b/net/websockets/websocket_stream_create_test_base.h index 1cdc4b40..3d6a7cf 100644 --- a/net/websockets/websocket_stream_create_test_base.h +++ b/net/websockets/websocket_stream_create_test_base.h
@@ -19,6 +19,8 @@ #include "net/websockets/websocket_event_interface.h" #include "net/websockets/websocket_test_util.h" +class GURL; + namespace net { class HttpRequestHeaders; @@ -37,9 +39,10 @@ // A wrapper for CreateAndConnectStreamForTesting that knows about our default // parameters. - void CreateAndConnectStream(const std::string& socket_url, + void CreateAndConnectStream(const GURL& socket_url, const std::vector<std::string>& sub_protocols, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& additional_headers, std::unique_ptr<base::Timer> timer);
diff --git a/net/websockets/websocket_stream_test.cc b/net/websockets/websocket_stream_test.cc index a7d25d7..f3938b34 100644 --- a/net/websockets/websocket_stream_test.cc +++ b/net/websockets/websocket_stream_test.cc
@@ -76,10 +76,18 @@ return url::Origin(GURL("http://localhost/")); } +static GURL LocalhostUrl() { + return GURL("http://localhost/foobar"); +} + static url::Origin GoogleOrigin() { return url::Origin(GURL("http://google.com/")); } +static GURL GoogleUrl() { + return GURL("http://google.com/foobar"); +} + class WebSocketStreamCreateTest : public ::testing::Test, public WebSocketStreamCreateTestBase { public: @@ -96,6 +104,7 @@ const std::string& socket_path, const std::vector<std::string>& sub_protocols, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& send_additional_request_headers, const std::string& extra_request_headers, const std::string& response_body, @@ -105,7 +114,8 @@ send_additional_request_headers, extra_request_headers), response_body); - CreateAndConnectStream(socket_url, sub_protocols, origin, + CreateAndConnectStream(GURL(socket_url), sub_protocols, origin, + first_party_for_cookies, send_additional_request_headers, std::move(timer)); } @@ -117,13 +127,15 @@ const std::string& socket_path, const std::vector<std::string>& sub_protocols, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& send_additional_request_headers, const std::string& extra_request_headers, const std::string& extra_response_headers, std::unique_ptr<base::Timer> timer = std::unique_ptr<base::Timer>()) { CreateAndConnectCustomResponse( socket_url, socket_host, socket_path, sub_protocols, origin, - send_additional_request_headers, extra_request_headers, + first_party_for_cookies, send_additional_request_headers, + extra_request_headers, WebSocketStandardResponse(extra_response_headers), std::move(timer)); } @@ -131,11 +143,13 @@ const std::string& socket_url, const std::vector<std::string>& sub_protocols, const url::Origin& origin, + const GURL& first_party_for_cookies, const std::string& send_additional_request_headers, std::unique_ptr<SequencedSocketData> socket_data, std::unique_ptr<base::Timer> timer = std::unique_ptr<base::Timer>()) { AddRawExpectations(std::move(socket_data)); - CreateAndConnectStream(socket_url, sub_protocols, origin, + CreateAndConnectStream(GURL(socket_url), sub_protocols, origin, + first_party_for_cookies, send_additional_request_headers, std::move(timer)); } @@ -156,7 +170,7 @@ const std::string& extensions_header_value) { CreateAndConnectStandard( "ws://localhost/testing_path", "localhost", "/testing_path", - NoSubProtocols(), LocalhostOrigin(), "", "", + NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(), "", "", "Sec-WebSocket-Extensions: " + extensions_header_value + "\r\n"); WaitUntilConnectDone(); } @@ -234,7 +248,7 @@ const std::string request = base::StringPrintf(request2format, base64_user_pass.c_str()); CreateAndConnectRawExpectations( - url, NoSubProtocols(), LocalhostOrigin(), "", + url, NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(), "", helper_.BuildSocketData2(request, response2)); } @@ -312,7 +326,8 @@ // Confirm that the basic case works as expected. TEST_F(WebSocketStreamCreateTest, SimpleSuccess) { CreateAndConnectStandard("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", ""); + NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(), + "", "", ""); EXPECT_FALSE(request_info_); EXPECT_FALSE(response_info_); WaitUntilConnectDone(); @@ -334,8 +349,8 @@ "\r\n"; CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", - kResponse); + NoSubProtocols(), LocalhostOrigin(), + LocalhostUrl(), "", "", kResponse); EXPECT_FALSE(request_info_); EXPECT_FALSE(response_info_); WaitUntilConnectDone(); @@ -391,7 +406,7 @@ "User-Agent: OveRrIde\r\n" "rAnDomHeader: foobar\r\n"); CreateAndConnectStandard("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), + NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(), additional_headers, additional_headers, ""); EXPECT_FALSE(request_info_); EXPECT_FALSE(response_info_); @@ -410,7 +425,8 @@ // Confirm that the stream isn't established until the message loop runs. TEST_F(WebSocketStreamCreateTest, NeedsToRunLoop) { CreateAndConnectStandard("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", ""); + NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(), + "", "", ""); EXPECT_FALSE(has_failed()); EXPECT_FALSE(stream_); } @@ -419,7 +435,7 @@ TEST_F(WebSocketStreamCreateTest, PathIsUsed) { CreateAndConnectStandard("ws://localhost/testing_path", "localhost", "/testing_path", NoSubProtocols(), LocalhostOrigin(), - "", "", ""); + LocalhostUrl(), "", "", ""); WaitUntilConnectDone(); EXPECT_FALSE(has_failed()); EXPECT_TRUE(stream_); @@ -429,7 +445,7 @@ TEST_F(WebSocketStreamCreateTest, OriginIsUsed) { CreateAndConnectStandard("ws://localhost/testing_path", "localhost", "/testing_path", NoSubProtocols(), GoogleOrigin(), - "", "", ""); + GoogleUrl(), "", "", ""); WaitUntilConnectDone(); EXPECT_FALSE(has_failed()); EXPECT_TRUE(stream_); @@ -441,7 +457,8 @@ sub_protocols.push_back("chatv11.chromium.org"); sub_protocols.push_back("chatv20.chromium.org"); CreateAndConnectStandard("ws://localhost/testing_path", "localhost", - "/testing_path", sub_protocols, GoogleOrigin(), "", + "/testing_path", sub_protocols, GoogleOrigin(), + GoogleUrl(), "", "Sec-WebSocket-Protocol: chatv11.chromium.org, " "chatv20.chromium.org\r\n", "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n"); @@ -455,7 +472,7 @@ TEST_F(WebSocketStreamCreateTest, UnsolicitedSubProtocol) { CreateAndConnectStandard("ws://localhost/testing_path", "localhost", "/testing_path", NoSubProtocols(), GoogleOrigin(), - "", "", + GoogleUrl(), "", "", "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n"); WaitUntilConnectDone(); EXPECT_FALSE(stream_); @@ -472,8 +489,8 @@ sub_protocols.push_back("chat.example.com"); CreateAndConnectStandard("ws://localhost/testing_path", "localhost", "/testing_path", sub_protocols, LocalhostOrigin(), - "", "Sec-WebSocket-Protocol: chat.example.com\r\n", - ""); + LocalhostUrl(), "", + "Sec-WebSocket-Protocol: chat.example.com\r\n", ""); WaitUntilConnectDone(); EXPECT_FALSE(stream_); EXPECT_TRUE(has_failed()); @@ -489,7 +506,8 @@ sub_protocols.push_back("chatv11.chromium.org"); sub_protocols.push_back("chatv20.chromium.org"); CreateAndConnectStandard("ws://localhost/testing_path", "localhost", - "/testing_path", sub_protocols, GoogleOrigin(), "", + "/testing_path", sub_protocols, GoogleOrigin(), + GoogleUrl(), "", "Sec-WebSocket-Protocol: chatv11.chromium.org, " "chatv20.chromium.org\r\n", "Sec-WebSocket-Protocol: chatv11.chromium.org, " @@ -509,7 +527,8 @@ sub_protocols.push_back("chatv11.chromium.org"); sub_protocols.push_back("chatv20.chromium.org"); CreateAndConnectStandard("ws://localhost/testing_path", "localhost", - "/testing_path", sub_protocols, GoogleOrigin(), "", + "/testing_path", sub_protocols, GoogleOrigin(), + GoogleUrl(), "", "Sec-WebSocket-Protocol: chatv11.chromium.org, " "chatv20.chromium.org\r\n", "Sec-WebSocket-Protocol: chatv21.chromium.org\r\n"); @@ -544,7 +563,7 @@ TEST_F(WebSocketStreamCreateExtensionTest, PerMessageDeflateInflates) { CreateAndConnectCustomResponse( "ws://localhost/testing_path", "localhost", "/testing_path", - NoSubProtocols(), LocalhostOrigin(), "", "", + NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(), "", "", WebSocketStandardResponse( "Sec-WebSocket-Extensions: permessage-deflate\r\n") + std::string( @@ -619,7 +638,8 @@ TEST_F(WebSocketStreamCreateTest, DoubleAccept) { CreateAndConnectStandard( "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(), - "", "", "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"); + LocalhostUrl(), "", "", + "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"); WaitUntilConnectDone(); EXPECT_FALSE(stream_); EXPECT_TRUE(has_failed()); @@ -637,9 +657,9 @@ "Connection: Upgrade\r\n" "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" "\r\n"; - CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", - kInvalidStatusCodeResponse); + CreateAndConnectCustomResponse( + "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(), + LocalhostUrl(), "", "", kInvalidStatusCodeResponse); WaitUntilConnectDone(); EXPECT_TRUE(has_failed()); EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 200", @@ -658,8 +678,8 @@ "\r\n" "<title>Moved</title><h1>Moved</h1>"; CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", - kRedirectResponse); + NoSubProtocols(), LocalhostOrigin(), + LocalhostUrl(), "", "", kRedirectResponse); WaitUntilConnectDone(); EXPECT_TRUE(has_failed()); EXPECT_EQ("Error during WebSocket handshake: Unexpected response code: 302", @@ -679,8 +699,8 @@ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" "\r\n"; CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", - kMalformedResponse); + NoSubProtocols(), LocalhostOrigin(), + LocalhostUrl(), "", "", kMalformedResponse); WaitUntilConnectDone(); EXPECT_TRUE(has_failed()); EXPECT_EQ("Error during WebSocket handshake: Invalid status line", @@ -694,9 +714,9 @@ "Connection: Upgrade\r\n" "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" "\r\n"; - CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", - kMissingUpgradeResponse); + CreateAndConnectCustomResponse( + "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(), + LocalhostUrl(), "", "", kMissingUpgradeResponse); WaitUntilConnectDone(); EXPECT_TRUE(has_failed()); EXPECT_EQ("Error during WebSocket handshake: 'Upgrade' header is missing", @@ -706,8 +726,8 @@ // There must only be one upgrade header. TEST_F(WebSocketStreamCreateTest, DoubleUpgradeHeader) { CreateAndConnectStandard("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", - "Upgrade: HTTP/2.0\r\n"); + NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(), + "", "", "Upgrade: HTTP/2.0\r\n"); WaitUntilConnectDone(); EXPECT_TRUE(has_failed()); EXPECT_EQ("Error during WebSocket handshake: " @@ -723,9 +743,9 @@ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" "Upgrade: hogefuga\r\n" "\r\n"; - CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", - kMissingUpgradeResponse); + CreateAndConnectCustomResponse( + "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(), + LocalhostUrl(), "", "", kMissingUpgradeResponse); WaitUntilConnectDone(); EXPECT_TRUE(has_failed()); EXPECT_EQ("Error during WebSocket handshake: " @@ -740,9 +760,9 @@ "Upgrade: websocket\r\n" "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" "\r\n"; - CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", - kMissingConnectionResponse); + CreateAndConnectCustomResponse( + "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(), + LocalhostUrl(), "", "", kMissingConnectionResponse); WaitUntilConnectDone(); EXPECT_TRUE(has_failed()); EXPECT_EQ("Error during WebSocket handshake: " @@ -758,9 +778,9 @@ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" "Connection: hogefuga\r\n" "\r\n"; - CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", - kMissingConnectionResponse); + CreateAndConnectCustomResponse( + "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(), + LocalhostUrl(), "", "", kMissingConnectionResponse); WaitUntilConnectDone(); EXPECT_TRUE(has_failed()); EXPECT_EQ("Error during WebSocket handshake: " @@ -776,9 +796,9 @@ "Connection: Upgrade, Keep-Alive\r\n" "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n" "\r\n"; - CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", - kAdditionalConnectionTokenResponse); + CreateAndConnectCustomResponse( + "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(), + LocalhostUrl(), "", "", kAdditionalConnectionTokenResponse); WaitUntilConnectDone(); EXPECT_FALSE(has_failed()); EXPECT_TRUE(stream_); @@ -791,9 +811,9 @@ "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" "\r\n"; - CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", - kMissingAcceptResponse); + CreateAndConnectCustomResponse( + "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(), + LocalhostUrl(), "", "", kMissingAcceptResponse); WaitUntilConnectDone(); EXPECT_TRUE(has_failed()); EXPECT_EQ("Error during WebSocket handshake: " @@ -809,9 +829,9 @@ "Connection: Upgrade\r\n" "Sec-WebSocket-Accept: x/byyPZ2tOFvJCGkkugcKvqhhPk=\r\n" "\r\n"; - CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", - kIncorrectAcceptResponse); + CreateAndConnectCustomResponse( + "ws://localhost/", "localhost", "/", NoSubProtocols(), LocalhostOrigin(), + LocalhostUrl(), "", "", kIncorrectAcceptResponse); WaitUntilConnectDone(); EXPECT_TRUE(has_failed()); EXPECT_EQ("Error during WebSocket handshake: " @@ -822,7 +842,8 @@ // Cancellation works. TEST_F(WebSocketStreamCreateTest, Cancellation) { CreateAndConnectStandard("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", ""); + NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(), + "", "", ""); stream_request_.reset(); // WaitUntilConnectDone doesn't work in this case. base::RunLoop().RunUntilIdle(); @@ -838,7 +859,7 @@ socket_data->set_connect_data( MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED)); CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), - LocalhostOrigin(), "", + LocalhostOrigin(), LocalhostUrl(), "", std::move(socket_data)); WaitUntilConnectDone(); EXPECT_TRUE(has_failed()); @@ -854,7 +875,7 @@ socket_data->set_connect_data( MockConnect(ASYNC, ERR_CONNECTION_TIMED_OUT)); CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), - LocalhostOrigin(), "", + LocalhostOrigin(), LocalhostUrl(), "", std::move(socket_data)); WaitUntilConnectDone(); EXPECT_TRUE(has_failed()); @@ -869,8 +890,8 @@ std::unique_ptr<MockWeakTimer> timer(new MockWeakTimer(false, false)); base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr(); CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), - LocalhostOrigin(), "", std::move(socket_data), - std::move(timer)); + LocalhostOrigin(), LocalhostUrl(), "", + std::move(socket_data), std::move(timer)); EXPECT_FALSE(has_failed()); ASSERT_TRUE(weak_timer.get()); EXPECT_TRUE(weak_timer->IsRunning()); @@ -890,8 +911,8 @@ base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr(); CreateAndConnectStandard("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", "", - std::move(timer)); + NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(), + "", "", "", std::move(timer)); ASSERT_TRUE(weak_timer); EXPECT_TRUE(weak_timer->IsRunning()); @@ -910,8 +931,8 @@ std::unique_ptr<MockWeakTimer> timer(new MockWeakTimer(false, false)); base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr(); CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), - LocalhostOrigin(), "", std::move(socket_data), - std::move(timer)); + LocalhostOrigin(), LocalhostUrl(), "", + std::move(socket_data), std::move(timer)); ASSERT_TRUE(weak_timer.get()); EXPECT_TRUE(weak_timer->IsRunning()); @@ -928,7 +949,7 @@ std::unique_ptr<SequencedSocketData> socket_data(BuildNullSocketData()); socket_data->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING)); CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), - LocalhostOrigin(), "", + LocalhostOrigin(), LocalhostUrl(), "", std::move(socket_data)); stream_request_.reset(); // WaitUntilConnectDone doesn't work in this case. @@ -945,7 +966,7 @@ new SequencedSocketData(NULL, 0, writes, arraysize(writes))); socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), - LocalhostOrigin(), "", + LocalhostOrigin(), LocalhostUrl(), "", base::WrapUnique(socket_data)); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(socket_data->AllWriteDataConsumed()); @@ -970,7 +991,7 @@ BuildSocketData(reads, writes)); SequencedSocketData* socket_data_raw_ptr = socket_data.get(); CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), - LocalhostOrigin(), "", + LocalhostOrigin(), LocalhostUrl(), "", std::move(socket_data)); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(socket_data_raw_ptr->AllReadDataConsumed()); @@ -994,8 +1015,8 @@ } ASSERT_GT(set_cookie_headers.size(), 256U * 1024U); CreateAndConnectStandard("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", - set_cookie_headers); + NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(), + "", "", set_cookie_headers); WaitUntilConnectDone(); EXPECT_TRUE(has_failed()); EXPECT_FALSE(response_info_); @@ -1013,7 +1034,7 @@ BuildSocketData(reads, writes)); SequencedSocketData* socket_data_raw_ptr = socket_data.get(); CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), - LocalhostOrigin(), "", + LocalhostOrigin(), LocalhostUrl(), "", std::move(socket_data)); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(socket_data_raw_ptr->AllReadDataConsumed()); @@ -1032,7 +1053,7 @@ ASSERT_TRUE(ssl_data_[0]->cert.get()); std::unique_ptr<SequencedSocketData> raw_socket_data(BuildNullSocketData()); CreateAndConnectRawExpectations("wss://localhost/", NoSubProtocols(), - LocalhostOrigin(), "", + LocalhostOrigin(), LocalhostUrl(), "", std::move(raw_socket_data)); // WaitUntilConnectDone doesn't work in this case. base::RunLoop().RunUntilIdle(); @@ -1055,7 +1076,8 @@ ssl_data_.push_back(std::move(ssl_data)); url_request_context_host_.AddRawExpectations(BuildNullSocketData()); CreateAndConnectStandard("wss://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", ""); + NoSubProtocols(), LocalhostOrigin(), LocalhostUrl(), + "", "", ""); // WaitUntilConnectDone doesn't work in this case. base::RunLoop().RunUntilIdle(); ASSERT_TRUE(ssl_error_callbacks_); @@ -1069,8 +1091,8 @@ // connection should fail cleanly. TEST_F(WebSocketStreamCreateBasicAuthTest, FailureNoCredentials) { CreateAndConnectCustomResponse("ws://localhost/", "localhost", "/", - NoSubProtocols(), LocalhostOrigin(), "", "", - kUnauthorizedResponse); + NoSubProtocols(), LocalhostOrigin(), + LocalhostUrl(), "", "", kUnauthorizedResponse); WaitUntilConnectDone(); EXPECT_TRUE(has_failed()); EXPECT_EQ("HTTP Authentication failed; no valid credentials available", @@ -1104,7 +1126,8 @@ AddRawExpectations(helper_.BuildSocketData1(kUnauthorizedResponse)); CreateAndConnectRawExpectations( - "ws://FooBar:pass@localhost/", NoSubProtocols(), LocalhostOrigin(), "", + "ws://FooBar:pass@localhost/", NoSubProtocols(), LocalhostOrigin(), + LocalhostUrl(), "", helper_.BuildSocketData2(kAuthorizedRequest, WebSocketStandardResponse(std::string()))); WaitUntilConnectDone(); @@ -1120,9 +1143,9 @@ { StreamCreation creation; - creation.CreateAndConnectStandard("ws://localhost/", "localhost", "/", - creation.NoSubProtocols(), - LocalhostOrigin(), "", "", ""); + creation.CreateAndConnectStandard( + "ws://localhost/", "localhost", "/", creation.NoSubProtocols(), + LocalhostOrigin(), LocalhostUrl(), "", "", ""); } std::unique_ptr<base::HistogramSamples> samples(GetSamples(name)); @@ -1141,9 +1164,9 @@ { StreamCreation creation; - creation.CreateAndConnectStandard("ws://localhost/", "localhost", "/", - creation.NoSubProtocols(), - LocalhostOrigin(), "", "", ""); + creation.CreateAndConnectStandard( + "ws://localhost/", "localhost", "/", creation.NoSubProtocols(), + LocalhostOrigin(), LocalhostUrl(), "", "", ""); creation.WaitUntilConnectDone(); } @@ -1171,7 +1194,7 @@ "\r\n"; creation.CreateAndConnectCustomResponse( "ws://localhost/", "localhost", "/", creation.NoSubProtocols(), - LocalhostOrigin(), "", "", kInvalidStatusCodeResponse); + LocalhostOrigin(), LocalhostUrl(), "", "", kInvalidStatusCodeResponse); creation.WaitUntilConnectDone(); } @@ -1204,7 +1227,7 @@ BuildSocketData(reads, writes)); socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK)); CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), - LocalhostOrigin(), "", + LocalhostOrigin(), LocalhostUrl(), "", std::move(socket_data)); WaitUntilConnectDone(); EXPECT_TRUE(has_failed()); @@ -1231,7 +1254,7 @@ BuildSocketData(reads, writes)); url_request_context_host_.SetProxyConfig("https=proxy:8000"); CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(), - LocalhostOrigin(), "", + LocalhostOrigin(), LocalhostUrl(), "", std::move(socket_data)); WaitUntilConnectDone(); EXPECT_TRUE(has_failed());
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc index 08e869de..d0796a5 100644 --- a/pdf/pdfium/pdfium_engine.cc +++ b/pdf/pdfium/pdfium_engine.cc
@@ -1527,8 +1527,11 @@ selection_.clear(); return true; } - if (event.GetButton() != PP_INPUTEVENT_MOUSEBUTTON_LEFT) + + if (event.GetButton() != PP_INPUTEVENT_MOUSEBUTTON_LEFT && + event.GetButton() != PP_INPUTEVENT_MOUSEBUTTON_MIDDLE) { return false; + } SelectionChangeInvalidator selection_invalidator(this); selection_.clear(); @@ -1546,6 +1549,10 @@ if (area == PDFiumPage::WEBLINK_AREA) return true; + // Prevent middle mouse button from selecting texts. + if (event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_MIDDLE) + return false; + if (area == PDFiumPage::DOCLINK_AREA) { client_->ScrollToPage(target.page); client_->FormTextFieldFocusChange(false); @@ -1620,8 +1627,11 @@ } bool PDFiumEngine::OnMouseUp(const pp::MouseInputEvent& event) { - if (event.GetButton() != PP_INPUTEVENT_MOUSEBUTTON_LEFT) + + if (event.GetButton() != PP_INPUTEVENT_MOUSEBUTTON_LEFT && + event.GetButton() != PP_INPUTEVENT_MOUSEBUTTON_MIDDLE) { return false; + } int page_index = -1; int char_index = -1; @@ -1633,13 +1643,18 @@ // Open link on mouse up for same link for which mouse down happened earlier. if (mouse_down_state_.Matches(area, target)) { if (area == PDFiumPage::WEBLINK_AREA) { - bool open_in_new_tab = !!(event.GetModifiers() & kDefaultKeyModifier); + bool open_in_new_tab = !!(event.GetModifiers() & kDefaultKeyModifier) || + !!(event.GetModifiers() & PP_INPUTEVENT_MODIFIER_MIDDLEBUTTONDOWN); client_->NavigateTo(target.url, open_in_new_tab); client_->FormTextFieldFocusChange(false); return true; } } + // Prevent middle mouse button from selecting texts. + if (event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_MIDDLE) + return false; + if (page_index != -1) { double page_x, page_y; pp::Point point = event.GetPosition();
diff --git a/ppapi/nacl_irt/irt_pnacl_translator_compile.cc b/ppapi/nacl_irt/irt_pnacl_translator_compile.cc index a79dd959..5a339f1 100644 --- a/ppapi/nacl_irt/irt_pnacl_translator_compile.cc +++ b/ppapi/nacl_irt/irt_pnacl_translator_compile.cc
@@ -100,9 +100,7 @@ void ServeTranslateRequest(const struct nacl_irt_pnacl_compile_funcs* funcs) { base::MessageLoop loop; - int fd = ppapi::GetRendererIPCFileDescriptor(); - IPC::ChannelHandle handle("NaCl IPC", base::FileDescriptor(fd, false)); - new TranslatorCompileListener(handle, funcs); + new TranslatorCompileListener(ppapi::GetRendererIPCChannelHandle(), funcs); loop.Run(); }
diff --git a/ppapi/nacl_irt/irt_pnacl_translator_link.cc b/ppapi/nacl_irt/irt_pnacl_translator_link.cc index dc88a7a2..e2e3541 100644 --- a/ppapi/nacl_irt/irt_pnacl_translator_link.cc +++ b/ppapi/nacl_irt/irt_pnacl_translator_link.cc
@@ -71,9 +71,7 @@ void ServeLinkRequest(CallbackFunc func) { base::MessageLoop loop; - int fd = ppapi::GetRendererIPCFileDescriptor(); - IPC::ChannelHandle handle("NaCl IPC", base::FileDescriptor(fd, false)); - new TranslatorLinkListener(handle, func); + new TranslatorLinkListener(ppapi::GetRendererIPCChannelHandle(), func); loop.Run(); }
diff --git a/ppapi/nacl_irt/irt_ppapi.cc b/ppapi/nacl_irt/irt_ppapi.cc index 8d2f715..e2f2dc92 100644 --- a/ppapi/nacl_irt/irt_ppapi.cc +++ b/ppapi/nacl_irt/irt_ppapi.cc
@@ -38,8 +38,8 @@ ppapi::PpapiDispatcher ppapi_dispatcher( ppapi::GetIOThread()->task_runner(), ppapi::GetShutdownEvent(), - ppapi::GetBrowserIPCFileDescriptor(), - ppapi::GetRendererIPCFileDescriptor()); + ppapi::GetBrowserIPCChannelHandle(), + ppapi::GetRendererIPCChannelHandle()); plugin_globals.SetPluginProxyDelegate(&ppapi_dispatcher); loop.Run();
diff --git a/ppapi/nacl_irt/irt_start.cc b/ppapi/nacl_irt/irt_start.cc index b0f09df..9390ace 100644 --- a/ppapi/nacl_irt/irt_start.cc +++ b/ppapi/nacl_irt/irt_start.cc
@@ -16,6 +16,13 @@ #include "ppapi/nacl_irt/irt_interfaces.h" #include "ppapi/nacl_irt/plugin_startup.h" +namespace { +IPC::ChannelHandle MakeIPCHandle(const char* name, int fd) { + return IPC::ChannelHandle(name, + base::FileDescriptor(fd, false /* auto_close */)); +} +} // namespace + void nacl_irt_start(uint32_t* info) { nacl_irt_init(info); @@ -24,10 +31,10 @@ // In SFI mode, the FDs of IPC channels are NACL_CHROME_DESC_BASE and its // successor, which is set in nacl_listener.cc. - ppapi::SetIPCFileDescriptors( - NACL_CHROME_DESC_BASE, - NACL_CHROME_DESC_BASE + 1, - NACL_CHROME_DESC_BASE + 2); + ppapi::SetIPCChannelHandles( + MakeIPCHandle("NaCl Browser", NACL_CHROME_DESC_BASE), + MakeIPCHandle("NaCl Renderer", NACL_CHROME_DESC_BASE + 1), + MakeIPCHandle("NaCl Manifest", NACL_CHROME_DESC_BASE + 2)); ppapi::StartUpPlugin(); nacl_irt_enter_user_code(info, chrome_irt_query);
diff --git a/ppapi/nacl_irt/plugin_startup.cc b/ppapi/nacl_irt/plugin_startup.cc index c7b818dd..d234a2d 100644 --- a/ppapi/nacl_irt/plugin_startup.cc +++ b/ppapi/nacl_irt/plugin_startup.cc
@@ -19,44 +19,50 @@ namespace ppapi { namespace { -int g_nacl_browser_ipc_fd = -1; -int g_nacl_renderer_ipc_fd = -1; -int g_manifest_service_fd = -1; +IPC::ChannelHandle* g_nacl_browser_ipc_handle = nullptr; +IPC::ChannelHandle* g_nacl_renderer_ipc_handle = nullptr; +IPC::ChannelHandle* g_manifest_service_handle = nullptr; base::WaitableEvent* g_shutdown_event = NULL; base::Thread* g_io_thread = NULL; ManifestService* g_manifest_service = NULL; +bool IsValidChannelHandle(IPC::ChannelHandle* handle) { + // ChannelMojo not yet supported. + return handle && handle->socket.fd != -1 && !handle->mojo_handle.is_valid(); +} + // Creates the manifest service on IO thread so that its Listener's thread and // IO thread are shared. Upon completion of the manifest service creation, // event is signaled. void StartUpManifestServiceOnIOThread(base::WaitableEvent* event) { // The start up must be called only once. DCHECK(!g_manifest_service); - // manifest_service_fd must be set. - DCHECK_NE(g_manifest_service_fd, -1); + // manifest_service_handle must be set. + DCHECK(IsValidChannelHandle(g_manifest_service_handle)); // IOThread and shutdown event must be initialized in advance. DCHECK(g_io_thread); DCHECK(g_shutdown_event); g_manifest_service = new ManifestService( - IPC::ChannelHandle("NaCl IPC", - base::FileDescriptor(g_manifest_service_fd, false)), - g_io_thread->task_runner(), g_shutdown_event); + *g_manifest_service_handle, g_io_thread->task_runner(), + g_shutdown_event); event->Signal(); } } // namespace -void SetIPCFileDescriptors( - int browser_ipc_fd, int renderer_ipc_fd, int manifest_service_fd) { +void SetIPCChannelHandles( + IPC::ChannelHandle browser_ipc_handle, + IPC::ChannelHandle renderer_ipc_handle, + IPC::ChannelHandle manifest_service_handle) { // The initialization must be only once. - DCHECK_EQ(g_nacl_browser_ipc_fd, -1); - DCHECK_EQ(g_nacl_renderer_ipc_fd, -1); - DCHECK_EQ(g_manifest_service_fd, -1); - g_nacl_browser_ipc_fd = browser_ipc_fd; - g_nacl_renderer_ipc_fd = renderer_ipc_fd; - g_manifest_service_fd = manifest_service_fd; + DCHECK(!g_nacl_browser_ipc_handle); + DCHECK(!g_nacl_renderer_ipc_handle); + DCHECK(!g_nacl_renderer_ipc_handle); + g_nacl_browser_ipc_handle = new IPC::ChannelHandle(browser_ipc_handle); + g_nacl_renderer_ipc_handle = new IPC::ChannelHandle(renderer_ipc_handle); + g_manifest_service_handle = new IPC::ChannelHandle(manifest_service_handle); } void StartUpPlugin() { @@ -74,7 +80,7 @@ g_io_thread->StartWithOptions( base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); - if (g_manifest_service_fd != -1) { + if (IsValidChannelHandle(g_manifest_service_handle)) { // Manifest service must be created on IOThread so that the main message // handling will be done on the thread, which has a message loop // even before irt_ppapi_start invocation. @@ -91,16 +97,16 @@ PPB_Audio_Shared::SetNaClMode(); } -int GetBrowserIPCFileDescriptor() { - // The descriptor must be initialized in advance. - DCHECK_NE(g_nacl_browser_ipc_fd, -1); - return g_nacl_browser_ipc_fd; +IPC::ChannelHandle GetBrowserIPCChannelHandle() { + // The handle must be initialized in advance. + DCHECK(IsValidChannelHandle(g_nacl_browser_ipc_handle)); + return *g_nacl_browser_ipc_handle; } -int GetRendererIPCFileDescriptor() { - // The descriptor must be initialized in advance. - DCHECK_NE(g_nacl_renderer_ipc_fd, -1); - return g_nacl_renderer_ipc_fd; +IPC::ChannelHandle GetRendererIPCChannelHandle() { + // The handle must be initialized in advance. + DCHECK(IsValidChannelHandle(g_nacl_renderer_ipc_handle)); + return *g_nacl_renderer_ipc_handle; } base::WaitableEvent* GetShutdownEvent() {
diff --git a/ppapi/nacl_irt/plugin_startup.h b/ppapi/nacl_irt/plugin_startup.h index 2684a783..06ce229d 100644 --- a/ppapi/nacl_irt/plugin_startup.h +++ b/ppapi/nacl_irt/plugin_startup.h
@@ -5,6 +5,7 @@ #ifndef PPAPI_NACL_IRT_PLUGIN_STARTUP_H_ #define PPAPI_NACL_IRT_PLUGIN_STARTUP_H_ +#include "ipc/ipc_channel_handle.h" #include "ppapi/proxy/ppapi_proxy_export.h" namespace base { @@ -16,22 +17,24 @@ class ManifestService; -// Sets the IPC channels for the browser and the renderer by the given FD -// numbers. This will be used for non-SFI mode. Must be called before the +// Sets the IPC channels for the browser and the renderer. +// This will be used for non-SFI mode. Must be called before the // ppapi_start() IRT interface is called. -PPAPI_PROXY_EXPORT void SetIPCFileDescriptors( - int browser_ipc_fd, int renderer_ipc_fd, int manifest_service_fd); +PPAPI_PROXY_EXPORT void SetIPCChannelHandles( + IPC::ChannelHandle browser_ipc_handle, + IPC::ChannelHandle renderer_ipc_handle, + IPC::ChannelHandle manifest_service_handle); // Runs start up procedure for the plugin. // Specifically, start background IO thread for IPC, and prepare // shutdown event instance. PPAPI_PROXY_EXPORT void StartUpPlugin(); -// Returns IPC file descriptor for PPAPI to the browser. -int GetBrowserIPCFileDescriptor(); +// Returns IPC channel handle for PPAPI to the browser. +IPC::ChannelHandle GetBrowserIPCChannelHandle(); -// Returns IPC file descriptor for PPAPI to the renderer. -int GetRendererIPCFileDescriptor(); +// Returns IPC channel handle for PPAPI to the renderer. +IPC::ChannelHandle GetRendererIPCChannelHandle(); // Returns the shutdown event instance for the plugin. // Must be called after StartUpPlugin(). @@ -40,8 +43,8 @@ // Returns the IOThread for the plugin. Must be called after StartUpPlugin(). base::Thread* GetIOThread(); -// Returns the ManifestService interface. To use this, manifest_service_fd -// needs to be set via SetIPCFileDescriptors. Must be called after +// Returns the ManifestService interface. To use this, manifest_service_handle +// needs to be set via SetIPCChannelHandles. Must be called after // StartUpPlugin(). // If not available, returns NULL. ManifestService* GetManifestService();
diff --git a/ppapi/nacl_irt/ppapi_dispatcher.cc b/ppapi/nacl_irt/ppapi_dispatcher.cc index 8fd69bc..789a75c 100644 --- a/ppapi/nacl_irt/ppapi_dispatcher.cc +++ b/ppapi/nacl_irt/ppapi_dispatcher.cc
@@ -34,15 +34,12 @@ PpapiDispatcher::PpapiDispatcher( scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, base::WaitableEvent* shutdown_event, - int browser_ipc_fd, - int renderer_ipc_fd) + IPC::ChannelHandle browser_ipc_handle, + IPC::ChannelHandle renderer_ipc_handle) : next_plugin_dispatcher_id_(0), task_runner_(io_task_runner), shutdown_event_(shutdown_event), - renderer_ipc_fd_(renderer_ipc_fd) { - IPC::ChannelHandle channel_handle( - "NaCl IPC", base::FileDescriptor(browser_ipc_fd, false)); - + renderer_ipc_handle_(renderer_ipc_handle) { proxy::PluginGlobals* globals = proxy::PluginGlobals::Get(); // Delay initializing the SyncChannel until after we add filters. This // ensures that the filters won't miss any messages received by @@ -56,7 +53,7 @@ globals->RegisterResourceMessageFilters(plugin_filter.get()); channel_->AddFilter(new tracing::ChildTraceMessageFilter(task_runner_.get())); - channel_->Init(channel_handle, IPC::Channel::MODE_SERVER, true); + channel_->Init(browser_ipc_handle, IPC::Channel::MODE_SERVER, true); } base::SingleThreadTaskRunner* PpapiDispatcher::GetIPCTaskRunner() { @@ -184,11 +181,8 @@ proxy::PluginDispatcher* dispatcher = new proxy::PluginDispatcher(::PPP_GetInterface, args.permissions, args.off_the_record); - IPC::ChannelHandle channel_handle( - "nacl", - base::FileDescriptor(renderer_ipc_fd_, false)); if (!dispatcher->InitPluginWithChannel(this, base::kNullProcessId, - channel_handle, false)) { + renderer_ipc_handle_, false)) { delete dispatcher; return; }
diff --git a/ppapi/nacl_irt/ppapi_dispatcher.h b/ppapi/nacl_irt/ppapi_dispatcher.h index 4cb3b11..953db41 100644 --- a/ppapi/nacl_irt/ppapi_dispatcher.h +++ b/ppapi/nacl_irt/ppapi_dispatcher.h
@@ -14,6 +14,7 @@ #include "base/files/file.h" #include "base/memory/ref_counted.h" #include "base/process/process_handle.h" +#include "ipc/ipc_channel_handle.h" #include "ipc/ipc_listener.h" #include "ipc/ipc_platform_file.h" #include "ipc/ipc_sender.h" @@ -50,8 +51,8 @@ public: PpapiDispatcher(scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, base::WaitableEvent* shutdown_event, - int browser_ipc_fd, - int renderer_ipc_fd); + IPC::ChannelHandle browser_ipc_handle, + IPC::ChannelHandle renderer_ipc_handle); // PluginDispatcher::PluginDelegate implementation. base::SingleThreadTaskRunner* GetIPCTaskRunner() override; @@ -94,7 +95,7 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner_; base::WaitableEvent* shutdown_event_; - int renderer_ipc_fd_; + IPC::ChannelHandle renderer_ipc_handle_; std::unique_ptr<IPC::SyncChannel> channel_; };
diff --git a/ppapi/ppapi_internal.gyp b/ppapi/ppapi_internal.gyp index 99b4652d..a1d53b0 100644 --- a/ppapi/ppapi_internal.gyp +++ b/ppapi/ppapi_internal.gyp
@@ -53,6 +53,7 @@ '../media/media.gyp:shared_memory_support', '../skia/skia.gyp:skia', '../third_party/icu/icu.gyp:icuuc', + '../ui/gfx/gfx.gyp:gfx_geometry', '../ui/surface/surface.gyp:surface', '../url/url.gyp:url_lib', 'ppapi.gyp:ppapi_c', @@ -87,6 +88,7 @@ '../gpu/gpu.gyp:command_buffer_traits', '../ipc/ipc.gyp:ipc', '../skia/skia.gyp:skia', + '../ui/gfx/ipc/geometry/gfx_ipc_geometry.gyp:gfx_ipc_geometry', 'ppapi.gyp:ppapi_c', 'ppapi_shared', ], @@ -168,6 +170,7 @@ '../third_party/icu/icu.gyp:icuuc', '../third_party/icu/icu.gyp:icui18n', '../ui/gfx/gfx.gyp:gfx_geometry', + '../ui/gfx/ipc/geometry/gfx_ipc_geometry.gyp:gfx_ipc_geometry', '../ui/surface/surface.gyp:surface', 'ppapi.gyp:ppapi_c', 'ppapi_shared', @@ -221,6 +224,7 @@ '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations_win64', '../gpu/gpu.gyp:command_buffer_common_win64', '../ipc/ipc.gyp:ipc_win64', + '../ui/gfx/gfx.gyp:gfx_geometry_win64', ], 'defines': [ '<@(nacl_win64_defines)', @@ -247,6 +251,8 @@ '../base/base.gyp:base_win64', '../ipc/ipc.gyp:ipc_win64', '../gpu/gpu.gyp:command_buffer_traits_win64', + '../ui/gfx/gfx.gyp:gfx_geometry_win64', + '../ui/gfx/ipc/geometry/gfx_ipc_geometry.gyp:gfx_ipc_geometry_win64', 'ppapi.gyp:ppapi_c', 'ppapi_shared_win64', ],
diff --git a/ppapi/ppapi_proxy_nacl.gyp b/ppapi/ppapi_proxy_nacl.gyp index 1f194792..dd49bb30 100644 --- a/ppapi/ppapi_proxy_nacl.gyp +++ b/ppapi/ppapi_proxy_nacl.gyp
@@ -47,6 +47,8 @@ '../ppapi/ppapi_shared_nacl.gyp:ppapi_shared_nacl', '../third_party/WebKit/public/blink_headers.gyp:blink_headers', '../third_party/khronos/khronos.gyp:khronos_headers', + '../ui/gfx/gfx_nacl.gyp:gfx_geometry_nacl', + '../ui/gfx/ipc/geometry/gfx_ipc_geometry_nacl.gyp:gfx_ipc_geometry_nacl', ], }, ],
diff --git a/ppapi/ppapi_shared_nacl.gyp b/ppapi/ppapi_shared_nacl.gyp index 05e4aca..c292a34 100644 --- a/ppapi/ppapi_shared_nacl.gyp +++ b/ppapi/ppapi_shared_nacl.gyp
@@ -38,6 +38,7 @@ '../gpu/gpu_nacl.gyp:gles2_implementation_nacl', '../media/media_nacl.gyp:shared_memory_support_nacl', '../third_party/khronos/khronos.gyp:khronos_headers', + '../ui/gfx/gfx_nacl.gyp:gfx_geometry_nacl', ], }, ],
diff --git a/ppapi/ppapi_tests.gypi b/ppapi/ppapi_tests.gypi index 9fdc8025..f6ff8e6 100644 --- a/ppapi/ppapi_tests.gypi +++ b/ppapi/ppapi_tests.gypi
@@ -209,6 +209,7 @@ '../skia/skia.gyp:skia', '../testing/gmock.gyp:gmock', '../testing/gtest.gyp:gtest', + '../ui/gfx/gfx.gyp:gfx_geometry', '../ui/surface/surface.gyp:surface', ], 'sources': [
diff --git a/ppapi/proxy/BUILD.gn b/ppapi/proxy/BUILD.gn index fd36af7..b50b61a 100644 --- a/ppapi/proxy/BUILD.gn +++ b/ppapi/proxy/BUILD.gn
@@ -287,6 +287,8 @@ "//mojo/edk/system", "//ppapi/c", "//ppapi/shared_impl", + "//ui/gfx/geometry", + "//ui/gfx/ipc/geometry", ] if (!is_nacl) {
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index eaf2feb..968fe57 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h
@@ -1087,11 +1087,10 @@ // after this message is sent. IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBGraphics3D_TakeFrontBuffer, ppapi::HostResource /* graphics_3d */) -IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBGraphics3D_SwapBuffers, +IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBGraphics3D_SwapBuffers, ppapi::HostResource /* graphics_3d */, gpu::SyncToken /* sync_token */, - int32_t /* width*/, - int32_t /* height*/) + gfx::Size /* size */) IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBGraphics3D_EnsureWorkVisible, ppapi::HostResource /* context */)
diff --git a/ppapi/proxy/ppb_graphics_3d_proxy.cc b/ppapi/proxy/ppb_graphics_3d_proxy.cc index ac08224..7725330b 100644 --- a/ppapi/proxy/ppb_graphics_3d_proxy.cc +++ b/ppapi/proxy/ppb_graphics_3d_proxy.cc
@@ -48,8 +48,8 @@ } // namespace -Graphics3D::Graphics3D(const HostResource& resource) - : PPB_Graphics3D_Shared(resource) { +Graphics3D::Graphics3D(const HostResource& resource, const gfx::Size& size) + : PPB_Graphics3D_Shared(resource, size) { } Graphics3D::~Graphics3D() { @@ -118,8 +118,7 @@ } int32_t Graphics3D::DoSwapBuffers(const gpu::SyncToken& sync_token, - int32_t width, - int32_t height) { + const gfx::Size& size) { // A valid sync token would indicate a swap buffer already happened somehow. DCHECK(!sync_token.HasData()); @@ -137,8 +136,7 @@ gl->GenSyncTokenCHROMIUM(fence_sync, new_sync_token.GetData()); IPC::Message* msg = new PpapiHostMsg_PPBGraphics3D_SwapBuffers( - API_ID_PPB_GRAPHICS_3D, host_resource(), new_sync_token, width, - height); + API_ID_PPB_GRAPHICS_3D, host_resource(), new_sync_token, size); msg->set_unblock(true); PluginDispatcher::GetForResource(this)->Send(msg); @@ -215,7 +213,8 @@ if (result.is_null()) return 0; - scoped_refptr<Graphics3D> graphics_3d(new Graphics3D(result)); + scoped_refptr<Graphics3D> graphics_3d( + new Graphics3D(result, attrib_helper.offscreen_framebuffer_size)); if (!graphics_3d->Init(share_gles2, capabilities, shared_state, command_buffer_id)) { return 0; @@ -361,14 +360,13 @@ void PPB_Graphics3D_Proxy::OnMsgSwapBuffers(const HostResource& context, const gpu::SyncToken& sync_token, - int32_t width, - int32_t height) { + const gfx::Size& size) { EnterHostFromHostResourceForceCallback<PPB_Graphics3D_API> enter( context, callback_factory_, &PPB_Graphics3D_Proxy::SendSwapBuffersACKToPlugin, context); if (enter.succeeded()) enter.SetResult(enter.object()->SwapBuffersWithSyncToken( - enter.callback(), sync_token, width, height)); + enter.callback(), sync_token, size)); } void PPB_Graphics3D_Proxy::OnMsgTakeFrontBuffer(const HostResource& context) {
diff --git a/ppapi/proxy/ppb_graphics_3d_proxy.h b/ppapi/proxy/ppb_graphics_3d_proxy.h index 2ae06e9..54c4c7a7 100644 --- a/ppapi/proxy/ppb_graphics_3d_proxy.h +++ b/ppapi/proxy/ppb_graphics_3d_proxy.h
@@ -39,7 +39,7 @@ class PPAPI_PROXY_EXPORT Graphics3D : public PPB_Graphics3D_Shared { public: - explicit Graphics3D(const HostResource& resource); + Graphics3D(const HostResource& resource, const gfx::Size& size); ~Graphics3D() override; bool Init(gpu::gles2::GLES2Implementation* share_gles2, @@ -65,8 +65,7 @@ gpu::CommandBuffer* GetCommandBuffer() override; gpu::GpuControl* GetGpuControl() override; int32_t DoSwapBuffers(const gpu::SyncToken& sync_token, - int32_t width, - int32_t height) override; + const gfx::Size& size) override; std::unique_ptr<PpapiCommandBufferProxy> command_buffer_; @@ -116,8 +115,7 @@ void OnMsgDestroyTransferBuffer(const HostResource& context, int32_t id); void OnMsgSwapBuffers(const HostResource& context, const gpu::SyncToken& sync_token, - int32_t width, - int32_t height); + const gfx::Size& size); void OnMsgTakeFrontBuffer(const HostResource& context); void OnMsgEnsureWorkVisible(const HostResource& context); // Renderer->plugin message handlers.
diff --git a/ppapi/proxy/video_decoder_resource_unittest.cc b/ppapi/proxy/video_decoder_resource_unittest.cc index a8e3c4fb..80c28035 100644 --- a/ppapi/proxy/video_decoder_resource_unittest.cc +++ b/ppapi/proxy/video_decoder_resource_unittest.cc
@@ -109,7 +109,7 @@ HostResource host_resource; host_resource.SetHostResource(pp_instance(), kGraphics3D); scoped_refptr<ppapi::proxy::Graphics3D> graphics_3d( - new ppapi::proxy::Graphics3D(host_resource)); + new ppapi::proxy::Graphics3D(host_resource, gfx::Size(640, 480))); return graphics_3d->GetReference(); }
diff --git a/ppapi/shared_impl/DEPS b/ppapi/shared_impl/DEPS index 3947af12..7f786933 100644 --- a/ppapi/shared_impl/DEPS +++ b/ppapi/shared_impl/DEPS
@@ -4,6 +4,7 @@ "+media/audio", "+media/base", "+skia", + "+ui/gfx/geometry", "-ppapi/cpp", "-ppapi/proxy",
diff --git a/ppapi/shared_impl/file_ref_util.cc b/ppapi/shared_impl/file_ref_util.cc index d111f69..a517b3f 100644 --- a/ppapi/shared_impl/file_ref_util.cc +++ b/ppapi/shared_impl/file_ref_util.cc
@@ -52,7 +52,7 @@ } void NormalizeInternalPath(std::string* path) { - if (path->size() > 1 && path->at(path->size() - 1) == '/') + if (path->size() > 1 && path->back() == '/') path->erase(path->size() - 1, 1); }
diff --git a/ppapi/shared_impl/ppb_graphics_3d_shared.cc b/ppapi/shared_impl/ppb_graphics_3d_shared.cc index 0c40b4cb..4d3a4b06 100644 --- a/ppapi/shared_impl/ppb_graphics_3d_shared.cc +++ b/ppapi/shared_impl/ppb_graphics_3d_shared.cc
@@ -17,8 +17,9 @@ PPB_Graphics3D_Shared::PPB_Graphics3D_Shared(PP_Instance instance) : Resource(OBJECT_IS_IMPL, instance) {} -PPB_Graphics3D_Shared::PPB_Graphics3D_Shared(const HostResource& host_resource) - : Resource(OBJECT_IS_PROXY, host_resource) {} +PPB_Graphics3D_Shared::PPB_Graphics3D_Shared(const HostResource& host_resource, + const gfx::Size& size) + : Resource(OBJECT_IS_PROXY, host_resource), size_(size) {} PPB_Graphics3D_Shared::~PPB_Graphics3D_Shared() { // Make sure that GLES2 implementation has already been destroyed. @@ -51,22 +52,20 @@ return PP_ERROR_BADARGUMENT; gles2_impl()->ResizeCHROMIUM(width, height, 1.f, true); - width_ = width; - height_ = height; + size_ = gfx::Size(width, height); // TODO(alokp): Check if resize succeeded and return appropriate error code. return PP_OK; } int32_t PPB_Graphics3D_Shared::SwapBuffers( scoped_refptr<TrackedCallback> callback) { - return SwapBuffersWithSyncToken(callback, gpu::SyncToken(), width_, height_); + return SwapBuffersWithSyncToken(callback, gpu::SyncToken(), size_); } int32_t PPB_Graphics3D_Shared::SwapBuffersWithSyncToken( scoped_refptr<TrackedCallback> callback, const gpu::SyncToken& sync_token, - int32_t width, - int32_t height) { + const gfx::Size& size) { if (HasPendingSwap()) { Log(PP_LOGLEVEL_ERROR, "PPB_Graphics3D.SwapBuffers: Plugin attempted swap " @@ -76,7 +75,7 @@ } swap_callback_ = callback; - return DoSwapBuffers(sync_token, width, height); + return DoSwapBuffers(sync_token, size); } int32_t PPB_Graphics3D_Shared::GetAttribMaxValue(int32_t attribute,
diff --git a/ppapi/shared_impl/ppb_graphics_3d_shared.h b/ppapi/shared_impl/ppb_graphics_3d_shared.h index 4c8a1ab6..84bad21d 100644 --- a/ppapi/shared_impl/ppb_graphics_3d_shared.h +++ b/ppapi/shared_impl/ppb_graphics_3d_shared.h
@@ -15,6 +15,7 @@ #include "ppapi/shared_impl/resource.h" #include "ppapi/shared_impl/tracked_callback.h" #include "ppapi/thunk/ppb_graphics_3d_api.h" +#include "ui/gfx/geometry/size.h" namespace gpu { class CommandBuffer; @@ -44,8 +45,7 @@ int32_t SwapBuffers(scoped_refptr<TrackedCallback> callback) override; int32_t SwapBuffersWithSyncToken(scoped_refptr<TrackedCallback> callback, const gpu::SyncToken& sync_token, - int32_t width, - int32_t height) override; + const gfx::Size& size) override; int32_t GetAttribMaxValue(int32_t attribute, int32_t* value) override; void* MapTexSubImage2DCHROMIUM(GLenum target, @@ -67,14 +67,14 @@ protected: PPB_Graphics3D_Shared(PP_Instance instance); - PPB_Graphics3D_Shared(const HostResource& host_resource); + PPB_Graphics3D_Shared(const HostResource& host_resource, + const gfx::Size& size); ~PPB_Graphics3D_Shared() override; virtual gpu::CommandBuffer* GetCommandBuffer() = 0; virtual gpu::GpuControl* GetGpuControl() = 0; virtual int32_t DoSwapBuffers(const gpu::SyncToken& sync_token, - int32_t width, - int32_t height) = 0; + const gfx::Size& size) = 0; bool HasPendingSwap() const; bool CreateGLES2Impl(int32_t command_buffer_size, @@ -87,9 +87,9 @@ std::unique_ptr<gpu::TransferBuffer> transfer_buffer_; std::unique_ptr<gpu::gles2::GLES2Implementation> gles2_impl_; - // A local cache of the size of the viewport. - int32_t width_ = -1; - int32_t height_ = -1; + // A local cache of the size of the viewport. This is only valid in plugin + // resources. + gfx::Size size_; // Callback that needs to be executed when swap-buffers is completed. scoped_refptr<TrackedCallback> swap_callback_;
diff --git a/ppapi/tests/test_case.html b/ppapi/tests/test_case.html index 529c9744..e28091e7 100644 --- a/ppapi/tests/test_case.html +++ b/ppapi/tests/test_case.html
@@ -60,8 +60,9 @@ return; // Otherwise, we are in a subframe, so we can use this opportunity to resize - // ourselves. - AdjustHeight(window); + // ourselves. This can only be done if the parent frame has the same origin. + if (window.frameElement) + AdjustHeight(window); } function AppendFrame(testcase, i) {
diff --git a/ppapi/thunk/ppb_graphics_3d_api.h b/ppapi/thunk/ppb_graphics_3d_api.h index 9c2e312..8d590ec9 100644 --- a/ppapi/thunk/ppb_graphics_3d_api.h +++ b/ppapi/thunk/ppb_graphics_3d_api.h
@@ -13,6 +13,10 @@ #include "ppapi/c/ppb_graphics_3d.h" #include "ppapi/thunk/ppapi_thunk_export.h" +namespace gfx { +class Size; +} + namespace gpu { struct SyncToken; } @@ -36,8 +40,7 @@ virtual int32_t SwapBuffersWithSyncToken( scoped_refptr<TrackedCallback> callback, const gpu::SyncToken& sync_token, - int32_t width, - int32_t height) = 0; + const gfx::Size& size) = 0; virtual int32_t GetAttribMaxValue(int32_t attribute, int32_t* value) = 0; // Graphics3DTrusted API.
diff --git a/remoting/android/BUILD.gn b/remoting/android/BUILD.gn index 5941237..067f30b 100644 --- a/remoting/android/BUILD.gn +++ b/remoting/android/BUILD.gn
@@ -26,6 +26,7 @@ "//remoting/android:jni_headers", "//remoting/base", "//remoting/client", + "//remoting/client:opengl_renderer", "//remoting/protocol", "//ui/events:dom_keycode_converter", "//ui/gfx",
diff --git a/remoting/android/java/src/org/chromium/chromoting/AbstractDesktopView.java b/remoting/android/java/src/org/chromium/chromoting/AbstractDesktopView.java index 63202bc..06f51a4 100644 --- a/remoting/android/java/src/org/chromium/chromoting/AbstractDesktopView.java +++ b/remoting/android/java/src/org/chromium/chromoting/AbstractDesktopView.java
@@ -8,8 +8,6 @@ import android.graphics.Point; import android.view.SurfaceView; -import org.chromium.chromoting.jni.Client; - /** * Callback interface to allow the TouchInputHandler to request actions on the DesktopView. */ @@ -18,12 +16,6 @@ super(context); } - /** - * Initializes the instance. Implementations can assume this function will be called exactly - * once after constructor but before other functions. - */ - public abstract void init(Desktop desktop, Client client); - /** Triggers a brief animation to indicate the existence and location of an input event. */ public abstract void showInputFeedback(DesktopView.InputFeedbackType feedbackToShow, Point pos);
diff --git a/remoting/android/java/src/org/chromium/chromoting/Desktop.java b/remoting/android/java/src/org/chromium/chromoting/Desktop.java index d328a030..81e454b 100644 --- a/remoting/android/java/src/org/chromium/chromoting/Desktop.java +++ b/remoting/android/java/src/org/chromium/chromoting/Desktop.java
@@ -105,11 +105,10 @@ mToolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(mToolbar); - AbstractDesktopView remoteHostDesktop = mClient.createDesktopView(this); + AbstractDesktopView remoteHostDesktop = mClient.createDesktopView(this, mClient); remoteHostDesktop.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); ((ViewGroup) findViewById(R.id.desktop_view_placeholder)).addView(remoteHostDesktop); - remoteHostDesktop.init(this, mClient); mSwitchToCardboardDesktopActivity = false; getSupportActionBar().setDisplayShowTitleEnabled(false);
diff --git a/remoting/android/java/src/org/chromium/chromoting/DesktopView.java b/remoting/android/java/src/org/chromium/chromoting/DesktopView.java index 56e3a8b..57b8a7c 100644 --- a/remoting/android/java/src/org/chromium/chromoting/DesktopView.java +++ b/remoting/android/java/src/org/chromium/chromoting/DesktopView.java
@@ -39,12 +39,9 @@ private final TouchInputHandler mInputHandler; /** The parent Desktop activity. */ - private Desktop mDesktop; + private final Desktop mDesktop; - /** The Client connection, used to inject input and fetch the video frames. */ - private Client mClient; - - private Display mDisplay; + private final Display mDisplay; // Flag to prevent multiple repaint requests from being backed up. Requests for repainting will @@ -72,17 +69,20 @@ /** Whether the TouchInputHandler has requested animation to be performed. */ private boolean mInputAnimationRunning = false; - public DesktopView(Context context, Display display) { - super(context); - + public DesktopView(Display display, Desktop desktop, Client client) { + super(desktop); Preconditions.notNull(display); + Preconditions.notNull(desktop); + Preconditions.notNull(client); mDisplay = display; + mDesktop = desktop; // Give this view keyboard focus, allowing us to customize the soft keyboard's settings. setFocusableInTouchMode(true); mRenderData = new RenderData(); - mInputHandler = new TouchInputHandler(this, context, mRenderData); + mInputHandler = new TouchInputHandler(this, desktop, mRenderData); + mInputHandler.init(desktop, new InputEventSender(client)); mRepaintPending = false; @@ -91,17 +91,6 @@ attachRedrawCallback(); } - @Override - public void init(Desktop desktop, Client client) { - Preconditions.isNull(mDesktop); - Preconditions.isNull(mClient); - Preconditions.notNull(desktop); - Preconditions.notNull(client); - mDesktop = desktop; - mClient = client; - mInputHandler.init(desktop, new InputEventSender(client)); - } - public Event<PaintEventParameter> onPaint() { return mOnPaint; }
diff --git a/remoting/android/java/src/org/chromium/chromoting/DesktopViewFactory.java b/remoting/android/java/src/org/chromium/chromoting/DesktopViewFactory.java index 3cb55ba..fd51d5d5 100644 --- a/remoting/android/java/src/org/chromium/chromoting/DesktopViewFactory.java +++ b/remoting/android/java/src/org/chromium/chromoting/DesktopViewFactory.java
@@ -4,7 +4,7 @@ package org.chromium.chromoting; -import android.content.Context; +import org.chromium.chromoting.jni.Client; /** * Interface for creating a implementation specific desktop view. @@ -14,5 +14,5 @@ * Creates an uninitialized implementation specific desktop view. Initializing and adding the * view should done separately. */ - AbstractDesktopView createDesktopView(Context context); + AbstractDesktopView createDesktopView(Desktop desktop, Client client); }
diff --git a/remoting/android/java/src/org/chromium/chromoting/jni/Client.java b/remoting/android/java/src/org/chromium/chromoting/jni/Client.java index 3a8114d..3373c07 100644 --- a/remoting/android/java/src/org/chromium/chromoting/jni/Client.java +++ b/remoting/android/java/src/org/chromium/chromoting/jni/Client.java
@@ -11,6 +11,7 @@ import org.chromium.base.annotations.SuppressFBWarnings; import org.chromium.chromoting.AbstractDesktopView; import org.chromium.chromoting.CapabilityManager; +import org.chromium.chromoting.Desktop; import org.chromium.chromoting.DesktopViewFactory; import org.chromium.chromoting.InputStub; import org.chromium.chromoting.Preconditions; @@ -45,20 +46,20 @@ } /** - * Sets the desktop view factory. Called by the native code when the connection starts. + * Sets the desktop view factory to be used by {@link Client#createDesktopView(Context)}. * @param factory The factory to create implementation-dependent desktop view. */ - @CalledByNative - private void setDesktopViewFactory(DesktopViewFactory factory) { + public void setDesktopViewFactory(DesktopViewFactory factory) { mDesktopViewFactory = factory; } /** - * Creates an implementation specific desktop view. + * Creates an implementation specific {@link AbstractDesktopView} using the + * {@link DesktopViewFactory} set by {@link Client#setDesktopViewFactory(DesktopViewFactory)}. */ - public AbstractDesktopView createDesktopView(Context context) { + public AbstractDesktopView createDesktopView(Desktop desktop, Client client) { Preconditions.notNull(mDesktopViewFactory); - return mDesktopViewFactory.createDesktopView(context); + return mDesktopViewFactory.createDesktopView(desktop, client); } // Suppress FindBugs warning, since |sClient| is only used on the UI thread.
diff --git a/remoting/android/java/src/org/chromium/chromoting/jni/Display.java b/remoting/android/java/src/org/chromium/chromoting/jni/Display.java index f7c7a10..926eb4f 100644 --- a/remoting/android/java/src/org/chromium/chromoting/jni/Display.java +++ b/remoting/android/java/src/org/chromium/chromoting/jni/Display.java
@@ -4,7 +4,6 @@ package org.chromium.chromoting.jni; -import android.content.Context; import android.graphics.Bitmap; import android.graphics.Point; import android.os.Looper; @@ -13,6 +12,7 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.chromoting.AbstractDesktopView; +import org.chromium.chromoting.Desktop; import org.chromium.chromoting.DesktopView; import org.chromium.chromoting.DesktopViewFactory; @@ -170,13 +170,13 @@ } @CalledByNative - private DesktopViewFactory createDesktopViewFactory() { - return new DesktopViewFactory() { + private void initializeClient(Client client) { + client.setDesktopViewFactory(new DesktopViewFactory() { @Override - public AbstractDesktopView createDesktopView(Context context) { - return new DesktopView(context, Display.this); + public AbstractDesktopView createDesktopView(Desktop desktop, Client client) { + return new DesktopView(Display.this, desktop, client); } - }; + }); } @CalledByNative
diff --git a/remoting/android/java/src/org/chromium/chromoting/jni/GlDisplay.java b/remoting/android/java/src/org/chromium/chromoting/jni/GlDisplay.java index 2c99bd2..0a32059 100644 --- a/remoting/android/java/src/org/chromium/chromoting/jni/GlDisplay.java +++ b/remoting/android/java/src/org/chromium/chromoting/jni/GlDisplay.java
@@ -4,12 +4,12 @@ package org.chromium.chromoting.jni; -import android.content.Context; import android.view.Surface; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.chromoting.AbstractDesktopView; +import org.chromium.chromoting.Desktop; import org.chromium.chromoting.DesktopViewFactory; import org.chromium.chromoting.Event; import org.chromium.chromoting.SizeChangedEventParameter; @@ -159,14 +159,14 @@ } @CalledByNative - private DesktopViewFactory createDesktopViewFactory() { - return new DesktopViewFactory() { + private void initializeClient(Client client) { + client.setDesktopViewFactory(new DesktopViewFactory() { @Override - public AbstractDesktopView createDesktopView(Context context) { + public AbstractDesktopView createDesktopView(Desktop desktop, Client client) { // UNIMPLEMENTED. return null; } - }; + }); } @CalledByNative
diff --git a/remoting/client/BUILD.gn b/remoting/client/BUILD.gn index d549eee..567876e 100644 --- a/remoting/client/BUILD.gn +++ b/remoting/client/BUILD.gn
@@ -41,6 +41,27 @@ } } +if (is_android || is_ios) { + source_set("opengl_renderer") { + sources = [ + "gl_canvas.cc", + "gl_canvas.h", + "gl_desktop.cc", + "gl_desktop.h", + "gl_helpers.cc", + "gl_helpers.h", + "gl_render_layer.cc", + "gl_render_layer.h", + ] + + deps = [ + "//third_party/webrtc", + ] + + configs += [ "//third_party/khronos:khronos_headers" ] + } +} + source_set("test_support") { testonly = true
diff --git a/remoting/client/gl_canvas.cc b/remoting/client/gl_canvas.cc new file mode 100644 index 0000000..74a3932b --- /dev/null +++ b/remoting/client/gl_canvas.cc
@@ -0,0 +1,113 @@ +// 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 "remoting/client/gl_canvas.h" + +#include "base/logging.h" +#include "remoting/client/gl_helpers.h" + +namespace { + +const int kVertexSize = 2; +const int kVertexCount = 4; + +const char kTexCoordToViewVert[] = + // Region of the texture to be used (normally the whole texture). + "varying vec2 v_texCoord;\n" + "attribute vec2 a_texCoord;\n" + + // Positions to draw the texture on the texture coordinates. + "attribute vec2 a_position;\n" + "uniform mat3 u_transform;\n" + + // This matrix translates normalized texture coordinates + // ([0, 1] starting at upper-left corner) to the view coordinates + // ([-1, 1] starting at the center of the screen). + // Note that the matrix is defined in column-major order. + "const mat3 tex_to_view = mat3(2, 0, 0,\n" + " 0, -2, 0,\n" + " -1, 1, 0);\n" + "void main() {\n" + " v_texCoord = a_texCoord;\n" + // Transforms coordinates related to the canvas to coordinates + // related to the view. + " vec3 trans_position = u_transform * vec3(a_position, 1.0);\n" + // Transforms texture coordinates to view coordinates and adds + // projection component 1. + " gl_Position = vec4(tex_to_view * trans_position, 1.0);\n" + "}"; + +const char kDrawTexFrag[] = + "precision mediump float;\n" + + // Region on the texture to be used (normally the whole texture). + "varying vec2 v_texCoord;\n" + "uniform sampler2D u_texture;\n" + "void main() {\n" + " gl_FragColor = texture2D(u_texture, v_texCoord);\n" + "}"; + +} // namespace + +namespace remoting { + +GlCanvas::GlCanvas(int gl_version) : gl_version_(gl_version) { + vertex_shader_ = CompileShader(GL_VERTEX_SHADER, kTexCoordToViewVert); + fragment_shader_ = CompileShader(GL_FRAGMENT_SHADER, kDrawTexFrag); + program_ = CreateProgram(vertex_shader_, fragment_shader_); + glUseProgram(program_); + + transform_location_ = glGetUniformLocation(program_, "u_transform"); + texture_location_ = glGetUniformLocation(program_, "u_texture"); + position_location_ = glGetAttribLocation(program_, "a_position"); + tex_cord_location_ = glGetAttribLocation(program_, "a_texCoord"); + glEnableVertexAttribArray(position_location_); + glEnableVertexAttribArray(tex_cord_location_); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} + +GlCanvas::~GlCanvas() { + DCHECK(thread_checker_.CalledOnValidThread()); + glDisable(GL_BLEND); + glDisableVertexAttribArray(tex_cord_location_); + glDisableVertexAttribArray(position_location_); + glDeleteProgram(program_); + glDeleteShader(vertex_shader_); + glDeleteShader(fragment_shader_); +} + +void GlCanvas::SetNormalizedTransformation(const std::array<float, 9>& matrix) { + DCHECK(thread_checker_.CalledOnValidThread()); + glUniformMatrix3fv(transform_location_, 1, GL_TRUE, matrix.data()); + transformation_set_ = true; +} + +void GlCanvas::DrawTexture(int texture_id, + GLuint texture_handle, + GLuint vertex_buffer) { + DCHECK(thread_checker_.CalledOnValidThread()); + if (!transformation_set_) { + return; + } + glActiveTexture(GL_TEXTURE0 + texture_id); + glBindTexture(GL_TEXTURE_2D, texture_handle); + glUniform1i(texture_location_, texture_id); + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); + + glVertexAttribPointer(position_location_, kVertexSize, GL_FLOAT, GL_FALSE, 0, + 0); + glVertexAttribPointer(tex_cord_location_, kVertexSize, GL_FLOAT, GL_FALSE, 0, + static_cast<float*>(0) + kVertexSize * kVertexCount); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, kVertexCount); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); +} + +int GlCanvas::GetGlVersion() const { + return gl_version_; +} + +} // namespace remoting
diff --git a/remoting/client/gl_canvas.h b/remoting/client/gl_canvas.h new file mode 100644 index 0000000..5a06273 --- /dev/null +++ b/remoting/client/gl_canvas.h
@@ -0,0 +1,82 @@ +// 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 REMOTING_CLIENT_OPENGL_GL_CANVAS_H_ +#define REMOTING_CLIENT_OPENGL_GL_CANVAS_H_ + +#include <array> + +#include "base/macros.h" +#include "base/threading/thread_checker.h" +#include "remoting/client/sys_opengl.h" + +namespace remoting { + +// This class holds zoom and pan configurations of the canvas and is used to +// draw textures on the canvas. +// Must be constructed after the OpenGL surface is created and destroyed before +// the surface is destroyed. +// +// Coordinates to be used for GlCanvas should be normalized texture coordinates. +// In the view of a point on the canvas, the canvas has width 1 and height 1, +// with the origin at the upper-left corner of the canvas. +class GlCanvas { + public: + // gl_version: version number of the OpenGL ES context. Either 2 or 3. + GlCanvas(int gl_version); + + ~GlCanvas(); + + // Sets the normalized transformation matrix. This matrix defines how the + // canvas should be shown on the view. + // 3 by 3 transformation matrix, [ m0, m1, m2, m3, m4, m5, m6, m7, m8 ]. + // The matrix will be multiplied with the positions (with projective space, + // (x, y, 1)) to draw the textures with the right zoom and pan configuration. + // + // | m0, m1, m2, | | x | + // | m3, m4, m5, | * | y | + // | m6, m7, m8 | | 1 | + // + // For a typical transformation matrix such that m1=m3=m6=m7=0 and m8=1, m0 + // and m4 defines the ratio of canvas width or height over view width or + // height. m2 and m5 defines the offset of the upper-left corner in percentage + // of the view's width or height. An identity matrix will stretch the canvas + // to fit the whole view. + void SetNormalizedTransformation(const std::array<float, 9>& matrix); + + // Draws the texture on the canvas. Nothing will happen if + // SetNormalizedTransformation() has not been called. + // vertex_buffer: reference to the 2x4x2 float vertex buffer. + // [ four (x, y) normalized vertex positions on the canvas, + // four (x, y) vertex positions to define the visible area ] + void DrawTexture(int texture_id, GLuint texture_handle, GLuint vertex_buffer); + + // Returns the version number of current OpenGL ES context. Either 2 or 3. + int GetGlVersion() const; + + private: + int gl_version_; + + // True IFF the transformation has been set. + bool transformation_set_ = false; + + // Handles. + GLuint vertex_shader_; + GLuint fragment_shader_; + GLuint program_; + + // Locations of the corresponding shader attributes. + GLuint transform_location_; + GLuint texture_location_; + GLuint position_location_; + GLuint tex_cord_location_; + + base::ThreadChecker thread_checker_; + + DISALLOW_COPY_AND_ASSIGN(GlCanvas); +}; + +} // namespace remoting + +#endif // REMOTING_CLIENT_OPENGL_GL_CANVAS_H_
diff --git a/remoting/client/gl_desktop.cc b/remoting/client/gl_desktop.cc new file mode 100644 index 0000000..a47506e --- /dev/null +++ b/remoting/client/gl_desktop.cc
@@ -0,0 +1,61 @@ +// 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 "remoting/client/gl_desktop.h" + +#include "base/logging.h" +#include "remoting/client/gl_canvas.h" +#include "remoting/client/gl_render_layer.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" + +namespace { + +const int kTextureId = 0; + +} // namespace + +namespace remoting { + +GlDesktop::GlDesktop() {} + +GlDesktop::~GlDesktop() {} + +void GlDesktop::SetCanvas(GlCanvas* canvas) { + if (!canvas) { + layer_.reset(); + return; + } + layer_.reset(new GlRenderLayer(kTextureId, canvas)); + if (last_frame_) { + layer_->SetTexture(last_frame_->data(), last_frame_->size().width(), + last_frame_->size().height()); + } +} + +void GlDesktop::SetVideoFrame(std::unique_ptr<webrtc::DesktopFrame> frame) { + if (layer_) { + if (!last_frame_ || !frame->size().equals(last_frame_->size())) { + layer_->SetTexture(frame->data(), frame->size().width(), + frame->size().height()); + } else { + for (webrtc::DesktopRegion::Iterator i(frame->updated_region()); + !i.IsAtEnd(); i.Advance()) { + const uint8_t* rect_start = + frame->GetFrameDataAtPos(i.rect().top_left()); + layer_->UpdateTexture( + rect_start, i.rect().left(), i.rect().top(), i.rect().width(), + i.rect().height(), frame->stride()); + } + } + } + last_frame_ = std::move(frame); +} + +void GlDesktop::Draw() { + if (layer_ && last_frame_) { + layer_->Draw(); + } +} + +} // namespace remoting
diff --git a/remoting/client/gl_desktop.h b/remoting/client/gl_desktop.h new file mode 100644 index 0000000..afdf0eb --- /dev/null +++ b/remoting/client/gl_desktop.h
@@ -0,0 +1,47 @@ +// 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 REMOTING_CLIENT_OPENGL_GL_DESKTOP_H_ +#define REMOTING_CLIENT_OPENGL_GL_DESKTOP_H_ + +#include <memory> + +#include "base/macros.h" + +namespace webrtc { +class DesktopFrame; +class DesktopRegion; +} // namespace webrtc + +namespace remoting { + +class GlCanvas; +class GlRenderLayer; + +// This class draws the desktop on the canvas. +class GlDesktop { + public: + GlDesktop(); + virtual ~GlDesktop(); + + void SetVideoFrame(std::unique_ptr<webrtc::DesktopFrame> frame); + + // Sets the canvas on which the desktop will be drawn. Resumes the current + // state of the desktop to the context of the new canvas. + // If |canvas| is nullptr, nothing will happen when calling Draw(). + void SetCanvas(GlCanvas* canvas); + + // Draws the desktop on the canvas. + void Draw(); + + private: + std::unique_ptr<GlRenderLayer> layer_; + std::unique_ptr<webrtc::DesktopFrame> last_frame_; + + DISALLOW_COPY_AND_ASSIGN(GlDesktop); +}; + +} // namespace remoting + +#endif // REMOTING_CLIENT_OPENGL_GL_DESKTOP_H_
diff --git a/remoting/client/gl_helpers.cc b/remoting/client/gl_helpers.cc new file mode 100644 index 0000000..5cd1863 --- /dev/null +++ b/remoting/client/gl_helpers.cc
@@ -0,0 +1,85 @@ +// 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 "remoting/client/gl_helpers.h" + +#include "base/logging.h" + +namespace remoting { + +GLuint CompileShader(GLenum shader_type, const char* shader_source) { + GLuint shader = glCreateShader(shader_type); + + if (shader != 0) { + int shader_source_length = strlen(shader_source); + // Pass in the shader source. + glShaderSource(shader, 1, &shader_source, &shader_source_length); + + // Compile the shader. + glCompileShader(shader); + + // Get the compilation status. + GLint compile_status; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); + + // If the compilation failed, delete the shader. + if (compile_status == GL_FALSE) { + LOG(ERROR) << "Error compiling shader: \n" << shader_source; + glDeleteShader(shader); + shader = 0; + } + } + + if (shader == 0) { + LOG(FATAL) << "Error creating shader."; + } + + return shader; +} + +GLuint CreateProgram(GLuint vertex_shader, GLuint fragment_shader) { + GLuint program = glCreateProgram(); + + if (program != 0) { + glAttachShader(program, vertex_shader); + glAttachShader(program, fragment_shader); + glLinkProgram(program); + + // Get the link status. + GLint link_status; + glGetProgramiv(program, GL_LINK_STATUS, &link_status); + // If the link failed, delete the program. + if (link_status == GL_FALSE) { + LOG(ERROR) << "Error compiling program."; + glDeleteProgram(program); + program = 0; + } + } + + if (program == 0) { + LOG(FATAL) << "Error creating program."; + } + + return program; +} + +GLuint CreateTexture() { + GLuint texture; + glGenTextures(1, &texture); + if (texture == 0) { + LOG(FATAL) << "Error creating texture."; + } + return texture; +} + +GLuint CreateBuffer(const void* data, int size) { + GLuint buffer; + glGenBuffers(1, &buffer); + glBindBuffer(GL_ARRAY_BUFFER, buffer); + glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + return buffer; +} + +} // namespace remoting
diff --git a/remoting/client/gl_helpers.h b/remoting/client/gl_helpers.h new file mode 100644 index 0000000..8dba721 --- /dev/null +++ b/remoting/client/gl_helpers.h
@@ -0,0 +1,29 @@ +// 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 REMOTING_CLIENT_GL_HELPERS_H_ +#define REMOTING_CLIENT_GL_HELPERS_H_ + +#include "base/macros.h" +#include "remoting/client/sys_opengl.h" + +namespace remoting { + +// Compiles a shader and returns the reference to the shader if it succeeds. +GLuint CompileShader(GLenum shader_type, const char* shader_source); + +// Creates a program with the given reference to the vertex shader and fragment +// shader. returns the reference of the program if it succeeds. +GLuint CreateProgram(GLuint vertex_shader, GLuint fragment_shader); + +// Creates and returns the texture names if it succeeds. +GLuint CreateTexture(); + +// Creates a GL_ARRAY_BUFFER and fills it with |data|. Returns the reference to +// the buffer. +GLuint CreateBuffer(const void* data, int size); + +} // namespace remoting + +#endif // REMOTING_CLIENT_GL_HELPERS_H_
diff --git a/remoting/client/gl_render_layer.cc b/remoting/client/gl_render_layer.cc new file mode 100644 index 0000000..836bcb9 --- /dev/null +++ b/remoting/client/gl_render_layer.cc
@@ -0,0 +1,143 @@ +// 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 "remoting/client/gl_render_layer.h" + +#include "base/logging.h" +#include "remoting/client/gl_canvas.h" +#include "remoting/client/gl_helpers.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" + +namespace { + +// Assign texture coordinates to buffers for use in shader program. +const float kVertices[] = { + // Points order: upper-left, bottom-left, upper-right, bottom-right. + + // Positions to draw the texture on the normalized canvas coordinate. + 0, 0, 0, 1, 1, 0, 1, 1, + + // Region of the texture to be used (normally the whole texture). + 0, 0, 0, 1, 1, 0, 1, 1}; + +const int kDefaultUpdateBufferCapacity = + 2048 * 2048 * webrtc::DesktopFrame::kBytesPerPixel; + +} + +namespace remoting { + +GlRenderLayer::GlRenderLayer(int texture_id, GlCanvas* canvas) + : texture_id_(texture_id), canvas_(canvas) { + texture_handle_ = CreateTexture(); + buffer_handle_ = CreateBuffer(kVertices, sizeof(kVertices)); +} + +GlRenderLayer::~GlRenderLayer() { + DCHECK(thread_checker_.CalledOnValidThread()); + glDeleteBuffers(1, &buffer_handle_); + glDeleteTextures(1, &texture_handle_); +} + +void GlRenderLayer::SetTexture(const uint8_t* texture, int width, int height) { + DCHECK(thread_checker_.CalledOnValidThread()); + CHECK(width > 0 && height > 0); + texture_set_ = true; + glActiveTexture(GL_TEXTURE0 + texture_id_); + glBindTexture(GL_TEXTURE_2D, texture_handle_); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glBindTexture(GL_TEXTURE_2D, 0); +} + +void PackDirtyRegion(uint8_t* dest, + const uint8_t* source, + int width, + int height, + int stride) { + for (int i = 0; i < height; i++) { + memcpy(dest, source, width * webrtc::DesktopFrame::kBytesPerPixel); + source += stride; + dest += webrtc::DesktopFrame::kBytesPerPixel * width; + } +} + +void GlRenderLayer::UpdateTexture(const uint8_t* subtexture, + int offset_x, + int offset_y, + int width, + int height, + int stride) { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(texture_set_); + DCHECK(width > 0 && height > 0); + glActiveTexture(GL_TEXTURE0 + texture_id_); + glBindTexture(GL_TEXTURE_2D, texture_handle_); + + bool stride_multiple_of_bytes_per_pixel = + stride % webrtc::DesktopFrame::kBytesPerPixel == 0; + bool loosely_packed = + !stride_multiple_of_bytes_per_pixel || + (stride > 0 && stride != webrtc::DesktopFrame::kBytesPerPixel * width); + + const void* buffer_to_update = subtexture; + + if (loosely_packed) { + if (stride_multiple_of_bytes_per_pixel && canvas_->GetGlVersion() >= 3) { + glPixelStorei(GL_UNPACK_ROW_LENGTH, + stride / webrtc::DesktopFrame::kBytesPerPixel); + } else { + // Doesn't support GL_UNPACK_ROW_LENGTH or stride not multiple of + // kBytesPerPixel. Manually pack the data. + int required_size = width * height * webrtc::DesktopFrame::kBytesPerPixel; + if (update_buffer_size_ < required_size) { + if (required_size < kDefaultUpdateBufferCapacity) { + update_buffer_size_ = kDefaultUpdateBufferCapacity; + } else { + update_buffer_size_ = required_size; + } + update_buffer_.reset(new uint8_t[update_buffer_size_]); + } + PackDirtyRegion(update_buffer_.get(), subtexture, width, height, stride); + buffer_to_update = update_buffer_.get(); + } + } + + glTexSubImage2D(GL_TEXTURE_2D, 0, offset_x, offset_y, width, height, GL_RGBA, + GL_UNSIGNED_BYTE, buffer_to_update); + + if (loosely_packed && stride_multiple_of_bytes_per_pixel && + canvas_->GetGlVersion() >= 3) { + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + } + glBindTexture(GL_TEXTURE_2D, 0); +} + +void GlRenderLayer::SetVertexPositions(const std::array<float, 8>& positions) { + DCHECK(thread_checker_.CalledOnValidThread()); + glBindBuffer(GL_ARRAY_BUFFER, buffer_handle_); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(kVertices) / 2, positions.data()); + glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +void GlRenderLayer::SetTextureVisibleArea( + const std::array<float, 8>& positions) { + DCHECK(thread_checker_.CalledOnValidThread()); + glBindBuffer(GL_ARRAY_BUFFER, buffer_handle_); + glBufferSubData(GL_ARRAY_BUFFER, sizeof(kVertices) / 2, sizeof(kVertices) / 2, + positions.data()); + glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +void GlRenderLayer::Draw() { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(texture_set_); + canvas_->DrawTexture(texture_id_, texture_handle_, buffer_handle_); +} + +} // namespace remoting
diff --git a/remoting/client/gl_render_layer.h b/remoting/client/gl_render_layer.h new file mode 100644 index 0000000..785961f --- /dev/null +++ b/remoting/client/gl_render_layer.h
@@ -0,0 +1,75 @@ +// 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 REMOTING_CLIENT_OPENGL_GL_RENDER_LAYER_H_ +#define REMOTING_CLIENT_OPENGL_GL_RENDER_LAYER_H_ + +#include "base/macros.h" +#include "base/threading/thread_checker.h" +#include "remoting/client/sys_opengl.h" + +namespace remoting { +class GlCanvas; + +// This class is for drawing a texture on the canvas. Must be deleted before the +// canvas is deleted. +class GlRenderLayer { + public: + // texture_id: An integer in range [0, GL_MAX_TEXTURE_IMAGE_UNITS], defining + // which slot to store the texture. + GlRenderLayer(int texture_id, GlCanvas* canvas); + ~GlRenderLayer(); + + // Sets the texture (RGBA 8888) to be drawn. Please use UpdateTexture() if the + // texture size isn't changed. + void SetTexture(const uint8_t* texture, int width, int height); + + // Updates a subregion (RGBA 8888) of the texture. + // stride: byte distance between two rows in |subtexture|. + // If |stride| is 0 or |stride| == |width|*kBytesPerPixel, |subtexture| will + // be treated as tightly packed. + void UpdateTexture(const uint8_t* subtexture, + int offset_x, + int offset_y, + int width, + int height, + int stride); + + // Sets the positions of four vertices of the texture in normalized + // coordinates. The default values are (0, 0), (0, 1), (1, 0), (1, 1), + // i.e. stretching the texture to fit the whole canvas. + // positions: [ x_upperleft, y_upperleft, x_lowerleft, y_lowerleft, + // x_upperright, y_upperright, x_lowerright, y_lowerright ] + void SetVertexPositions(const std::array<float, 8>& positions); + + // Sets the visible area of the texture. The default values are (0, 0), + // (0, 1), (1, 0), (1, 1), i.e. showing the whole texture. + // positions: [ x_upperleft, y_upperleft, x_lowerleft, y_lowerleft, + // x_upperright, y_upperright, x_lowerright, y_lowerright ] + void SetTextureVisibleArea(const std::array<float, 8>& positions); + + // Draws the texture on the canvas. Texture must be set before calling Draw(). + void Draw(); + + private: + int texture_id_; + GlCanvas* canvas_; + + GLuint texture_handle_; + GLuint buffer_handle_; + + // true IFF the texture is already set by calling SetTexture(). + bool texture_set_ = false; + + // Used in OpenGL ES 2 context which doesn't support GL_UNPACK_ROW_LENGTH to + // tightly pack dirty regions before sending them to GPU. + std::unique_ptr<uint8_t[]> update_buffer_; + int update_buffer_size_ = 0; + + base::ThreadChecker thread_checker_; + DISALLOW_COPY_AND_ASSIGN(GlRenderLayer); +}; + +} // namespace remoting +#endif // REMOTING_CLIENT_OPENGL_GL_RENDER_LAYER_H_
diff --git a/remoting/client/ios/example_view_controller.mm b/remoting/client/ios/example_view_controller.mm index 43651d24..dbac4297 100644 --- a/remoting/client/ios/example_view_controller.mm +++ b/remoting/client/ios/example_view_controller.mm
@@ -8,7 +8,7 @@ #import "remoting/client/ios/example_view_controller.h" -#import "remoting/client/opengl_wrapper.h" +#import "remoting/client/sys_opengl.h" @interface ExampleViewController()
diff --git a/remoting/client/jni/chromoting_jni_instance.cc b/remoting/client/jni/chromoting_jni_instance.cc index de73b4f..97f6693f 100644 --- a/remoting/client/jni/chromoting_jni_instance.cc +++ b/remoting/client/jni/chromoting_jni_instance.cc
@@ -74,6 +74,7 @@ capabilities_(capabilities), weak_factory_(this) { DCHECK(jni_runtime_->ui_task_runner()->BelongsToCurrentThread()); + weak_ptr_ = weak_factory_.GetWeakPtr(); // Initialize XMPP config. xmpp_config_.host = kXmppServer; @@ -369,7 +370,7 @@ } base::WeakPtr<ChromotingJniInstance> ChromotingJniInstance::GetWeakPtr() { - return weak_factory_.GetWeakPtr(); + return weak_ptr_; } void ChromotingJniInstance::ConnectToHostOnNetworkThread() {
diff --git a/remoting/client/jni/chromoting_jni_instance.h b/remoting/client/jni/chromoting_jni_instance.h index beeaa91..b4cc64f 100644 --- a/remoting/client/jni/chromoting_jni_instance.h +++ b/remoting/client/jni/chromoting_jni_instance.h
@@ -200,6 +200,7 @@ // thread. bool connected_ = false; + base::WeakPtr<ChromotingJniInstance> weak_ptr_; base::WeakPtrFactory<ChromotingJniInstance> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ChromotingJniInstance);
diff --git a/remoting/client/jni/jni_client.cc b/remoting/client/jni/jni_client.cc index 90db7a9..b3c7114a 100644 --- a/remoting/client/jni/jni_client.cc +++ b/remoting/client/jni/jni_client.cc
@@ -26,7 +26,9 @@ base::android::ScopedJavaGlobalRef<jobject> java_client) : runtime_(runtime), java_client_(java_client), - weak_factory_(this) {} + weak_factory_(this) { + weak_ptr_ = weak_factory_.GetWeakPtr(); +} JniClient::~JniClient() { DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); @@ -166,9 +168,7 @@ #else JniDisplayHandler* raw_display_handler = new JniDisplayHandler(runtime_); #endif // defined(REMOTING_ANDROID_ENABLE_OPENGL_RENDERER) - Java_Client_setDesktopViewFactory( - env, java_client_.obj(), - raw_display_handler->CreateDesktopViewFactory().obj()); + raw_display_handler->InitializeClient(java_client_); display_handler_.reset(raw_display_handler); ConnectToHost(raw_display_handler, ConvertJavaStringToUTF8(env, username), @@ -295,7 +295,7 @@ } base::WeakPtr<JniClient> JniClient::GetWeakPtr() { - return weak_factory_.GetWeakPtr(); + return weak_ptr_; } static jlong Init(JNIEnv* env, const JavaParamRef<jobject>& caller) {
diff --git a/remoting/client/jni/jni_client.h b/remoting/client/jni/jni_client.h index 697f82a..75e5c539 100644 --- a/remoting/client/jni/jni_client.h +++ b/remoting/client/jni/jni_client.h
@@ -166,6 +166,7 @@ std::unique_ptr<ChromotingJniInstance> session_; // Holds pointer for the UI thread. + base::WeakPtr<JniClient> weak_ptr_; base::WeakPtrFactory<JniClient> weak_factory_; DISALLOW_COPY_AND_ASSIGN(JniClient);
diff --git a/remoting/client/jni/jni_display_handler.cc b/remoting/client/jni/jni_display_handler.cc index 185a972..e139e7b 100644 --- a/remoting/client/jni/jni_display_handler.cc +++ b/remoting/client/jni/jni_display_handler.cc
@@ -55,6 +55,7 @@ JniDisplayHandler::JniDisplayHandler(ChromotingJniRuntime* runtime) : runtime_(runtime), weak_factory_(this) { + weak_ptr_ = weak_factory_.GetWeakPtr(); JNIEnv* env = base::android::AttachCurrentThread(); java_display_.Reset(Java_Display_createJavaDisplayObject( env, reinterpret_cast<intptr_t>(this))); @@ -66,10 +67,10 @@ java_display_.obj()); } -base::android::ScopedJavaLocalRef<jobject> -JniDisplayHandler::CreateDesktopViewFactory() { - return Java_Display_createDesktopViewFactory( - base::android::AttachCurrentThread(), java_display_.obj()); +void JniDisplayHandler::InitializeClient( + const base::android::JavaRef<jobject>& java_client) { + return Java_Display_initializeClient(base::android::AttachCurrentThread(), + java_display_.obj(), java_client.obj()); } void JniDisplayHandler::UpdateCursorShape( @@ -95,14 +96,13 @@ std::unique_ptr<protocol::CursorShapeStub> JniDisplayHandler::CreateCursorShapeStub() { return base::WrapUnique( - new DisplayCursorShapeStub(weak_factory_.GetWeakPtr(), - runtime_->display_task_runner())); + new DisplayCursorShapeStub(weak_ptr_, runtime_->display_task_runner())); } std::unique_ptr<protocol::VideoRenderer> JniDisplayHandler::CreateVideoRenderer() { return base::WrapUnique( - new JniVideoRenderer(runtime_, weak_factory_.GetWeakPtr())); + new JniVideoRenderer(runtime_, weak_ptr_)); } // static @@ -137,8 +137,7 @@ JNIEnv* env, const base::android::JavaParamRef<jobject>& caller) { runtime_->display_task_runner()->PostTask( - FROM_HERE, base::Bind(&JniDisplayHandler::RedrawCanvas, - weak_factory_.GetWeakPtr())); + FROM_HERE, base::Bind(&JniDisplayHandler::RedrawCanvas, weak_ptr_)); } } // namespace remoting
diff --git a/remoting/client/jni/jni_display_handler.h b/remoting/client/jni/jni_display_handler.h index e62d354..2f804885 100644 --- a/remoting/client/jni/jni_display_handler.h +++ b/remoting/client/jni/jni_display_handler.h
@@ -30,7 +30,9 @@ // Must be deleted on the display thread. ~JniDisplayHandler() override; - base::android::ScopedJavaLocalRef<jobject> CreateDesktopViewFactory(); + // Sets the DesktopViewFactory for the Java client. + void InitializeClient( + const base::android::JavaRef<jobject>& java_client); void UpdateCursorShape(const protocol::CursorShapeInfo& cursor_shape); @@ -60,6 +62,7 @@ ChromotingJniRuntime* runtime_; base::android::ScopedJavaGlobalRef<jobject> java_display_; + base::WeakPtr<JniDisplayHandler> weak_ptr_; base::WeakPtrFactory<JniDisplayHandler> weak_factory_; DISALLOW_COPY_AND_ASSIGN(JniDisplayHandler);
diff --git a/remoting/client/jni/jni_gl_display_handler.cc b/remoting/client/jni/jni_gl_display_handler.cc index 20e24e9..4e86735f 100644 --- a/remoting/client/jni/jni_gl_display_handler.cc +++ b/remoting/client/jni/jni_gl_display_handler.cc
@@ -23,10 +23,11 @@ java_display_.obj()); } -base::android::ScopedJavaLocalRef<jobject> -JniGlDisplayHandler::CreateDesktopViewFactory() { - return Java_GlDisplay_createDesktopViewFactory( - base::android::AttachCurrentThread(), java_display_.obj()); +void JniGlDisplayHandler::InitializeClient( + const base::android::JavaRef<jobject>& java_client) { + return Java_GlDisplay_initializeClient(base::android::AttachCurrentThread(), + java_display_.obj(), + java_client.obj()); } std::unique_ptr<protocol::CursorShapeStub>
diff --git a/remoting/client/jni/jni_gl_display_handler.h b/remoting/client/jni/jni_gl_display_handler.h index 45ec72fc..7ddfaaa 100644 --- a/remoting/client/jni/jni_gl_display_handler.h +++ b/remoting/client/jni/jni_gl_display_handler.h
@@ -26,8 +26,9 @@ JniGlDisplayHandler(ChromotingJniRuntime* runtime); ~JniGlDisplayHandler() override; - base::android::ScopedJavaLocalRef<jobject> CreateDesktopViewFactory(); - + // Sets the DesktopViewFactory for the Java client. + void InitializeClient( + const base::android::JavaRef<jobject>& java_client); // DisplayUpdaterFactory overrides. std::unique_ptr<protocol::CursorShapeStub> CreateCursorShapeStub() override; std::unique_ptr<protocol::VideoRenderer> CreateVideoRenderer() override;
diff --git a/remoting/client/jni/jni_pairing_secret_fetcher.cc b/remoting/client/jni/jni_pairing_secret_fetcher.cc index f659327..39a3652 100644 --- a/remoting/client/jni/jni_pairing_secret_fetcher.cc +++ b/remoting/client/jni/jni_pairing_secret_fetcher.cc
@@ -16,7 +16,9 @@ jni_runtime_(runtime), jni_client_(client), host_id_(host_id), - weak_factory_(this) {} + weak_factory_(this) { + weak_ptr_ = weak_factory_.GetWeakPtr(); +} JniPairingSecretFetcher::~JniPairingSecretFetcher() { DCHECK(jni_runtime_->network_task_runner()->BelongsToCurrentThread()); @@ -42,7 +44,7 @@ } base::WeakPtr<JniPairingSecretFetcher> JniPairingSecretFetcher::GetWeakPtr() { - return weak_factory_.GetWeakPtr(); + return weak_ptr_; } // static
diff --git a/remoting/client/jni/jni_pairing_secret_fetcher.h b/remoting/client/jni/jni_pairing_secret_fetcher.h index 39f448d..db329e33 100644 --- a/remoting/client/jni/jni_pairing_secret_fetcher.h +++ b/remoting/client/jni/jni_pairing_secret_fetcher.h
@@ -51,6 +51,7 @@ // the UI thread, but must be posted to the network thread to call it. protocol::SecretFetchedCallback callback_; + base::WeakPtr<JniPairingSecretFetcher> weak_ptr_; base::WeakPtrFactory<JniPairingSecretFetcher> weak_factory_; DISALLOW_COPY_AND_ASSIGN(JniPairingSecretFetcher);
diff --git a/remoting/client/opengl/BUILD.gn b/remoting/client/opengl/BUILD.gn deleted file mode 100644 index 0a9d785d..0000000 --- a/remoting/client/opengl/BUILD.gn +++ /dev/null
@@ -1,14 +0,0 @@ -shaders = [ - "tex_coord_to_view.vert", - "draw_tex.frag", -] - -action("inline_shaders") { - script = "../../tools/build/shader_to_header.py" - out_path = "${root_gen_dir}/remoting/client/opengl/shaders.h" - inputs = shaders - outputs = [ - out_path, - ] - args = [ rebase_path(out_path) ] + rebase_path(shaders) -}
diff --git a/remoting/client/opengl_wrapper.h b/remoting/client/opengl_wrapper.h deleted file mode 100644 index 16ea2d2..0000000 --- a/remoting/client/opengl_wrapper.h +++ /dev/null
@@ -1,12 +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 REMOTING_CLIENT_OPENGL_WRAPPER_H_ -#define REMOTING_CLIENT_OPENGL_WRAPPER_H_ - -#if defined(OS_IOS) -#include <OpenGLES/ES2/gl.h> -#endif // defined(OS_IOS) - -#endif // REMOTING_CLIENT_OPENGL_WRAPPER_H_
diff --git a/remoting/client/sys_opengl.h b/remoting/client/sys_opengl.h new file mode 100644 index 0000000..142f5d4 --- /dev/null +++ b/remoting/client/sys_opengl.h
@@ -0,0 +1,18 @@ +// 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 REMOTING_CLIENT_SYS_OPENGL_H_ +#define REMOTING_CLIENT_SYS_OPENGL_H_ + +#include "build/build_config.h" + +#if defined(OS_IOS) +#include <OpenGLES/ES3/gl.h> +#elif defined(OS_ANDROID) +#include <GLES3/gl3.h> +#else +#error OpenGL renderer not supported on this platform. +#endif + +#endif // REMOTING_CLIENT_SYS_OPENGL_H_
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn index e85af02..0100db9 100644 --- a/remoting/host/BUILD.gn +++ b/remoting/host/BUILD.gn
@@ -987,6 +987,7 @@ ":credits", ":remoting_me2me_host_static", "//build/config/sanitizers:deps", + "//remoting/base:breakpad", "//remoting/resources", ] if (is_mac) { @@ -1233,44 +1234,45 @@ root_build_dir) _extra_files = [] - args = [ - rebase_path("$root_gen_dir/installation", root_build_dir), - rebase_path(_output, root_build_dir), - "--source-file-roots", - rebase_path("//remoting/host/installer/win"), - "--source-files", - rebase_path("//remoting/host/installer/win/chromoting.wxs"), - rebase_path("//remoting/host/installer/win/parameters.json"), + args = + [ + rebase_path("$root_gen_dir/remoting_installation", root_build_dir), + rebase_path(_output, root_build_dir), + "--source-file-roots", + rebase_path("//remoting/host/installer/win"), + "--source-files", + rebase_path("//remoting/host/installer/win/chromoting.wxs"), + rebase_path("//remoting/host/installer/win/parameters.json"), - # Input files - "--generated-files", - ] + _generated_files + - [ - rebase_path("//remoting/resources/chromoting.ico"), + # Input files + "--generated-files", + ] + _generated_files + + [ + rebase_path("//remoting/resources/chromoting.ico"), - # Position of files in zip file - "--generated-files-dst", - "files/remote_assistance_host.exe", - "files/remote_security_key.exe", - "files/remoting_core.dll", - "files/remoting_desktop.exe", - "files/remoting_host.exe", - "files/remoting_native_messaging_host.exe", - "files/remoting_start_host.exe", - "files/CREDITS.txt", - "files/com.google.chrome.remote_assistance.json", - "files/com.google.chrome.remote_desktop.json", - "files/chromoting.ico", - "files/icudtl.dat", - ] + _extra_files + # Defs - [ - "--defs", - "BRANDING=$_branding", - "DAEMON_CONTROLLER_CLSID={$daemon_controller_clsid}", - "RDP_DESKTOP_SESSION_CLSID={$rdp_desktop_session_clsid}", - "VERSION=$chrome_version_full", - "OFFICIAL_BUILD=$_official_build", - ] + # Position of files in zip file + "--generated-files-dst", + "files/remote_assistance_host.exe", + "files/remote_security_key.exe", + "files/remoting_core.dll", + "files/remoting_desktop.exe", + "files/remoting_host.exe", + "files/remoting_native_messaging_host.exe", + "files/remoting_start_host.exe", + "files/CREDITS.txt", + "files/com.google.chrome.remote_assistance.json", + "files/com.google.chrome.remote_desktop.json", + "files/chromoting.ico", + "files/icudtl.dat", + ] + _extra_files + # Defs + [ + "--defs", + "BRANDING=$_branding", + "DAEMON_CONTROLLER_CLSID={$daemon_controller_clsid}", + "RDP_DESKTOP_SESSION_CLSID={$rdp_desktop_session_clsid}", + "VERSION=$chrome_version_full", + "OFFICIAL_BUILD=$_official_build", + ] } } else if (is_mac) { import("//build/config/zip.gni") @@ -1311,7 +1313,8 @@ host_uninstaller_name_nospace = host_uninstaller_name args = [ - rebase_path(target_gen_dir, root_build_dir), + rebase_path("$target_gen_dir/remoting_installation", + root_build_dir), rebase_path(zip_path, root_build_dir), "--source-file-roots", rebase_path("installer/mac/", root_build_dir), @@ -1545,7 +1548,7 @@ "--wix_path", rebase_path("//third_party/wix"), "--intermediate_dir", - rebase_path("$root_gen_dir/installation", root_build_dir), + rebase_path("$root_gen_dir/remoting_installation", root_build_dir), "--target_arch", msi_script_arch, rebase_path("$root_out_dir/remoting-me2me-host-$current_os.zip",
diff --git a/remoting/protocol/webrtc_transport.cc b/remoting/protocol/webrtc_transport.cc index 665ff7a..ab8b3fd4 100644 --- a/remoting/protocol/webrtc_transport.cc +++ b/remoting/protocol/webrtc_transport.cc
@@ -556,7 +556,7 @@ if (peer_connection_->signaling_state() == webrtc::PeerConnectionInterface::kStable) { - for (auto candidate : pending_incoming_candidates_) { + for (auto* candidate : pending_incoming_candidates_) { if (!peer_connection_->AddIceCandidate(candidate)) { LOG(ERROR) << "Failed to add incoming candidate"; Close(INCOMPATIBLE_PROTOCOL);
diff --git a/remoting/protocol/webrtc_video_renderer_adapter.cc b/remoting/protocol/webrtc_video_renderer_adapter.cc index 6d54992..1320b9c 100644 --- a/remoting/protocol/webrtc_video_renderer_adapter.cc +++ b/remoting/protocol/webrtc_video_renderer_adapter.cc
@@ -1,4 +1,4 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. + // Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -19,6 +19,7 @@ #include "remoting/protocol/frame_stats.h" #include "remoting/protocol/video_renderer.h" #include "third_party/libyuv/include/libyuv/convert_argb.h" +#include "third_party/libyuv/include/libyuv/convert_from.h" #include "third_party/libyuv/include/libyuv/video_common.h" #include "third_party/webrtc/media/base/videoframe.h" #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
diff --git a/remoting/remoting_client.gypi b/remoting/remoting_client.gypi index 91628825..c92a792 100644 --- a/remoting/remoting_client.gypi +++ b/remoting/remoting_client.gypi
@@ -186,4 +186,22 @@ 'includes': [ 'remoting_webapp.gypi', ], }, # end of target 'remoting_webapp' ], # end of targets + + 'conditions': [ + ['OS=="ios" or OS=="android"', { + 'targets': [ + { + 'target_name': 'remoting_opengl_renderer', + 'type': '<(component)', + 'sources': [ + '<@(remoting_opengl_renderer_sources)', + ], + 'dependencies': [ + '../third_party/khronos/khronos.gyp:khronos_headers', + '../third_party/webrtc/webrtc.gyp:webrtc' + ] + } # end of target 'remoting_opengl_renderer' + ] + }] # end of conditions 'OS=="ios" or OS=="android"' + ] }
diff --git a/remoting/remoting_srcs.gypi b/remoting/remoting_srcs.gypi index 38034e8d..ec4d654 100644 --- a/remoting/remoting_srcs.gypi +++ b/remoting/remoting_srcs.gypi
@@ -349,5 +349,16 @@ 'client/plugin/pepper_video_renderer_3d.cc', 'client/plugin/pepper_video_renderer_3d.h', ], + + 'remoting_opengl_renderer_sources': [ + 'client/gl_canvas.cc', + 'client/gl_canvas.h', + 'client/gl_desktop.cc', + 'client/gl_desktop.h', + 'client/gl_helpers.cc', + 'client/gl_helpers.h', + 'client/gl_render_layer.cc', + 'client/gl_render_layer.h' + ], } }
diff --git a/sandbox/win/PRESUBMIT.py b/sandbox/win/PRESUBMIT.py index e03c9d1..0dee565 100644 --- a/sandbox/win/PRESUBMIT.py +++ b/sandbox/win/PRESUBMIT.py
@@ -23,7 +23,7 @@ return [] bots = [ - 'tryserver.chromium.win:win10_chromium_x64_rel_ng', + 'master.tryserver.chromium.win:win10_chromium_x64_rel_ng', ] results = []
diff --git a/sandbox/win/sandbox_poc/main_ui_window.cc b/sandbox/win/sandbox_poc/main_ui_window.cc index c000ce1..4ca6b07f 100644 --- a/sandbox/win/sandbox_poc/main_ui_window.cc +++ b/sandbox/win/sandbox_poc/main_ui_window.cc
@@ -513,9 +513,11 @@ policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, sandbox::TargetPolicy::FILES_ALLOW_ANY, dll_path_.c_str()); - sandbox::ResultCode result = broker_->SpawnTarget(spawn_target_.c_str(), - arguments, policy, - &target_); + sandbox::ResultCode warning_result = sandbox::SBOX_ALL_OK; + DWORD last_error = ERROR_SUCCESS; + sandbox::ResultCode result = + broker_->SpawnTarget(spawn_target_.c_str(), arguments, policy, + &warning_result, &last_error, &target_); policy->Release(); policy = NULL;
diff --git a/sandbox/win/src/broker_services.cc b/sandbox/win/src/broker_services.cc index 1339abf..64a0afeca 100644 --- a/sandbox/win/src/broker_services.cc +++ b/sandbox/win/src/broker_services.cc
@@ -37,13 +37,9 @@ // Utility function to do the cleanup necessary when something goes wrong // while in SpawnTarget and we must terminate the target process. -sandbox::ResultCode SpawnCleanup(sandbox::TargetProcess* target, DWORD error) { - if (0 == error) - error = ::GetLastError(); - +sandbox::ResultCode SpawnCleanup(sandbox::TargetProcess* target) { target->Terminate(); delete target; - ::SetLastError(error); return sandbox::SBOX_ERROR_GENERIC; } @@ -273,6 +269,8 @@ ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, const wchar_t* command_line, TargetPolicy* policy, + ResultCode* last_warning, + DWORD* last_error, PROCESS_INFORMATION* target_info) { if (!exe_path) return SBOX_ERROR_BAD_PARAMS; @@ -286,6 +284,7 @@ // the child process. static DWORD thread_id = ::GetCurrentThreadId(); DCHECK(thread_id == ::GetCurrentThreadId()); + *last_warning = SBOX_ALL_OK; AutoLock lock(&lock_); @@ -303,6 +302,11 @@ policy_base->MakeTokens(&initial_token, &lockdown_token, &lowbox_token); if (SBOX_ALL_OK != result) return result; + if (lowbox_token.IsValid() && + base::win::GetVersion() < base::win::VERSION_WIN8) { + // We don't allow lowbox_token below Windows 8. + return SBOX_ERROR_BAD_PARAMS; + } base::win::ScopedHandle job; result = policy_base->MakeJobObject(&job); @@ -407,22 +411,31 @@ base::win::ScopedProcessInformation process_info; TargetProcess* target = new TargetProcess(std::move(initial_token), std::move(lockdown_token), - std::move(lowbox_token), job.Get(), thread_pool_); + job.Get(), thread_pool_); - DWORD win_result; result = target->Create(exe_path, command_line, inherit_handles, startup_info, - &process_info, &win_result); + &process_info, last_error); if (result != SBOX_ALL_OK) { - SpawnCleanup(target, win_result); + SpawnCleanup(target); return result; } + if (lowbox_token.IsValid()) { + *last_warning = target->AssignLowBoxToken(lowbox_token); + // If this fails we continue, but report the error as a warning. + // This is due to certain configurations causing the setting of the + // token to fail post creation, and we'd rather continue if possible. + if (*last_warning != SBOX_ALL_OK) + *last_error = ::GetLastError(); + } + // Now the policy is the owner of the target. result = policy_base->AddTarget(target); if (result != SBOX_ALL_OK) { - SpawnCleanup(target, 0); + *last_error = ::GetLastError(); + SpawnCleanup(target); return result; }
diff --git a/sandbox/win/src/broker_services.h b/sandbox/win/src/broker_services.h index 22e83b1..555f52bb 100644 --- a/sandbox/win/src/broker_services.h +++ b/sandbox/win/src/broker_services.h
@@ -49,6 +49,8 @@ ResultCode SpawnTarget(const wchar_t* exe_path, const wchar_t* command_line, TargetPolicy* policy, + ResultCode* last_warning, + DWORD* last_error, PROCESS_INFORMATION* target) override; ResultCode WaitForAllTargets() override;
diff --git a/sandbox/win/src/nt_internals.h b/sandbox/win/src/nt_internals.h index a206e94d..6469c2bf 100644 --- a/sandbox/win/src/nt_internals.h +++ b/sandbox/win/src/nt_internals.h
@@ -333,18 +333,18 @@ }; } PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION; -typedef NTSTATUS (WINAPI *NtQueryInformationProcessFunction)( - IN HANDLE ProcessHandle, - IN PROCESSINFOCLASS ProcessInformationClass, - OUT PVOID ProcessInformation, - IN ULONG ProcessInformationLength, - OUT PULONG ReturnLength OPTIONAL); +typedef NTSTATUS(WINAPI* NtQueryInformationProcessFunction)( + IN HANDLE ProcessHandle, + IN PROCESSINFOCLASS ProcessInformationClass, + OUT PVOID ProcessInformation, + IN ULONG ProcessInformationLength, + OUT PULONG ReturnLength OPTIONAL); -typedef NTSTATUS (WINAPI *NtSetInformationProcessFunction)( - HANDLE ProcessHandle, - IN PROCESSINFOCLASS ProcessInformationClass, - IN PVOID ProcessInformation, - IN ULONG ProcessInformationLength); +typedef NTSTATUS(WINAPI* NtSetInformationProcessFunction)( + HANDLE ProcessHandle, + IN PROCESSINFOCLASS ProcessInformationClass, + IN PVOID ProcessInformation, + IN ULONG ProcessInformationLength); typedef NTSTATUS (WINAPI *NtOpenThreadTokenFunction) ( IN HANDLE ThreadHandle, @@ -370,21 +370,50 @@ IN ULONG HandleAttributes, OUT PHANDLE TokenHandle); -typedef NTSTATUS (WINAPI * RtlCreateUserThreadFunction)( - IN HANDLE Process, - IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, - IN BOOLEAN CreateSuspended, - IN ULONG ZeroBits, - IN SIZE_T MaximumStackSize, - IN SIZE_T CommittedStackSize, - IN LPTHREAD_START_ROUTINE StartAddress, - IN PVOID Parameter, - OUT PHANDLE Thread, - OUT PCLIENT_ID ClientId); +typedef NTSTATUS(WINAPI* NtQueryInformationTokenFunction)( + IN HANDLE TokenHandle, + IN TOKEN_INFORMATION_CLASS TokenInformationClass, + OUT PVOID TokenInformation, + IN ULONG TokenInformationLength, + OUT PULONG ReturnLength); + +typedef NTSTATUS(WINAPI* RtlCreateUserThreadFunction)( + IN HANDLE Process, + IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, + IN BOOLEAN CreateSuspended, + IN ULONG ZeroBits, + IN SIZE_T MaximumStackSize, + IN SIZE_T CommittedStackSize, + IN LPTHREAD_START_ROUTINE StartAddress, + IN PVOID Parameter, + OUT PHANDLE Thread, + OUT PCLIENT_ID ClientId); + +typedef NTSTATUS(WINAPI* RtlConvertSidToUnicodeStringFunction)( + OUT PUNICODE_STRING UnicodeString, + IN PSID Sid, + IN BOOLEAN AllocateDestinationString); + +typedef VOID(WINAPI* RtlFreeUnicodeStringFunction)( + IN OUT PUNICODE_STRING UnicodeString); // ----------------------------------------------------------------------- // Registry +typedef enum _KEY_VALUE_INFORMATION_CLASS { + KeyValueFullInformation = 1 +} KEY_VALUE_INFORMATION_CLASS, + *PKEY_VALUE_INFORMATION_CLASS; + +typedef struct _KEY_VALUE_FULL_INFORMATION { + ULONG TitleIndex; + ULONG Type; + ULONG DataOffset; + ULONG DataLength; + ULONG NameLength; + WCHAR Name[1]; +} KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION; + typedef NTSTATUS (WINAPI *NtCreateKeyFunction)( OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, @@ -408,6 +437,24 @@ typedef NTSTATUS (WINAPI *NtDeleteKeyFunction)( IN HANDLE KeyHandle); +typedef NTSTATUS(WINAPI* RtlFormatCurrentUserKeyPathFunction)( + OUT PUNICODE_STRING RegistryPath); + +typedef NTSTATUS(WINAPI* NtQueryValueKeyFunction)(IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName, + IN KEY_VALUE_INFORMATION_CLASS + KeyValueInformationClass, + OUT PVOID KeyValueInformation, + IN ULONG Length, + OUT PULONG ResultLength); + +typedef NTSTATUS(WINAPI* NtSetValueKeyFunction)(IN HANDLE KeyHandle, + IN PUNICODE_STRING ValueName, + IN ULONG TitleIndex OPTIONAL, + IN ULONG Type, + IN PVOID Data, + IN ULONG DataSize); + // ----------------------------------------------------------------------- // Memory
diff --git a/sandbox/win/src/policy_target_test.cc b/sandbox/win/src/policy_target_test.cc index 71054abd..e6a8ff3 100644 --- a/sandbox/win/src/policy_target_test.cc +++ b/sandbox/win/src/policy_target_test.cc
@@ -238,14 +238,17 @@ // Launch the app. ResultCode result = SBOX_ALL_OK; + ResultCode warning_result = SBOX_ALL_OK; + DWORD last_error = ERROR_SUCCESS; base::win::ScopedProcessInformation target; TargetPolicy* policy = broker->CreatePolicy(); policy->SetAlternateDesktop(false); policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN); PROCESS_INFORMATION temp_process_info = {}; - result = broker->SpawnTarget(prog_name, arguments.c_str(), policy, - &temp_process_info); + result = + broker->SpawnTarget(prog_name, arguments.c_str(), policy, &warning_result, + &last_error, &temp_process_info); base::string16 desktop_name = policy->GetAlternateDesktop(); policy->Release(); @@ -302,14 +305,17 @@ // Launch the app. ResultCode result = SBOX_ALL_OK; + ResultCode warning_result = SBOX_ALL_OK; base::win::ScopedProcessInformation target; TargetPolicy* policy = broker->CreatePolicy(); policy->SetAlternateDesktop(true); policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN); PROCESS_INFORMATION temp_process_info = {}; - result = broker->SpawnTarget(prog_name, arguments.c_str(), policy, - &temp_process_info); + DWORD last_error = ERROR_SUCCESS; + result = + broker->SpawnTarget(prog_name, arguments.c_str(), policy, &warning_result, + &last_error, &temp_process_info); base::string16 desktop_name = policy->GetAlternateDesktop(); policy->Release(); @@ -382,12 +388,15 @@ // Launch the app. ResultCode result = SBOX_ALL_OK; + ResultCode warning_result = SBOX_ALL_OK; base::win::ScopedProcessInformation target; policy->SetTokenLevel(USER_INTERACTIVE, USER_LOCKDOWN); PROCESS_INFORMATION temp_process_info = {}; - result = broker->SpawnTarget(prog_name, arguments.c_str(), policy, - &temp_process_info); + DWORD last_error = ERROR_SUCCESS; + result = + broker->SpawnTarget(prog_name, arguments.c_str(), policy, &warning_result, + &last_error, &temp_process_info); policy->Release(); EXPECT_EQ(SBOX_ALL_OK, result);
diff --git a/sandbox/win/src/sandbox.h b/sandbox/win/src/sandbox.h index fd9cd66..029868d 100644 --- a/sandbox/win/src/sandbox.h +++ b/sandbox/win/src/sandbox.h
@@ -67,6 +67,11 @@ // process. This can be null if the exe_path parameter is not null. // policy: This is the pointer to the policy object for the sandbox to // be created. + // last_warning: The argument will contain an indication on whether + // the process security was initialized completely, Only set if the + // process can be used without a serious compromise in security. + // last_error: If an error or warning is returned from this method this + // parameter will hold the last Win32 error value. // target: returns the resulting target process information such as process // handle and PID just as if CreateProcess() had been called. The caller is // responsible for closing the handles returned in this structure. @@ -75,6 +80,8 @@ virtual ResultCode SpawnTarget(const wchar_t* exe_path, const wchar_t* command_line, TargetPolicy* policy, + ResultCode* last_warning, + DWORD* last_error, PROCESS_INFORMATION* target) = 0; // This call blocks (waits) for all the targets to terminate.
diff --git a/sandbox/win/src/target_process.cc b/sandbox/win/src/target_process.cc index 7e09171..7fddffb 100644 --- a/sandbox/win/src/target_process.cc +++ b/sandbox/win/src/target_process.cc
@@ -72,7 +72,6 @@ TargetProcess::TargetProcess(base::win::ScopedHandle initial_token, base::win::ScopedHandle lockdown_token, - base::win::ScopedHandle lowbox_token, HANDLE job, ThreadProvider* thread_pool) // This object owns everything initialized here except thread_pool and @@ -80,7 +79,6 @@ // eventually in a call to our dtor. : lockdown_token_(std::move(lockdown_token)), initial_token_(std::move(initial_token)), - lowbox_token_(std::move(lowbox_token)), job_(job), thread_pool_(thread_pool), base_address_(NULL) {} @@ -126,12 +124,6 @@ const base::win::StartupInformation& startup_info, base::win::ScopedProcessInformation* target_info, DWORD* win_error) { - if (lowbox_token_.IsValid() && - base::win::GetVersion() < base::win::VERSION_WIN8) { - // We don't allow lowbox_token below Windows 8. - return SBOX_ERROR_BAD_PARAMS; - } - exe_name_.reset(_wcsdup(exe_path)); // the command line needs to be writable by CreateProcess(). @@ -212,25 +204,6 @@ return SBOX_ERROR_DUPLICATE_TARGET_INFO; } - if (lowbox_token_.IsValid()) { - PROCESS_ACCESS_TOKEN process_access_token; - process_access_token.thread = process_info.thread_handle(); - process_access_token.token = lowbox_token_.Get(); - - NtSetInformationProcess SetInformationProcess = NULL; - ResolveNTFunctionPtr("NtSetInformationProcess", &SetInformationProcess); - - NTSTATUS status = SetInformationProcess( - process_info.process_handle(), - static_cast<PROCESS_INFORMATION_CLASS>(NtProcessInformationAccessToken), - &process_access_token, sizeof(process_access_token)); - if (!NT_SUCCESS(status)) { - *win_error = GetLastErrorFromNtStatus(status); - ::TerminateProcess(process_info.process_handle(), 0); // exit code - return SBOX_ERROR_SET_LOW_BOX_TOKEN; - } - } - base_address_ = GetBaseAddress(exe_path, entry_point); sandbox_process_info_.Set(process_info.Take()); return SBOX_ALL_OK; @@ -362,10 +335,30 @@ ::TerminateProcess(sandbox_process_info_.process_handle(), 0); } +ResultCode TargetProcess::AssignLowBoxToken( + const base::win::ScopedHandle& token) { + if (!token.IsValid()) + return SBOX_ALL_OK; + PROCESS_ACCESS_TOKEN process_access_token = {}; + process_access_token.token = token.Get(); + + NtSetInformationProcess SetInformationProcess = NULL; + ResolveNTFunctionPtr("NtSetInformationProcess", &SetInformationProcess); + + NTSTATUS status = SetInformationProcess( + sandbox_process_info_.process_handle(), + static_cast<PROCESS_INFORMATION_CLASS>(NtProcessInformationAccessToken), + &process_access_token, sizeof(process_access_token)); + if (!NT_SUCCESS(status)) { + ::SetLastError(GetLastErrorFromNtStatus(status)); + return SBOX_ERROR_SET_LOW_BOX_TOKEN; + } + return SBOX_ALL_OK; +} + TargetProcess* MakeTestTargetProcess(HANDLE process, HMODULE base_address) { - TargetProcess* target = - new TargetProcess(base::win::ScopedHandle(), base::win::ScopedHandle(), - base::win::ScopedHandle(), NULL, NULL); + TargetProcess* target = new TargetProcess( + base::win::ScopedHandle(), base::win::ScopedHandle(), NULL, NULL); PROCESS_INFORMATION process_info = {}; process_info.hProcess = process; target->sandbox_process_info_.Set(process_info);
diff --git a/sandbox/win/src/target_process.h b/sandbox/win/src/target_process.h index 384f2c18..70b7b32 100644 --- a/sandbox/win/src/target_process.h +++ b/sandbox/win/src/target_process.h
@@ -40,7 +40,6 @@ // and |lowbox_token|. TargetProcess(base::win::ScopedHandle initial_token, base::win::ScopedHandle lockdown_token, - base::win::ScopedHandle lowbox_token, HANDLE job, ThreadProvider* thread_pool); ~TargetProcess(); @@ -60,6 +59,11 @@ base::win::ScopedProcessInformation* target_info, DWORD* win_error); + // Assign a new lowbox token to the process post creation. The process + // must still be in its initial suspended state, however this still + // might fail in the presence of third-party software. + ResultCode AssignLowBoxToken(const base::win::ScopedHandle& token); + // Destroys the target process. void Terminate(); @@ -114,9 +118,6 @@ // The token given to the initial thread so that the target process can // start. It has more powers than the lockdown_token. base::win::ScopedHandle initial_token_; - // The lowbox token associated with the process. This token is set after the - // process creation. - base::win::ScopedHandle lowbox_token_; // Kernel handle to the shared memory used by the IPC server. base::win::ScopedHandle shared_section_; // Job object containing the target process.
diff --git a/sandbox/win/tests/common/controller.cc b/sandbox/win/tests/common/controller.cc index 0bdb033..9f57137 100644 --- a/sandbox/win/tests/common/controller.cc +++ b/sandbox/win/tests/common/controller.cc
@@ -222,6 +222,8 @@ // Launch the sandboxed process. ResultCode result = SBOX_ALL_OK; + ResultCode warning_result = SBOX_ALL_OK; + DWORD last_error = ERROR_SUCCESS; PROCESS_INFORMATION target = {0}; base::string16 arguments(L"\""); @@ -238,7 +240,7 @@ } } else { result = broker_->SpawnTarget(prog_name, arguments.c_str(), policy_, - &target); + &warning_result, &last_error, &target); } if (SBOX_ALL_OK != result)
diff --git a/services/catalog/reader.cc b/services/catalog/reader.cc index ad8dd748..1f4a4ef 100644 --- a/services/catalog/reader.cc +++ b/services/catalog/reader.cc
@@ -133,7 +133,7 @@ } void AddEntryToCache(EntryCache* cache, std::unique_ptr<Entry> entry) { - for (auto child : entry->applications()) + for (auto* child : entry->applications()) AddEntryToCache(cache, base::WrapUnique(child)); (*cache)[entry->name()] = std::move(entry); }
diff --git a/services/tracing/tracing_app.cc b/services/tracing/tracing_app.cc index e6ea96e..44a747e 100644 --- a/services/tracing/tracing_app.cc +++ b/services/tracing/tracing_app.cc
@@ -107,7 +107,7 @@ MojoDeadline mojo_deadline = end - now; std::vector<mojo::Handle> handles; std::vector<MojoHandleSignals> signals; - for (const auto& it : recorder_impls_) { + for (auto* it : recorder_impls_) { handles.push_back(it->TraceRecorderHandle()); signals.push_back(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED);
diff --git a/services/ui/public/cpp/lib/output_surface.cc b/services/ui/public/cpp/lib/output_surface.cc index d8ce012..2d58a0a9 100644 --- a/services/ui/public/cpp/lib/output_surface.cc +++ b/services/ui/public/cpp/lib/output_surface.cc
@@ -45,8 +45,6 @@ } void OutputSurface::SwapBuffers(cc::CompositorFrame frame) { - // TODO(fsamuel, rjkroege): We should probably throttle compositor frames. - client_->DidSwapBuffers(); // OutputSurface owns WindowSurface, and so if OutputSurface is // destroyed then SubmitCompositorFrame's callback will never get called. // Thus, base::Unretained is safe here.
diff --git a/services/ui/public/cpp/lib/window.cc b/services/ui/public/cpp/lib/window.cc index ae25fcd..f3dde513 100644 --- a/services/ui/public/cpp/lib/window.cc +++ b/services/ui/public/cpp/lib/window.cc
@@ -447,6 +447,14 @@ client_->SetCanFocus(server_id_, can_focus); } +void Window::SetCanAcceptEvents(bool can_accept_events) { + if (can_accept_events_ == can_accept_events) + return; + can_accept_events_ = can_accept_events; + if (client_) + client_->SetCanAcceptEvents(server_id_, can_accept_events_); +} + void Window::Embed(ui::mojom::WindowTreeClientPtr client, uint32_t flags) { Embed(std::move(client), base::Bind(&EmptyEmbedCallback), flags); }
diff --git a/services/ui/public/cpp/lib/window_tree_client.cc b/services/ui/public/cpp/lib/window_tree_client.cc index 8c13573..fcc0f98 100644 --- a/services/ui/public/cpp/lib/window_tree_client.cc +++ b/services/ui/public/cpp/lib/window_tree_client.cc
@@ -705,6 +705,12 @@ observers_.RemoveObserver(observer); } +void WindowTreeClient::SetCanAcceptEvents(Id window_id, + bool can_accept_events) { + DCHECK(tree_); + tree_->SetCanAcceptEvents(window_id, can_accept_events); +} + void WindowTreeClient::OnEmbed(ClientSpecificId client_id, mojom::WindowDataPtr root_data, mojom::WindowTreePtr tree,
diff --git a/services/ui/public/cpp/tests/test_window_tree.cc b/services/ui/public/cpp/tests/test_window_tree.cc index 2b0204b..edf803e 100644 --- a/services/ui/public/cpp/tests/test_window_tree.cc +++ b/services/ui/public/cpp/tests/test_window_tree.cc
@@ -139,6 +139,9 @@ void TestWindowTree::SetCanFocus(uint32_t window_id, bool can_focus) {} +void TestWindowTree::SetCanAcceptEvents(uint32_t window_id, + bool can_accept_events) {} + void TestWindowTree::SetPredefinedCursor(uint32_t change_id, uint32_t window_id, ui::mojom::Cursor cursor_id) {}
diff --git a/services/ui/public/cpp/tests/test_window_tree.h b/services/ui/public/cpp/tests/test_window_tree.h index 6bd8beab..8506b14 100644 --- a/services/ui/public/cpp/tests/test_window_tree.h +++ b/services/ui/public/cpp/tests/test_window_tree.h
@@ -85,6 +85,7 @@ const EmbedCallback& callback) override; void SetFocus(uint32_t change_id, uint32_t window_id) override; void SetCanFocus(uint32_t window_id, bool can_focus) override; + void SetCanAcceptEvents(uint32_t window_id, bool can_accept_events) override; void SetPredefinedCursor(uint32_t change_id, uint32_t window_id, ui::mojom::Cursor cursor_id) override;
diff --git a/services/ui/public/cpp/window.h b/services/ui/public/cpp/window.h index c902e58ee..fc5efd9 100644 --- a/services/ui/public/cpp/window.h +++ b/services/ui/public/cpp/window.h
@@ -209,6 +209,9 @@ bool HasFocus() const; void SetCanFocus(bool can_focus); + // Sets whether this window accepts events. + void SetCanAcceptEvents(bool can_accept_events); + // Embedding. See window_tree.mojom for details. void Embed(ui::mojom::WindowTreeClientPtr client, uint32_t flags = 0); @@ -339,6 +342,10 @@ float opacity_; int64_t display_id_; + // Whether this window can accept events. Initialized to true to + // match ServerWindow. + bool can_accept_events_ = true; + mojom::Cursor cursor_id_; SharedProperties properties_;
diff --git a/services/ui/public/cpp/window_tree_client.h b/services/ui/public/cpp/window_tree_client.h index 898178c..08a5e10 100644 --- a/services/ui/public/cpp/window_tree_client.h +++ b/services/ui/public/cpp/window_tree_client.h
@@ -112,6 +112,7 @@ void ClearHitTestMask(Id window_id); void SetFocus(Window* window); void SetCanFocus(Id window_id, bool can_focus); + void SetCanAcceptEvents(Id window_id, bool can_accept_events); void SetPredefinedCursor(Id window_id, ui::mojom::Cursor cursor_id); void SetVisible(Window* window, bool visible); void SetOpacity(Window* window, float opacity);
diff --git a/services/ui/public/interfaces/BUILD.gn b/services/ui/public/interfaces/BUILD.gn index 33a07da..66bce555 100644 --- a/services/ui/public/interfaces/BUILD.gn +++ b/services/ui/public/interfaces/BUILD.gn
@@ -7,6 +7,7 @@ mojom("interfaces") { sources = [ "accelerator_registrar.mojom", + "accessibility_manager.mojom", "animations.mojom", "channel_handle.mojom", "clipboard.mojom",
diff --git a/services/ui/public/interfaces/accessibility_manager.mojom b/services/ui/public/interfaces/accessibility_manager.mojom new file mode 100644 index 0000000..a63873d --- /dev/null +++ b/services/ui/public/interfaces/accessibility_manager.mojom
@@ -0,0 +1,13 @@ +// 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. + +module ui.mojom; + +// Allows controlling accessibility in the UI service. Only one client at a time +// can connect to AccessibilityManager per user. If a new client connects to it, +// then any previously connected client for that user is disconnected. +interface AccessibilityManager { + // Enables (or disables) high contrast mode. + SetHighContrastMode(bool enabled); +};
diff --git a/services/ui/public/interfaces/window_tree.mojom b/services/ui/public/interfaces/window_tree.mojom index 6440e2a..65416a8 100644 --- a/services/ui/public/interfaces/window_tree.mojom +++ b/services/ui/public/interfaces/window_tree.mojom
@@ -238,6 +238,10 @@ // Otherwise the existing state is used. SetImeVisibility(uint32 window_id, bool visible, mojo.TextInputState? state); + // Set whether the specified window can accept events. If a window does not + // accept events, none of its descendant windows accept events either. + SetCanAcceptEvents(uint32 window_id, bool accept_events); + // See documentation for WindowTreeClient::OnWindowInputEvent(). OnWindowInputEventAck(uint32 event_id, EventResult result);
diff --git a/services/ui/service.cc b/services/ui/service.cc index e229e59..b11c4cf 100644 --- a/services/ui/service.cc +++ b/services/ui/service.cc
@@ -23,6 +23,7 @@ #include "services/ui/gles2/gpu_impl.h" #include "services/ui/gpu/gpu_service_impl.h" #include "services/ui/gpu/gpu_service_mus.h" +#include "services/ui/ws/accessibility_manager.h" #include "services/ui/ws/display.h" #include "services/ui/ws/display_binding.h" #include "services/ui/ws/display_manager.h" @@ -75,6 +76,7 @@ struct Service::UserState { std::unique_ptr<clipboard::ClipboardImpl> clipboard; + std::unique_ptr<ws::AccessibilityManager> accessibility; std::unique_ptr<ws::WindowTreeHostFactory> window_tree_host_factory; }; @@ -224,6 +226,7 @@ } bool Service::OnConnect(Connection* connection) { + connection->AddInterface<mojom::AccessibilityManager>(this); connection->AddInterface<mojom::Clipboard>(this); connection->AddInterface<mojom::DisplayManager>(this); connection->AddInterface<mojom::UserAccessManager>(this); @@ -281,6 +284,17 @@ } void Service::Create(shell::Connection* connection, + mojom::AccessibilityManagerRequest request) { + UserState* user_state = GetUserState(connection); + if (!user_state->accessibility) { + const ws::UserId& user_id = connection->GetRemoteIdentity().user_id(); + user_state->accessibility.reset( + new ws::AccessibilityManager(window_server_.get(), user_id)); + } + user_state->accessibility->Bind(std::move(request)); +} + +void Service::Create(shell::Connection* connection, mojom::ClipboardRequest request) { UserState* user_state = GetUserState(connection); if (!user_state->clipboard)
diff --git a/services/ui/service.h b/services/ui/service.h index 5251e9b..a9103ce 100644 --- a/services/ui/service.h +++ b/services/ui/service.h
@@ -19,6 +19,7 @@ #include "services/shell/public/cpp/service.h" #include "services/tracing/public/cpp/tracing_impl.h" #include "services/ui/input_devices/input_device_server.h" +#include "services/ui/public/interfaces/accessibility_manager.mojom.h" #include "services/ui/public/interfaces/clipboard.mojom.h" #include "services/ui/public/interfaces/display.mojom.h" #include "services/ui/public/interfaces/gpu.mojom.h" @@ -64,6 +65,7 @@ class Service : public shell::Service, public ws::WindowServerDelegate, + public shell::InterfaceFactory<mojom::AccessibilityManager>, public shell::InterfaceFactory<mojom::Clipboard>, public shell::InterfaceFactory<mojom::DisplayManager>, public shell::InterfaceFactory<mojom::Gpu>, @@ -108,6 +110,10 @@ bool IsTestConfig() const override; void CreateDefaultDisplays() override; + // shell::InterfaceFactory<mojom::AccessibilityManager> implementation. + void Create(shell::Connection* connection, + mojom::AccessibilityManagerRequest request) override; + // shell::InterfaceFactory<mojom::Clipboard> implementation. void Create(shell::Connection* connection, mojom::ClipboardRequest request) override;
diff --git a/services/ui/surfaces/direct_output_surface.cc b/services/ui/surfaces/direct_output_surface.cc index e390763..ed7d6b89 100644 --- a/services/ui/surfaces/direct_output_surface.cc +++ b/services/ui/surfaces/direct_output_surface.cc
@@ -69,7 +69,6 @@ context_provider_->ContextSupport()->SignalSyncToken( sync_token, base::Bind(&OutputSurface::OnSwapBuffersComplete, weak_ptr_factory_.GetWeakPtr())); - client_->DidSwapBuffers(); } uint32_t DirectOutputSurface::GetFramebufferCopyTextureFormat() {
diff --git a/services/ui/surfaces/direct_output_surface_ozone.cc b/services/ui/surfaces/direct_output_surface_ozone.cc index 3307716..57e1c86 100644 --- a/services/ui/surfaces/direct_output_surface_ozone.cc +++ b/services/ui/surfaces/direct_output_surface_ozone.cc
@@ -99,8 +99,6 @@ gpu::SyncToken sync_token; gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); - - client_->DidSwapBuffers(); } bool DirectOutputSurfaceOzone::BindToClient(cc::OutputSurfaceClient* client) {
diff --git a/services/ui/surfaces/display_compositor.cc b/services/ui/surfaces/display_compositor.cc index bdf1424..c5eb071 100644 --- a/services/ui/surfaces/display_compositor.cc +++ b/services/ui/surfaces/display_compositor.cc
@@ -30,10 +30,10 @@ : task_runner_(task_runner), surfaces_state_(surfaces_state), factory_(surfaces_state->manager(), this), - allocator_(surfaces_state->next_id_namespace()) { - allocator_.RegisterSurfaceIdNamespace(surfaces_state_->manager()); + allocator_(surfaces_state->next_client_id()) { + allocator_.RegisterSurfaceClientId(surfaces_state_->manager()); surfaces_state_->manager()->RegisterSurfaceFactoryClient( - allocator_.id_namespace(), this); + allocator_.client_id(), this); scoped_refptr<SurfacesContextProvider> surfaces_context_provider( new SurfacesContextProvider(widget, gpu_state)); @@ -69,7 +69,7 @@ display_.reset(new cc::Display( surfaces_state_->manager(), nullptr /* bitmap_manager */, nullptr /* gpu_memory_buffer_manager */, cc::RendererSettings(), - allocator_.id_namespace(), std::move(synthetic_begin_frame_source), + allocator_.client_id(), std::move(synthetic_begin_frame_source), std::move(display_output_surface), std::move(scheduler), base::MakeUnique<cc::TextureMailboxDeleter>(task_runner_.get()))); display_->Initialize(this); @@ -77,7 +77,7 @@ DisplayCompositor::~DisplayCompositor() { surfaces_state_->manager()->UnregisterSurfaceFactoryClient( - allocator_.id_namespace()); + allocator_.client_id()); } void DisplayCompositor::SubmitCompositorFrame(
diff --git a/services/ui/surfaces/surfaces_state.cc b/services/ui/surfaces/surfaces_state.cc index 38ebeef..edb1e8e 100644 --- a/services/ui/surfaces/surfaces_state.cc +++ b/services/ui/surfaces/surfaces_state.cc
@@ -6,7 +6,7 @@ namespace ui { -SurfacesState::SurfacesState() : next_id_namespace_(1u) {} +SurfacesState::SurfacesState() : next_client_id_(1u) {} SurfacesState::~SurfacesState() {}
diff --git a/services/ui/surfaces/surfaces_state.h b/services/ui/surfaces/surfaces_state.h index c55fb08..c35f900 100644 --- a/services/ui/surfaces/surfaces_state.h +++ b/services/ui/surfaces/surfaces_state.h
@@ -27,7 +27,7 @@ public: SurfacesState(); - uint32_t next_id_namespace() { return next_id_namespace_++; } + uint32_t next_client_id() { return next_client_id_++; } cc::SurfaceManager* manager() { return &manager_; } @@ -38,7 +38,7 @@ // A Surface ID is an unsigned 64-bit int where the high 32-bits are generated // by the Surfaces service, and the low 32-bits are generated by the process // that requested the Surface. - uint32_t next_id_namespace_; + uint32_t next_client_id_; cc::SurfaceManager manager_; DISALLOW_COPY_AND_ASSIGN(SurfacesState);
diff --git a/services/ui/ws/BUILD.gn b/services/ui/ws/BUILD.gn index 456a5d8..c61fba8 100644 --- a/services/ui/ws/BUILD.gn +++ b/services/ui/ws/BUILD.gn
@@ -13,6 +13,8 @@ "accelerator.h", "access_policy.h", "access_policy_delegate.h", + "accessibility_manager.cc", + "accessibility_manager.h", "animation_runner.cc", "animation_runner.h", "animation_runner_observer.h",
diff --git a/services/ui/ws/access_policy.h b/services/ui/ws/access_policy.h index 638c81e..452f17a9 100644 --- a/services/ui/ws/access_policy.h +++ b/services/ui/ws/access_policy.h
@@ -58,6 +58,7 @@ virtual bool CanSetFocus(const ServerWindow* window) const = 0; virtual bool CanSetClientArea(const ServerWindow* window) const = 0; virtual bool CanSetHitTestMask(const ServerWindow* window) const = 0; + virtual bool CanSetAcceptEvents(const ServerWindow* window) const = 0; // Used for all client controllable cursor properties; which cursor should be // displayed, visibility, locking, etc. virtual bool CanSetCursorProperties(const ServerWindow* window) const = 0;
diff --git a/services/ui/ws/accessibility_manager.cc b/services/ui/ws/accessibility_manager.cc new file mode 100644 index 0000000..3b934bb --- /dev/null +++ b/services/ui/ws/accessibility_manager.cc
@@ -0,0 +1,30 @@ +// 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 "services/ui/ws/accessibility_manager.h" + +#include "services/ui/ws/window_server.h" + +namespace ui { +namespace ws { + +AccessibilityManager::AccessibilityManager(WindowServer* window_server, + const UserId& user) + : window_server_(window_server), user_(user), binding_(this) { + DCHECK(window_server_); +} + +AccessibilityManager::~AccessibilityManager() {} + +void AccessibilityManager::Bind(mojom::AccessibilityManagerRequest request) { + binding_.Close(); + binding_.Bind(std::move(request)); +} + +void AccessibilityManager::SetHighContrastMode(bool enabled) { + window_server_->SetHighContrastMode(user_, enabled); +} + +} // namespace ws +} // namespace ui
diff --git a/services/ui/ws/accessibility_manager.h b/services/ui/ws/accessibility_manager.h new file mode 100644 index 0000000..aaf8992 --- /dev/null +++ b/services/ui/ws/accessibility_manager.h
@@ -0,0 +1,38 @@ +// 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 SERVICES_UI_WS_ACCESSIBILITY_MANAGER_H_ +#define SERVICES_UI_WS_ACCESSIBILITY_MANAGER_H_ + +#include "mojo/public/cpp/bindings/binding.h" +#include "services/ui/public/interfaces/accessibility_manager.mojom.h" +#include "services/ui/ws/user_id.h" + +namespace ui { +namespace ws { + +class WindowServer; + +class AccessibilityManager : public mojom::AccessibilityManager { + public: + AccessibilityManager(WindowServer* window_server, const UserId& user); + ~AccessibilityManager() override; + + void Bind(mojom::AccessibilityManagerRequest request); + + private: + // mojom::AccessibilityManager: + void SetHighContrastMode(bool enabled) override; + + WindowServer* window_server_; + const UserId user_; + mojo::Binding<mojom::AccessibilityManager> binding_; + + DISALLOW_COPY_AND_ASSIGN(AccessibilityManager); +}; + +} // namespace ws +} // namespace ui + +#endif // SERVICES_UI_WS_ACCESSIBILITY_MANAGER_H_
diff --git a/services/ui/ws/default_access_policy.cc b/services/ui/ws/default_access_policy.cc index 892adc0e..5d97659 100644 --- a/services/ui/ws/default_access_policy.cc +++ b/services/ui/ws/default_access_policy.cc
@@ -149,6 +149,11 @@ delegate_->HasRootForAccessPolicy(window); } +bool DefaultAccessPolicy::CanSetAcceptEvents(const ServerWindow* window) const { + return WasCreatedByThisClient(window) || + delegate_->HasRootForAccessPolicy(window); +} + bool DefaultAccessPolicy::CanSetCursorProperties( const ServerWindow* window) const { return WasCreatedByThisClient(window) ||
diff --git a/services/ui/ws/default_access_policy.h b/services/ui/ws/default_access_policy.h index b2172e1..5918d90c 100644 --- a/services/ui/ws/default_access_policy.h +++ b/services/ui/ws/default_access_policy.h
@@ -51,6 +51,7 @@ bool CanSetFocus(const ServerWindow* window) const override; bool CanSetClientArea(const ServerWindow* window) const override; bool CanSetHitTestMask(const ServerWindow* window) const override; + bool CanSetAcceptEvents(const ServerWindow* window) const override; bool CanSetCursorProperties(const ServerWindow* window) const override; bool CanInitiateMoveLoop(const ServerWindow* window) const override; bool ShouldNotifyOnHierarchyChange(
diff --git a/services/ui/ws/display.cc b/services/ui/ws/display.cc index c1b75eb..f733e83 100644 --- a/services/ui/ws/display.cc +++ b/services/ui/ws/display.cc
@@ -275,6 +275,10 @@ return root_.get(); } +bool Display::IsInHighContrastMode() { + return window_server_->IsActiveUserInHighContrastMode(); +} + void Display::OnEvent(const ui::Event& event) { WindowManagerDisplayRoot* display_root = GetActiveWindowManagerDisplayRoot(); if (display_root)
diff --git a/services/ui/ws/display.h b/services/ui/ws/display.h index 2d8d6dd..aaca1cf 100644 --- a/services/ui/ws/display.h +++ b/services/ui/ws/display.h
@@ -168,6 +168,7 @@ // PlatformDisplayDelegate: ServerWindow* GetRootWindow() override; + bool IsInHighContrastMode() override; void OnEvent(const ui::Event& event) override; void OnNativeCaptureLost() override; void OnDisplayClosed() override;
diff --git a/services/ui/ws/frame_generator.cc b/services/ui/ws/frame_generator.cc index d09b0d7..b361bf3 100644 --- a/services/ui/ws/frame_generator.cc +++ b/services/ui/ws/frame_generator.cc
@@ -7,6 +7,7 @@ #include "base/containers/adapters.h" #include "cc/output/compositor_frame.h" #include "cc/quads/render_pass.h" +#include "cc/quads/render_pass_draw_quad.h" #include "cc/quads/shared_quad_state.h" #include "cc/quads/surface_draw_quad.h" #include "services/ui/surfaces/display_compositor.h" @@ -26,7 +27,9 @@ gpu_state_(gpu_state), surfaces_state_(surfaces_state), draw_timer_(false, false), - weak_factory_(this) {} + weak_factory_(this) { + DCHECK(delegate_); +} FrameGenerator::~FrameGenerator() { // Invalidate WeakPtrs now to avoid callbacks back into the @@ -90,8 +93,11 @@ cc::CompositorFrame FrameGenerator::GenerateCompositorFrame() { const ViewportMetrics& metrics = delegate_->GetViewportMetrics(); std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create(); - render_pass->damage_rect = dirty_rect_; - render_pass->output_rect = gfx::Rect(metrics.size_in_pixels); + gfx::Rect output_rect(metrics.size_in_pixels); + dirty_rect_.Intersect(output_rect); + const cc::RenderPassId render_pass_id(1, 1); + render_pass->SetNew(render_pass_id, output_rect, dirty_rect_, + gfx::Transform()); DrawWindowTree(render_pass.get(), delegate_->GetRootWindow(), gfx::Vector2d(), 1.0f); @@ -99,6 +105,24 @@ std::unique_ptr<cc::DelegatedFrameData> frame_data( new cc::DelegatedFrameData); frame_data->render_pass_list.push_back(std::move(render_pass)); + if (delegate_->IsInHighContrastMode()) { + std::unique_ptr<cc::RenderPass> invert_pass = cc::RenderPass::Create(); + invert_pass->SetNew(cc::RenderPassId(2, 0), output_rect, dirty_rect_, + gfx::Transform()); + cc::SharedQuadState* shared_state = + invert_pass->CreateAndAppendSharedQuadState(); + shared_state->SetAll(gfx::Transform(), output_rect.size(), output_rect, + output_rect, false, 1.f, SkXfermode::kSrcOver_Mode, 0); + auto* quad = invert_pass->CreateAndAppendDrawQuad<cc::RenderPassDrawQuad>(); + cc::FilterOperations filters; + filters.Append(cc::FilterOperation::CreateInvertFilter(1.f)); + quad->SetNew(shared_state, output_rect, output_rect, render_pass_id, + 0 /* mask_resource_id */, gfx::Vector2dF() /* mask_uv_scale */, + gfx::Size() /* mask_texture_size */, filters, + gfx::Vector2dF() /* filters_scale */, + cc::FilterOperations() /* background_filters */); + frame_data->render_pass_list.push_back(std::move(invert_pass)); + } cc::CompositorFrame frame; frame.delegated_frame_data = std::move(frame_data);
diff --git a/services/ui/ws/frame_generator_delegate.h b/services/ui/ws/frame_generator_delegate.h index 456bab2e..fa82a8f9 100644 --- a/services/ui/ws/frame_generator_delegate.h +++ b/services/ui/ws/frame_generator_delegate.h
@@ -25,6 +25,8 @@ // Called when a compositor frame is finished drawing. virtual void OnCompositorFrameDrawn() = 0; + virtual bool IsInHighContrastMode() = 0; + virtual const ViewportMetrics& GetViewportMetrics() = 0; protected:
diff --git a/services/ui/ws/platform_display.cc b/services/ui/ws/platform_display.cc index 801a8a4c..93d4e08 100644 --- a/services/ui/ws/platform_display.cc +++ b/services/ui/ws/platform_display.cc
@@ -271,6 +271,10 @@ delegate_->OnCompositorFrameDrawn(); } +bool DefaultPlatformDisplay::IsInHighContrastMode() { + return delegate_ ? delegate_->IsInHighContrastMode() : false; +} + const ViewportMetrics& DefaultPlatformDisplay::GetViewportMetrics() { return metrics_; }
diff --git a/services/ui/ws/platform_display.h b/services/ui/ws/platform_display.h index 5da5f5c2..209daeb 100644 --- a/services/ui/ws/platform_display.h +++ b/services/ui/ws/platform_display.h
@@ -142,6 +142,7 @@ // FrameGeneratorDelegate: ServerWindow* GetRootWindow() override; void OnCompositorFrameDrawn() override; + bool IsInHighContrastMode() override; const ViewportMetrics& GetViewportMetrics() override; int64_t display_id_;
diff --git a/services/ui/ws/platform_display_delegate.h b/services/ui/ws/platform_display_delegate.h index 0371eb2..9c92f58 100644 --- a/services/ui/ws/platform_display_delegate.h +++ b/services/ui/ws/platform_display_delegate.h
@@ -26,6 +26,8 @@ // Returns the root window of this display. virtual ServerWindow* GetRootWindow() = 0; + virtual bool IsInHighContrastMode() = 0; + // Called when the window managed by the PlatformDisplay is closed. virtual void OnDisplayClosed() = 0;
diff --git a/services/ui/ws/server_window.cc b/services/ui/ws/server_window.cc index 834dcd8..1c21787e 100644 --- a/services/ui/ws/server_window.cc +++ b/services/ui/ws/server_window.cc
@@ -35,6 +35,7 @@ non_client_cursor_id_(mojom::Cursor::CURSOR_NULL), opacity_(1), can_focus_(true), + can_accept_events_(true), properties_(properties), // Don't notify newly added observers during notification. This causes // problems for code that adds an observer as part of an observer
diff --git a/services/ui/ws/server_window.h b/services/ui/ws/server_window.h index 6d66668..562a32c 100644 --- a/services/ui/ws/server_window.h +++ b/services/ui/ws/server_window.h
@@ -151,6 +151,9 @@ void set_can_focus(bool can_focus) { can_focus_ = can_focus; } bool can_focus() const { return can_focus_; } + void set_can_accept_events(bool value) { can_accept_events_ = value; } + bool can_accept_events() const { return can_accept_events_; } + // Returns true if this window is attached to a root and all ancestors are // visible. bool IsDrawn() const; @@ -221,6 +224,7 @@ mojom::Cursor non_client_cursor_id_; float opacity_; bool can_focus_; + bool can_accept_events_; gfx::Transform transform_; ui::TextInputState text_input_state_;
diff --git a/services/ui/ws/server_window_surface.cc b/services/ui/ws/server_window_surface.cc index 92dd57b6..154667fe 100644 --- a/services/ui/ws/server_window_surface.cc +++ b/services/ui/ws/server_window_surface.cc
@@ -44,7 +44,7 @@ if (registered_surface_factory_client_) { cc::SurfaceManager* surface_manager = manager_->GetSurfaceManager(); - surface_manager->UnregisterSurfaceFactoryClient(manager_->id_namespace()); + surface_manager->UnregisterSurfaceFactoryClient(manager_->client_id()); } } @@ -87,7 +87,7 @@ DCHECK(!registered_surface_factory_client_); registered_surface_factory_client_ = true; cc::SurfaceManager* surface_manager = manager_->GetSurfaceManager(); - surface_manager->RegisterSurfaceFactoryClient(manager_->id_namespace(), this); + surface_manager->RegisterSurfaceFactoryClient(manager_->client_id(), this); } ServerWindow* ServerWindowSurface::window() {
diff --git a/services/ui/ws/server_window_surface_manager.cc b/services/ui/ws/server_window_surface_manager.cc index 13a3ff5..9f82135 100644 --- a/services/ui/ws/server_window_surface_manager.cc +++ b/services/ui/ws/server_window_surface_manager.cc
@@ -15,11 +15,11 @@ ServerWindowSurfaceManager::ServerWindowSurfaceManager(ServerWindow* window) : window_(window), surface_id_allocator_( - window->delegate()->GetSurfacesState()->next_id_namespace()), + window->delegate()->GetSurfacesState()->next_client_id()), waiting_for_initial_frames_( window_->properties().count(ui::mojom::kWaitForUnderlay_Property) > 0) { - surface_id_allocator_.RegisterSurfaceIdNamespace(GetSurfaceManager()); + surface_id_allocator_.RegisterSurfaceClientId(GetSurfaceManager()); } ServerWindowSurfaceManager::~ServerWindowSurfaceManager() {
diff --git a/services/ui/ws/server_window_surface_manager.h b/services/ui/ws/server_window_surface_manager.h index b3ce36a..41f1d84b 100644 --- a/services/ui/ws/server_window_surface_manager.h +++ b/services/ui/ws/server_window_surface_manager.h
@@ -46,7 +46,7 @@ bool HasSurfaceOfType(mojom::SurfaceType type) const; bool HasAnySurface() const; - uint32_t id_namespace() const { return surface_id_allocator_.id_namespace(); } + uint32_t client_id() const { return surface_id_allocator_.client_id(); } cc::SurfaceManager* GetSurfaceManager(); private:
diff --git a/services/ui/ws/test_utils.cc b/services/ui/ws/test_utils.cc index f870d0a7..40debd5 100644 --- a/services/ui/ws/test_utils.cc +++ b/services/ui/ws/test_utils.cc
@@ -120,6 +120,10 @@ return root_.get(); } +bool TestFrameGeneratorDelegate::IsInHighContrastMode() { + return false; +} + const ViewportMetrics& TestFrameGeneratorDelegate::GetViewportMetrics() { return metrics_; }
diff --git a/services/ui/ws/test_utils.h b/services/ui/ws/test_utils.h index e701b55..6ce9e43 100644 --- a/services/ui/ws/test_utils.h +++ b/services/ui/ws/test_utils.h
@@ -94,6 +94,9 @@ void set_window_manager_internal(mojom::WindowManager* wm_internal) { tree_->window_manager_internal_ = wm_internal; } + void SetCanAcceptEvents(Id transport_window_id, bool can_accept_events) { + tree_->SetCanAcceptEvents(transport_window_id, can_accept_events); + } void AckOldestEvent() { tree_->OnWindowInputEventAck(tree_->event_ack_id_, mojom::EventResult::UNHANDLED); @@ -256,6 +259,7 @@ // FrameGeneratorDelegate: ServerWindow* GetRootWindow() override; void OnCompositorFrameDrawn() override {} + bool IsInHighContrastMode() override; const ViewportMetrics& GetViewportMetrics() override; private:
diff --git a/services/ui/ws/window_finder.cc b/services/ui/ws/window_finder.cc index 09be99308..0b46df6 100644 --- a/services/ui/ws/window_finder.cc +++ b/services/ui/ws/window_finder.cc
@@ -26,9 +26,12 @@ ServerWindow* FindDeepestVisibleWindowForEvents(ServerWindow* window, gfx::Point* location) { + if (!window->can_accept_events()) + return nullptr; + const ServerWindow::Windows& children = window->children(); for (ServerWindow* child : base::Reversed(children)) { - if (!child->visible()) + if (!child->visible() || !child->can_accept_events()) continue; // TODO(sky): support transform.
diff --git a/services/ui/ws/window_finder_unittest.cc b/services/ui/ws/window_finder_unittest.cc index af96b06..3cb3103 100644 --- a/services/ui/ws/window_finder_unittest.cc +++ b/services/ui/ws/window_finder_unittest.cc
@@ -41,6 +41,11 @@ EXPECT_EQ(&child1, FindDeepestVisibleWindowForEvents(&root, &local_point)); EXPECT_EQ(gfx::Point(3, 4), local_point); + local_point.SetPoint(13, 14); + child1.set_can_accept_events(false); + EXPECT_EQ(&root, FindDeepestVisibleWindowForEvents(&root, &local_point)); + EXPECT_EQ(gfx::Point(13, 14), local_point); + child2.set_extended_hit_test_region(gfx::Insets(10, 10, 10, 10)); local_point.SetPoint(13, 14); EXPECT_EQ(&child2, FindDeepestVisibleWindowForEvents(&root, &local_point));
diff --git a/services/ui/ws/window_manager_access_policy.cc b/services/ui/ws/window_manager_access_policy.cc index 948ca2ae..816d8996 100644 --- a/services/ui/ws/window_manager_access_policy.cc +++ b/services/ui/ws/window_manager_access_policy.cc
@@ -134,6 +134,12 @@ delegate_->HasRootForAccessPolicy(window); } +bool WindowManagerAccessPolicy::CanSetAcceptEvents( + const ServerWindow* window) const { + return WasCreatedByThisClient(window) || + delegate_->HasRootForAccessPolicy(window); +} + bool WindowManagerAccessPolicy::CanSetCursorProperties( const ServerWindow* window) const { return WasCreatedByThisClient(window) ||
diff --git a/services/ui/ws/window_manager_access_policy.h b/services/ui/ws/window_manager_access_policy.h index bb2ece9..da8ce52d 100644 --- a/services/ui/ws/window_manager_access_policy.h +++ b/services/ui/ws/window_manager_access_policy.h
@@ -50,6 +50,7 @@ bool CanSetFocus(const ServerWindow* window) const override; bool CanSetClientArea(const ServerWindow* window) const override; bool CanSetHitTestMask(const ServerWindow* window) const override; + bool CanSetAcceptEvents(const ServerWindow* window) const override; bool CanSetCursorProperties(const ServerWindow* window) const override; bool CanInitiateMoveLoop(const ServerWindow* window) const override; bool ShouldNotifyOnHierarchyChange(
diff --git a/services/ui/ws/window_server.cc b/services/ui/ws/window_server.cc index 1510881..92aa4ae 100644 --- a/services/ui/ws/window_server.cc +++ b/services/ui/ws/window_server.cc
@@ -282,6 +282,22 @@ return nullptr; } +bool WindowServer::IsActiveUserInHighContrastMode() const { + return IsUserInHighContrastMode(user_id_tracker_.active_id()); +} + +void WindowServer::SetHighContrastMode(const UserId& user, bool enabled) { + if (IsUserInHighContrastMode(user) == enabled) + return; + high_contrast_mode_[user] = enabled; + if (user_id_tracker_.active_id() != user) + return; + for (Display* display : display_manager_->displays()) { + display->SchedulePaint(display->root_window(), + gfx::Rect(display->root_window()->bounds().size())); + } +} + uint32_t WindowServer::GenerateWindowManagerChangeId( WindowTree* source, uint32_t client_change_id) { @@ -515,6 +531,11 @@ display_root->display()->UpdateNativeCursor(cursor_id); } +bool WindowServer::IsUserInHighContrastMode(const UserId& user) const { + const auto iter = high_contrast_mode_.find(user); + return (iter == high_contrast_mode_.end()) ? false : iter->second; +} + ui::SurfacesState* WindowServer::GetSurfacesState() { return surfaces_state_.get(); } @@ -736,7 +757,15 @@ } void WindowServer::OnActiveUserIdChanged(const UserId& previously_active_id, - const UserId& active_id) {} + const UserId& active_id) { + if (IsUserInHighContrastMode(previously_active_id) == + IsUserInHighContrastMode(active_id)) + return; + for (Display* display : display_manager_->displays()) { + display->SchedulePaint(display->root_window(), + gfx::Rect(display->root_window()->bounds().size())); + } +} void WindowServer::OnUserIdAdded(const UserId& id) { activity_monitor_map_[id] = base::MakeUnique<UserActivityMonitor>(nullptr);
diff --git a/services/ui/ws/window_server.h b/services/ui/ws/window_server.h index 64e42116..8978098 100644 --- a/services/ui/ws/window_server.h +++ b/services/ui/ws/window_server.h
@@ -143,6 +143,9 @@ bool SetFocusedWindow(ServerWindow* window); ServerWindow* GetFocusedWindow(); + bool IsActiveUserInHighContrastMode() const; + void SetHighContrastMode(const UserId& user, bool enabled); + // Returns a change id for the window manager that is associated with // |source| and |client_change_id|. When the window manager replies // WindowManagerChangeCompleted() is called to obtain the original source @@ -252,6 +255,8 @@ // |window|. void UpdateNativeCursorIfOver(ServerWindow* window); + bool IsUserInHighContrastMode(const UserId& user) const; + // Overridden from ServerWindowDelegate: ui::SurfacesState* GetSurfacesState() override; void OnScheduleWindowPaint(ServerWindow* window) override; @@ -333,6 +338,7 @@ Operation* current_operation_; bool in_destructor_; + std::map<UserId, bool> high_contrast_mode_; // Maps from window manager change id to the client that initiated the // request.
diff --git a/services/ui/ws/window_tree.cc b/services/ui/ws/window_tree.cc index 8a62bdd..56cbea50 100644 --- a/services/ui/ws/window_tree.cc +++ b/services/ui/ws/window_tree.cc
@@ -1165,25 +1165,35 @@ // Do not allow key events to be observed, as a compromised app could register // itself as an event observer and spy on keystrokes to another app. - if (!matcher->type_matcher) { + if (!matcher->type_matcher && !matcher->pointer_kind_matcher) { DVLOG(1) << "SetEventObserver must specify an event type."; return; } + const ui::mojom::EventType event_type_whitelist[] = { ui::mojom::EventType::POINTER_CANCEL, ui::mojom::EventType::POINTER_DOWN, ui::mojom::EventType::POINTER_MOVE, ui::mojom::EventType::POINTER_UP, ui::mojom::EventType::MOUSE_EXIT, ui::mojom::EventType::WHEEL, }; - bool allowed = false; - for (ui::mojom::EventType event_type : event_type_whitelist) { - if (matcher->type_matcher->type == event_type) { - allowed = true; - break; + + if (matcher->type_matcher) { + auto iter = + std::find(std::begin(event_type_whitelist), + std::end(event_type_whitelist), matcher->type_matcher->type); + if (iter == std::end(event_type_whitelist)) { + DVLOG(1) << "SetEventObserver event type not allowed"; + return; } } - if (!allowed) { - DVLOG(1) << "SetEventObserver event type not allowed"; - return; + if (matcher->pointer_kind_matcher) { + ui::mojom::PointerKind pointer_kind = + matcher->pointer_kind_matcher->pointer_kind; + if (pointer_kind != ui::mojom::PointerKind::MOUSE && + pointer_kind != ui::mojom::PointerKind::TOUCH && + pointer_kind != ui::mojom::PointerKind::PEN) { + DVLOG(1) << "SetEventObserver pointer kind not allowed"; + return; + } } event_observer_matcher_.reset(new EventMatcher(*matcher)); @@ -1384,6 +1394,15 @@ window->set_can_focus(can_focus); } +void WindowTree::SetCanAcceptEvents(Id transport_window_id, + bool can_accept_events) { + ServerWindow* window = + GetWindowByClientId(ClientWindowId(transport_window_id)); + // TODO(riajiang): check |event_queue_| is empty for |window|. + if (window && access_policy_->CanSetAcceptEvents(window)) + window->set_can_accept_events(can_accept_events); +} + void WindowTree::SetPredefinedCursor(uint32_t change_id, Id transport_window_id, ui::mojom::Cursor cursor_id) {
diff --git a/services/ui/ws/window_tree.h b/services/ui/ws/window_tree.h index 6555ff33..ff71bda 100644 --- a/services/ui/ws/window_tree.h +++ b/services/ui/ws/window_tree.h
@@ -394,6 +394,8 @@ const EmbedCallback& callback) override; void SetFocus(uint32_t change_id, Id transport_window_id) override; void SetCanFocus(Id transport_window_id, bool can_focus) override; + void SetCanAcceptEvents(Id transport_window_id, + bool can_accept_events) override; void SetPredefinedCursor(uint32_t change_id, Id transport_window_id, ui::mojom::Cursor cursor_id) override;
diff --git a/services/ui/ws/window_tree_unittest.cc b/services/ui/ws/window_tree_unittest.cc index 028ba9be..dc230f89 100644 --- a/services/ui/ws/window_tree_unittest.cc +++ b/services/ui/ws/window_tree_unittest.cc
@@ -1245,6 +1245,18 @@ SingleChangeToDescription(*embed_client->tracker()->changes())); } +TEST_F(WindowTreeTest, SetCanAcceptEvents) { + TestWindowTreeClient* embed_client = nullptr; + WindowTree* tree = nullptr; + ServerWindow* window = nullptr; + EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); + + EXPECT_TRUE(window->can_accept_events()); + WindowTreeTestApi(tree).SetCanAcceptEvents( + ClientWindowIdForWindow(tree, window).id, false); + EXPECT_FALSE(window->can_accept_events()); +} + } // namespace test } // namespace ws } // namespace ui
diff --git a/skia/ext/skia_memory_dump_provider.cc b/skia/ext/skia_memory_dump_provider.cc index c53cf7e6..5c61225 100644 --- a/skia/ext/skia_memory_dump_provider.cc +++ b/skia/ext/skia_memory_dump_provider.cc
@@ -28,13 +28,13 @@ base::trace_event::ProcessMemoryDump* process_memory_dump) { if (args.level_of_detail == base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) { - auto glyph_cache_dump = + auto* glyph_cache_dump = process_memory_dump->CreateAllocatorDump("skia/sk_glyph_cache"); glyph_cache_dump->AddScalar( base::trace_event::MemoryAllocatorDump::kNameSize, base::trace_event::MemoryAllocatorDump::kUnitsBytes, SkGraphics::GetFontCacheUsed()); - auto resource_cache_dump = + auto* resource_cache_dump = process_memory_dump->CreateAllocatorDump("skia/sk_resource_cache"); resource_cache_dump->AddScalar( base::trace_event::MemoryAllocatorDump::kNameSize,
diff --git a/skia/ext/skia_trace_memory_dump_impl.cc b/skia/ext/skia_trace_memory_dump_impl.cc index b7784e7..920fa222 100644 --- a/skia/ext/skia_trace_memory_dump_impl.cc +++ b/skia/ext/skia_trace_memory_dump_impl.cc
@@ -37,7 +37,7 @@ const char* valueName, const char* units, uint64_t value) { - auto dump = process_memory_dump_->GetOrCreateAllocatorDump(dumpName); + auto* dump = process_memory_dump_->GetOrCreateAllocatorDump(dumpName); dump->AddScalar(valueName, units, value); } @@ -45,7 +45,7 @@ const char* backingType, const char* backingObjectId) { if (strcmp(backingType, kMallocBackingType) == 0) { - auto dump = process_memory_dump_->GetOrCreateAllocatorDump(dumpName); + auto* dump = process_memory_dump_->GetOrCreateAllocatorDump(dumpName); const char* system_allocator_name = base::trace_event::MemoryDumpManager::GetInstance() ->system_allocator_pool_name(); @@ -65,7 +65,7 @@ DCHECK(!process_memory_dump_->GetAllocatorDump(name)); const SkDiscardableMemoryChrome& discardable_memory_obj = static_cast<const SkDiscardableMemoryChrome&>(discardableMemoryObject); - auto dump = discardable_memory_obj.CreateMemoryAllocatorDump( + auto* dump = discardable_memory_obj.CreateMemoryAllocatorDump( name.c_str(), process_memory_dump_); DCHECK(dump); }
diff --git a/sql/statement.cc b/sql/statement.cc index 1502b09..5778fd0d 100644 --- a/sql/statement.cc +++ b/sql/statement.cc
@@ -294,7 +294,7 @@ return sqlite3_column_blob(ref_->stmt(), col); } -bool Statement::ColumnBlobAsString(int col, std::string* blob) { +bool Statement::ColumnBlobAsString(int col, std::string* blob) const { if (!CheckValid()) return false;
diff --git a/sql/statement.h b/sql/statement.h index 83a5a2d..3bc99ed 100644 --- a/sql/statement.h +++ b/sql/statement.h
@@ -139,7 +139,7 @@ // vector. Danger! ColumnBlob may return NULL if there is no data! int ColumnByteLength(int col) const; const void* ColumnBlob(int col) const; - bool ColumnBlobAsString(int col, std::string* blob); + bool ColumnBlobAsString(int col, std::string* blob) const; bool ColumnBlobAsString16(int col, base::string16* val) const; bool ColumnBlobAsVector(int col, std::vector<char>* val) const; bool ColumnBlobAsVector(int col, std::vector<unsigned char>* val) const;
diff --git a/storage/browser/quota/usage_tracker.cc b/storage/browser/quota/usage_tracker.cc index 7c96a247..03ebecd0 100644 --- a/storage/browser/quota/usage_tracker.cc +++ b/storage/browser/quota/usage_tracker.cc
@@ -32,7 +32,7 @@ : type_(type), storage_monitor_(storage_monitor), weak_factory_(this) { - for (const auto& client : clients) { + for (auto* client : clients) { if (client->DoesSupport(type)) { client_tracker_map_[client->id()] = new ClientUsageTracker(this, client, type, special_storage_policy,
diff --git a/storage/common/fileapi/file_system_util.cc b/storage/common/fileapi/file_system_util.cc index f3d7ddb..0472c95 100644 --- a/storage/common/fileapi/file_system_util.cc +++ b/storage/common/fileapi/file_system_util.cc
@@ -138,7 +138,7 @@ } bool VirtualPath::IsAbsolute(const base::FilePath::StringType& path) { - return path.find(kRoot) == 0; + return base::StartsWith(path, kRoot, base::CompareCase::SENSITIVE); } bool VirtualPath::IsRootPath(const base::FilePath& path) {
diff --git a/sync/internal_api/sync_manager_impl.cc b/sync/internal_api/sync_manager_impl.cc index 3f5c370..cc59e645 100644 --- a/sync/internal_api/sync_manager_impl.cc +++ b/sync/internal_api/sync_manager_impl.cc
@@ -74,10 +74,11 @@ return GetUpdatesCallerInfo::NEW_CLIENT; case CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE: case CONFIGURE_REASON_CRYPTO: + case CONFIGURE_REASON_CATCH_UP: return GetUpdatesCallerInfo::NEWLY_SUPPORTED_DATATYPE; case CONFIGURE_REASON_PROGRAMMATIC: return GetUpdatesCallerInfo::PROGRAMMATIC; - default: + case CONFIGURE_REASON_UNKNOWN: NOTREACHED(); } return GetUpdatesCallerInfo::UNKNOWN;
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index c6c1e341..776ac47 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -2906,7 +2906,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -2922,7 +2921,7 @@ "os": "Linux" } ], - "shards": 12 + "shards": 15 } }, { @@ -3318,7 +3317,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -3334,7 +3332,7 @@ "os": "Linux" } ], - "shards": 12 + "shards": 15 } }, { @@ -3730,7 +3728,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -3746,7 +3743,7 @@ "os": "Linux" } ], - "shards": 12 + "shards": 15 } }, { @@ -4176,7 +4173,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -4192,7 +4188,7 @@ "os": "Linux" } ], - "shards": 12 + "shards": 15 } }, { @@ -4203,7 +4199,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -4219,7 +4214,7 @@ "os": "Linux" } ], - "shards": 12 + "shards": 15 } }, { @@ -4615,7 +4610,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -4631,6 +4625,33 @@ "os": "Linux" } ], + "shards": 15 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--webgl-conformance-version=2.0.0", + "--webgl2-only=true", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl2_conformance_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test_run" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:0412", + "os": "Linux" + } + ], "shards": 12 } }, @@ -5731,7 +5752,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -5747,7 +5767,7 @@ "os": "Mac-10.10" } ], - "shards": 12 + "shards": 15 } }, { @@ -6126,7 +6146,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -6142,7 +6161,7 @@ "os": "Mac-10.10" } ], - "shards": 12 + "shards": 15 } }, { @@ -6905,7 +6924,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -6922,7 +6940,7 @@ "os": "Mac-10.10" } ], - "shards": 12 + "shards": 15 } }, { @@ -7686,7 +7704,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -7703,7 +7720,7 @@ "os": "Mac" } ], - "shards": 12 + "shards": 15 } }, { @@ -7790,7 +7807,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -7806,7 +7822,7 @@ "os": "Linux" } ], - "shards": 12 + "shards": 15 } } ] @@ -7855,7 +7871,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -7871,7 +7886,7 @@ "os": "Mac-10.10" } ], - "shards": 12 + "shards": 15 } } ] @@ -7922,7 +7937,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -7939,7 +7953,7 @@ "os": "Mac-10.10" } ], - "shards": 12 + "shards": 15 } } ] @@ -7990,7 +8004,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -8007,7 +8020,7 @@ "os": "Mac" } ], - "shards": 12 + "shards": 15 } } ] @@ -8093,7 +8106,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -8109,7 +8121,7 @@ "os": "Windows-2008ServerR2-SP1" } ], - "shards": 12 + "shards": 15 } }, { @@ -8245,7 +8257,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -8261,7 +8272,7 @@ "os": "Windows-2008ServerR2-SP1" } ], - "shards": 12 + "shards": 15 } }, { @@ -9959,7 +9970,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -9975,7 +9985,7 @@ "os": "Windows-2008ServerR2-SP1" } ], - "shards": 12 + "shards": 15 } }, { @@ -10408,7 +10418,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -10424,7 +10433,7 @@ "os": "Windows-2008ServerR2-SP1" } ], - "shards": 12 + "shards": 15 } }, { @@ -10857,7 +10866,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -10873,7 +10881,7 @@ "os": "Windows-2008ServerR2-SP1" } ], - "shards": 12 + "shards": 15 } }, { @@ -11376,7 +11384,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -11392,7 +11399,7 @@ "os": "Windows-2008ServerR2-SP1" } ], - "shards": 12 + "shards": 15 } }, { @@ -11848,7 +11855,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -11864,7 +11870,7 @@ "os": "Windows-2008ServerR2-SP1" } ], - "shards": 12 + "shards": 15 } }, { @@ -12765,7 +12771,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -12781,7 +12786,7 @@ "os": "Windows-2008ServerR2-SP1" } ], - "shards": 12 + "shards": 15 } }, { @@ -13678,7 +13683,6 @@ "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.0", - "--webgl2-only=true", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], "isolate_name": "telemetry_gpu_integration_test", @@ -13694,7 +13698,7 @@ "os": "Windows-2012ServerR2-SP0" } ], - "shards": 12 + "shards": 15 } }, {
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index 2816817..6deb600c 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -639,9 +639,6 @@ }, { "test": "webapk_client_junit_tests" - }, - { - "test": "webapk_runtime_library_junit_tests" } ], "scripts": [
diff --git a/testing/buildbot/manage.py b/testing/buildbot/manage.py index cb445034..2f6e199 100755 --- a/testing/buildbot/manage.py +++ b/testing/buildbot/manage.py
@@ -224,6 +224,7 @@ raise Error( '%s: %s is broken: %s' % (filename, builder, data['gtest_tests'])) + seen = set() for d in data['gtest_tests']: if (d['test'] not in ninja_targets and d['test'] not in SKIP_GN_ISOLATE_MAP_TARGETS): @@ -232,6 +233,12 @@ elif d['test'] in ninja_targets: ninja_targets_seen.add(d['test']) + name = d.get('name', d['test']) + if name in seen: + raise Error('%s: %s / %s is listed multiple times.' % + (filename, builder, name)) + seen.add(name) + config[builder]['gtest_tests'] = sorted( data['gtest_tests'], key=lambda x: x['test'])
diff --git a/testing/gtest.gyp b/testing/gtest.gyp index d61772e..dd9435ea 100644 --- a/testing/gtest.gyp +++ b/testing/gtest.gyp
@@ -64,8 +64,7 @@ }, 'mac_bundle': 1, 'xcode_settings': { - 'BUNDLE_ID_TEST_NAME': - '>!(echo ">(_target_name)" | sed -e "s/_//g")', + 'BUNDLE_ID_TEST_NAME': '>(_target_name)', 'INFOPLIST_FILE': '>(ios_unittest_info_plist_path)', }, 'mac_bundle_resources': [
diff --git a/testing/gtest_ios/unittest-Info.plist b/testing/gtest_ios/unittest-Info.plist index f3c38c88..dc34aa0 100644 --- a/testing/gtest_ios/unittest-Info.plist +++ b/testing/gtest_ios/unittest-Info.plist
@@ -9,7 +9,7 @@ <key>CFBundleExecutable</key> <string>${EXECUTABLE_NAME}</string> <key>CFBundleIdentifier</key> - <string>com.google.gtest.${BUNDLE_ID_TEST_NAME}</string> + <string>com.google.gtest.${BUNDLE_ID_TEST_NAME:rfc1034identifier}</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> @@ -57,8 +57,8 @@ <true/> <key>NSAppTransportSecurity</key> <dict> - <key>NSAllowsArbitraryLoads</key> - <true/> + <key>NSAllowsArbitraryLoads</key> + <true/> </dict> <key>NSMainNibFile</key> <string>${MAIN_NIB_FILE}</string> @@ -151,10 +151,10 @@ <dict> <key>CFBundleURLSchemes</key> <array> - <string>${BUNDLE_ID_TEST_NAME}.http</string> - <string>${BUNDLE_ID_TEST_NAME}.https</string> - <string>${BUNDLE_ID_TEST_NAME}-x-callback</string> - <string>com.google.sso.${BUNDLE_ID_TEST_NAME}</string> + <string>${BUNDLE_ID_TEST_NAME:rfc1034identifier}.http</string> + <string>${BUNDLE_ID_TEST_NAME:rfc1034identifier}.https</string> + <string>${BUNDLE_ID_TEST_NAME:rfc1034identifier}-x-callback</string> + <string>com.google.sso.${BUNDLE_ID_TEST_NAME:rfc1034identifier}</string> </array> </dict> </array> @@ -186,7 +186,7 @@ <array> <string>fetch</string> </array> - <key>SSOAuthURLScheme</key> - <string>com.google.sso.${BUNDLE_ID_TEST_NAME}</string> + <key>SSOAuthURLScheme</key> + <string>com.google.sso.${BUNDLE_ID_TEST_NAME:rfc1034identifier}</string> </dict> </plist>
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/Ahem.woff b/testing/libfuzzer/fuzzers/woff2_corpus/Ahem.woff deleted file mode 100644 index 0bc8093..0000000 --- a/testing/libfuzzer/fuzzers/woff2_corpus/Ahem.woff +++ /dev/null Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/Ahem.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/Ahem.woff2 new file mode 100644 index 0000000..7729324 --- /dev/null +++ b/testing/libfuzzer/fuzzers/woff2_corpus/Ahem.woff2 Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/AhemSpaceLigature.woff b/testing/libfuzzer/fuzzers/woff2_corpus/AhemSpaceLigature.woff deleted file mode 100644 index 2f576b9a..0000000 --- a/testing/libfuzzer/fuzzers/woff2_corpus/AhemSpaceLigature.woff +++ /dev/null Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/AhemSpaceLigature.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/AhemSpaceLigature.woff2 new file mode 100644 index 0000000..dc15e79d --- /dev/null +++ b/testing/libfuzzer/fuzzers/woff2_corpus/AhemSpaceLigature.woff2 Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif-webfont.woff b/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif-webfont.woff deleted file mode 100644 index 4583cc6..0000000 --- a/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif-webfont.woff +++ /dev/null Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif-webfont.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif-webfont.woff2 new file mode 100644 index 0000000..953010a --- /dev/null +++ b/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif-webfont.woff2 Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif.woff2 new file mode 100644 index 0000000..b972c08 --- /dev/null +++ b/testing/libfuzzer/fuzzers/woff2_corpus/DejaVuSerif.woff2 Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/EzraSIL.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/EzraSIL.woff2 new file mode 100644 index 0000000..e987c38 --- /dev/null +++ b/testing/libfuzzer/fuzzers/woff2_corpus/EzraSIL.woff2 Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/LinLibertineO.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/LinLibertineO.woff2 new file mode 100644 index 0000000..e843c8c --- /dev/null +++ b/testing/libfuzzer/fuzzers/woff2_corpus/LinLibertineO.woff2 Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/LinLibertine_R.woff b/testing/libfuzzer/fuzzers/woff2_corpus/LinLibertine_R.woff deleted file mode 100644 index 0357ad4..0000000 --- a/testing/libfuzzer/fuzzers/woff2_corpus/LinLibertine_R.woff +++ /dev/null Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/MEgalopolisExtra.woff b/testing/libfuzzer/fuzzers/woff2_corpus/MEgalopolisExtra.woff deleted file mode 100644 index ee37efff..0000000 --- a/testing/libfuzzer/fuzzers/woff2_corpus/MEgalopolisExtra.woff +++ /dev/null Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/MEgalopolisExtra.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/MEgalopolisExtra.woff2 new file mode 100644 index 0000000..2d0def4 --- /dev/null +++ b/testing/libfuzzer/fuzzers/woff2_corpus/MEgalopolisExtra.woff2 Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/OpenSans-Regular.woff b/testing/libfuzzer/fuzzers/woff2_corpus/OpenSans-Regular.woff deleted file mode 100644 index 55b25f8..0000000 --- a/testing/libfuzzer/fuzzers/woff2_corpus/OpenSans-Regular.woff +++ /dev/null Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/OpenSans.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/OpenSans.woff2 new file mode 100644 index 0000000..f898c34 --- /dev/null +++ b/testing/libfuzzer/fuzzers/woff2_corpus/OpenSans.woff2 Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/mplus-1p-regular.woff b/testing/libfuzzer/fuzzers/woff2_corpus/mplus-1p-regular.woff deleted file mode 100644 index 42cfff6..0000000 --- a/testing/libfuzzer/fuzzers/woff2_corpus/mplus-1p-regular.woff +++ /dev/null Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/mplus-1p-regular.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/mplus-1p-regular.woff2 new file mode 100644 index 0000000..171e366 --- /dev/null +++ b/testing/libfuzzer/fuzzers/woff2_corpus/mplus-1p-regular.woff2 Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/open_sans.woff b/testing/libfuzzer/fuzzers/woff2_corpus/open_sans.woff deleted file mode 100644 index 55b25f8..0000000 --- a/testing/libfuzzer/fuzzers/woff2_corpus/open_sans.woff +++ /dev/null Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/sileot-webfont.woff b/testing/libfuzzer/fuzzers/woff2_corpus/sileot-webfont.woff deleted file mode 100644 index 81547578..0000000 --- a/testing/libfuzzer/fuzzers/woff2_corpus/sileot-webfont.woff +++ /dev/null Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/tcu-font.woff b/testing/libfuzzer/fuzzers/woff2_corpus/tcu-font.woff deleted file mode 100644 index c880aaab..0000000 --- a/testing/libfuzzer/fuzzers/woff2_corpus/tcu-font.woff +++ /dev/null Binary files differ
diff --git a/testing/libfuzzer/fuzzers/woff2_corpus/tcu-font.woff2 b/testing/libfuzzer/fuzzers/woff2_corpus/tcu-font.woff2 new file mode 100644 index 0000000..df15e4cd --- /dev/null +++ b/testing/libfuzzer/fuzzers/woff2_corpus/tcu-font.woff2 Binary files differ
diff --git a/testing/variations/fieldtrial_testing_config_android.json b/testing/variations/fieldtrial_testing_config_android.json index 39241df..faee7b51 100644 --- a/testing/variations/fieldtrial_testing_config_android.json +++ b/testing/variations/fieldtrial_testing_config_android.json
@@ -115,6 +115,14 @@ "group_name": "Enabled" } ], + "ExpectCTReporting": [ + { + "enable_features": [ + "ExpectCTReporting" + ], + "group_name": "ExpectCTReportingEnabled" + } + ], "ImeThread": [ { "enable_features": [ @@ -252,14 +260,6 @@ "group_name": "Enabled" } ], - "PassiveDocumentEventListeners": [ - { - "enable_features": [ - "PassiveDocumentEventListeners" - ], - "group_name": "Enabled" - } - ], "PasswordBranding": [ { "group_name": "SmartLockBrandingSavePromptOnly"
diff --git a/testing/variations/fieldtrial_testing_config_chromeos.json b/testing/variations/fieldtrial_testing_config_chromeos.json index 56fde3f..0f5a3555 100644 --- a/testing/variations/fieldtrial_testing_config_chromeos.json +++ b/testing/variations/fieldtrial_testing_config_chromeos.json
@@ -64,6 +64,14 @@ "group_name": "Enabled" } ], + "ExpectCTReporting": [ + { + "enable_features": [ + "ExpectCTReporting" + ], + "group_name": "ExpectCTReportingEnabled" + } + ], "ExtensionActionRedesign": [ { "group_name": "Enabled" @@ -120,14 +128,6 @@ "group_name": "Enabled" } ], - "PassiveDocumentEventListeners": [ - { - "enable_features": [ - "PassiveDocumentEventListeners" - ], - "group_name": "Enabled" - } - ], "PasswordBranding": [ { "group_name": "SmartLockBrandingSavePromptOnly"
diff --git a/testing/variations/fieldtrial_testing_config_ios.json b/testing/variations/fieldtrial_testing_config_ios.json index bb8cfc3d..95c1922 100644 --- a/testing/variations/fieldtrial_testing_config_ios.json +++ b/testing/variations/fieldtrial_testing_config_ios.json
@@ -28,6 +28,14 @@ "group_name": "Enabled" } ], + "ExpectCTReporting": [ + { + "enable_features": [ + "ExpectCTReporting" + ], + "group_name": "ExpectCTReportingEnabled" + } + ], "NetworkTimeQueries": [ { "enable_features": [
diff --git a/testing/variations/fieldtrial_testing_config_linux.json b/testing/variations/fieldtrial_testing_config_linux.json index 9a910c46..75da65df 100644 --- a/testing/variations/fieldtrial_testing_config_linux.json +++ b/testing/variations/fieldtrial_testing_config_linux.json
@@ -74,6 +74,14 @@ "group_name": "Enabled" } ], + "ExpectCTReporting": [ + { + "enable_features": [ + "ExpectCTReporting" + ], + "group_name": "ExpectCTReportingEnabled" + } + ], "ExtensionActionRedesign": [ { "group_name": "Enabled" @@ -151,14 +159,6 @@ "group_name": "Enabled" } ], - "PassiveDocumentEventListeners": [ - { - "enable_features": [ - "PassiveDocumentEventListeners" - ], - "group_name": "Enabled" - } - ], "PasswordBranding": [ { "group_name": "SmartLockBrandingSavePromptOnly"
diff --git a/testing/variations/fieldtrial_testing_config_mac.json b/testing/variations/fieldtrial_testing_config_mac.json index d2d5faa..98ed8f8 100644 --- a/testing/variations/fieldtrial_testing_config_mac.json +++ b/testing/variations/fieldtrial_testing_config_mac.json
@@ -83,6 +83,14 @@ "group_name": "Enabled" } ], + "ExpectCTReporting": [ + { + "enable_features": [ + "ExpectCTReporting" + ], + "group_name": "ExpectCTReportingEnabled" + } + ], "ExtensionActionRedesign": [ { "group_name": "Enabled" @@ -188,14 +196,6 @@ "group_name": "Enabled" } ], - "PassiveDocumentEventListeners": [ - { - "enable_features": [ - "PassiveDocumentEventListeners" - ], - "group_name": "Enabled" - } - ], "PasswordBranding": [ { "group_name": "SmartLockBrandingSavePromptOnly"
diff --git a/testing/variations/fieldtrial_testing_config_win.json b/testing/variations/fieldtrial_testing_config_win.json index ffafb44..33da7706 100644 --- a/testing/variations/fieldtrial_testing_config_win.json +++ b/testing/variations/fieldtrial_testing_config_win.json
@@ -95,6 +95,14 @@ "group_name": "Enabled" } ], + "ExpectCTReporting": [ + { + "enable_features": [ + "ExpectCTReporting" + ], + "group_name": "ExpectCTReportingEnabled" + } + ], "ExtensionActionRedesign": [ { "group_name": "Enabled" @@ -226,14 +234,6 @@ "group_name": "Enabled" } ], - "PassiveDocumentEventListeners": [ - { - "enable_features": [ - "PassiveDocumentEventListeners" - ], - "group_name": "Enabled" - } - ], "PasswordBranding": [ { "group_name": "SmartLockBrandingSavePromptOnly"
diff --git a/third_party/WebKit/LayoutTests/ASANExpectations b/third_party/WebKit/LayoutTests/ASANExpectations index 02b0be0..7841948a 100644 --- a/third_party/WebKit/LayoutTests/ASANExpectations +++ b/third_party/WebKit/LayoutTests/ASANExpectations
@@ -46,13 +46,6 @@ # #0 0x8c2ee4 in WebCore::reportFatalErrorInMainThread crbug.com/173366 [ Linux ] fast/js/string-replacement-outofmemory.html [ Skip ] -# Crash in fast/speechsynthesis/speech-synthesis-cancel.html: -# ==10454==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x00000558b918 sp 0x7fff3153dcf0 bp 0x7fff3153dcf0 T0) -# AddressSanitizer can not provide additional info. -# #0 0x558b917 in WebCore::PlatformSpeechSynthesisUtterance::client() const /mnt/data/b/build/slave/WebKit_Linux_ASAN/build/src/out/Release/../../third_party/WebKit/Source/core/platform/PlatformSpeechSynthesisUtterance.h:71:0 -# [pkasting] July 23 2014: Now timing out instead of crashing. -crbug.com/250520 [ Linux ] fast/speechsynthesis/speech-synthesis-cancel.html [ Timeout ] - # These tests consistently fail on slow bots. crbug.com/231357 [ Linux ] compositing/video-page-visibility.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation index faf96106..3c501846 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-browser-side-navigation
@@ -69,9 +69,7 @@ http/tests/misc/webtiming-cross-origin-and-back.html [ Failure ] http/tests/misc/webtiming-one-redirect.php [ Failure ] http/tests/misc/webtiming-two-redirects.php [ Failure ] - http/tests/w3c/webperf/approved/navigation-timing/html/test_navigation_type_reload.html [ Failure ] http/tests/w3c/webperf/approved/navigation-timing/html/test_timing_attributes_order.html [ Failure ] - http/tests/w3c/webperf/approved/navigation-timing/html/test_timing_reload.html [ Failure ] http/tests/w3c/webperf/approved/navigation-timing/html/test_timing_server_redirect.html [ Failure ] http/tests/w3c/webperf/submission/Google/resource-timing/html/test_resource_redirects.html [ Failure ] http/tests/w3c/webperf/submission/Intel/resource-timing/test_resource_timing_cross_origin_redirect_chain_allow_timing.html [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 index 9d84010..b6988e8a 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -249,7 +249,6 @@ compositing/images/direct-image-dynamic-border-draws-content.html [ Failure ] compositing/images/direct-image-dynamic-clip-path.html [ Failure ] compositing/img-layer-grow.html [ Failure ] -compositing/img-layer-object-fit.html [ Failure ] compositing/layer-creation/animation-overlap-with-children.html [ Failure ] compositing/layer-creation/assumed-overlap-for-inline-transform.html [ Failure ] compositing/layer-creation/compositing-reason-removed.html [ Failure ] @@ -667,21 +666,9 @@ fast/css/margin-top-bottom-dynamic.html [ Failure ] fast/css/nested-rounded-corners.html [ Failure ] fast/css/number-parsing-crash.html [ Crash ] -fast/css/object-fit-embed.html [ Failure ] -fast/css/object-fit-grow-landscape.html [ Failure ] -fast/css/object-fit-grow-portrait.html [ Failure ] fast/css/object-fit-img-svg.html [ Failure ] fast/css/object-fit-img-svg2.html [ Failure ] -fast/css/object-fit-img.html [ Failure ] -fast/css/object-fit-input-image.html [ Failure ] -fast/css/object-fit-object.html [ Failure ] -fast/css/object-fit-shrink.html [ Failure ] -fast/css/object-fit-video-poster.html [ Failure ] fast/css/object-position-svg.html [ Failure ] -fast/css/object-position-with-fit-contain.html [ Failure ] -fast/css/object-position-with-fit-cover.html [ Failure ] -fast/css/object-position-with-fit-none.html [ Failure ] -fast/css/object-position.html [ Failure ] fast/css/only-child-pseudo-class.html [ Failure ] fast/css/only-of-type-pseudo-class.html [ Failure ] fast/css/outline-auto-empty-rects.html [ Failure ] @@ -1060,7 +1047,6 @@ fast/images/color-profile-reflection.html [ Crash ] fast/images/color-profile-svg-fill-text.html [ Failure ] fast/images/color-profile-svg-foreign-object.html [ Failure ] -fast/images/content-url-broken-image-with-alt-text.html [ Failure ] fast/images/content-url-image-with-alt-text.html [ Crash Failure ] fast/images/fixed-img-src-change-after-scroll.html [ Failure ] fast/images/mask-box-image-crash.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls b/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls index 13c7932..a769c86 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls +++ b/third_party/WebKit/LayoutTests/FlagExpectations/root-layer-scrolls
@@ -469,7 +469,7 @@ inspector/elements/shadow/elements-panel-shadow-selection-on-refresh.html [ Timeout ] inspector/layers/layer-tree-model.html [ Failure ] inspector/tracing/scroll-invalidations.html [ Failure ] -inspector/tracing/timeline-paint-with-layout-invalidations.html [ Failure ] +inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations.html [ Failure ] media/video-controls-rendering.html [ Failure ] media/video-controls-with-cast-rendering.html [ Failure ] media/video-overlay-cast-dark-rendering.html [ Failure ] @@ -716,7 +716,7 @@ virtual/threaded/fast/scroll-behavior/subframe-scrollTo.html [ Failure ] virtual/threaded/fast/scroll-behavior/subframe-scrollTop.html [ Failure ] virtual/threaded/inspector/tracing/scroll-invalidations.html [ Failure ] -virtual/threaded/inspector/tracing/timeline-paint-with-layout-invalidations.html [ Failure ] +virtual/threaded/inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations.html [ Failure ] virtual/threaded/printing/forced-break-tree-dump-only.html [ Failure ] virtual/threaded/printing/page-count-relayout-shrink.html [ Failure ] virtual/threaded/printing/return-from-printing-mode.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests index e2a2426..1381294 100644 --- a/third_party/WebKit/LayoutTests/SlowTests +++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -57,6 +57,7 @@ crbug.com/433711 [ Debug ] virtual/gpu/fast/canvas/canvas-composite-image.html [ Slow ] crbug.com/24182 virtual/gpu/fast/canvas/canvas-composite-canvas.html [ Slow ] crbug.com/24182 virtual/gpu/fast/canvas/canvas-createImageBitmap-drawImage.html [ Slow ] +crbug.com/24182 virtual/gpu/fast/canvas/canvas-createImageBitmap-resize.html [ Slow ] crbug.com/24182 virtual/gpu/fast/canvas/canvas-draw-canvas-on-canvas-shadow.html [ Slow ] crbug.com/24182 virtual/gpu/fast/canvas/canvas-drawImage-shadow.html [ Slow ] crbug.com/24182 virtual/gpu/fast/canvas/canvas-imageSmoothingEnabled-repaint.html [ Slow ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 8e76b1d9..43ad7b41 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -195,35 +195,6 @@ # TODO(oshima): Mac Android are currently not supported. crbug.com/567837 [ Mac Android ] virtual/scalefactor200withzoom/fast/hidpi/static [ Skip ] -crbug.com/613414 [ Win ] fast/hidpi/broken-image-icon-hidpi.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] svg/custom/masking-clipping-hidpi.svg [ NeedsRebaseline ] -crbug.com/613414 [ Win ] css3/filters/effect-reference-hidpi.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] fast/hidpi/device-scale-factor-paint.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] virtual/display_list_2d_canvas/fast/canvas/canvas-hidpi-blurry.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] fast/hidpi/focus-rings.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] css3/filters/effect-reference-hidpi-hw.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] fast/hidpi/resize-corner-hidpi.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] fast/hidpi/broken-image-with-size-hidpi.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] virtual/gpu/fast/canvas/canvas-hidpi-blurry.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] fast/sub-pixel/shadows-hidpi.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] compositing/tiled-layers-hidpi.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] svg/as-image/image-respects-deviceScaleFactor.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] fast/hidpi/clip-text-in-hidpi.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] fast/canvas/canvas-hidpi-blurry.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] fast/backgrounds/gradient-background-leakage-hidpi.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] fast/hidpi/gradient-with-scaled-ancestor.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] editing/spelling/grammar-markers-hidpi.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] editing/spelling/inline-spelling-markers-hidpi.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] editing/spelling/inline-spelling-markers-hidpi-composited.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] fast/hidpi/image-srcset-intrinsic-size-zero.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] svg/filters/filter-source-position.svg [ NeedsRebaseline ] -crbug.com/613414 [ Win ] virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance.html [ NeedsRebaseline ] -crbug.com/613414 [ Win ] virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance.html [ NeedsRebaseline ] - # Mac does not support fractional scale factor. crbug.com/567837 [ Mac ] virtual/scalefactor150/fast/hidpi/static [ Skip ] @@ -246,13 +217,13 @@ crbug.com/498539 http/tests/inspector/elements/styles/selector-line.html [ Pass Timeout ] crbug.com/498539 http/tests/inspector/network/network-datareceived.html [ Pass Timeout ] crbug.com/498539 [ Win ] inspector/tracing/decode-resize.html [ Failure Timeout ] -crbug.com/498539 [ Win ] inspector/tracing/timeline-event-dispatch.html [ Failure Pass ] +crbug.com/498539 [ Win ] inspector/tracing/timeline-misc/timeline-event-dispatch.html [ Failure Pass ] crbug.com/498539 inspector/console/console-log-syntax-error.html [ Pass Timeout ] -crbug.com/498539 inspector/tracing/timeline-bound-function.html [ Pass Failure ] -crbug.com/498539 virtual/threaded/inspector/tracing/timeline-bound-function.html [ Pass Failure ] -crbug.com/498539 inspector/tracing/timeline-injected-script-eval.html [ Pass Failure ] -crbug.com/498539 inspector/tracing/timeline-time.html [ Pass Failure Timeout ] -crbug.com/498539 inspector/tracing/timeline-timer.html [ Pass Failure ] +crbug.com/498539 inspector/tracing/timeline-misc/timeline-bound-function.html [ Pass Failure ] +crbug.com/498539 virtual/threaded/inspector/tracing/timeline-misc/timeline-bound-function.html [ Pass Failure ] +crbug.com/498539 inspector/tracing/timeline-js/timeline-injected-script-eval.html [ Pass Failure ] +crbug.com/498539 inspector/tracing/timeline-time/timeline-time.html [ Pass Failure Timeout ] +crbug.com/498539 inspector/tracing/timeline-time/timeline-timer.html [ Pass Failure ] crbug.com/498539 inspector/elements/styles-3/styles-change-node-while-editing.html [ Failure Pass ] crbug.com/498539 [ Mac ] inspector/sources/debugger/live-edit-no-reveal.html [ Crash Pass Timeout ] crbug.com/498539 [ Mac10.10 ] inspector/sources/debugger/debug-inlined-scripts-fragment-id.html [ Pass Timeout ] @@ -475,6 +446,7 @@ crbug.com/490511 imported/wpt/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback.html [ Failure ] crbug.com/490511 imported/wpt/html/semantics/document-metadata/styling/LinkStyle.html [ Failure Pass ] crbug.com/490511 imported/wpt/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/src.html [ Failure ] +crbug.com/627706 imported/wpt/html/semantics/embedded-content/the-img-element/invalid-src.html [ Skip ] crbug.com/525889 imported/wpt/html/webappapis/scripting/processing-model-2/compile-error-in-setInterval.html [ Failure ] crbug.com/525889 imported/wpt/html/webappapis/scripting/processing-model-2/compile-error-in-setTimeout.html [ Failure ] crbug.com/525889 imported/wpt/html/webappapis/scripting/processing-model-2/runtime-error-in-setInterval.html [ Failure ] @@ -517,9 +489,6 @@ # Web Components related tests (Shadow DOM, Custom Elements) failures. crbug.com/505364 imported/wpt/shadow-dom/untriaged/styles/test-003.html [ Failure ] -crbug.com/505364 imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html [ Failure ] -crbug.com/505364 imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html [ Failure ] -crbug.com/505364 imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html [ Failure ] crbug.com/505364 imported/wpt/shadow-dom/untriaged/elements-and-dom-objects/extensions-to-event-interface/event-path-001.html [ Failure ] crbug.com/505364 imported/wpt/custom-elements/v0/instantiating/extensions-to-document-interface/create-element-interface-type-is-a-type-extension.html [ Failure ] crbug.com/505364 imported/csswg-test/css-scoping-1/css-scoping-shadow-slot-display-override.html [ Failure ] @@ -789,7 +758,6 @@ crbug.com/564403 http/tests/inspector/service-workers/service-worker-manager.html [ Failure Pass ] crbug.com/613728 fast/table/border-collapsing/cached-cell-append.html [ Failure ] -crbug.com/613728 fast/table/border-collapsing/cached-change-tbody-border-width.html [ Failure ] crbug.com/613728 fast/table/border-collapsing/cached-change-col-border-width.html [ Failure ] crbug.com/613728 fast/table/border-collapsing/cached-cell-remove.html [ Failure ] crbug.com/613728 fast/table/border-collapsing/cached-69296.html [ Failure ] @@ -811,7 +779,6 @@ # We only want to run one of the web-animations-api tests in stable mode. crbug.com/441553 virtual/stable/web-animations-api [ Skip ] -crbug.com/368946 virtual/stable/web-animations-api/eased-keyframes.html [ Pass ] # These tests *only* run in stable, to verify that these features are unsupported and throw exceptions. crbug.com/441559 virtual/stable/web-animations-api/partial-keyframes-unsupported.html [ Pass ] crbug.com/437696 virtual/stable/web-animations-api/additive-animations-unsupported.html [ Pass ] @@ -956,10 +923,10 @@ crbug.com/619060 imported/wpt/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual.html [ Skip ] crbug.com/619060 imported/wpt/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual.html [ Skip ] crbug.com/619060 imported/wpt/pointerevents/pointerevent_pointerleave_touch-manual.html [ Skip ] -crbug.com/620236 imported/wpt/pointerevents/pointerevent_properties_mouse-manual.html [ Skip ] crbug.com/620236 imported/wpt/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_suppress_compat_events_on_click.html [ Skip ] +crbug.com/620236 imported/wpt/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse.html [ Skip ] crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-auto-css_touch-manual.html [ Skip ] -crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-button-test_touch-manual.html [ Skip ] crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html [ Skip ] crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual.html [ Skip ] crbug.com/620236 imported/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html [ Skip ] @@ -978,6 +945,7 @@ crbug.com/583413 imported/wpt/pointerevents/pointerevent_pointerleave_pen-manual.html [ Failure ] +crbug.com/627716 imported/wpt/pointerevents/pointerevent_touch-action-button-test_touch-manual.html [ Skip ] # These testcases are incorrect, mark them as failing until they're fixed in the testsuite. # https://lists.w3.org/Archives/Public/www-style/2016Jan/0275.html @@ -1254,7 +1222,7 @@ crbug.com/572723 [ Linux Mac10.9 ] inspector/sources/debugger/debugger-disable-enable.html [ Pass Failure Timeout ] crbug.com/572723 inspector/sources/debugger/debugger-uncaught-promise-on-pause.html [ Timeout Pass ] -crbug.com/572726 inspector/tracing/timeline-node-reference.html [ Timeout Pass Crash ] +crbug.com/572726 inspector/tracing/timeline-misc/timeline-node-reference.html [ Timeout Pass Crash ] crbug.com/155836 fast/text/emphasis-ellipsis-complextext.html [ Failure Pass ] @@ -1333,8 +1301,6 @@ crbug.com/624019 [ Mac ] bluetooth/notifications/stop-twice.html [ Skip ] crbug.com/624019 [ Mac ] bluetooth/notifications/stop-without-starting.html [ Skip ] -crbug.com/626992 paint/invalidation/outline-containing-image-in-non-standard-mode.html [ NeedsRebaseline ] - crbug.com/487344 compositing/video/video-controls-layer-creation.html [ Failure ] crbug.com/487344 fast/hidpi/video-controls-in-hidpi.html [ Failure ] crbug.com/487344 fast/layers/video-layer.html [ Failure ] @@ -1390,3 +1356,40 @@ crbug.com/625020 [ Debug ] compositing/repaint/page-scale-repaint.html [ Timeout ] crbug.com/620432 accessibility/aria-activedescendant.html [ Failure ] + +crbug.com/593567 [ Linux Debug ] virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance.html [ Skip ] +crbug.com/593567 [ Linux Debug ] virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance.html [ Skip ] + +crbug.com/627782 [ Win ] svg/filters/filter-source-position.svg [ Pass Failure ] + +crbug.com/627798 editing/spelling/inline-spelling-markers-hidpi-composited.html [ Pass Failure ] +crbug.com/627798 fast/repaint/line-flow-with-floats-9.html [ Pass Failure ] +crbug.com/627798 fast/repaint/nested-fixed-iframe-scrolled.html [ Pass Failure ] +crbug.com/627798 fast/repaint/repaint-during-scroll-with-zoom.html [ Pass Failure ] +crbug.com/627798 fast/repaint/resize-scrollable-iframe.html [ Pass Failure ] +crbug.com/627798 fast/repaint/text-match-document-change.html [ Pass Failure ] + +# Very slight rendering changes caused by Skia rect clipping change. +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-background-image-space.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/png-with-color-profile.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-image-profile-match.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/exif-orientation-height-image-document.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-reflection.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-background-image-cross-fade-png.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-background-image-repeat.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-background-image-cross-fade.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-image.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-border-image-source.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-munsell-srgb-to-srgb.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-image-canvas-pattern.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-border-image.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-munsell-adobe-to-srgb.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-mask-image-svg.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-group.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-image-canvas.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/jpeg-with-color-profile.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-svg.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-background-image-cover.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/color-profile-object.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu-rasterization/fast/images/ycbcr-with-cmyk-color-profile.html [ NeedsManualRebaseline ] +crbug.com/627844 virtual/gpu/fast/canvas/canvas-createImageBitmap-colorClamping.html [ Pass Failure ] \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/W3CImportExpectations b/third_party/WebKit/LayoutTests/W3CImportExpectations index 0db0697..cda5870 100644 --- a/third_party/WebKit/LayoutTests/W3CImportExpectations +++ b/third_party/WebKit/LayoutTests/W3CImportExpectations
@@ -196,6 +196,7 @@ imported/wpt/XMLHttpRequest [ Skip ] imported/wpt/ambient-light [ Skip ] imported/wpt/animation-timing [ Skip ] +imported/wpt/annotation-model [ Skip ] imported/wpt/app-uri [ Skip ] imported/wpt/battery-status [ Skip ] ## Owners: none; No tests in the directory.
diff --git a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-width-interpolation.html b/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-width-interpolation.html index 311fc51..c561683 100644 --- a/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-width-interpolation.html +++ b/third_party/WebKit/LayoutTests/animations/svg-attribute-interpolation/svg-width-interpolation.html
@@ -89,6 +89,78 @@ {at: 1, is: '20rem'}, {at: 1.4, is: '0'} ]); +assertAttributeInterpolation({ + property: 'width', + from: '1vw', + to: '6vw' +}, [ + {at: -0.4, is: '0vw'}, + {at: 0, is: '1vw'}, + {at: 0.2, is: '2vw'}, + {at: 0.6, is: '4vw'}, + {at: 1, is: '6vw'}, + {at: 1.4, is: '8vw'} +]); +assertAttributeInterpolation({ + property: 'width', + from: '1vh', + to: '6vh' +}, [ + {at: -0.4, is: '0vh'}, + {at: 0, is: '1vh'}, + {at: 0.2, is: '2vh'}, + {at: 0.6, is: '4vh'}, + {at: 1, is: '6vh'}, + {at: 1.4, is: '8vh'} +]); +assertAttributeInterpolation({ + property: 'width', + from: '1vmin', + to: '6vmin' +}, [ + {at: -0.4, is: '0vmin'}, + {at: 0, is: '1vmin'}, + {at: 0.2, is: '2vmin'}, + {at: 0.6, is: '4vmin'}, + {at: 1, is: '6vmin'}, + {at: 1.4, is: '8vmin'} +]); +assertAttributeInterpolation({ + property: 'width', + from: '1vmax', + to: '6vmax' +}, [ + {at: -0.4, is: '0vmax'}, + {at: 0, is: '1vmax'}, + {at: 0.2, is: '2vmax'}, + {at: 0.6, is: '4vmax'}, + {at: 1, is: '6vmax'}, + {at: 1.4, is: '8vmax'} +]); +assertAttributeInterpolation({ + property: 'width', + from: '10vh', + to: '20vw' +}, [ + {at: -0.4, is: '20'}, + {at: 0, is: '10vh'}, + {at: 0.2, is: '80'}, + {at: 0.6, is: '120'}, + {at: 1, is: '20vw'}, + {at: 1.4, is: '200'} +]); +assertAttributeInterpolation({ + property: 'width', + from: '10vmin', + to: '20vmax' +}, [ + {at: -0.4, is: '20'}, + {at: 0, is: '10vmin'}, + {at: 0.2, is: '80'}, + {at: 0.6, is: '120'}, + {at: 1, is: '20vmax'}, + {at: 1.4, is: '200'} +]); </script> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/compositing/img-layer-object-fit-expected.html b/third_party/WebKit/LayoutTests/compositing/img-layer-object-fit-expected.html deleted file mode 100644 index b1beeecd8..0000000 --- a/third_party/WebKit/LayoutTests/compositing/img-layer-object-fit-expected.html +++ /dev/null
@@ -1,11 +0,0 @@ -<!DOCTYPE html> -<style> - img { - width: 100px; - height: 30px; - } -</style> -<img src="resources/simple_image.png" style="object-fit: contain"/><br/> -<img src="resources/simple_image.png" style="object-fit: cover"/><br/> -<img src="resources/simple_image.png" style="object-fit: none"/><br/> -<img src="resources/simple_image.png" style="object-fit: scale-down"/><br/> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/compositing/img-layer-object-fit-expected.png b/third_party/WebKit/LayoutTests/compositing/img-layer-object-fit-expected.png new file mode 100644 index 0000000..9c9cc0c --- /dev/null +++ b/third_party/WebKit/LayoutTests/compositing/img-layer-object-fit-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/css3/motion-path/motion-rotation-overflow-crash.html b/third_party/WebKit/LayoutTests/css3/motion-path/motion-rotation-overflow-crash.html new file mode 100644 index 0000000..060d15d --- /dev/null +++ b/third_party/WebKit/LayoutTests/css3/motion-path/motion-rotation-overflow-crash.html
@@ -0,0 +1,10 @@ +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<style> +body { + motion: path("M 2 9223372036854775640 h 112 v 18446744073709551478") 170141183460469231731687303715884105727rad 44px; +} +</style> +<script> +test(() => {}, "Don't crash when using very large rotation angles."); +</script>
diff --git a/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom-expected.png b/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom-expected.png new file mode 100644 index 0000000..2385f47 --- /dev/null +++ b/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom-expected.txt b/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom-expected.txt new file mode 100644 index 0000000..61418eaf --- /dev/null +++ b/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom-expected.txt
@@ -0,0 +1,8 @@ +CONSOLE MESSAGE: line 31: The worklet should log: 'width: 100, height: 100' +CONSOLE MESSAGE: line 8: width: 100, height: 100 +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x348 + LayoutBlockFlow {HTML} at (0,0) size 800x348 + LayoutBlockFlow {BODY} at (24,24) size 752x300 + LayoutBlockFlow {DIV} at (0,0) size 300x300
diff --git a/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom.html b/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom.html new file mode 100644 index 0000000..ba22299 --- /dev/null +++ b/third_party/WebKit/LayoutTests/csspaint/paint2d-zoom.html
@@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html> +<head> +<script src="../resources/run-after-layout-and-paint.js"></script> +<script src="resources/test-runner-paint-worklet.js"></script> +<style> + #output { + width: 100px; + height: 100px; + background-image: paint(worklet); + } +</style> +</head> +<body> +<div id="output"></div> + +<script id="code" type="text/worklet"> +registerPaint('worklet', class { + paint(ctx, geom) { + ctx.rotate(10 * Math.PI / 180); + ctx.strokeStyle = 'blue'; + ctx.lineWidth = 4; + ctx.strokeRect(30, 10, 30, 30); + console.log('width: ' + geom.width + ', height: ' + geom.height); + } +}); +</script> + +<script> + document.body.style.zoom = "300%"; + console.log('The worklet should log: \'width: 100, height: 100\''); + importPaintWorkletAndTerminateTestAfterAsyncPaint(document.getElementById('code').textContent); +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/editing/execCommand/insert_list/insert_list_in_summary_crash.html b/third_party/WebKit/LayoutTests/editing/execCommand/insert_list/insert_list_in_summary_crash.html new file mode 100644 index 0000000..0a139fc3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/editing/execCommand/insert_list/insert_list_in_summary_crash.html
@@ -0,0 +1,11 @@ +<!-- this test requies quirks mode. --> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../assert_selection.js"></script> +<script> +test(() => assert_selection( + '<div contenteditable><summary><ol><li>^abc|</li></ol></summary></div>', + 'insertOrderedList', + '<div contenteditable><summary>^abc|</summary></div>', + 'styleFromMatchedRulesForElement() should be called after distribution')); +</script>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/mouse/click-user-select-all-contenteditable.html b/third_party/WebKit/LayoutTests/editing/selection/mouse/click-user-select-all-contenteditable.html new file mode 100644 index 0000000..1518d82 --- /dev/null +++ b/third_party/WebKit/LayoutTests/editing/selection/mouse/click-user-select-all-contenteditable.html
@@ -0,0 +1,21 @@ +<!doctype HTML> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../assert_selection.js"></script> +<div id="log"></div> +<script> +test(function(){ + assert_true(window.hasOwnProperty('eventSender'), 'this test requires window.eventSender'); + assert_selection( + '<div contenteditable="true" id="div" style="-webkit-user-select:all">bar</div>', + selection => { + var div = selection.document.getElementById('div'); + eventSender.mouseMoveTo(selection.document.offsetLeft + div.offsetLeft + 5, selection.document.offsetTop + div.offsetTop + 5); + eventSender.mouseDown(); + eventSender.mouseUp(); + eventSender.leapForward(100); + }, + '<div contenteditable="true" id="div" style="-webkit-user-select:all">|bar</div>'); + }, +'User can focus in -webkit-user-select:all contenteditable element'); +</script>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/mouse/click-user-select-all-textarea.html b/third_party/WebKit/LayoutTests/editing/selection/mouse/click-user-select-all-textarea.html new file mode 100644 index 0000000..acd67fc --- /dev/null +++ b/third_party/WebKit/LayoutTests/editing/selection/mouse/click-user-select-all-textarea.html
@@ -0,0 +1,17 @@ +<!doctype HTML> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<textarea id="textarea" style="-webkit-user-select:all"></textarea> +<script> +test(function(){ + assert_true(window.hasOwnProperty('eventSender'), 'this test requires window.eventSender'); + eventSender.mouseMoveTo(textarea.offsetLeft + 5, textarea.offsetTop + 5); + eventSender.mouseDown(); + eventSender.mouseUp(); + eventSender.keyDown('f'); + eventSender.keyDown('o'); + eventSender.keyDown('o'); + assert_equals(textarea.value, 'foo'); + }, +'User can ipnut in -webkit-user-select:all textarea'); +</script>
diff --git a/third_party/WebKit/LayoutTests/editing/selection/user-select/user-select-all-contenteditable.html b/third_party/WebKit/LayoutTests/editing/selection/user-select/user-select-all-contenteditable.html new file mode 100644 index 0000000..8a8862d4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/editing/selection/user-select/user-select-all-contenteditable.html
@@ -0,0 +1,67 @@ +<!doctype HTML> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script src="../../assert_selection.js"></script> +<div id="log"></div> +<script> +test(function(){ + assert_selection( + '<div contenteditable="true" id="div" style="-webkit-user-select:all">foo</div>', + selection => selection.collapse(selection.document.getElementById('div').firstChild, 1), + '<div contenteditable="true" id="div" style="-webkit-user-select:all">f|oo</div>'); + assert_selection( + '<div contenteditable="true" id="div" style="-webkit-user-select:all">f|oo</div>', + selection => selection.extend(selection.document.getElementById('div').firstChild, 2), + '<div contenteditable="true" id="div" style="-webkit-user-select:all">f^o|o</div>'); + assert_selection( + '<div contenteditable="true" id="div" style="-webkit-user-select:all">foo</div>', + selection => { + var div = selection.document.getElementById('div'); + selection.setBaseAndExtent(div.firstChild, 1, div.firstChild, 2); + }, + '<div contenteditable="true" id="div" style="-webkit-user-select:all">f^o|o</div>'); + assert_selection( + '<div contenteditable="true" id="div" style="-webkit-user-select:all">foo</div>', + selection => { + var range = selection.document.createRange(); + var div = selection.document.getElementById('div'); + range.setStart(div, 0); + range.setEnd(div, 1); + selection.addRange(range); + }, + '<div contenteditable="true" id="div" style="-webkit-user-select:all">^foo|</div>'); + assert_selection( + '<div contenteditable="true" id="div" style="-webkit-user-select:all">|foo</div>', + selection => selection.modify('move', 'forward', 'character'), + '<div contenteditable="true" id="div" style="-webkit-user-select:all">f|oo</div>'); + assert_selection( + '<div contenteditable="true" id="div" style="-webkit-user-select:all">f|oo</div>', + selection => selection.modify('move', 'backward', 'character'), + '<div contenteditable="true" id="div" style="-webkit-user-select:all">|foo</div>'); + assert_selection( + '<div contenteditable="true" id="div" style="-webkit-user-select:all">|foo</div>', + selection => selection.modify('extend', 'forward', 'character'), + '<div contenteditable="true" id="div" style="-webkit-user-select:all">^foo|</div>'); + assert_selection( + '<div contenteditable="true" id="div" style="-webkit-user-select:all">foo|</div>', + selection => selection.modify('extend', 'backward', 'character'), + '<div contenteditable="true" id="div" style="-webkit-user-select:all">|foo^</div>'); + }, +'Selection API can edit in -webkit-user-select:all contenteditable element'); + +test(function(){ + assert_selection( + '<div contenteditable="true" id="div" style="-webkit-user-select:all">|foo</div>', + selection => selection.document.execCommand('insertText', false, 'bar'), + '<div contenteditable="true" id="div" style="-webkit-user-select:all">bar|foo</div>'); + }, +'Execcommand inserttext in -webkit-user-select:all contenteditable element'); + +test(function(){ + assert_selection( + '<div contenteditable="true" id="div" style="-webkit-user-select:all">foo</div>', + selection => assert_true(selection.document.getElementById('div').isContentEditable), + '<div contenteditable="true" id="div" style="-webkit-user-select:all">foo</div>'); + }, +'-webkit-user-select:all contenteditable element is HTMLElement.isContentEditable == true'); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-resize.html b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-resize.html new file mode 100644 index 0000000..b734fb0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-createImageBitmap-resize.html
@@ -0,0 +1,156 @@ +<!DOCTYPE HTML> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script> +function checkNoCrop(imageBitmap) +{ + var canvas = document.createElement("canvas"); + canvas.width = 50; + canvas.height = 50; + var ctx = canvas.getContext("2d"); + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(imageBitmap, 0, 0); + var d = ctx.getImageData(0, 0, 1, 1).data; + assert_array_equals(d, [255, 0, 0, 255], "This pixel should be red."); + console.log(d[0] + " " + d[1] + " " + d[2] + " " + d[3]); + d = ctx.getImageData(39, 0, 1, 1).data; + assert_array_equals(d, [0, 255, 0, 255], "This pixel should be green."); + console.log(d[0] + " " + d[1] + " " + d[2] + " " + d[3]); + d = ctx.getImageData(0, 39, 1, 1).data; + assert_array_equals(d, [0, 0, 255, 255], "This pixel should be blue."); + console.log(d[0] + " " + d[1] + " " + d[2] + " " + d[3]); + d = ctx.getImageData(39, 39, 1, 1).data; + assert_array_equals(d, [0, 0, 0, 255], "This pixel should be black."); + console.log(d[0] + " " + d[1] + " " + d[2] + " " + d[3]); + d = ctx.getImageData(41, 41, 1, 1).data; + assert_array_equals(d, [0, 0, 0, 0], "This pixel should be transparent black."); + console.log(d[0] + " " + d[1] + " " + d[2] + " " + d[3]); +} + +function checkCrop(imageBitmap) +{ + var canvas = document.createElement("canvas"); + canvas.width = 50; + canvas.height = 50; + var ctx = canvas.getContext("2d"); + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(imageBitmap, 0, 0); + var d = ctx.getImageData(0, 0, 1, 1).data; + assert_array_equals(d, [255, 0, 0, 255], "This pixel should be red."); + d = ctx.getImageData(19, 0, 1, 1).data; + assert_array_equals(d, [0, 255, 0, 255], "This pixel should be green."); + d = ctx.getImageData(0, 19, 1, 1).data; + assert_array_equals(d, [0, 0, 255, 255], "This pixel should be blue."); + d = ctx.getImageData(19, 19, 1, 1).data; + assert_array_equals(d, [0, 0, 0, 255], "This pixel should be black."); + d = ctx.getImageData(21, 21, 1, 1).data; + assert_array_equals(d, [0, 0, 0, 0], "This pixel should be transparent black."); +} + +function compareBitmaps(bitmap1, bitmap2) +{ + var canvas1 = document.createElement("canvas"); + var canvas2 = document.createElement("canvas"); + canvas1.width = 50; + canvas1.height = 50; + canvas2.width = 50; + canvas2.height = 50; + var ctx1 = canvas1.getContext("2d"); + var ctx2 = canvas2.getContext("2d"); + ctx1.clearRect(0, 0, canvas1.width, canvas1.height); + ctx2.clearRect(0, 0, canvas2.width, canvas2.height); + ctx1.drawImage(bitmap1, 0, 0); + ctx2.drawImage(bitmap2, 0, 0); + var data1 = ctx1.getImageData(0, 0, 50, 50).data; + var data2 = ctx2.getImageData(0, 0, 50, 50).data; + var dataMatched = true; + for (var i = 0; i < data1.length; i++) { + if (data1[i] != data2[i]) { + dataMatched = false; + break; + } + } + assert_false(dataMatched); +} + +function testImageBitmap(source) +{ + return Promise.all([ + createImageBitmap(source, {resizeWidth: 40, resizeHeight: 40, resizeQuality: "high"}), + createImageBitmap(source, {resizeWidth: 40, resizeHeight: 40, resizeQuality: "medium"}), + createImageBitmap(source, {resizeWidth: 40, resizeHeight: 40, resizeQuality: "low"}), + createImageBitmap(source, {resizeWidth: 40, resizeHeight: 40, resizeQuality: "pixelated"}), + createImageBitmap(source, 10, 10, 20, 20, {resizeWidth: 40, resizeHeight: 40, resizeQuality: "high"}), + createImageBitmap(source, 10, 10, 20, 20, {resizeWidth: 40, resizeHeight: 40, resizeQuality: "medium"}), + createImageBitmap(source, 10, 10, 20, 20, {resizeWidth: 40, resizeHeight: 40, resizeQuality: "low"}), + createImageBitmap(source, 10, 10, 20, 20, {resizeWidth: 40, resizeHeight: 40, resizeQuality: "pixelated"}), + ]).then(([noCropHigh, noCropMedium, noCropLow, noCropPixelated, cropHigh, cropMedium, cropLow, cropPixelated]) => { + checkNoCrop(noCropHigh); + checkNoCrop(noCropMedium); + checkNoCrop(noCropLow); + checkNoCrop(noCropPixelated); + checkCrop(cropHigh); + checkCrop(cropMedium); + checkCrop(cropLow); + checkCrop(cropPixelated); + // Brute-force comparison among all bitmaps is too expensive + compareBitmaps(noCropHigh, noCropMedium); + compareBitmaps(noCropLow, noCropPixelated); + compareBitmaps(cropHigh, cropMedium); + compareBitmaps(cropLow, cropPixelated); + }); +} + +function initializeTestCanvas() +{ + var testCanvas = document.createElement("canvas"); + testCanvas.width = 20; + testCanvas.height = 20; + var testCtx = testCanvas.getContext("2d"); + testCtx.fillStyle = "rgb(255, 0, 0)"; + testCtx.fillRect(0, 0, 10, 10); + testCtx.fillStyle = "rgb(0, 255, 0)"; + testCtx.fillRect(10, 0, 10, 10); + testCtx.fillStyle = "rgb(0, 0, 255)"; + testCtx.fillRect(0, 10, 10, 10); + testCtx.fillStyle = "rgb(0, 0, 0)"; + testCtx.fillRect(10, 10, 10, 10); + return testCanvas; +} + +// Blob +promise_test(function() { + return new Promise((resolve, reject) => { + var xhr = new XMLHttpRequest(); + xhr.open("GET", 'resources/pattern.png'); + xhr.responseType = 'blob'; + xhr.send(); + xhr.onload = function() { + resolve(xhr.response); + }; + }).then(testImageBitmap); +}, 'createImageBitmap from a Blob with resize option.'); + +// HTMLCanvasElement +promise_test(function() { + var testCanvas = initializeTestCanvas(); + return testImageBitmap(testCanvas); +}, 'createImageBitmap from a HTMLCanvasElement with resize option.'); + +// HTMLImageElement +promise_test(function() { + return new Promise((resolve, reject) => { + var image = new Image(); + image.onload = function() { + resolve(image); + } + image.src = 'resources/pattern.png' + }).then(testImageBitmap); +}, 'createImageBitmap from a HTMLImageElement with resize option.'); + +// ImageBitmap +promise_test(function() { + var testCanvas = initializeTestCanvas(); + return createImageBitmap(testCanvas).then(testImageBitmap); +}, 'createImageBitmap from an ImageBitmap with resize option.'); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/canvas-imageSmoothingEnabled-expected.txt b/third_party/WebKit/LayoutTests/fast/canvas/canvas-imageSmoothingEnabled-expected.txt index 0be2d8c5..fe7f03a 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/canvas-imageSmoothingEnabled-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/canvas/canvas-imageSmoothingEnabled-expected.txt
@@ -1,4 +1,4 @@ -CONSOLE WARNING: line 1: 'CanvasRenderingContext2D.webkitImageSmoothingEnabled' is deprecated. Please use 'CanvasRenderingContext2D.imageSmoothingEnabled' instead. +CONSOLE WARNING: line 1: 'CanvasRenderingContext2D.webkitImageSmoothingEnabled' is deprecated and will be removed in M55, around November 2016. Please use 'CanvasRenderingContext2D.imageSmoothingEnabled' instead. See https://www.chromestatus.com/features/5639849247768576 for more details. Tests for the imageSmoothingEnabled attribute. On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/offscreenCanvas-transferToImageBitmap-expected.html b/third_party/WebKit/LayoutTests/fast/canvas/webgl/offscreenCanvas-transferToImageBitmap-expected.html index 9dd3bab..1a91427 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/webgl/offscreenCanvas-transferToImageBitmap-expected.html +++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/offscreenCanvas-transferToImageBitmap-expected.html
@@ -1,6 +1,7 @@ <!DOCTYPE html> <html> <body> -<canvas id='output' width='100' height='100' style='background:red'></canvas> +<canvas id='output1' width='100' height='100' style='background:red'></canvas> +<canvas id='output2' width='100' height='100' style='background:blue'></canvas> </body> </html>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/offscreenCanvas-transferToImageBitmap-invalid-mailbox-expected.html b/third_party/WebKit/LayoutTests/fast/canvas/webgl/offscreenCanvas-transferToImageBitmap-invalid-mailbox-expected.html new file mode 100644 index 0000000..20db20d3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/offscreenCanvas-transferToImageBitmap-invalid-mailbox-expected.html
@@ -0,0 +1,7 @@ +<!DOCTYPE html> +<html> +<body> +<canvas id='output1' width='100' height='100' style='background:red'></canvas> +<canvas id='output2' width='100' height='100'></canvas> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/offscreenCanvas-transferToImageBitmap-invalid-mailbox.html b/third_party/WebKit/LayoutTests/fast/canvas/webgl/offscreenCanvas-transferToImageBitmap-invalid-mailbox.html new file mode 100644 index 0000000..79ecaae6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/offscreenCanvas-transferToImageBitmap-invalid-mailbox.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<body> +<canvas id='output1' width = '100' height = '100'></canvas> +<canvas id='output2' width = '100' height = '100'></canvas> +<script> +if (window.testRunner) { + testRunner.waitUntilDone(); +} + +var width = 100; +var height = 100; +var aCanvas = new OffscreenCanvas(width, height); +var gl = aCanvas.getContext('webgl'); +gl.clearColor(1.0, 0.0, 0.0, 1.0); +gl.clear(gl.COLOR_BUFFER_BIT); +var image1 = aCanvas.transferToImageBitmap(); +var image2 = aCanvas.transferToImageBitmap(); + +var canvas1 = document.getElementById("output1"); +var ctx1 = canvas1.getContext('bitmaprenderer'); +ctx1.transferFromImageBitmap(image1); + +var canvas2 = document.getElementById('output2'); +var ctx2 = canvas2.getContext('bitmaprenderer'); +ctx2.transferFromImageBitmap(image2); + +if (window.testRunner) { + testRunner.notifyDone(); +} +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/webgl/offscreenCanvas-transferToImageBitmap.html b/third_party/WebKit/LayoutTests/fast/canvas/webgl/offscreenCanvas-transferToImageBitmap.html index b2b97e3..862cc19 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas/webgl/offscreenCanvas-transferToImageBitmap.html +++ b/third_party/WebKit/LayoutTests/fast/canvas/webgl/offscreenCanvas-transferToImageBitmap.html
@@ -1,7 +1,8 @@ <!DOCTYPE html> <html> <body> -<canvas id='output' width = '100' height = '100'></canvas> +<canvas id='output1' width = '100' height = '100'></canvas> +<canvas id='output2' width = '100' height = '100'></canvas> <script> if (window.testRunner) { testRunner.waitUntilDone(); @@ -13,11 +14,18 @@ var gl = aCanvas.getContext('webgl'); gl.clearColor(1.0, 0.0, 0.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT); -var image = aCanvas.transferToImageBitmap(); +var image1 = aCanvas.transferToImageBitmap(); +gl.clearColor(0.0, 0.0, 1.0, 1.0); +gl.clear(gl.COLOR_BUFFER_BIT); +var image2 = aCanvas.transferToImageBitmap(); -var canvas = document.getElementById("output"); -var ctx = canvas.getContext('bitmaprenderer'); -ctx.transferFromImageBitmap(image); +var canvas1 = document.getElementById("output1"); +var ctx1 = canvas1.getContext('bitmaprenderer'); +ctx1.transferFromImageBitmap(image1); + +var canvas2 = document.getElementById('output2'); +var ctx2 = canvas2.getContext('bitmaprenderer'); +ctx2.transferFromImageBitmap(image2); if (window.testRunner) { testRunner.notifyDone();
diff --git a/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-item-with-percent-height-replaced-element.html b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-item-with-percent-height-replaced-element.html new file mode 100644 index 0000000..93f1700 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/css-grid-layout/grid-item-with-percent-height-replaced-element.html
@@ -0,0 +1,73 @@ +<!DOCTYPE html> + +<link href="resources/grid.css" rel="stylesheet"> +<link href="resources/grid-alignment.css" rel="stylesheet"> +<link href="../css-intrinsic-dimensions/resources/width-keyword-classes.css" rel="stylesheet"> + +<style> + .grid { + grid: 200px / 200px; + width: 200px; + } + + .red { + background-color: red; + } + + img { + height: 100%; + display: block; + } +</style> + +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../../resources/check-layout-th.js"></script> + +<body onload="checkLayout('.grid')"> +<div id="log"></div> + +<p>This test checks that percentage heights are properly resolved for grid items that are replaced elements. +You shouldn't see any red if the test is working as expected.</p> + +<p>1) 100% height on the image (grid item) should be resolved against the height of the grid area (200px). +Actually we don't need the 100% height in this case as the grid items are stretched by default.</p> + +<div class="grid red"> + <img src="../css/resources/greenbox-100px.png" + data-expected-width="200" data-expected-height="200"> +</div> + +<p>2) 100% height on the image (grid item's child) should be resolved against the height of the grid item, +which is stretched by default to the height of the grid area (200px).</p> + + +<div class="grid red"> + <div data-expected-width="200" data-expected-height="200"> + <img src="../css/resources/greenbox-100px.png" + data-expected-width="200" data-expected-height="200"> + </div> +</div> + +<p>3) 100% height on the image (grid item) should be resolved against the height of the grid area (200px). +The grid item is not stretched in this case but the height percentage can be resolved anyway.</p> + +<div class="grid red alignItemsStart"> + <img src="../css/resources/greenbox-100px.png" + data-expected-width="200" data-expected-height="200"> +</div> + +<p>4) 100% height on the image (grid item's child) should be resolved against the height of the grid item, +as it's not stretched the grid item's height is indefinite, so the percentage cannot be resolved.</p> + +<div class="grid alignItemsStart justifyItemsStart"> + <div class="firstRowFirstColumn red" style="width: 100px; height: 100px;" + data-expected-width="100" data-expected-height="100"> + </div> + <div class="firstRowFirstColumn"> + <img src="../css/resources/greenbox-100px.png" + data-expected-width="100" data-expected-height="100"> + </div> +</div> + +</body>
diff --git a/third_party/WebKit/LayoutTests/fast/css/object-fit-grow-landscape-expected.html b/third_party/WebKit/LayoutTests/fast/css/object-fit-grow-landscape-expected.html deleted file mode 100644 index 76c1e9e3..0000000 --- a/third_party/WebKit/LayoutTests/fast/css/object-fit-grow-landscape-expected.html +++ /dev/null
@@ -1,36 +0,0 @@ -<!DOCTYPE html> - -<html> - <head> - <title>object-fit, landscape images smaller than content box</title> - <style type="text/css"> - .group > div { - display: inline-block; - overflow: hidden; - width: 144px; - height: 144px; - margin: 10px; - border: 1px solid black; - background-color: gray; - } - - .group > * > * { display: block; } - .group.landscape > *:nth-child(1) > * { width:100%; height:100%; } - .group.landscape > *:nth-child(2) > * { width:100%; margin-top:25%; } - .group.landscape > *:nth-child(3) > * { height:100%; margin-left:-50%; } - .group.landscape > *:nth-child(4) > * { margin-left: 36px; margin-top:54px; } - .group.landscape > *:nth-child(5) > * { margin-left: 36px; margin-top:54px; } - </style> - </head> - <body> - - <!-- Small images, should be scaled up when allowed. --> - <div class="group landscape"> - <div><img src="resources/circles-landscape-small.png"></div> - <div><img src="resources/circles-landscape-small.png"></div> - <div><img src="resources/circles-landscape-small.png"></div> - <div><img src="resources/circles-landscape-small.png"></div> - <div><img src="resources/circles-landscape-small.png"></div> - </div> - </body> -</html>
diff --git a/third_party/WebKit/LayoutTests/fast/css/object-fit-grow-portrait-expected.html b/third_party/WebKit/LayoutTests/fast/css/object-fit-grow-portrait-expected.html deleted file mode 100644 index b11997c8..0000000 --- a/third_party/WebKit/LayoutTests/fast/css/object-fit-grow-portrait-expected.html +++ /dev/null
@@ -1,35 +0,0 @@ -<!DOCTYPE html> - -<html> - <head> - <title>object-fit, portrait images smaller than content box</title> - <style type="text/css"> - .group > div { - display: inline-block; - overflow: hidden; - height: 144px; - width: 144px; - margin: 10px; - border: 1px solid black; - background-color: gray; - } - div > * > * { display:block; } - .group.portrait > *:nth-child(1) > * { width:100%; height:100%; } - .group.portrait > *:nth-child(2) > * { height:100%; margin-left:25%; } - .group.portrait > *:nth-child(3) > * { width:100%; margin-top:-50%; } - .group.portrait > *:nth-child(4) > * { margin-top:36px; margin-left:54px; } - .group.portrait > *:nth-child(5) > * { margin-top:36px; margin-left:54px; } - </style> - </head> - <body> - - <!-- Small images, should be scaled up when allowed. --> - <div class="group portrait"> - <div><img src="resources/circles-portrait-small.png"></div> - <div><img src="resources/circles-portrait-small.png"></div> - <div><img src="resources/circles-portrait-small.png"></div> - <div><img src="resources/circles-portrait-small.png"></div> - <div><img src="resources/circles-portrait-small.png"></div> - </div> - </body> -</html>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/HTMLTemplateElement/no-form-association2.html b/third_party/WebKit/LayoutTests/fast/dom/HTMLTemplateElement/no-form-association2.html new file mode 100644 index 0000000..e819b2d --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/dom/HTMLTemplateElement/no-form-association2.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<body> +<!-- based on WebKit test: https://trac.webkit.org/changeset/160182 --> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script> +function stripSpaces(str) { + return str.replace(/[\s\n]/gm, ''); +} +</script> +<form> + <template id="templateWithFormInsideForm"> + <form> + <input> + </form> + </template> +</form> +<script> +test(function() { + var templateWithFormInsideForm = document.getElementById('templateWithFormInsideForm'); + assert_equals(stripSpaces(templateWithFormInsideForm.innerHTML), '<form><input></form>'); + var formInsideTemplate = templateWithFormInsideForm.content.firstElementChild; + assert_equals(formInsideTemplate.localName, 'form'); + var inputInsideTemplate = templateWithFormInsideForm.content.querySelector('input'); + assert_equals(inputInsideTemplate.form, formInsideTemplate); + assert_equals(formInsideTemplate.firstElementChild, inputInsideTemplate); +}, 'Form control elements inside templates should not be associated with forms outside the template.'); +</script> +<template id="templateWithNestedForms"> + <form> + <form></form> + </form> +</template> +<script> +test(function() { + var templateWithNestedForms = document.getElementById('templateWithNestedForms'); + assert_equals(stripSpaces(templateWithNestedForms.innerHTML), '<form><form></form></form>'); +}, '(Nested) form elements inside templates should be parsed correctly.'); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/comment-not-documentElement.html b/third_party/WebKit/LayoutTests/fast/dom/comment-not-documentElement.html index b5586ee..d3455c46 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/comment-not-documentElement.html +++ b/third_party/WebKit/LayoutTests/fast/dom/comment-not-documentElement.html
@@ -4,7 +4,7 @@ <body> <script> if (document.documentElement.nodeType == Node.ELEMENT_NODE) - document.write("SUCESS"); + document.write("SUCCESS"); else document.write("FAIL"); </script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/event-creation-expected.txt b/third_party/WebKit/LayoutTests/fast/events/event-creation-expected.txt index fa2b75d..fe9ab579 100644 --- a/third_party/WebKit/LayoutTests/fast/events/event-creation-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/events/event-creation-expected.txt
@@ -1,4 +1,3 @@ -CONSOLE WARNING: line 1: 'SVGZoomEvent' is deprecated and will be removed in M52, around July 2016. See https://www.chromestatus.com/features/5760883808534528 for more details. This tests that document.createEvent is hooked up for all Event interfaces (and alternatives) and creates the right instance. On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". @@ -111,12 +110,6 @@ PASS document.createEvent('StorageEvent').constructor === window.StorageEvent is true PASS document.createEvent('SVGEvents') instanceof window.Event is true PASS document.createEvent('SVGEvents').constructor === window.Event is true -PASS document.createEvent('SVGZoomEvent') instanceof window.SVGZoomEvent is true -PASS document.createEvent('SVGZoomEvent') instanceof window.Event is true -PASS document.createEvent('SVGZoomEvent').constructor === window.SVGZoomEvent is true -PASS document.createEvent('SVGZoomEvents') instanceof window.SVGZoomEvent is true -PASS document.createEvent('SVGZoomEvents') instanceof window.Event is true -PASS document.createEvent('SVGZoomEvents').constructor === window.SVGZoomEvent is true PASS document.createEvent('CloseEvent') instanceof window.CloseEvent is true PASS document.createEvent('CloseEvent') instanceof window.Event is true PASS document.createEvent('CloseEvent').constructor === window.CloseEvent is true
diff --git a/third_party/WebKit/LayoutTests/fast/events/event-creation.html b/third_party/WebKit/LayoutTests/fast/events/event-creation.html index e08d06b..7b43650 100644 --- a/third_party/WebKit/LayoutTests/fast/events/event-creation.html +++ b/third_party/WebKit/LayoutTests/fast/events/event-creation.html
@@ -166,16 +166,6 @@ shouldBeTrue("document.createEvent('SVGEvents') instanceof window.Event"); shouldBeTrue("document.createEvent('SVGEvents').constructor === window.Event"); - // SVGZoomEvent - shouldBeTrue("document.createEvent('SVGZoomEvent') instanceof window.SVGZoomEvent"); - shouldBeTrue("document.createEvent('SVGZoomEvent') instanceof window.Event"); - shouldBeTrue("document.createEvent('SVGZoomEvent').constructor === window.SVGZoomEvent"); - - // SVGZoomEvents (SVGZoomEvent alternative) - shouldBeTrue("document.createEvent('SVGZoomEvents') instanceof window.SVGZoomEvent"); - shouldBeTrue("document.createEvent('SVGZoomEvents') instanceof window.Event"); - shouldBeTrue("document.createEvent('SVGZoomEvents').constructor === window.SVGZoomEvent"); - // CloseEvent shouldBeTrue("document.createEvent('CloseEvent') instanceof window.CloseEvent"); shouldBeTrue("document.createEvent('CloseEvent') instanceof window.Event");
diff --git a/third_party/WebKit/LayoutTests/fast/events/mouse-cursor-change-after-image-load.html b/third_party/WebKit/LayoutTests/fast/events/mouse-cursor-change-after-image-load.html new file mode 100644 index 0000000..031e576 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/events/mouse-cursor-change-after-image-load.html
@@ -0,0 +1,53 @@ +<!DOCTYPE html> +<html> +<head> +<title>Cursor: should update after image loaded even when stationary</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<style> +#target { + height: 500px; + width: 500px; +} +</style> +</head> +<body> +<div id="target"></div> +<script> +var cursorTest = async_test('Test cursor update after image loaded'); +cursorTest.step(function() { + assert_not_equals(window.eventSender, undefined, 'This test requires eventSender.'); + + assert_equals(internals.getCurrentCursorInfo(), "type=Pointer hotSpot=0,0"); + + var target = document.getElementById('target'); + var rect = target.getBoundingClientRect(); + eventSender.mouseMoveTo(rect.left + 3, rect.top + 3); + + // Wait for condition until timeout. + function waitForCondition(condition, completion) { + if (condition()) { + completion(); + } else { + requestAnimationFrame(() => waitForCondition(condition, completion)); + } + } + + function testSetCursorImage(url, expectedCursorInfo, complete) { + const currentCursorInfo = internals.getCurrentCursorInfo(); + target.style.cursor = `url(${url}),auto`; + waitForCondition(() => internals.getCurrentCursorInfo() != currentCursorInfo, cursorTest.step_func(() => { + assert_equals(internals.getCurrentCursorInfo(), expectedCursorInfo); + complete(); + })); + } + + testSetCursorImage('resources/greenbox.png', 'type=Custom hotSpot=0,0 image=25x25', () => { + testSetCursorImage('resources/abe.png', 'type=Custom hotSpot=0,0 image=76x103', () => { + cursorTest.done(); + }) + }); +}); +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/select/menulist-appearance-none.html b/third_party/WebKit/LayoutTests/fast/forms/select/menulist-appearance-none.html new file mode 100644 index 0000000..85e0f63 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/forms/select/menulist-appearance-none.html
@@ -0,0 +1,7 @@ +<p> + Rendering test for <i><a href="https://bugs.chromium.org/p/chromium/issues/detail?id=626278">https://bugs.chromium.org/p/chromium/issues/detail?id=626278</a> + Regression: HTML Select's text appears chopped if appearance is set to none</i>. +</p> +<select style="-webkit-appearance: none; line-height: 40px;"> + <option>Test</option> +</select>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/text/text-dir-auto-with-placeholder.html b/third_party/WebKit/LayoutTests/fast/forms/text/text-dir-auto-with-placeholder.html new file mode 100644 index 0000000..24be51f6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/forms/text/text-dir-auto-with-placeholder.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<body> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<input dir="auto" placeholder="LTR placeholder string" value="ע"> +<script> +test(() => { + assert_equals(getComputedStyle(document.querySelector('input'), '').direction, 'rtl'); +}, 'Placeholder\'s direction shouldn\'t affect INPUT direction.'); +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-dir-auto-with-placeholder.html b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-dir-auto-with-placeholder.html new file mode 100644 index 0000000..a97f68d1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/forms/textarea/textarea-dir-auto-with-placeholder.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<body> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<textarea dir="auto" placeholder="LTR placeholder string">ע</textarea> +<script> +test(() => { + assert_equals(getComputedStyle(document.querySelector('textarea'), '').direction, 'rtl'); +}, 'Placeholder\'s direction shouldn\'t affect TEXTAREA direction.'); +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/fast/table/border-collapsing/cached-change-tbody-border-width-expected.txt b/third_party/WebKit/LayoutTests/fast/table/border-collapsing/cached-change-tbody-border-width-expected.txt index 2514bae..e9d80df 100644 --- a/third_party/WebKit/LayoutTests/fast/table/border-collapsing/cached-change-tbody-border-width-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/table/border-collapsing/cached-change-tbody-border-width-expected.txt
@@ -1,53 +1,55 @@ { + "name": "Content Root Layer", "bounds": [800, 600], "children": [ { + "name": "LayoutView #document", "bounds": [800, 600], "contentsOpaque": true, "drawsContent": true, "paintInvalidations": [ { "object": "LayoutTable TABLE", - "rect": [8, 159, 111, 2], + "rect": [8, 159, 114, 2], "reason": "incremental" }, { "object": "LayoutTable TABLE", - "rect": [8, 160, 111, 1], + "rect": [8, 160, 114, 1], "reason": "incremental" }, { "object": "LayoutTableSection TBODY id='tbody'", - "rect": [10, 10, 107, 100], + "rect": [10, 10, 110, 100], "reason": "style change" }, { + "object": "LayoutTableRow TR", + "rect": [10, 110, 110, 50], + "reason": "bounds change" + }, + { + "object": "LayoutTableSection TBODY", + "rect": [10, 110, 110, 50], + "reason": "bounds change" + }, + { + "object": "LayoutTableRow TR", + "rect": [10, 60, 110, 50], + "reason": "bounds change" + }, + { + "object": "LayoutTableRow TR", + "rect": [10, 10, 110, 50], + "reason": "bounds change" + }, + { "object": "LayoutTableSection TBODY id='tbody'", "rect": [9, 9, 107, 100], "reason": "style change" }, { "object": "LayoutTableRow TR", - "rect": [10, 110, 107, 50], - "reason": "bounds change" - }, - { - "object": "LayoutTableSection TBODY", - "rect": [10, 110, 107, 50], - "reason": "bounds change" - }, - { - "object": "LayoutTableRow TR", - "rect": [10, 60, 107, 50], - "reason": "bounds change" - }, - { - "object": "LayoutTableRow TR", - "rect": [10, 10, 107, 50], - "reason": "bounds change" - }, - { - "object": "LayoutTableRow TR", "rect": [9, 109, 107, 50], "reason": "bounds change" }, @@ -68,27 +70,32 @@ }, { "object": "LayoutTableCell TD", - "rect": [62, 8, 57, 53], - "reason": "location change" - }, - { - "object": "LayoutTableCell TD", - "rect": [63, 108, 56, 53], + "rect": [64, 8, 58, 53], "reason": "bounds change" }, { "object": "LayoutTableCell TD", - "rect": [8, 59, 56, 53], + "rect": [8, 59, 58, 53], "reason": "bounds change" }, { "object": "LayoutTableCell TD", - "rect": [8, 8, 56, 53], + "rect": [8, 8, 58, 53], "reason": "location change" }, { "object": "LayoutTableCell TD", - "rect": [63, 60, 56, 52], + "rect": [65, 108, 57, 53], + "reason": "bounds change" + }, + { + "object": "LayoutTableCell TD", + "rect": [8, 108, 57, 53], + "reason": "bounds change" + }, + { + "object": "LayoutTableCell TD", + "rect": [65, 60, 57, 52], "reason": "bounds change" }, { @@ -98,7 +105,12 @@ }, { "object": "LayoutTableCell TD", - "rect": [8, 108, 55, 53], + "rect": [62, 8, 55, 52], + "reason": "bounds change" + }, + { + "object": "LayoutTableCell TD", + "rect": [63, 109, 54, 51], "reason": "bounds change" }, { @@ -108,40 +120,90 @@ }, { "object": "LayoutTable TABLE", - "rect": [115, 8, 4, 153], + "rect": [115, 8, 7, 153], "reason": "incremental" }, { "object": "LayoutTable TABLE", - "rect": [117, 8, 2, 153], + "rect": [117, 8, 5, 153], "reason": "incremental" - }, - { - "object": "LayoutTableCell TD", - "reason": "full" - }, - { - "object": "LayoutTableCell TD", - "reason": "full" - }, - { - "object": "LayoutTableCell TD", - "reason": "full" - }, - { - "object": "LayoutTableCell TD", - "reason": "full" - }, - { - "object": "LayoutTableCell TD", - "reason": "full" - }, - { - "object": "LayoutTableCell TD", - "reason": "full" } ] } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutTableCell TD", + "reason": "style change" + }, + { + "object": "LayoutTableCell TD", + "reason": "style change" + }, + { + "object": "LayoutTableCell TD", + "reason": "style change" + }, + { + "object": "LayoutTableCell TD", + "reason": "style change" + }, + { + "object": "LayoutTableCell TD", + "reason": "style change" + }, + { + "object": "LayoutTableCell TD", + "reason": "style change" + }, + { + "object": "LayoutTable TABLE", + "reason": "incremental" + }, + { + "object": "LayoutTableSection TBODY id='tbody'", + "reason": "style change" + }, + { + "object": "LayoutTableRow TR", + "reason": "bounds change" + }, + { + "object": "LayoutTableCell TD", + "reason": "location change" + }, + { + "object": "LayoutTableCell TD", + "reason": "bounds change" + }, + { + "object": "LayoutTableRow TR", + "reason": "bounds change" + }, + { + "object": "LayoutTableCell TD", + "reason": "bounds change" + }, + { + "object": "LayoutTableCell TD", + "reason": "bounds change" + }, + { + "object": "LayoutTableSection TBODY", + "reason": "bounds change" + }, + { + "object": "LayoutTableRow TR", + "reason": "bounds change" + }, + { + "object": "LayoutTableCell TD", + "reason": "bounds change" + }, + { + "object": "LayoutTableCell TD", + "reason": "bounds change" + } ] }
diff --git a/third_party/WebKit/LayoutTests/fast/table/change-tbody-border-width-expected.txt b/third_party/WebKit/LayoutTests/fast/table/change-tbody-border-width-expected.txt new file mode 100644 index 0000000..d93f49f --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/table/change-tbody-border-width-expected.txt
@@ -0,0 +1,9 @@ +Changing a collapsed border's width should change the width of the table and the width of a shrink-to-fit containing block. + +There should be a square with a 4px inner blue border and a 1px outer black border. + +Firefox 50.0a1 (nightly 2016-07-07) fails this, so it should probably be upstreamed, except it uses chrome-specific `runAfterLayoutAndPaint`. + +The table cell has rowspan=2 because we almost didn't cover the case where a cell's rowspan exceeded the declared rows. + +PASS
diff --git a/third_party/WebKit/LayoutTests/fast/table/change-tbody-border-width.html b/third_party/WebKit/LayoutTests/fast/table/change-tbody-border-width.html new file mode 100644 index 0000000..6760bc58 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/table/change-tbody-border-width.html
@@ -0,0 +1,30 @@ +<!doctype html> +<style> + td { + width: 50px; + height: 50px; + padding: 0px; + } +</style> +<script src="../../resources/check-layout.js"></script> +<script src="../../resources/run-after-layout-and-paint.js"></script> +<script type="text/javascript"> + function shrinkSectionBorder() { + document.getElementById("section").style.borderWidth = "4px"; + checkLayout("div"); + } + runAfterLayoutAndPaint(shrinkSectionBorder, true); +</script> +<p>Changing a collapsed border's width should change the width of the table and the width of a shrink-to-fit containing block.</p> +<p>There should be a square with a 4px inner blue border and a 1px outer black border.</p> +<p>Firefox 50.0a1 (nightly 2016-07-07) fails this, so it should probably be upstreamed, except it uses chrome-specific `runAfterLayoutAndPaint`.</p> +<p>The table cell has rowspan=2 because we almost didn't cover the case where a cell's rowspan exceeded the declared rows.</p> +<div style="float:left; border: 1px solid black" data-expected-width=60> + <table style="border-collapse:collapse" data-expected-width=58 data-expected-height=58> + <tbody style="border:18px solid lightblue" id="section"> + <tr> + <td rowspan=2></td> + </tr> + </tbody> + </table> +</div>
diff --git a/third_party/WebKit/LayoutTests/fast/text/hyphens/can-hyphenate-locale-expected.txt b/third_party/WebKit/LayoutTests/fast/text/hyphens/can-hyphenate-locale-expected.txt new file mode 100644 index 0000000..632165c7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/text/hyphens/can-hyphenate-locale-expected.txt
@@ -0,0 +1,6 @@ +This is a testharness.js-based test. +PASS This test requires "internals.canHyphenate" +FAIL "en-us" can hyphenate assert_true: expected true got false +PASS "ja-jp" cannot hyphenate +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/fast/text/hyphens/can-hyphenate-locale.html b/third_party/WebKit/LayoutTests/fast/text/hyphens/can-hyphenate-locale.html new file mode 100644 index 0000000..86f7ccf1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/text/hyphens/can-hyphenate-locale.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<script src="../../../resources/testharness.js"></script> +<script src="../../../resources/testharnessreport.js"></script> +<script> +'use strict'; +(function () { + test(function () { + assert_exists(window, 'internals'); + }, 'This test requires "internals.canHyphenate"'); + + ['en-us'].forEach(function (locale) { + test(function () { + assert_true(internals.canHyphenate(locale)); + }, `"${locale}" can hyphenate`); + }); + + ['ja-jp'].forEach(function (locale) { + test(function () { + assert_false(internals.canHyphenate(locale)); + }, `"${locale}" cannot hyphenate`); + }); +})(); +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/dom/EventListener-incumbent-global-1.html b/third_party/WebKit/LayoutTests/http/tests/dom/EventListener-incumbent-global-1.html new file mode 100644 index 0000000..893763e --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/dom/EventListener-incumbent-global-1.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<!-- +This test is imported from +https://github.com/w3c/web-platform-tests/blob/master/dom/events/EventListener-incumbent-global-1.sub.html +--> +<title></title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe src="//www1.web-platform.test:8080/dom/resources/EventListener-incumbent-global-subframe-1.html"></iframe> +<script> + +var t = async_test("Check the incumbent global EventListeners are called with"); + +onload = t.step_func(function() { + onmessage = t.step_func_done(function(e) { + var d = e.data; + assert_equals(d.actual, d.expected, d.reason); + }); + + frames[0].postMessage("start", "*"); +}); + +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/dom/EventListener-incumbent-global-2-expected.txt b/third_party/WebKit/LayoutTests/http/tests/dom/EventListener-incumbent-global-2-expected.txt new file mode 100644 index 0000000..2811292 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/dom/EventListener-incumbent-global-2-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Check the incumbent global EventListeners are called with assert_equals: Incumbent should have been the caller of addEventListener() expected "http://www1.web-platform.test:8080" but got "http://www2.web-platform.test:8080" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/http/tests/dom/EventListener-incumbent-global-2.html b/third_party/WebKit/LayoutTests/http/tests/dom/EventListener-incumbent-global-2.html new file mode 100644 index 0000000..1179e8c --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/dom/EventListener-incumbent-global-2.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<!-- +This test is imported from +https://github.com/w3c/web-platform-tests/blob/master/dom/events/EventListener-incumbent-global-2.sub.html +--> +<title></title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe src="//www1.web-platform.test:8080/dom/resources/EventListener-incumbent-global-subframe-2.html"></iframe> +<script> + +var t = async_test("Check the incumbent global EventListeners are called with"); + +onload = t.step_func(function() { + onmessage = t.step_func_done(function(e) { + var d = e.data; + assert_equals(d.actual, d.expected, d.reason); + }); + + frames[0].postMessage("start", "*"); +}); + +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/dom/resources/EventListener-incumbent-global-subframe-1.html b/third_party/WebKit/LayoutTests/http/tests/dom/resources/EventListener-incumbent-global-subframe-1.html new file mode 100644 index 0000000..e385e49b6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/dom/resources/EventListener-incumbent-global-subframe-1.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<iframe src="//www2.web-platform.test:8080/dom/resources/EventListener-incumbent-global-subsubframe.html"></iframe> +<script> + document.domain = "web-platform.test"; + onmessage = function(e) { + if (e.data == "start") { + frames[0].document.body.addEventListener("click", frames[0].postMessage.bind(frames[0], "respond", "*", undefined)); + frames[0].postMessage("sendclick", "*"); + } else { + parent.postMessage(e.data, "*"); + } + } +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/dom/resources/EventListener-incumbent-global-subframe-2.html b/third_party/WebKit/LayoutTests/http/tests/dom/resources/EventListener-incumbent-global-subframe-2.html new file mode 100644 index 0000000..75a4ba36 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/dom/resources/EventListener-incumbent-global-subframe-2.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<iframe src="//www2.web-platform.test:8080/dom/resources/EventListener-incumbent-global-subsubframe.html"></iframe> +<script> + document.domain = "web-platform.test"; + onmessage = function(e) { + if (e.data == "start") { + frames[0].document.body.addEventListener("click", frames[0].getTheListener()); + frames[0].postMessage("sendclick", "*"); + } else { + parent.postMessage(e.data, "*"); + } + } +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/dom/resources/EventListener-incumbent-global-subsubframe.html b/third_party/WebKit/LayoutTests/http/tests/dom/resources/EventListener-incumbent-global-subsubframe.html new file mode 100644 index 0000000..8656578 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/dom/resources/EventListener-incumbent-global-subsubframe.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<script> + function getTheListener() { + return postMessage.bind(this, "respond", "*", undefined); + } + document.domain = "web-platform.test"; + onmessage = function (e) { + if (e.data == "sendclick") { + document.body.click(); + } else { + parent.postMessage( + { + actual: e.origin, + expected: location.protocol + "//www1.web-platform.test:8080", + reason: "Incumbent should have been the caller of addEventListener()" + }, + "*") + }; + } +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/console-show-all-messages.html b/third_party/WebKit/LayoutTests/http/tests/inspector/console-show-all-messages.html index 54be7f8..fbb08c2 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/console-show-all-messages.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/console-show-all-messages.html
@@ -30,6 +30,7 @@ function testPageOnlyMessages(next) { + InspectorTest.changeExecutionContext("top"); checkbox.click(); dumpVisibleConsoleMessageText(); next();
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js index 1f346e4d..5768313 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js
@@ -305,9 +305,7 @@ function runtimeCallFramePosition() { - var lineNumber = this.lineNumber ? this.lineNumber - 1 : 0; - var columnNumber = this.columnNumber ? this.columnNumber - 1 : 0; - return new WebInspector.DebuggerModel.Location(debuggerModel, this.scriptId, lineNumber, columnNumber); + return new WebInspector.DebuggerModel.Location(debuggerModel, this.scriptId, this.lineNumber, this.columnNumber); } results.push("Call stack:");
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/event-listeners-framework-with-service-worker-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/event-listeners-framework-with-service-worker-expected.txt index a1b29e9..e651ae9 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/event-listeners-framework-with-service-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/event-listeners-framework-with-service-worker-expected.txt
@@ -10,7 +10,7 @@ ======== load ======== == normal -[expanded] WindowRemoveevent-listeners-framework-with-service-worker.html:56 +[expanded] WindowRemoveevent-listeners-framework-with-service-worker.html:62 useCapture: false passive: false handler: function onload(event) {
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/event-listeners-framework-with-service-worker.html b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/event-listeners-framework-with-service-worker.html index 2bd44f7..9b0e117 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/elements/event-listeners-framework-with-service-worker.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/elements/event-listeners-framework-with-service-worker.html
@@ -16,6 +16,12 @@ var objectEventListenersPane = WebInspector.panels.sources.sidebarPanes.objectEventListeners; + function isDedicatedWorker() + { + var target = WebInspector.context.flavor(WebInspector.ExecutionContext).target(); + return InspectorTest.isDedicatedWorker(target); + } + function forceUpdate() { objectEventListenersPane.expand(); @@ -31,7 +37,7 @@ { InspectorTest.addResult("Selecting service worker thread"); InspectorTest.selectThread(executionContext.target()); - InspectorTest.addResult("Context is dedicated worker: " + WebInspector.context.flavor(WebInspector.ExecutionContext).target().isDedicatedWorker()); + InspectorTest.addResult("Context is dedicated worker: " + isDedicatedWorker()); InspectorTest.addResult("Dumping listeners"); InspectorTest.expandAndDumpEventListeners(objectEventListenersPane._eventListenersView, forceUpdate, step3); } @@ -40,7 +46,7 @@ { InspectorTest.addResult("Selecting main thread"); InspectorTest.selectThread(WebInspector.targetManager.mainTarget()); - InspectorTest.addResult("Context is dedicated worker: " + WebInspector.context.flavor(WebInspector.ExecutionContext).target().isDedicatedWorker()); + InspectorTest.addResult("Context is dedicated worker: " + isDedicatedWorker()); InspectorTest.addResult("Dumping listeners"); InspectorTest.expandAndDumpEventListeners(objectEventListenersPane._eventListenersView, forceUpdate, step4); } @@ -59,4 +65,4 @@ </p> <button id="inspectedNode">Inspect Me</button> </body> -</html> \ No newline at end of file +</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js index c21526c..36333f67 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js
@@ -998,7 +998,17 @@ InspectorTest._modulesToPreload.push(moduleName); } -}; // initialize_InspectorTest +InspectorTest.isDedicatedWorker = function(target) +{ + return target && !target.hasBrowserCapability() && target.hasJSCapability() && !target.hasNetworkCapability() && !target.hasWorkerCapability(); +} + +InspectorTest.isServiceWorker = function(target) +{ + return target && !target.hasBrowserCapability() && !target.hasJSCapability() && target.hasNetworkCapability() && target.hasWorkerCapability(); +} + + }; // initialize_InspectorTest var initializeCallId = 0; var runTestCallId = 1;
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-document-initiator-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-document-initiator-expected.txt index 0963b31..9fc76a7 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-document-initiator-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-document-initiator-expected.txt
@@ -2,5 +2,5 @@ Page reloaded. http://127.0.0.1:8000/inspector/network/network-document-initiator.html?foo: script - navigateFromScript http://127.0.0.1:8000/inspector/network/network-document-initiator.html 9 + navigateFromScript http://127.0.0.1:8000/inspector/network/network-document-initiator.html 8
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-initiator-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-initiator-expected.txt index 5074d5c..8936c55 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-initiator-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/network/network-initiator-expected.txt
@@ -7,7 +7,7 @@ http://127.0.0.1:8000/inspector/network/resources/resource.php?type=image&random=1&size=100: parser http://127.0.0.1:8000/inspector/network/resources/network-initiator-frame.html 5 http://127.0.0.1:8000/inspector/network/resources/resource.php?type=image&random=1&size=400: script - loadData http://127.0.0.1:8000/inspector/network/resources/network-initiator-frame.html 14 + loadData http://127.0.0.1:8000/inspector/network/resources/network-initiator-frame.html 13 http://127.0.0.1:8000/inspector/network/resources/style.css: parser http://127.0.0.1:8000/inspector/network/resources/network-initiator-frame.html 8 http://127.0.0.1:8000/inspector/network/resources/empty.html: parser
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-test.js index 4d236ae3..4b78f61 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-test.js
@@ -19,7 +19,7 @@ { function isRightTarget(target) { - return target.isDedicatedWorker() && target.parentTarget() && target.parentTarget().isServiceWorker(); + return InspectorTest.isDedicatedWorker(target) && InspectorTest.isServiceWorker(target.parentTarget()); } WebInspector.targetManager.observeTargets({
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/user-agent-override.html b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/user-agent-override.html index 8393d89..277eea6 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/user-agent-override.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/user-agent-override.html
@@ -13,7 +13,7 @@ var sniffer = { targetAdded: function(target) { - if (target.isServiceWorker()) { + if (InspectorTest.isServiceWorker(target)) { resolve(); WebInspector.targetManager.unobserveTargets(sniffer); }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/sources/debugger/async-callstack-network-initiator-image-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/sources/debugger/async-callstack-network-initiator-image-expected.txt index 0f3e069..2509230 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/sources/debugger/async-callstack-network-initiator-image-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/sources/debugger/async-callstack-network-initiator-image-expected.txt
@@ -1,5 +1,5 @@ Tests asynchronous network initiator for image loaded from JS. -async-callstack-network-initiator-image.html:12 +async-callstack-network-initiator-image.html:11
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-inline-warning-contains-stacktrace-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-inline-warning-contains-stacktrace-expected.txt index 5f6dfc7..1137f966 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-inline-warning-contains-stacktrace-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-inline-warning-contains-stacktrace-expected.txt
@@ -8,5 +8,5 @@ url: http://127.0.0.1:8000/inspector/stacktraces/resources/csp-inline-test.js function: thisTest - line: 4 + line: 3
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-setInterval-warning-contains-stacktrace-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-setInterval-warning-contains-stacktrace-expected.txt index 90ce322..aef89db2 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-setInterval-warning-contains-stacktrace-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-setInterval-warning-contains-stacktrace-expected.txt
@@ -8,5 +8,5 @@ url: http://127.0.0.1:8000/inspector/stacktraces/csp-setInterval-warning-contains-stacktrace.html function: thisTest - line: 11 + line: 10
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-setTimeout-warning-contains-stacktrace-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-setTimeout-warning-contains-stacktrace-expected.txt index 01d3338c7..f4fc3ce4 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-setTimeout-warning-contains-stacktrace-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/stacktraces/csp-setTimeout-warning-contains-stacktrace-expected.txt
@@ -8,5 +8,5 @@ url: http://127.0.0.1:8000/inspector/stacktraces/csp-setTimeout-warning-contains-stacktrace.html function: thisTest - line: 11 + line: 10
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/workspace-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/workspace-test.js index 58c70a5..6b7c24c 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/workspace-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/workspace-test.js
@@ -35,19 +35,19 @@ InspectorTest._mockTargetId = 1; -InspectorTest.createMockTarget = function(id, debuggerModelConstructor, targetType) +InspectorTest.createMockTarget = function(id, debuggerModelConstructor, capabilities) { + capabilities = capabilities || (WebInspector.Target.Capability.Browser | WebInspector.Target.Capability.JS | WebInspector.Target.Capability.Network | WebInspector.Target.Capability.Worker); var MockTarget = function(name, connection, callback) { - var type = typeof targetType === "undefined" ? WebInspector.Target.Type.Page : targetType; - WebInspector.Target.call(this, InspectorTest.testTargetManager, name, type, connection, null, callback); + WebInspector.Target.call(this, InspectorTest.testTargetManager, name, capabilities, connection, null, callback); this.consoleModel = new WebInspector.ConsoleModel(this); this.networkManager = new WebInspector.NetworkManager(this); + this.runtimeModel = new WebInspector.RuntimeModel(this); this.resourceTreeModel = new WebInspector.ResourceTreeModel(this); this.resourceTreeModel._inspectedPageURL = InspectorTest.resourceTreeModel._inspectedPageURL; this.resourceTreeModel._cachedResourcesProcessed = true; this.resourceTreeModel._frameAttached("42", 0); - this.runtimeModel = new WebInspector.RuntimeModel(this); this.debuggerModel = debuggerModelConstructor ? new debuggerModelConstructor(this) : new WebInspector.DebuggerModel(this); this._modelByConstructor.set(WebInspector.DebuggerModel, this.debuggerModel); this.domModel = new WebInspector.DOMModel(this);
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/nonces/import-enforce-allowed.php b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/nonces/import-enforce-allowed.php new file mode 100644 index 0000000..e1f91e9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/nonces/import-enforce-allowed.php
@@ -0,0 +1,24 @@ +<?php + header("Content-Security-Policy: script-src 'nonce-abc'"); +?> +<!doctype html> +<script nonce="abc" src="/resources/testharness.js"></script> +<script nonce="abc" src="/resources/testharnessreport.js"></script> +<script nonce="abc"> + async_test(t => { + document.addEventListener('securitypolicyviolation', t.unreached_func("No report should be generated")); + window.onload = t.step_func(_ => { + var link = document.createElement('link'); + link.setAttribute("rel", "import"); + link.setAttribute("nonce", "abc"); + link.setAttribute("href", "/security/resources/blank.html"); + + link.onerror = t.unreached_func("The import should load."); + link.onload = t.step_func_done(_ => { + assert_true(!!link.import); + }); + + document.body.appendChild(link); + }); + }, "Nonced imports load, and do not trigger reports."); +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/nonces/import-enforce-blocked.php b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/nonces/import-enforce-blocked.php new file mode 100644 index 0000000..2f134fc --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/nonces/import-enforce-blocked.php
@@ -0,0 +1,27 @@ +<?php + header("Content-Security-Policy: script-src 'nonce-abc'"); +?> +<!doctype html> +<script nonce="abc" src="/resources/testharness.js"></script> +<script nonce="abc" src="/resources/testharnessreport.js"></script> +<script nonce="abc"> + async_test(t => { + window.onload = t.step_func(_ => { + var link = document.createElement('link'); + link.setAttribute("rel", "import"); + link.setAttribute("nonce", "zyx"); + link.setAttribute("href", "/security/resources/blank.html"); + + var watcher = new EventWatcher(t, document, ['securitypolicyviolation']); + watcher + .wait_for('securitypolicyviolation') + .then(t.step_func_done(e => { + assert_false(!!link.import, "The import was not loaded."); + assert_equals(e.blockedURI, "http://127.0.0.1:8000/security/resources/blank.html"); + assert_equals(e.lineNumber, 21); + })); + + document.body.appendChild(link); + }); + }, "Incorrectly nonced imports do not load, and trigger reports."); +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/nonces/import-multiple-allowed.php b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/nonces/import-multiple-allowed.php new file mode 100644 index 0000000..ddbf9da --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/nonces/import-multiple-allowed.php
@@ -0,0 +1,25 @@ +<?php + header("Content-Security-Policy: script-src 'unsafe-inline' 'self'"); + header("Content-Security-Policy-Report-Only: script-src 'nonce-abc'"); +?> +<!doctype html> +<script nonce="abc" src="/resources/testharness.js"></script> +<script nonce="abc" src="/resources/testharnessreport.js"></script> +<script nonce="abc"> + async_test(t => { + document.addEventListener('securitypolicyviolation', t.unreached_func("No report should be generated")); + window.onload = t.step_func(_ => { + var link = document.createElement('link'); + link.setAttribute("rel", "import"); + link.setAttribute("nonce", "abc"); + link.setAttribute("href", "/security/resources/blank.html"); + + link.onerror = t.unreached_func("The import should load."); + link.onload = t.step_func_done(_ => { + assert_true(!!link.import); + }); + + document.body.appendChild(link); + }); + }, "Nonced imports load, and do not trigger reports."); +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/nonces/import-multiple-blocked.php b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/nonces/import-multiple-blocked.php new file mode 100644 index 0000000..a63cf622 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/nonces/import-multiple-blocked.php
@@ -0,0 +1,33 @@ +<?php + header("Content-Security-Policy: script-src 'unsafe-inline' 'self'"); + header("Content-Security-Policy-Report-Only: script-src 'nonce-abc'"); +?> +<!doctype html> +<script nonce="abc" src="/resources/testharness.js"></script> +<script nonce="abc" src="/resources/testharnessreport.js"></script> +<script nonce="abc"> + async_test(t => { + var link = document.createElement('link'); + link.setAttribute("rel", "import"); + link.setAttribute("nonce", "zyx"); + link.setAttribute("href", "/security/resources/blank.html"); + link.onerror = t.unreached_func("The import should load."); + link.onload = t.step_func(_ => assert_true(!!link.import, "The import was loaded.")); + + var watcher = new EventWatcher(t, document, ['securitypolicyviolation', 'securitypolicyviolation']); + watcher + .wait_for('securitypolicyviolation') + .then(t.step_func(e => { + assert_equals(e.blockedURI, "http://127.0.0.1:8000/security/resources/blank.html"); + assert_equals(e.lineNumber, 27); + // TODO(mkwst): We shouldn't be generating another violation report here. + return watcher.wait_for('securitypolicyviolation'); + })) + .then(t.step_func_done(e => { + assert_equals(e.blockedURI, "http://127.0.0.1:8000/security/resources/blank.html"); + assert_equals(e.lineNumber, 0); + })); + + document.head.appendChild(link); + }, "Nonced imports load, and do not trigger reports."); +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/nonces/import-reportonly-allowed.php b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/nonces/import-reportonly-allowed.php new file mode 100644 index 0000000..34256fb --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/nonces/import-reportonly-allowed.php
@@ -0,0 +1,32 @@ +<?php + header("Content-Security-Policy-Report-Only: script-src 'nonce-abc'"); +?> +<!doctype html> +<script nonce="abc" src="/resources/testharness.js"></script> +<script nonce="abc" src="/resources/testharnessreport.js"></script> +<script nonce="abc"> + async_test(t => { + var link = document.createElement('link'); + link.setAttribute("rel", "import"); + link.setAttribute("nonce", "zyx"); + link.setAttribute("href", "/security/resources/blank.html"); + link.onerror = t.unreached_func("The import should load."); + link.onload = t.step_func(_ => assert_true(!!link.import, "The import was loaded.")); + + var watcher = new EventWatcher(t, document, ['securitypolicyviolation', 'securitypolicyviolation']); + watcher + .wait_for('securitypolicyviolation') + .then(t.step_func(e => { + assert_equals(e.blockedURI, "http://127.0.0.1:8000/security/resources/blank.html"); + assert_equals(e.lineNumber, 27); + // TODO(mkwst): We shouldn't be generating another violation report here. + return watcher.wait_for('securitypolicyviolation'); + })) + .then(t.step_func_done(e => { + assert_equals(e.blockedURI, "http://127.0.0.1:8000/security/resources/blank.html"); + assert_equals(e.lineNumber, 0); + })); + + document.head.appendChild(link); + }, "Nonced imports load, and do not trigger reports."); +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/first-party-cookie-accepted.html b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/first-party-cookie-accepted.html new file mode 100644 index 0000000..d060b65 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/first-party-cookie-accepted.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/websocket/resources/get-request-header.js"></script> +<script src="/websocket/resources/cookie-test-util.js"></script> +<script> +if (window.testRunner) { + // Block third-party cookies. + testRunner.setBlockThirdPartyCookies(true); +} + +const origin = WS_ORIGIN; + +promise_test(() => { + return setCookie(origin).then( + () => { + return connectAndGetRequestHeadersFrom(origin); + } + ).then( + headers => { + const cookie = headers['cookie']; + assert_not_equals(cookie, undefined, + 'headers should contain a cookie header.'); + assert_equals( + normalizeCookie(cookie), + 'same-site-lax=1; same-site-strict=1; ws-domain-local-ip=1; ' + + 'ws-path-root=1; ws=1'); + return clear(origin); + } + ); +}, "Test that first-party cookies not blocked for WebSockets."); +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/resources/set-cookie.html b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/resources/set-cookie.html new file mode 100644 index 0000000..a0a59c11 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/resources/set-cookie.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<script src="/websocket/resources/get-request-header.js"></script> +<script src="/websocket/resources/cookie-test-util.js"></script> +<script> +function notifySuccess(value) { + window.parent.postMessage('DONE: ' + value, '*'); +} + +function notifyFailure(reason) { + window.parent.postMessage('FAIL: ' + reason, '*'); +} + +let origin = WS_ORIGIN; +if (location.search == '?remote') { + origin = WS_REMOTE_ORIGIN; +} + +setCookie(origin).then( + () => connectAndGetRequestHeadersFrom(origin), + notifyFailure +).then( + headers => { + const cookie = headers['cookie']; + return clear(origin).then(() => { + notifySuccess(JSON.stringify(cookie)); + }); + } +).catch( + notifyFailure +); +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-accepted.html b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-accepted.html new file mode 100644 index 0000000..0c1f45c --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-accepted.html
@@ -0,0 +1,31 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/websocket/resources/get-request-header.js"></script> +<script src="/websocket/resources/cookie-test-util.js"></script> +<script> +if (window.testRunner) { + // Don't block third-party cookies. + testRunner.setBlockThirdPartyCookies(false); +} + +const origin = WS_REMOTE_ORIGIN; + +promise_test(t => { + return setCookie(origin).then( + () => { + return connectAndGetRequestHeadersFrom(origin); + } + ).then( + headers => { + const cookie = headers['cookie']; + assert_not_equals(cookie, undefined, + 'headers should contain a cookie header.'); + // Same-site cookies are not included. + assert_equals(normalizeCookie(cookie), 'ws-path-root=1; ws=1'); + return clear(origin); + } + ); +}, "Test that third-party cookies are accepted for WebSockets when blocking " + + "is disabled."); +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked-on-cross-origin-websocket.html b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked-on-cross-origin-websocket.html new file mode 100644 index 0000000..17ee16c --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked-on-cross-origin-websocket.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +if (window.testRunner) { + // Block third-party cookies. + testRunner.setBlockThirdPartyCookies(true); +} + +async_test(t => { + window.addEventListener( + 'message', + t.step_func_done(event => { + assert_equals(event.data, 'DONE: undefined'); + }), + false); +}, "Test that first-party cookies are blocked for WebSockets conforming the " + + "requirements of the SameSite attribute."); +</script> +<!-- + The iframe is a remote origin. It uses the same origin as this test case file + for the WebSocket. +--> +<iframe src="http://localhost:8000/security/cookies/websocket/resources/set-cookie.html"></iframe>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked-on-same-origin-websocket.html b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked-on-same-origin-websocket.html new file mode 100644 index 0000000..c93d819 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked-on-same-origin-websocket.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +if (window.testRunner) { + // Block third-party cookies. + testRunner.setBlockThirdPartyCookies(true); +} + +async_test(t => { + window.addEventListener( + 'message', + t.step_func_done(event => { + assert_equals(event.data, 'DONE: undefined'); + }), + false); +}, "Test that third-party cookies are blocked for WebSockets even when the " + + "WebSocket's URL's domain is an exact match for the domain of its " + + "initiator."); +</script> +<!-- + The iframe is a remote origin. It uses a remote origin for the WebSocket. +--> +<iframe src="http://localhost:8000/security/cookies/websocket/resources/set-cookie.html?remote"></iframe>
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked.html b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked.html new file mode 100644 index 0000000..78fca21 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/security/cookies/websocket/third-party-cookie-blocked.html
@@ -0,0 +1,28 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/websocket/resources/get-request-header.js"></script> +<script src="/websocket/resources/cookie-test-util.js"></script> +<script> +if (window.testRunner) { + // Block third-party cookies. + testRunner.setBlockThirdPartyCookies(true); +} + +const origin = WS_REMOTE_ORIGIN; + +promise_test(t => { + return setCookie(origin).then( + () => { + return connectAndGetRequestHeadersFrom(origin); + } + ).then( + headers => { + const cookie = headers['cookie']; + assert_equals(cookie, undefined, + 'headers should not contain any cookie header.'); + return clear(origin); + } + ); +}, "Test third-party cookie blocking for WebSockets"); +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/websocket/cookie-ws-to-ws-expected.txt b/third_party/WebKit/LayoutTests/http/tests/websocket/cookie-ws-to-ws-expected.txt index 33fb8c1..c08104b9 100644 --- a/third_party/WebKit/LayoutTests/http/tests/websocket/cookie-ws-to-ws-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/websocket/cookie-ws-to-ws-expected.txt
@@ -3,7 +3,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". -PASS cookie is "ws-domain-local-ip=1; ws-path-root=1; ws=1" +PASS cookie is "same-site-lax=1; same-site-strict=1; ws-domain-local-ip=1; ws-path-root=1; ws=1" PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/http/tests/websocket/cookie-ws-to-ws.html b/third_party/WebKit/LayoutTests/http/tests/websocket/cookie-ws-to-ws.html index 74cd330..095712b 100644 --- a/third_party/WebKit/LayoutTests/http/tests/websocket/cookie-ws-to-ws.html +++ b/third_party/WebKit/LayoutTests/http/tests/websocket/cookie-ws-to-ws.html
@@ -22,7 +22,7 @@ ws_set_cookie.onclose = function (e) { connectAndGetRequestHeader('cookie').then(function(value) { cookie = normalizeCookie(value); - shouldBeEqualToString('cookie', 'ws-domain-local-ip=1; ws-path-root=1; ws=1'); + shouldBeEqualToString('cookie', 'same-site-lax=1; same-site-strict=1; ws-domain-local-ip=1; ws-path-root=1; ws=1'); clear(); }, finishAsFailed); };
diff --git a/third_party/WebKit/LayoutTests/http/tests/websocket/extensions.html b/third_party/WebKit/LayoutTests/http/tests/websocket/extensions.html index 91549f8..c25f97c6 100644 --- a/third_party/WebKit/LayoutTests/http/tests/websocket/extensions.html +++ b/third_party/WebKit/LayoutTests/http/tests/websocket/extensions.html
@@ -6,7 +6,7 @@ window.jsTestIsAsync = true; -var ws = new WebSocket(ECHO_REQUEST_HEADERS_WS_URL); +var ws = new WebSocket(WS_ECHO_REQUEST_HEADERS_URL); debug("Check the value before opening the connection:"); shouldBeEqualToString("ws.extensions", "");
diff --git a/third_party/WebKit/LayoutTests/http/tests/websocket/resources/cookie-test-util.js b/third_party/WebKit/LayoutTests/http/tests/websocket/resources/cookie-test-util.js new file mode 100644 index 0000000..9d5492e --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/websocket/resources/cookie-test-util.js
@@ -0,0 +1,25 @@ +// Normalize a cookie string +function normalizeCookie(cookie) { + // Split the cookie string, sort it and then put it back together. + return cookie.split('; ').sort().join('; '); +} + +function clear(server) { + return new Promise(resolve => { + const ws = new WebSocket(server + '/set-cookie?clear=1'); + ws.onopen = () => { + ws.close(); + }; + ws.onclose = resolve; + }); +} + +function setCookie(server) { + return new Promise(resolve => { + const ws = new WebSocket(server + '/set-cookie'); + ws.onopen = () => { + ws.close(); + }; + ws.onclose = resolve; + }); +}
diff --git a/third_party/WebKit/LayoutTests/http/tests/websocket/resources/get-request-header.js b/third_party/WebKit/LayoutTests/http/tests/websocket/resources/get-request-header.js index da429bd2e..23791e3 100644 --- a/third_party/WebKit/LayoutTests/http/tests/websocket/resources/get-request-header.js +++ b/third_party/WebKit/LayoutTests/http/tests/websocket/resources/get-request-header.js
@@ -1,22 +1,27 @@ -var ECHO_REQUEST_HEADERS_WS_URL = 'ws://127.0.0.1:8880/echo-request-headers'; +var WS_ORIGIN = 'ws://127.0.0.1:8880'; +var WS_REMOTE_ORIGIN = 'ws://localhost:8880'; +var WS_ECHO_REQUEST_HEADERS_URL = WS_ORIGIN + '/echo-request-headers'; // Returns a Promise which will create a new WebSocket, and resolve to the value // of the specified header in the request, or reject with an error message if // something goes wrong. The header must be specified in lower-case. function connectAndGetRequestHeader(request_header) { - return connectAndGetRequestHeaders().then(function(headers) - { - return headers[request_header]; - }); + return connectAndGetRequestHeaders(WS_ORIGIN).then( + headers => headers[request_header]); +} + +function connectAndGetRequestHeaders() +{ + return connectAndGetRequestHeadersFrom(WS_ORIGIN); } // Returns a Promise which will create a new WebSocket, and return all the // request headers as an object, with the header names as keys in lower-case. -function connectAndGetRequestHeaders() +function connectAndGetRequestHeadersFrom(server) { return new Promise(function(resolve, reject) { - var header_ws = new WebSocket(ECHO_REQUEST_HEADERS_WS_URL); + var header_ws = new WebSocket(server + '/echo-request-headers'); header_ws.onmessage = function (evt) { try { var headers = JSON.parse(evt.data);
diff --git a/third_party/WebKit/LayoutTests/http/tests/websocket/set-cookie_wsh.py b/third_party/WebKit/LayoutTests/http/tests/websocket/set-cookie_wsh.py index 1c8bf05..15db410 100644 --- a/third_party/WebKit/LayoutTests/http/tests/websocket/set-cookie_wsh.py +++ b/third_party/WebKit/LayoutTests/http/tests/websocket/set-cookie_wsh.py
@@ -41,6 +41,8 @@ 'ws-path-root=1; Path=/' + max_age, 'ws-path-foobar=1; Path=/foo/bar' + max_age, 'ws=1' + max_age, + 'same-site-strict=1; SameSite=Strict' + max_age, + 'same-site-lax=1; SameSite=Lax' + max_age ] for value in cookie_values: request.extra_headers.append(('Set-Cookie', value))
diff --git a/third_party/WebKit/LayoutTests/http/tests/websocket/workers/resources/cookie-ws-to-ws.js b/third_party/WebKit/LayoutTests/http/tests/websocket/workers/resources/cookie-ws-to-ws.js index 1039663a..050eac8 100644 --- a/third_party/WebKit/LayoutTests/http/tests/websocket/workers/resources/cookie-ws-to-ws.js +++ b/third_party/WebKit/LayoutTests/http/tests/websocket/workers/resources/cookie-ws-to-ws.js
@@ -48,8 +48,8 @@ .then(echoCookie) .then( function (cookie) { - if (cookie != 'ws-domain-local-ip=1; ws-path-root=1; ws=1') - return Promise.reject('Echoed cookie is incorrect'); + if (cookie != 'ws-domain-local-ip=1; ws-path-root=1; ws=1; same-site-strict=1; same-site-lax=1') + return Promise.reject('Echoed cookie is incorrect: ' + cookie); postMessage("DONE"); }
diff --git a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt index 48596722..36222a1 100644 --- a/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
@@ -109,6 +109,9 @@ CONSOLE MESSAGE: line 137: getter y CONSOLE MESSAGE: line 137: getter z CONSOLE MESSAGE: line 137: method constructor +CONSOLE MESSAGE: line 137: interface CSSVariableReferenceValue +CONSOLE MESSAGE: line 137: getter variable +CONSOLE MESSAGE: line 137: method constructor CONSOLE MESSAGE: line 137: interface CountQueuingStrategy CONSOLE MESSAGE: line 137: method constructor CONSOLE MESSAGE: line 137: method size
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness-expected.txt index cfaa630..4c03728c 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness-expected.txt +++ b/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness-expected.txt
@@ -95,5 +95,6 @@ PASS FileReader interface: new FileReader() must inherit property "onabort" with the proper type (13) PASS FileReader interface: new FileReader() must inherit property "onerror" with the proper type (14) PASS FileReader interface: new FileReader() must inherit property "onloadend" with the proper type (15) +PASS FileReaderSync interface: existence and properties of interface object Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness.idl b/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness.idl index ae83a9cb..62e6c5d 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness.idl +++ b/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness.idl
@@ -79,3 +79,13 @@ static void revokeObjectURL(DOMString url); }; + +[Constructor, Exposed=Worker] +interface FileReaderSync { + + // Synchronously return strings + + ArrayBuffer readAsArrayBuffer(Blob blob); + DOMString readAsText(Blob blob, optional DOMString label); + DOMString readAsDataURL(Blob blob); +};
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness.worker.js b/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness.worker.js index 40ba816..3243e34 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness.worker.js +++ b/third_party/WebKit/LayoutTests/imported/wpt/FileAPI/idlharness.worker.js
@@ -18,20 +18,7 @@ idl_array.add_untested_idls("[TreatNonCallableAsNull] callback EventHandlerNonNull = any (Event event);"); idl_array.add_untested_idls("typedef EventHandlerNonNull? EventHandler;"); - - var worker_idls = - '[Constructor, Exposed=Worker]\n' + - 'interface FileReaderSync {\n' + - '\n' + - ' // Synchronously return strings\n' + - '\n' + - ' ArrayBuffer readAsArrayBuffer(Blob blob);\n' + - ' DOMString readAsText(Blob blob, optional DOMString label);\n' + - ' DOMString readAsDataURL(Blob blob);\n' + - '};'; - idl_array.add_idls(idls); - idl_array.add_idls(worker_idls); idl_array.add_objects({ Blob: ['new Blob(["TEST"])'],
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/common/entities.json b/third_party/WebKit/LayoutTests/imported/wpt/common/entities.json new file mode 100644 index 0000000..8a1f590 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt/common/entities.json
@@ -0,0 +1,2233 @@ +{ + "Á": { "codepoints": [193], "characters": "\u00C1" }, + "Á": { "codepoints": [193], "characters": "\u00C1" }, + "á": { "codepoints": [225], "characters": "\u00E1" }, + "á": { "codepoints": [225], "characters": "\u00E1" }, + "Ă": { "codepoints": [258], "characters": "\u0102" }, + "ă": { "codepoints": [259], "characters": "\u0103" }, + "∾": { "codepoints": [8766], "characters": "\u223E" }, + "∿": { "codepoints": [8767], "characters": "\u223F" }, + "∾̳": { "codepoints": [8766, 819], "characters": "\u223E\u0333" }, + "Â": { "codepoints": [194], "characters": "\u00C2" }, + "Â": { "codepoints": [194], "characters": "\u00C2" }, + "â": { "codepoints": [226], "characters": "\u00E2" }, + "â": { "codepoints": [226], "characters": "\u00E2" }, + "´": { "codepoints": [180], "characters": "\u00B4" }, + "´": { "codepoints": [180], "characters": "\u00B4" }, + "А": { "codepoints": [1040], "characters": "\u0410" }, + "а": { "codepoints": [1072], "characters": "\u0430" }, + "Æ": { "codepoints": [198], "characters": "\u00C6" }, + "Æ": { "codepoints": [198], "characters": "\u00C6" }, + "æ": { "codepoints": [230], "characters": "\u00E6" }, + "æ": { "codepoints": [230], "characters": "\u00E6" }, + "⁡": { "codepoints": [8289], "characters": "\u2061" }, + "𝔄": { "codepoints": [120068], "characters": "\uD835\uDD04" }, + "𝔞": { "codepoints": [120094], "characters": "\uD835\uDD1E" }, + "À": { "codepoints": [192], "characters": "\u00C0" }, + "À": { "codepoints": [192], "characters": "\u00C0" }, + "à": { "codepoints": [224], "characters": "\u00E0" }, + "à": { "codepoints": [224], "characters": "\u00E0" }, + "ℵ": { "codepoints": [8501], "characters": "\u2135" }, + "ℵ": { "codepoints": [8501], "characters": "\u2135" }, + "Α": { "codepoints": [913], "characters": "\u0391" }, + "α": { "codepoints": [945], "characters": "\u03B1" }, + "Ā": { "codepoints": [256], "characters": "\u0100" }, + "ā": { "codepoints": [257], "characters": "\u0101" }, + "⨿": { "codepoints": [10815], "characters": "\u2A3F" }, + "&": { "codepoints": [38], "characters": "\u0026" }, + "&": { "codepoints": [38], "characters": "\u0026" }, + "&": { "codepoints": [38], "characters": "\u0026" }, + "&": { "codepoints": [38], "characters": "\u0026" }, + "⩕": { "codepoints": [10837], "characters": "\u2A55" }, + "⩓": { "codepoints": [10835], "characters": "\u2A53" }, + "∧": { "codepoints": [8743], "characters": "\u2227" }, + "⩜": { "codepoints": [10844], "characters": "\u2A5C" }, + "⩘": { "codepoints": [10840], "characters": "\u2A58" }, + "⩚": { "codepoints": [10842], "characters": "\u2A5A" }, + "∠": { "codepoints": [8736], "characters": "\u2220" }, + "⦤": { "codepoints": [10660], "characters": "\u29A4" }, + "∠": { "codepoints": [8736], "characters": "\u2220" }, + "⦨": { "codepoints": [10664], "characters": "\u29A8" }, + "⦩": { "codepoints": [10665], "characters": "\u29A9" }, + "⦪": { "codepoints": [10666], "characters": "\u29AA" }, + "⦫": { "codepoints": [10667], "characters": "\u29AB" }, + "⦬": { "codepoints": [10668], "characters": "\u29AC" }, + "⦭": { "codepoints": [10669], "characters": "\u29AD" }, + "⦮": { "codepoints": [10670], "characters": "\u29AE" }, + "⦯": { "codepoints": [10671], "characters": "\u29AF" }, + "∡": { "codepoints": [8737], "characters": "\u2221" }, + "∟": { "codepoints": [8735], "characters": "\u221F" }, + "⊾": { "codepoints": [8894], "characters": "\u22BE" }, + "⦝": { "codepoints": [10653], "characters": "\u299D" }, + "∢": { "codepoints": [8738], "characters": "\u2222" }, + "Å": { "codepoints": [197], "characters": "\u00C5" }, + "⍼": { "codepoints": [9084], "characters": "\u237C" }, + "Ą": { "codepoints": [260], "characters": "\u0104" }, + "ą": { "codepoints": [261], "characters": "\u0105" }, + "𝔸": { "codepoints": [120120], "characters": "\uD835\uDD38" }, + "𝕒": { "codepoints": [120146], "characters": "\uD835\uDD52" }, + "⩯": { "codepoints": [10863], "characters": "\u2A6F" }, + "≈": { "codepoints": [8776], "characters": "\u2248" }, + "⩰": { "codepoints": [10864], "characters": "\u2A70" }, + "≊": { "codepoints": [8778], "characters": "\u224A" }, + "≋": { "codepoints": [8779], "characters": "\u224B" }, + "'": { "codepoints": [39], "characters": "\u0027" }, + "⁡": { "codepoints": [8289], "characters": "\u2061" }, + "≈": { "codepoints": [8776], "characters": "\u2248" }, + "≊": { "codepoints": [8778], "characters": "\u224A" }, + "Å": { "codepoints": [197], "characters": "\u00C5" }, + "Å": { "codepoints": [197], "characters": "\u00C5" }, + "å": { "codepoints": [229], "characters": "\u00E5" }, + "å": { "codepoints": [229], "characters": "\u00E5" }, + "𝒜": { "codepoints": [119964], "characters": "\uD835\uDC9C" }, + "𝒶": { "codepoints": [119990], "characters": "\uD835\uDCB6" }, + "≔": { "codepoints": [8788], "characters": "\u2254" }, + "*": { "codepoints": [42], "characters": "\u002A" }, + "≈": { "codepoints": [8776], "characters": "\u2248" }, + "≍": { "codepoints": [8781], "characters": "\u224D" }, + "Ã": { "codepoints": [195], "characters": "\u00C3" }, + "Ã": { "codepoints": [195], "characters": "\u00C3" }, + "ã": { "codepoints": [227], "characters": "\u00E3" }, + "ã": { "codepoints": [227], "characters": "\u00E3" }, + "Ä": { "codepoints": [196], "characters": "\u00C4" }, + "Ä": { "codepoints": [196], "characters": "\u00C4" }, + "ä": { "codepoints": [228], "characters": "\u00E4" }, + "ä": { "codepoints": [228], "characters": "\u00E4" }, + "∳": { "codepoints": [8755], "characters": "\u2233" }, + "⨑": { "codepoints": [10769], "characters": "\u2A11" }, + "≌": { "codepoints": [8780], "characters": "\u224C" }, + "϶": { "codepoints": [1014], "characters": "\u03F6" }, + "‵": { "codepoints": [8245], "characters": "\u2035" }, + "∽": { "codepoints": [8765], "characters": "\u223D" }, + "⋍": { "codepoints": [8909], "characters": "\u22CD" }, + "∖": { "codepoints": [8726], "characters": "\u2216" }, + "⫧": { "codepoints": [10983], "characters": "\u2AE7" }, + "⊽": { "codepoints": [8893], "characters": "\u22BD" }, + "⌅": { "codepoints": [8965], "characters": "\u2305" }, + "⌆": { "codepoints": [8966], "characters": "\u2306" }, + "⌅": { "codepoints": [8965], "characters": "\u2305" }, + "⎵": { "codepoints": [9141], "characters": "\u23B5" }, + "⎶": { "codepoints": [9142], "characters": "\u23B6" }, + "≌": { "codepoints": [8780], "characters": "\u224C" }, + "Б": { "codepoints": [1041], "characters": "\u0411" }, + "б": { "codepoints": [1073], "characters": "\u0431" }, + "„": { "codepoints": [8222], "characters": "\u201E" }, + "∵": { "codepoints": [8757], "characters": "\u2235" }, + "∵": { "codepoints": [8757], "characters": "\u2235" }, + "∵": { "codepoints": [8757], "characters": "\u2235" }, + "⦰": { "codepoints": [10672], "characters": "\u29B0" }, + "϶": { "codepoints": [1014], "characters": "\u03F6" }, + "ℬ": { "codepoints": [8492], "characters": "\u212C" }, + "ℬ": { "codepoints": [8492], "characters": "\u212C" }, + "Β": { "codepoints": [914], "characters": "\u0392" }, + "β": { "codepoints": [946], "characters": "\u03B2" }, + "ℶ": { "codepoints": [8502], "characters": "\u2136" }, + "≬": { "codepoints": [8812], "characters": "\u226C" }, + "𝔅": { "codepoints": [120069], "characters": "\uD835\uDD05" }, + "𝔟": { "codepoints": [120095], "characters": "\uD835\uDD1F" }, + "⋂": { "codepoints": [8898], "characters": "\u22C2" }, + "◯": { "codepoints": [9711], "characters": "\u25EF" }, + "⋃": { "codepoints": [8899], "characters": "\u22C3" }, + "⨀": { "codepoints": [10752], "characters": "\u2A00" }, + "⨁": { "codepoints": [10753], "characters": "\u2A01" }, + "⨂": { "codepoints": [10754], "characters": "\u2A02" }, + "⨆": { "codepoints": [10758], "characters": "\u2A06" }, + "★": { "codepoints": [9733], "characters": "\u2605" }, + "▽": { "codepoints": [9661], "characters": "\u25BD" }, + "△": { "codepoints": [9651], "characters": "\u25B3" }, + "⨄": { "codepoints": [10756], "characters": "\u2A04" }, + "⋁": { "codepoints": [8897], "characters": "\u22C1" }, + "⋀": { "codepoints": [8896], "characters": "\u22C0" }, + "⤍": { "codepoints": [10509], "characters": "\u290D" }, + "⧫": { "codepoints": [10731], "characters": "\u29EB" }, + "▪": { "codepoints": [9642], "characters": "\u25AA" }, + "▴": { "codepoints": [9652], "characters": "\u25B4" }, + "▾": { "codepoints": [9662], "characters": "\u25BE" }, + "◂": { "codepoints": [9666], "characters": "\u25C2" }, + "▸": { "codepoints": [9656], "characters": "\u25B8" }, + "␣": { "codepoints": [9251], "characters": "\u2423" }, + "▒": { "codepoints": [9618], "characters": "\u2592" }, + "░": { "codepoints": [9617], "characters": "\u2591" }, + "▓": { "codepoints": [9619], "characters": "\u2593" }, + "█": { "codepoints": [9608], "characters": "\u2588" }, + "=⃥": { "codepoints": [61, 8421], "characters": "\u003D\u20E5" }, + "≡⃥": { "codepoints": [8801, 8421], "characters": "\u2261\u20E5" }, + "⫭": { "codepoints": [10989], "characters": "\u2AED" }, + "⌐": { "codepoints": [8976], "characters": "\u2310" }, + "𝔹": { "codepoints": [120121], "characters": "\uD835\uDD39" }, + "𝕓": { "codepoints": [120147], "characters": "\uD835\uDD53" }, + "⊥": { "codepoints": [8869], "characters": "\u22A5" }, + "⊥": { "codepoints": [8869], "characters": "\u22A5" }, + "⋈": { "codepoints": [8904], "characters": "\u22C8" }, + "⧉": { "codepoints": [10697], "characters": "\u29C9" }, + "┐": { "codepoints": [9488], "characters": "\u2510" }, + "╕": { "codepoints": [9557], "characters": "\u2555" }, + "╖": { "codepoints": [9558], "characters": "\u2556" }, + "╗": { "codepoints": [9559], "characters": "\u2557" }, + "┌": { "codepoints": [9484], "characters": "\u250C" }, + "╒": { "codepoints": [9554], "characters": "\u2552" }, + "╓": { "codepoints": [9555], "characters": "\u2553" }, + "╔": { "codepoints": [9556], "characters": "\u2554" }, + "─": { "codepoints": [9472], "characters": "\u2500" }, + "═": { "codepoints": [9552], "characters": "\u2550" }, + "┬": { "codepoints": [9516], "characters": "\u252C" }, + "╤": { "codepoints": [9572], "characters": "\u2564" }, + "╥": { "codepoints": [9573], "characters": "\u2565" }, + "╦": { "codepoints": [9574], "characters": "\u2566" }, + "┴": { "codepoints": [9524], "characters": "\u2534" }, + "╧": { "codepoints": [9575], "characters": "\u2567" }, + "╨": { "codepoints": [9576], "characters": "\u2568" }, + "╩": { "codepoints": [9577], "characters": "\u2569" }, + "⊟": { "codepoints": [8863], "characters": "\u229F" }, + "⊞": { "codepoints": [8862], "characters": "\u229E" }, + "⊠": { "codepoints": [8864], "characters": "\u22A0" }, + "┘": { "codepoints": [9496], "characters": "\u2518" }, + "╛": { "codepoints": [9563], "characters": "\u255B" }, + "╜": { "codepoints": [9564], "characters": "\u255C" }, + "╝": { "codepoints": [9565], "characters": "\u255D" }, + "└": { "codepoints": [9492], "characters": "\u2514" }, + "╘": { "codepoints": [9560], "characters": "\u2558" }, + "╙": { "codepoints": [9561], "characters": "\u2559" }, + "╚": { "codepoints": [9562], "characters": "\u255A" }, + "│": { "codepoints": [9474], "characters": "\u2502" }, + "║": { "codepoints": [9553], "characters": "\u2551" }, + "┼": { "codepoints": [9532], "characters": "\u253C" }, + "╪": { "codepoints": [9578], "characters": "\u256A" }, + "╫": { "codepoints": [9579], "characters": "\u256B" }, + "╬": { "codepoints": [9580], "characters": "\u256C" }, + "┤": { "codepoints": [9508], "characters": "\u2524" }, + "╡": { "codepoints": [9569], "characters": "\u2561" }, + "╢": { "codepoints": [9570], "characters": "\u2562" }, + "╣": { "codepoints": [9571], "characters": "\u2563" }, + "├": { "codepoints": [9500], "characters": "\u251C" }, + "╞": { "codepoints": [9566], "characters": "\u255E" }, + "╟": { "codepoints": [9567], "characters": "\u255F" }, + "╠": { "codepoints": [9568], "characters": "\u2560" }, + "‵": { "codepoints": [8245], "characters": "\u2035" }, + "˘": { "codepoints": [728], "characters": "\u02D8" }, + "˘": { "codepoints": [728], "characters": "\u02D8" }, + "¦": { "codepoints": [166], "characters": "\u00A6" }, + "¦": { "codepoints": [166], "characters": "\u00A6" }, + "𝒷": { "codepoints": [119991], "characters": "\uD835\uDCB7" }, + "ℬ": { "codepoints": [8492], "characters": "\u212C" }, + "⁏": { "codepoints": [8271], "characters": "\u204F" }, + "∽": { "codepoints": [8765], "characters": "\u223D" }, + "⋍": { "codepoints": [8909], "characters": "\u22CD" }, + "⧅": { "codepoints": [10693], "characters": "\u29C5" }, + "\": { "codepoints": [92], "characters": "\u005C" }, + "⟈": { "codepoints": [10184], "characters": "\u27C8" }, + "•": { "codepoints": [8226], "characters": "\u2022" }, + "•": { "codepoints": [8226], "characters": "\u2022" }, + "≎": { "codepoints": [8782], "characters": "\u224E" }, + "⪮": { "codepoints": [10926], "characters": "\u2AAE" }, + "≏": { "codepoints": [8783], "characters": "\u224F" }, + "≎": { "codepoints": [8782], "characters": "\u224E" }, + "≏": { "codepoints": [8783], "characters": "\u224F" }, + "Ć": { "codepoints": [262], "characters": "\u0106" }, + "ć": { "codepoints": [263], "characters": "\u0107" }, + "⩄": { "codepoints": [10820], "characters": "\u2A44" }, + "⩉": { "codepoints": [10825], "characters": "\u2A49" }, + "⩋": { "codepoints": [10827], "characters": "\u2A4B" }, + "∩": { "codepoints": [8745], "characters": "\u2229" }, + "⋒": { "codepoints": [8914], "characters": "\u22D2" }, + "⩇": { "codepoints": [10823], "characters": "\u2A47" }, + "⩀": { "codepoints": [10816], "characters": "\u2A40" }, + "ⅅ": { "codepoints": [8517], "characters": "\u2145" }, + "∩︀": { "codepoints": [8745, 65024], "characters": "\u2229\uFE00" }, + "⁁": { "codepoints": [8257], "characters": "\u2041" }, + "ˇ": { "codepoints": [711], "characters": "\u02C7" }, + "ℭ": { "codepoints": [8493], "characters": "\u212D" }, + "⩍": { "codepoints": [10829], "characters": "\u2A4D" }, + "Č": { "codepoints": [268], "characters": "\u010C" }, + "č": { "codepoints": [269], "characters": "\u010D" }, + "Ç": { "codepoints": [199], "characters": "\u00C7" }, + "Ç": { "codepoints": [199], "characters": "\u00C7" }, + "ç": { "codepoints": [231], "characters": "\u00E7" }, + "ç": { "codepoints": [231], "characters": "\u00E7" }, + "Ĉ": { "codepoints": [264], "characters": "\u0108" }, + "ĉ": { "codepoints": [265], "characters": "\u0109" }, + "∰": { "codepoints": [8752], "characters": "\u2230" }, + "⩌": { "codepoints": [10828], "characters": "\u2A4C" }, + "⩐": { "codepoints": [10832], "characters": "\u2A50" }, + "Ċ": { "codepoints": [266], "characters": "\u010A" }, + "ċ": { "codepoints": [267], "characters": "\u010B" }, + "¸": { "codepoints": [184], "characters": "\u00B8" }, + "¸": { "codepoints": [184], "characters": "\u00B8" }, + "¸": { "codepoints": [184], "characters": "\u00B8" }, + "⦲": { "codepoints": [10674], "characters": "\u29B2" }, + "¢": { "codepoints": [162], "characters": "\u00A2" }, + "¢": { "codepoints": [162], "characters": "\u00A2" }, + "·": { "codepoints": [183], "characters": "\u00B7" }, + "·": { "codepoints": [183], "characters": "\u00B7" }, + "𝔠": { "codepoints": [120096], "characters": "\uD835\uDD20" }, + "ℭ": { "codepoints": [8493], "characters": "\u212D" }, + "Ч": { "codepoints": [1063], "characters": "\u0427" }, + "ч": { "codepoints": [1095], "characters": "\u0447" }, + "✓": { "codepoints": [10003], "characters": "\u2713" }, + "✓": { "codepoints": [10003], "characters": "\u2713" }, + "Χ": { "codepoints": [935], "characters": "\u03A7" }, + "χ": { "codepoints": [967], "characters": "\u03C7" }, + "ˆ": { "codepoints": [710], "characters": "\u02C6" }, + "≗": { "codepoints": [8791], "characters": "\u2257" }, + "↺": { "codepoints": [8634], "characters": "\u21BA" }, + "↻": { "codepoints": [8635], "characters": "\u21BB" }, + "⊛": { "codepoints": [8859], "characters": "\u229B" }, + "⊚": { "codepoints": [8858], "characters": "\u229A" }, + "⊝": { "codepoints": [8861], "characters": "\u229D" }, + "⊙": { "codepoints": [8857], "characters": "\u2299" }, + "®": { "codepoints": [174], "characters": "\u00AE" }, + "Ⓢ": { "codepoints": [9416], "characters": "\u24C8" }, + "⊖": { "codepoints": [8854], "characters": "\u2296" }, + "⊕": { "codepoints": [8853], "characters": "\u2295" }, + "⊗": { "codepoints": [8855], "characters": "\u2297" }, + "○": { "codepoints": [9675], "characters": "\u25CB" }, + "⧃": { "codepoints": [10691], "characters": "\u29C3" }, + "≗": { "codepoints": [8791], "characters": "\u2257" }, + "⨐": { "codepoints": [10768], "characters": "\u2A10" }, + "⫯": { "codepoints": [10991], "characters": "\u2AEF" }, + "⧂": { "codepoints": [10690], "characters": "\u29C2" }, + "∲": { "codepoints": [8754], "characters": "\u2232" }, + "”": { "codepoints": [8221], "characters": "\u201D" }, + "’": { "codepoints": [8217], "characters": "\u2019" }, + "♣": { "codepoints": [9827], "characters": "\u2663" }, + "♣": { "codepoints": [9827], "characters": "\u2663" }, + ":": { "codepoints": [58], "characters": "\u003A" }, + "∷": { "codepoints": [8759], "characters": "\u2237" }, + "⩴": { "codepoints": [10868], "characters": "\u2A74" }, + "≔": { "codepoints": [8788], "characters": "\u2254" }, + "≔": { "codepoints": [8788], "characters": "\u2254" }, + ",": { "codepoints": [44], "characters": "\u002C" }, + "@": { "codepoints": [64], "characters": "\u0040" }, + "∁": { "codepoints": [8705], "characters": "\u2201" }, + "∘": { "codepoints": [8728], "characters": "\u2218" }, + "∁": { "codepoints": [8705], "characters": "\u2201" }, + "ℂ": { "codepoints": [8450], "characters": "\u2102" }, + "≅": { "codepoints": [8773], "characters": "\u2245" }, + "⩭": { "codepoints": [10861], "characters": "\u2A6D" }, + "≡": { "codepoints": [8801], "characters": "\u2261" }, + "∮": { "codepoints": [8750], "characters": "\u222E" }, + "∯": { "codepoints": [8751], "characters": "\u222F" }, + "∮": { "codepoints": [8750], "characters": "\u222E" }, + "𝕔": { "codepoints": [120148], "characters": "\uD835\uDD54" }, + "ℂ": { "codepoints": [8450], "characters": "\u2102" }, + "∐": { "codepoints": [8720], "characters": "\u2210" }, + "∐": { "codepoints": [8720], "characters": "\u2210" }, + "©": { "codepoints": [169], "characters": "\u00A9" }, + "©": { "codepoints": [169], "characters": "\u00A9" }, + "©": { "codepoints": [169], "characters": "\u00A9" }, + "©": { "codepoints": [169], "characters": "\u00A9" }, + "℗": { "codepoints": [8471], "characters": "\u2117" }, + "∳": { "codepoints": [8755], "characters": "\u2233" }, + "↵": { "codepoints": [8629], "characters": "\u21B5" }, + "✗": { "codepoints": [10007], "characters": "\u2717" }, + "⨯": { "codepoints": [10799], "characters": "\u2A2F" }, + "𝒞": { "codepoints": [119966], "characters": "\uD835\uDC9E" }, + "𝒸": { "codepoints": [119992], "characters": "\uD835\uDCB8" }, + "⫏": { "codepoints": [10959], "characters": "\u2ACF" }, + "⫑": { "codepoints": [10961], "characters": "\u2AD1" }, + "⫐": { "codepoints": [10960], "characters": "\u2AD0" }, + "⫒": { "codepoints": [10962], "characters": "\u2AD2" }, + "⋯": { "codepoints": [8943], "characters": "\u22EF" }, + "⤸": { "codepoints": [10552], "characters": "\u2938" }, + "⤵": { "codepoints": [10549], "characters": "\u2935" }, + "⋞": { "codepoints": [8926], "characters": "\u22DE" }, + "⋟": { "codepoints": [8927], "characters": "\u22DF" }, + "↶": { "codepoints": [8630], "characters": "\u21B6" }, + "⤽": { "codepoints": [10557], "characters": "\u293D" }, + "⩈": { "codepoints": [10824], "characters": "\u2A48" }, + "⩆": { "codepoints": [10822], "characters": "\u2A46" }, + "≍": { "codepoints": [8781], "characters": "\u224D" }, + "∪": { "codepoints": [8746], "characters": "\u222A" }, + "⋓": { "codepoints": [8915], "characters": "\u22D3" }, + "⩊": { "codepoints": [10826], "characters": "\u2A4A" }, + "⊍": { "codepoints": [8845], "characters": "\u228D" }, + "⩅": { "codepoints": [10821], "characters": "\u2A45" }, + "∪︀": { "codepoints": [8746, 65024], "characters": "\u222A\uFE00" }, + "↷": { "codepoints": [8631], "characters": "\u21B7" }, + "⤼": { "codepoints": [10556], "characters": "\u293C" }, + "⋞": { "codepoints": [8926], "characters": "\u22DE" }, + "⋟": { "codepoints": [8927], "characters": "\u22DF" }, + "⋎": { "codepoints": [8910], "characters": "\u22CE" }, + "⋏": { "codepoints": [8911], "characters": "\u22CF" }, + "¤": { "codepoints": [164], "characters": "\u00A4" }, + "¤": { "codepoints": [164], "characters": "\u00A4" }, + "↶": { "codepoints": [8630], "characters": "\u21B6" }, + "↷": { "codepoints": [8631], "characters": "\u21B7" }, + "⋎": { "codepoints": [8910], "characters": "\u22CE" }, + "⋏": { "codepoints": [8911], "characters": "\u22CF" }, + "∲": { "codepoints": [8754], "characters": "\u2232" }, + "∱": { "codepoints": [8753], "characters": "\u2231" }, + "⌭": { "codepoints": [9005], "characters": "\u232D" }, + "†": { "codepoints": [8224], "characters": "\u2020" }, + "‡": { "codepoints": [8225], "characters": "\u2021" }, + "ℸ": { "codepoints": [8504], "characters": "\u2138" }, + "↓": { "codepoints": [8595], "characters": "\u2193" }, + "↡": { "codepoints": [8609], "characters": "\u21A1" }, + "⇓": { "codepoints": [8659], "characters": "\u21D3" }, + "‐": { "codepoints": [8208], "characters": "\u2010" }, + "⫤": { "codepoints": [10980], "characters": "\u2AE4" }, + "⊣": { "codepoints": [8867], "characters": "\u22A3" }, + "⤏": { "codepoints": [10511], "characters": "\u290F" }, + "˝": { "codepoints": [733], "characters": "\u02DD" }, + "Ď": { "codepoints": [270], "characters": "\u010E" }, + "ď": { "codepoints": [271], "characters": "\u010F" }, + "Д": { "codepoints": [1044], "characters": "\u0414" }, + "д": { "codepoints": [1076], "characters": "\u0434" }, + "‡": { "codepoints": [8225], "characters": "\u2021" }, + "⇊": { "codepoints": [8650], "characters": "\u21CA" }, + "ⅅ": { "codepoints": [8517], "characters": "\u2145" }, + "ⅆ": { "codepoints": [8518], "characters": "\u2146" }, + "⤑": { "codepoints": [10513], "characters": "\u2911" }, + "⩷": { "codepoints": [10871], "characters": "\u2A77" }, + "°": { "codepoints": [176], "characters": "\u00B0" }, + "°": { "codepoints": [176], "characters": "\u00B0" }, + "∇": { "codepoints": [8711], "characters": "\u2207" }, + "Δ": { "codepoints": [916], "characters": "\u0394" }, + "δ": { "codepoints": [948], "characters": "\u03B4" }, + "⦱": { "codepoints": [10673], "characters": "\u29B1" }, + "⥿": { "codepoints": [10623], "characters": "\u297F" }, + "𝔇": { "codepoints": [120071], "characters": "\uD835\uDD07" }, + "𝔡": { "codepoints": [120097], "characters": "\uD835\uDD21" }, + "⥥": { "codepoints": [10597], "characters": "\u2965" }, + "⇃": { "codepoints": [8643], "characters": "\u21C3" }, + "⇂": { "codepoints": [8642], "characters": "\u21C2" }, + "´": { "codepoints": [180], "characters": "\u00B4" }, + "˙": { "codepoints": [729], "characters": "\u02D9" }, + "˝": { "codepoints": [733], "characters": "\u02DD" }, + "`": { "codepoints": [96], "characters": "\u0060" }, + "˜": { "codepoints": [732], "characters": "\u02DC" }, + "⋄": { "codepoints": [8900], "characters": "\u22C4" }, + "⋄": { "codepoints": [8900], "characters": "\u22C4" }, + "⋄": { "codepoints": [8900], "characters": "\u22C4" }, + "♦": { "codepoints": [9830], "characters": "\u2666" }, + "♦": { "codepoints": [9830], "characters": "\u2666" }, + "¨": { "codepoints": [168], "characters": "\u00A8" }, + "ⅆ": { "codepoints": [8518], "characters": "\u2146" }, + "ϝ": { "codepoints": [989], "characters": "\u03DD" }, + "⋲": { "codepoints": [8946], "characters": "\u22F2" }, + "÷": { "codepoints": [247], "characters": "\u00F7" }, + "÷": { "codepoints": [247], "characters": "\u00F7" }, + "÷": { "codepoints": [247], "characters": "\u00F7" }, + "⋇": { "codepoints": [8903], "characters": "\u22C7" }, + "⋇": { "codepoints": [8903], "characters": "\u22C7" }, + "Ђ": { "codepoints": [1026], "characters": "\u0402" }, + "ђ": { "codepoints": [1106], "characters": "\u0452" }, + "⌞": { "codepoints": [8990], "characters": "\u231E" }, + "⌍": { "codepoints": [8973], "characters": "\u230D" }, + "$": { "codepoints": [36], "characters": "\u0024" }, + "𝔻": { "codepoints": [120123], "characters": "\uD835\uDD3B" }, + "𝕕": { "codepoints": [120149], "characters": "\uD835\uDD55" }, + "¨": { "codepoints": [168], "characters": "\u00A8" }, + "˙": { "codepoints": [729], "characters": "\u02D9" }, + "⃜": { "codepoints": [8412], "characters": "\u20DC" }, + "≐": { "codepoints": [8784], "characters": "\u2250" }, + "≑": { "codepoints": [8785], "characters": "\u2251" }, + "≐": { "codepoints": [8784], "characters": "\u2250" }, + "∸": { "codepoints": [8760], "characters": "\u2238" }, + "∔": { "codepoints": [8724], "characters": "\u2214" }, + "⊡": { "codepoints": [8865], "characters": "\u22A1" }, + "⌆": { "codepoints": [8966], "characters": "\u2306" }, + "∯": { "codepoints": [8751], "characters": "\u222F" }, + "¨": { "codepoints": [168], "characters": "\u00A8" }, + "⇓": { "codepoints": [8659], "characters": "\u21D3" }, + "⇐": { "codepoints": [8656], "characters": "\u21D0" }, + "⇔": { "codepoints": [8660], "characters": "\u21D4" }, + "⫤": { "codepoints": [10980], "characters": "\u2AE4" }, + "⟸": { "codepoints": [10232], "characters": "\u27F8" }, + "⟺": { "codepoints": [10234], "characters": "\u27FA" }, + "⟹": { "codepoints": [10233], "characters": "\u27F9" }, + "⇒": { "codepoints": [8658], "characters": "\u21D2" }, + "⊨": { "codepoints": [8872], "characters": "\u22A8" }, + "⇑": { "codepoints": [8657], "characters": "\u21D1" }, + "⇕": { "codepoints": [8661], "characters": "\u21D5" }, + "∥": { "codepoints": [8741], "characters": "\u2225" }, + "⤓": { "codepoints": [10515], "characters": "\u2913" }, + "↓": { "codepoints": [8595], "characters": "\u2193" }, + "↓": { "codepoints": [8595], "characters": "\u2193" }, + "⇓": { "codepoints": [8659], "characters": "\u21D3" }, + "⇵": { "codepoints": [8693], "characters": "\u21F5" }, + "̑": { "codepoints": [785], "characters": "\u0311" }, + "⇊": { "codepoints": [8650], "characters": "\u21CA" }, + "⇃": { "codepoints": [8643], "characters": "\u21C3" }, + "⇂": { "codepoints": [8642], "characters": "\u21C2" }, + "⥐": { "codepoints": [10576], "characters": "\u2950" }, + "⥞": { "codepoints": [10590], "characters": "\u295E" }, + "⥖": { "codepoints": [10582], "characters": "\u2956" }, + "↽": { "codepoints": [8637], "characters": "\u21BD" }, + "⥟": { "codepoints": [10591], "characters": "\u295F" }, + "⥗": { "codepoints": [10583], "characters": "\u2957" }, + "⇁": { "codepoints": [8641], "characters": "\u21C1" }, + "↧": { "codepoints": [8615], "characters": "\u21A7" }, + "⊤": { "codepoints": [8868], "characters": "\u22A4" }, + "⤐": { "codepoints": [10512], "characters": "\u2910" }, + "⌟": { "codepoints": [8991], "characters": "\u231F" }, + "⌌": { "codepoints": [8972], "characters": "\u230C" }, + "𝒟": { "codepoints": [119967], "characters": "\uD835\uDC9F" }, + "𝒹": { "codepoints": [119993], "characters": "\uD835\uDCB9" }, + "Ѕ": { "codepoints": [1029], "characters": "\u0405" }, + "ѕ": { "codepoints": [1109], "characters": "\u0455" }, + "⧶": { "codepoints": [10742], "characters": "\u29F6" }, + "Đ": { "codepoints": [272], "characters": "\u0110" }, + "đ": { "codepoints": [273], "characters": "\u0111" }, + "⋱": { "codepoints": [8945], "characters": "\u22F1" }, + "▿": { "codepoints": [9663], "characters": "\u25BF" }, + "▾": { "codepoints": [9662], "characters": "\u25BE" }, + "⇵": { "codepoints": [8693], "characters": "\u21F5" }, + "⥯": { "codepoints": [10607], "characters": "\u296F" }, + "⦦": { "codepoints": [10662], "characters": "\u29A6" }, + "Џ": { "codepoints": [1039], "characters": "\u040F" }, + "џ": { "codepoints": [1119], "characters": "\u045F" }, + "⟿": { "codepoints": [10239], "characters": "\u27FF" }, + "É": { "codepoints": [201], "characters": "\u00C9" }, + "É": { "codepoints": [201], "characters": "\u00C9" }, + "é": { "codepoints": [233], "characters": "\u00E9" }, + "é": { "codepoints": [233], "characters": "\u00E9" }, + "⩮": { "codepoints": [10862], "characters": "\u2A6E" }, + "Ě": { "codepoints": [282], "characters": "\u011A" }, + "ě": { "codepoints": [283], "characters": "\u011B" }, + "Ê": { "codepoints": [202], "characters": "\u00CA" }, + "Ê": { "codepoints": [202], "characters": "\u00CA" }, + "ê": { "codepoints": [234], "characters": "\u00EA" }, + "ê": { "codepoints": [234], "characters": "\u00EA" }, + "≖": { "codepoints": [8790], "characters": "\u2256" }, + "≕": { "codepoints": [8789], "characters": "\u2255" }, + "Э": { "codepoints": [1069], "characters": "\u042D" }, + "э": { "codepoints": [1101], "characters": "\u044D" }, + "⩷": { "codepoints": [10871], "characters": "\u2A77" }, + "Ė": { "codepoints": [278], "characters": "\u0116" }, + "ė": { "codepoints": [279], "characters": "\u0117" }, + "≑": { "codepoints": [8785], "characters": "\u2251" }, + "ⅇ": { "codepoints": [8519], "characters": "\u2147" }, + "≒": { "codepoints": [8786], "characters": "\u2252" }, + "𝔈": { "codepoints": [120072], "characters": "\uD835\uDD08" }, + "𝔢": { "codepoints": [120098], "characters": "\uD835\uDD22" }, + "⪚": { "codepoints": [10906], "characters": "\u2A9A" }, + "È": { "codepoints": [200], "characters": "\u00C8" }, + "È": { "codepoints": [200], "characters": "\u00C8" }, + "è": { "codepoints": [232], "characters": "\u00E8" }, + "è": { "codepoints": [232], "characters": "\u00E8" }, + "⪖": { "codepoints": [10902], "characters": "\u2A96" }, + "⪘": { "codepoints": [10904], "characters": "\u2A98" }, + "⪙": { "codepoints": [10905], "characters": "\u2A99" }, + "∈": { "codepoints": [8712], "characters": "\u2208" }, + "⏧": { "codepoints": [9191], "characters": "\u23E7" }, + "ℓ": { "codepoints": [8467], "characters": "\u2113" }, + "⪕": { "codepoints": [10901], "characters": "\u2A95" }, + "⪗": { "codepoints": [10903], "characters": "\u2A97" }, + "Ē": { "codepoints": [274], "characters": "\u0112" }, + "ē": { "codepoints": [275], "characters": "\u0113" }, + "∅": { "codepoints": [8709], "characters": "\u2205" }, + "∅": { "codepoints": [8709], "characters": "\u2205" }, + "◻": { "codepoints": [9723], "characters": "\u25FB" }, + "∅": { "codepoints": [8709], "characters": "\u2205" }, + "▫": { "codepoints": [9643], "characters": "\u25AB" }, + " ": { "codepoints": [8196], "characters": "\u2004" }, + " ": { "codepoints": [8197], "characters": "\u2005" }, + " ": { "codepoints": [8195], "characters": "\u2003" }, + "Ŋ": { "codepoints": [330], "characters": "\u014A" }, + "ŋ": { "codepoints": [331], "characters": "\u014B" }, + " ": { "codepoints": [8194], "characters": "\u2002" }, + "Ę": { "codepoints": [280], "characters": "\u0118" }, + "ę": { "codepoints": [281], "characters": "\u0119" }, + "𝔼": { "codepoints": [120124], "characters": "\uD835\uDD3C" }, + "𝕖": { "codepoints": [120150], "characters": "\uD835\uDD56" }, + "⋕": { "codepoints": [8917], "characters": "\u22D5" }, + "⧣": { "codepoints": [10723], "characters": "\u29E3" }, + "⩱": { "codepoints": [10865], "characters": "\u2A71" }, + "ε": { "codepoints": [949], "characters": "\u03B5" }, + "Ε": { "codepoints": [917], "characters": "\u0395" }, + "ε": { "codepoints": [949], "characters": "\u03B5" }, + "ϵ": { "codepoints": [1013], "characters": "\u03F5" }, + "≖": { "codepoints": [8790], "characters": "\u2256" }, + "≕": { "codepoints": [8789], "characters": "\u2255" }, + "≂": { "codepoints": [8770], "characters": "\u2242" }, + "⪖": { "codepoints": [10902], "characters": "\u2A96" }, + "⪕": { "codepoints": [10901], "characters": "\u2A95" }, + "⩵": { "codepoints": [10869], "characters": "\u2A75" }, + "=": { "codepoints": [61], "characters": "\u003D" }, + "≂": { "codepoints": [8770], "characters": "\u2242" }, + "≟": { "codepoints": [8799], "characters": "\u225F" }, + "⇌": { "codepoints": [8652], "characters": "\u21CC" }, + "≡": { "codepoints": [8801], "characters": "\u2261" }, + "⩸": { "codepoints": [10872], "characters": "\u2A78" }, + "⧥": { "codepoints": [10725], "characters": "\u29E5" }, + "⥱": { "codepoints": [10609], "characters": "\u2971" }, + "≓": { "codepoints": [8787], "characters": "\u2253" }, + "ℯ": { "codepoints": [8495], "characters": "\u212F" }, + "ℰ": { "codepoints": [8496], "characters": "\u2130" }, + "≐": { "codepoints": [8784], "characters": "\u2250" }, + "⩳": { "codepoints": [10867], "characters": "\u2A73" }, + "≂": { "codepoints": [8770], "characters": "\u2242" }, + "Η": { "codepoints": [919], "characters": "\u0397" }, + "η": { "codepoints": [951], "characters": "\u03B7" }, + "Ð": { "codepoints": [208], "characters": "\u00D0" }, + "Ð": { "codepoints": [208], "characters": "\u00D0" }, + "ð": { "codepoints": [240], "characters": "\u00F0" }, + "ð": { "codepoints": [240], "characters": "\u00F0" }, + "Ë": { "codepoints": [203], "characters": "\u00CB" }, + "Ë": { "codepoints": [203], "characters": "\u00CB" }, + "ë": { "codepoints": [235], "characters": "\u00EB" }, + "ë": { "codepoints": [235], "characters": "\u00EB" }, + "€": { "codepoints": [8364], "characters": "\u20AC" }, + "!": { "codepoints": [33], "characters": "\u0021" }, + "∃": { "codepoints": [8707], "characters": "\u2203" }, + "∃": { "codepoints": [8707], "characters": "\u2203" }, + "ℰ": { "codepoints": [8496], "characters": "\u2130" }, + "ⅇ": { "codepoints": [8519], "characters": "\u2147" }, + "ⅇ": { "codepoints": [8519], "characters": "\u2147" }, + "≒": { "codepoints": [8786], "characters": "\u2252" }, + "Ф": { "codepoints": [1060], "characters": "\u0424" }, + "ф": { "codepoints": [1092], "characters": "\u0444" }, + "♀": { "codepoints": [9792], "characters": "\u2640" }, + "ffi": { "codepoints": [64259], "characters": "\uFB03" }, + "ff": { "codepoints": [64256], "characters": "\uFB00" }, + "ffl": { "codepoints": [64260], "characters": "\uFB04" }, + "𝔉": { "codepoints": [120073], "characters": "\uD835\uDD09" }, + "𝔣": { "codepoints": [120099], "characters": "\uD835\uDD23" }, + "fi": { "codepoints": [64257], "characters": "\uFB01" }, + "◼": { "codepoints": [9724], "characters": "\u25FC" }, + "▪": { "codepoints": [9642], "characters": "\u25AA" }, + "fj": { "codepoints": [102, 106], "characters": "\u0066\u006A" }, + "♭": { "codepoints": [9837], "characters": "\u266D" }, + "fl": { "codepoints": [64258], "characters": "\uFB02" }, + "▱": { "codepoints": [9649], "characters": "\u25B1" }, + "ƒ": { "codepoints": [402], "characters": "\u0192" }, + "𝔽": { "codepoints": [120125], "characters": "\uD835\uDD3D" }, + "𝕗": { "codepoints": [120151], "characters": "\uD835\uDD57" }, + "∀": { "codepoints": [8704], "characters": "\u2200" }, + "∀": { "codepoints": [8704], "characters": "\u2200" }, + "⋔": { "codepoints": [8916], "characters": "\u22D4" }, + "⫙": { "codepoints": [10969], "characters": "\u2AD9" }, + "ℱ": { "codepoints": [8497], "characters": "\u2131" }, + "⨍": { "codepoints": [10765], "characters": "\u2A0D" }, + "½": { "codepoints": [189], "characters": "\u00BD" }, + "½": { "codepoints": [189], "characters": "\u00BD" }, + "⅓": { "codepoints": [8531], "characters": "\u2153" }, + "¼": { "codepoints": [188], "characters": "\u00BC" }, + "¼": { "codepoints": [188], "characters": "\u00BC" }, + "⅕": { "codepoints": [8533], "characters": "\u2155" }, + "⅙": { "codepoints": [8537], "characters": "\u2159" }, + "⅛": { "codepoints": [8539], "characters": "\u215B" }, + "⅔": { "codepoints": [8532], "characters": "\u2154" }, + "⅖": { "codepoints": [8534], "characters": "\u2156" }, + "¾": { "codepoints": [190], "characters": "\u00BE" }, + "¾": { "codepoints": [190], "characters": "\u00BE" }, + "⅗": { "codepoints": [8535], "characters": "\u2157" }, + "⅜": { "codepoints": [8540], "characters": "\u215C" }, + "⅘": { "codepoints": [8536], "characters": "\u2158" }, + "⅚": { "codepoints": [8538], "characters": "\u215A" }, + "⅝": { "codepoints": [8541], "characters": "\u215D" }, + "⅞": { "codepoints": [8542], "characters": "\u215E" }, + "⁄": { "codepoints": [8260], "characters": "\u2044" }, + "⌢": { "codepoints": [8994], "characters": "\u2322" }, + "𝒻": { "codepoints": [119995], "characters": "\uD835\uDCBB" }, + "ℱ": { "codepoints": [8497], "characters": "\u2131" }, + "ǵ": { "codepoints": [501], "characters": "\u01F5" }, + "Γ": { "codepoints": [915], "characters": "\u0393" }, + "γ": { "codepoints": [947], "characters": "\u03B3" }, + "Ϝ": { "codepoints": [988], "characters": "\u03DC" }, + "ϝ": { "codepoints": [989], "characters": "\u03DD" }, + "⪆": { "codepoints": [10886], "characters": "\u2A86" }, + "Ğ": { "codepoints": [286], "characters": "\u011E" }, + "ğ": { "codepoints": [287], "characters": "\u011F" }, + "Ģ": { "codepoints": [290], "characters": "\u0122" }, + "Ĝ": { "codepoints": [284], "characters": "\u011C" }, + "ĝ": { "codepoints": [285], "characters": "\u011D" }, + "Г": { "codepoints": [1043], "characters": "\u0413" }, + "г": { "codepoints": [1075], "characters": "\u0433" }, + "Ġ": { "codepoints": [288], "characters": "\u0120" }, + "ġ": { "codepoints": [289], "characters": "\u0121" }, + "≥": { "codepoints": [8805], "characters": "\u2265" }, + "≧": { "codepoints": [8807], "characters": "\u2267" }, + "⪌": { "codepoints": [10892], "characters": "\u2A8C" }, + "⋛": { "codepoints": [8923], "characters": "\u22DB" }, + "≥": { "codepoints": [8805], "characters": "\u2265" }, + "≧": { "codepoints": [8807], "characters": "\u2267" }, + "⩾": { "codepoints": [10878], "characters": "\u2A7E" }, + "⪩": { "codepoints": [10921], "characters": "\u2AA9" }, + "⩾": { "codepoints": [10878], "characters": "\u2A7E" }, + "⪀": { "codepoints": [10880], "characters": "\u2A80" }, + "⪂": { "codepoints": [10882], "characters": "\u2A82" }, + "⪄": { "codepoints": [10884], "characters": "\u2A84" }, + "⋛︀": { "codepoints": [8923, 65024], "characters": "\u22DB\uFE00" }, + "⪔": { "codepoints": [10900], "characters": "\u2A94" }, + "𝔊": { "codepoints": [120074], "characters": "\uD835\uDD0A" }, + "𝔤": { "codepoints": [120100], "characters": "\uD835\uDD24" }, + "≫": { "codepoints": [8811], "characters": "\u226B" }, + "⋙": { "codepoints": [8921], "characters": "\u22D9" }, + "⋙": { "codepoints": [8921], "characters": "\u22D9" }, + "ℷ": { "codepoints": [8503], "characters": "\u2137" }, + "Ѓ": { "codepoints": [1027], "characters": "\u0403" }, + "ѓ": { "codepoints": [1107], "characters": "\u0453" }, + "⪥": { "codepoints": [10917], "characters": "\u2AA5" }, + "≷": { "codepoints": [8823], "characters": "\u2277" }, + "⪒": { "codepoints": [10898], "characters": "\u2A92" }, + "⪤": { "codepoints": [10916], "characters": "\u2AA4" }, + "⪊": { "codepoints": [10890], "characters": "\u2A8A" }, + "⪊": { "codepoints": [10890], "characters": "\u2A8A" }, + "⪈": { "codepoints": [10888], "characters": "\u2A88" }, + "≩": { "codepoints": [8809], "characters": "\u2269" }, + "⪈": { "codepoints": [10888], "characters": "\u2A88" }, + "≩": { "codepoints": [8809], "characters": "\u2269" }, + "⋧": { "codepoints": [8935], "characters": "\u22E7" }, + "𝔾": { "codepoints": [120126], "characters": "\uD835\uDD3E" }, + "𝕘": { "codepoints": [120152], "characters": "\uD835\uDD58" }, + "`": { "codepoints": [96], "characters": "\u0060" }, + "≥": { "codepoints": [8805], "characters": "\u2265" }, + "⋛": { "codepoints": [8923], "characters": "\u22DB" }, + "≧": { "codepoints": [8807], "characters": "\u2267" }, + "⪢": { "codepoints": [10914], "characters": "\u2AA2" }, + "≷": { "codepoints": [8823], "characters": "\u2277" }, + "⩾": { "codepoints": [10878], "characters": "\u2A7E" }, + "≳": { "codepoints": [8819], "characters": "\u2273" }, + "𝒢": { "codepoints": [119970], "characters": "\uD835\uDCA2" }, + "ℊ": { "codepoints": [8458], "characters": "\u210A" }, + "≳": { "codepoints": [8819], "characters": "\u2273" }, + "⪎": { "codepoints": [10894], "characters": "\u2A8E" }, + "⪐": { "codepoints": [10896], "characters": "\u2A90" }, + "⪧": { "codepoints": [10919], "characters": "\u2AA7" }, + "⩺": { "codepoints": [10874], "characters": "\u2A7A" }, + ">": { "codepoints": [62], "characters": "\u003E" }, + ">": { "codepoints": [62], "characters": "\u003E" }, + ">": { "codepoints": [62], "characters": "\u003E" }, + ">": { "codepoints": [62], "characters": "\u003E" }, + "≫": { "codepoints": [8811], "characters": "\u226B" }, + "⋗": { "codepoints": [8919], "characters": "\u22D7" }, + "⦕": { "codepoints": [10645], "characters": "\u2995" }, + "⩼": { "codepoints": [10876], "characters": "\u2A7C" }, + "⪆": { "codepoints": [10886], "characters": "\u2A86" }, + "⥸": { "codepoints": [10616], "characters": "\u2978" }, + "⋗": { "codepoints": [8919], "characters": "\u22D7" }, + "⋛": { "codepoints": [8923], "characters": "\u22DB" }, + "⪌": { "codepoints": [10892], "characters": "\u2A8C" }, + "≷": { "codepoints": [8823], "characters": "\u2277" }, + "≳": { "codepoints": [8819], "characters": "\u2273" }, + "≩︀": { "codepoints": [8809, 65024], "characters": "\u2269\uFE00" }, + "≩︀": { "codepoints": [8809, 65024], "characters": "\u2269\uFE00" }, + "ˇ": { "codepoints": [711], "characters": "\u02C7" }, + " ": { "codepoints": [8202], "characters": "\u200A" }, + "½": { "codepoints": [189], "characters": "\u00BD" }, + "ℋ": { "codepoints": [8459], "characters": "\u210B" }, + "Ъ": { "codepoints": [1066], "characters": "\u042A" }, + "ъ": { "codepoints": [1098], "characters": "\u044A" }, + "⥈": { "codepoints": [10568], "characters": "\u2948" }, + "↔": { "codepoints": [8596], "characters": "\u2194" }, + "⇔": { "codepoints": [8660], "characters": "\u21D4" }, + "↭": { "codepoints": [8621], "characters": "\u21AD" }, + "^": { "codepoints": [94], "characters": "\u005E" }, + "ℏ": { "codepoints": [8463], "characters": "\u210F" }, + "Ĥ": { "codepoints": [292], "characters": "\u0124" }, + "ĥ": { "codepoints": [293], "characters": "\u0125" }, + "♥": { "codepoints": [9829], "characters": "\u2665" }, + "♥": { "codepoints": [9829], "characters": "\u2665" }, + "…": { "codepoints": [8230], "characters": "\u2026" }, + "⊹": { "codepoints": [8889], "characters": "\u22B9" }, + "𝔥": { "codepoints": [120101], "characters": "\uD835\uDD25" }, + "ℌ": { "codepoints": [8460], "characters": "\u210C" }, + "ℋ": { "codepoints": [8459], "characters": "\u210B" }, + "⤥": { "codepoints": [10533], "characters": "\u2925" }, + "⤦": { "codepoints": [10534], "characters": "\u2926" }, + "⇿": { "codepoints": [8703], "characters": "\u21FF" }, + "∻": { "codepoints": [8763], "characters": "\u223B" }, + "↩": { "codepoints": [8617], "characters": "\u21A9" }, + "↪": { "codepoints": [8618], "characters": "\u21AA" }, + "𝕙": { "codepoints": [120153], "characters": "\uD835\uDD59" }, + "ℍ": { "codepoints": [8461], "characters": "\u210D" }, + "―": { "codepoints": [8213], "characters": "\u2015" }, + "─": { "codepoints": [9472], "characters": "\u2500" }, + "𝒽": { "codepoints": [119997], "characters": "\uD835\uDCBD" }, + "ℋ": { "codepoints": [8459], "characters": "\u210B" }, + "ℏ": { "codepoints": [8463], "characters": "\u210F" }, + "Ħ": { "codepoints": [294], "characters": "\u0126" }, + "ħ": { "codepoints": [295], "characters": "\u0127" }, + "≎": { "codepoints": [8782], "characters": "\u224E" }, + "≏": { "codepoints": [8783], "characters": "\u224F" }, + "⁃": { "codepoints": [8259], "characters": "\u2043" }, + "‐": { "codepoints": [8208], "characters": "\u2010" }, + "Í": { "codepoints": [205], "characters": "\u00CD" }, + "Í": { "codepoints": [205], "characters": "\u00CD" }, + "í": { "codepoints": [237], "characters": "\u00ED" }, + "í": { "codepoints": [237], "characters": "\u00ED" }, + "⁣": { "codepoints": [8291], "characters": "\u2063" }, + "Î": { "codepoints": [206], "characters": "\u00CE" }, + "Î": { "codepoints": [206], "characters": "\u00CE" }, + "î": { "codepoints": [238], "characters": "\u00EE" }, + "î": { "codepoints": [238], "characters": "\u00EE" }, + "И": { "codepoints": [1048], "characters": "\u0418" }, + "и": { "codepoints": [1080], "characters": "\u0438" }, + "İ": { "codepoints": [304], "characters": "\u0130" }, + "Е": { "codepoints": [1045], "characters": "\u0415" }, + "е": { "codepoints": [1077], "characters": "\u0435" }, + "¡": { "codepoints": [161], "characters": "\u00A1" }, + "¡": { "codepoints": [161], "characters": "\u00A1" }, + "⇔": { "codepoints": [8660], "characters": "\u21D4" }, + "𝔦": { "codepoints": [120102], "characters": "\uD835\uDD26" }, + "ℑ": { "codepoints": [8465], "characters": "\u2111" }, + "Ì": { "codepoints": [204], "characters": "\u00CC" }, + "Ì": { "codepoints": [204], "characters": "\u00CC" }, + "ì": { "codepoints": [236], "characters": "\u00EC" }, + "ì": { "codepoints": [236], "characters": "\u00EC" }, + "ⅈ": { "codepoints": [8520], "characters": "\u2148" }, + "⨌": { "codepoints": [10764], "characters": "\u2A0C" }, + "∭": { "codepoints": [8749], "characters": "\u222D" }, + "⧜": { "codepoints": [10716], "characters": "\u29DC" }, + "℩": { "codepoints": [8489], "characters": "\u2129" }, + "IJ": { "codepoints": [306], "characters": "\u0132" }, + "ij": { "codepoints": [307], "characters": "\u0133" }, + "Ī": { "codepoints": [298], "characters": "\u012A" }, + "ī": { "codepoints": [299], "characters": "\u012B" }, + "ℑ": { "codepoints": [8465], "characters": "\u2111" }, + "ⅈ": { "codepoints": [8520], "characters": "\u2148" }, + "ℐ": { "codepoints": [8464], "characters": "\u2110" }, + "ℑ": { "codepoints": [8465], "characters": "\u2111" }, + "ı": { "codepoints": [305], "characters": "\u0131" }, + "ℑ": { "codepoints": [8465], "characters": "\u2111" }, + "⊷": { "codepoints": [8887], "characters": "\u22B7" }, + "Ƶ": { "codepoints": [437], "characters": "\u01B5" }, + "⇒": { "codepoints": [8658], "characters": "\u21D2" }, + "℅": { "codepoints": [8453], "characters": "\u2105" }, + "∈": { "codepoints": [8712], "characters": "\u2208" }, + "∞": { "codepoints": [8734], "characters": "\u221E" }, + "⧝": { "codepoints": [10717], "characters": "\u29DD" }, + "ı": { "codepoints": [305], "characters": "\u0131" }, + "⊺": { "codepoints": [8890], "characters": "\u22BA" }, + "∫": { "codepoints": [8747], "characters": "\u222B" }, + "∬": { "codepoints": [8748], "characters": "\u222C" }, + "ℤ": { "codepoints": [8484], "characters": "\u2124" }, + "∫": { "codepoints": [8747], "characters": "\u222B" }, + "⊺": { "codepoints": [8890], "characters": "\u22BA" }, + "⋂": { "codepoints": [8898], "characters": "\u22C2" }, + "⨗": { "codepoints": [10775], "characters": "\u2A17" }, + "⨼": { "codepoints": [10812], "characters": "\u2A3C" }, + "⁣": { "codepoints": [8291], "characters": "\u2063" }, + "⁢": { "codepoints": [8290], "characters": "\u2062" }, + "Ё": { "codepoints": [1025], "characters": "\u0401" }, + "ё": { "codepoints": [1105], "characters": "\u0451" }, + "Į": { "codepoints": [302], "characters": "\u012E" }, + "į": { "codepoints": [303], "characters": "\u012F" }, + "𝕀": { "codepoints": [120128], "characters": "\uD835\uDD40" }, + "𝕚": { "codepoints": [120154], "characters": "\uD835\uDD5A" }, + "Ι": { "codepoints": [921], "characters": "\u0399" }, + "ι": { "codepoints": [953], "characters": "\u03B9" }, + "⨼": { "codepoints": [10812], "characters": "\u2A3C" }, + "¿": { "codepoints": [191], "characters": "\u00BF" }, + "¿": { "codepoints": [191], "characters": "\u00BF" }, + "𝒾": { "codepoints": [119998], "characters": "\uD835\uDCBE" }, + "ℐ": { "codepoints": [8464], "characters": "\u2110" }, + "∈": { "codepoints": [8712], "characters": "\u2208" }, + "⋵": { "codepoints": [8949], "characters": "\u22F5" }, + "⋹": { "codepoints": [8953], "characters": "\u22F9" }, + "⋴": { "codepoints": [8948], "characters": "\u22F4" }, + "⋳": { "codepoints": [8947], "characters": "\u22F3" }, + "∈": { "codepoints": [8712], "characters": "\u2208" }, + "⁢": { "codepoints": [8290], "characters": "\u2062" }, + "Ĩ": { "codepoints": [296], "characters": "\u0128" }, + "ĩ": { "codepoints": [297], "characters": "\u0129" }, + "І": { "codepoints": [1030], "characters": "\u0406" }, + "і": { "codepoints": [1110], "characters": "\u0456" }, + "Ï": { "codepoints": [207], "characters": "\u00CF" }, + "Ï": { "codepoints": [207], "characters": "\u00CF" }, + "ï": { "codepoints": [239], "characters": "\u00EF" }, + "ï": { "codepoints": [239], "characters": "\u00EF" }, + "Ĵ": { "codepoints": [308], "characters": "\u0134" }, + "ĵ": { "codepoints": [309], "characters": "\u0135" }, + "Й": { "codepoints": [1049], "characters": "\u0419" }, + "й": { "codepoints": [1081], "characters": "\u0439" }, + "𝔍": { "codepoints": [120077], "characters": "\uD835\uDD0D" }, + "𝔧": { "codepoints": [120103], "characters": "\uD835\uDD27" }, + "ȷ": { "codepoints": [567], "characters": "\u0237" }, + "𝕁": { "codepoints": [120129], "characters": "\uD835\uDD41" }, + "𝕛": { "codepoints": [120155], "characters": "\uD835\uDD5B" }, + "𝒥": { "codepoints": [119973], "characters": "\uD835\uDCA5" }, + "𝒿": { "codepoints": [119999], "characters": "\uD835\uDCBF" }, + "Ј": { "codepoints": [1032], "characters": "\u0408" }, + "ј": { "codepoints": [1112], "characters": "\u0458" }, + "Є": { "codepoints": [1028], "characters": "\u0404" }, + "є": { "codepoints": [1108], "characters": "\u0454" }, + "Κ": { "codepoints": [922], "characters": "\u039A" }, + "κ": { "codepoints": [954], "characters": "\u03BA" }, + "ϰ": { "codepoints": [1008], "characters": "\u03F0" }, + "Ķ": { "codepoints": [310], "characters": "\u0136" }, + "ķ": { "codepoints": [311], "characters": "\u0137" }, + "К": { "codepoints": [1050], "characters": "\u041A" }, + "к": { "codepoints": [1082], "characters": "\u043A" }, + "𝔎": { "codepoints": [120078], "characters": "\uD835\uDD0E" }, + "𝔨": { "codepoints": [120104], "characters": "\uD835\uDD28" }, + "ĸ": { "codepoints": [312], "characters": "\u0138" }, + "Х": { "codepoints": [1061], "characters": "\u0425" }, + "х": { "codepoints": [1093], "characters": "\u0445" }, + "Ќ": { "codepoints": [1036], "characters": "\u040C" }, + "ќ": { "codepoints": [1116], "characters": "\u045C" }, + "𝕂": { "codepoints": [120130], "characters": "\uD835\uDD42" }, + "𝕜": { "codepoints": [120156], "characters": "\uD835\uDD5C" }, + "𝒦": { "codepoints": [119974], "characters": "\uD835\uDCA6" }, + "𝓀": { "codepoints": [120000], "characters": "\uD835\uDCC0" }, + "⇚": { "codepoints": [8666], "characters": "\u21DA" }, + "Ĺ": { "codepoints": [313], "characters": "\u0139" }, + "ĺ": { "codepoints": [314], "characters": "\u013A" }, + "⦴": { "codepoints": [10676], "characters": "\u29B4" }, + "ℒ": { "codepoints": [8466], "characters": "\u2112" }, + "Λ": { "codepoints": [923], "characters": "\u039B" }, + "λ": { "codepoints": [955], "characters": "\u03BB" }, + "⟨": { "codepoints": [10216], "characters": "\u27E8" }, + "⟪": { "codepoints": [10218], "characters": "\u27EA" }, + "⦑": { "codepoints": [10641], "characters": "\u2991" }, + "⟨": { "codepoints": [10216], "characters": "\u27E8" }, + "⪅": { "codepoints": [10885], "characters": "\u2A85" }, + "ℒ": { "codepoints": [8466], "characters": "\u2112" }, + "«": { "codepoints": [171], "characters": "\u00AB" }, + "«": { "codepoints": [171], "characters": "\u00AB" }, + "⇤": { "codepoints": [8676], "characters": "\u21E4" }, + "⤟": { "codepoints": [10527], "characters": "\u291F" }, + "←": { "codepoints": [8592], "characters": "\u2190" }, + "↞": { "codepoints": [8606], "characters": "\u219E" }, + "⇐": { "codepoints": [8656], "characters": "\u21D0" }, + "⤝": { "codepoints": [10525], "characters": "\u291D" }, + "↩": { "codepoints": [8617], "characters": "\u21A9" }, + "↫": { "codepoints": [8619], "characters": "\u21AB" }, + "⤹": { "codepoints": [10553], "characters": "\u2939" }, + "⥳": { "codepoints": [10611], "characters": "\u2973" }, + "↢": { "codepoints": [8610], "characters": "\u21A2" }, + "⤙": { "codepoints": [10521], "characters": "\u2919" }, + "⤛": { "codepoints": [10523], "characters": "\u291B" }, + "⪫": { "codepoints": [10923], "characters": "\u2AAB" }, + "⪭": { "codepoints": [10925], "characters": "\u2AAD" }, + "⪭︀": { "codepoints": [10925, 65024], "characters": "\u2AAD\uFE00" }, + "⤌": { "codepoints": [10508], "characters": "\u290C" }, + "⤎": { "codepoints": [10510], "characters": "\u290E" }, + "❲": { "codepoints": [10098], "characters": "\u2772" }, + "{": { "codepoints": [123], "characters": "\u007B" }, + "[": { "codepoints": [91], "characters": "\u005B" }, + "⦋": { "codepoints": [10635], "characters": "\u298B" }, + "⦏": { "codepoints": [10639], "characters": "\u298F" }, + "⦍": { "codepoints": [10637], "characters": "\u298D" }, + "Ľ": { "codepoints": [317], "characters": "\u013D" }, + "ľ": { "codepoints": [318], "characters": "\u013E" }, + "Ļ": { "codepoints": [315], "characters": "\u013B" }, + "ļ": { "codepoints": [316], "characters": "\u013C" }, + "⌈": { "codepoints": [8968], "characters": "\u2308" }, + "{": { "codepoints": [123], "characters": "\u007B" }, + "Л": { "codepoints": [1051], "characters": "\u041B" }, + "л": { "codepoints": [1083], "characters": "\u043B" }, + "⤶": { "codepoints": [10550], "characters": "\u2936" }, + "“": { "codepoints": [8220], "characters": "\u201C" }, + "„": { "codepoints": [8222], "characters": "\u201E" }, + "⥧": { "codepoints": [10599], "characters": "\u2967" }, + "⥋": { "codepoints": [10571], "characters": "\u294B" }, + "↲": { "codepoints": [8626], "characters": "\u21B2" }, + "≤": { "codepoints": [8804], "characters": "\u2264" }, + "≦": { "codepoints": [8806], "characters": "\u2266" }, + "⟨": { "codepoints": [10216], "characters": "\u27E8" }, + "⇤": { "codepoints": [8676], "characters": "\u21E4" }, + "←": { "codepoints": [8592], "characters": "\u2190" }, + "←": { "codepoints": [8592], "characters": "\u2190" }, + "⇐": { "codepoints": [8656], "characters": "\u21D0" }, + "⇆": { "codepoints": [8646], "characters": "\u21C6" }, + "↢": { "codepoints": [8610], "characters": "\u21A2" }, + "⌈": { "codepoints": [8968], "characters": "\u2308" }, + "⟦": { "codepoints": [10214], "characters": "\u27E6" }, + "⥡": { "codepoints": [10593], "characters": "\u2961" }, + "⥙": { "codepoints": [10585], "characters": "\u2959" }, + "⇃": { "codepoints": [8643], "characters": "\u21C3" }, + "⌊": { "codepoints": [8970], "characters": "\u230A" }, + "↽": { "codepoints": [8637], "characters": "\u21BD" }, + "↼": { "codepoints": [8636], "characters": "\u21BC" }, + "⇇": { "codepoints": [8647], "characters": "\u21C7" }, + "↔": { "codepoints": [8596], "characters": "\u2194" }, + "↔": { "codepoints": [8596], "characters": "\u2194" }, + "⇔": { "codepoints": [8660], "characters": "\u21D4" }, + "⇆": { "codepoints": [8646], "characters": "\u21C6" }, + "⇋": { "codepoints": [8651], "characters": "\u21CB" }, + "↭": { "codepoints": [8621], "characters": "\u21AD" }, + "⥎": { "codepoints": [10574], "characters": "\u294E" }, + "↤": { "codepoints": [8612], "characters": "\u21A4" }, + "⊣": { "codepoints": [8867], "characters": "\u22A3" }, + "⥚": { "codepoints": [10586], "characters": "\u295A" }, + "⋋": { "codepoints": [8907], "characters": "\u22CB" }, + "⧏": { "codepoints": [10703], "characters": "\u29CF" }, + "⊲": { "codepoints": [8882], "characters": "\u22B2" }, + "⊴": { "codepoints": [8884], "characters": "\u22B4" }, + "⥑": { "codepoints": [10577], "characters": "\u2951" }, + "⥠": { "codepoints": [10592], "characters": "\u2960" }, + "⥘": { "codepoints": [10584], "characters": "\u2958" }, + "↿": { "codepoints": [8639], "characters": "\u21BF" }, + "⥒": { "codepoints": [10578], "characters": "\u2952" }, + "↼": { "codepoints": [8636], "characters": "\u21BC" }, + "⪋": { "codepoints": [10891], "characters": "\u2A8B" }, + "⋚": { "codepoints": [8922], "characters": "\u22DA" }, + "≤": { "codepoints": [8804], "characters": "\u2264" }, + "≦": { "codepoints": [8806], "characters": "\u2266" }, + "⩽": { "codepoints": [10877], "characters": "\u2A7D" }, + "⪨": { "codepoints": [10920], "characters": "\u2AA8" }, + "⩽": { "codepoints": [10877], "characters": "\u2A7D" }, + "⩿": { "codepoints": [10879], "characters": "\u2A7F" }, + "⪁": { "codepoints": [10881], "characters": "\u2A81" }, + "⪃": { "codepoints": [10883], "characters": "\u2A83" }, + "⋚︀": { "codepoints": [8922, 65024], "characters": "\u22DA\uFE00" }, + "⪓": { "codepoints": [10899], "characters": "\u2A93" }, + "⪅": { "codepoints": [10885], "characters": "\u2A85" }, + "⋖": { "codepoints": [8918], "characters": "\u22D6" }, + "⋚": { "codepoints": [8922], "characters": "\u22DA" }, + "⪋": { "codepoints": [10891], "characters": "\u2A8B" }, + "⋚": { "codepoints": [8922], "characters": "\u22DA" }, + "≦": { "codepoints": [8806], "characters": "\u2266" }, + "≶": { "codepoints": [8822], "characters": "\u2276" }, + "≶": { "codepoints": [8822], "characters": "\u2276" }, + "⪡": { "codepoints": [10913], "characters": "\u2AA1" }, + "≲": { "codepoints": [8818], "characters": "\u2272" }, + "⩽": { "codepoints": [10877], "characters": "\u2A7D" }, + "≲": { "codepoints": [8818], "characters": "\u2272" }, + "⥼": { "codepoints": [10620], "characters": "\u297C" }, + "⌊": { "codepoints": [8970], "characters": "\u230A" }, + "𝔏": { "codepoints": [120079], "characters": "\uD835\uDD0F" }, + "𝔩": { "codepoints": [120105], "characters": "\uD835\uDD29" }, + "≶": { "codepoints": [8822], "characters": "\u2276" }, + "⪑": { "codepoints": [10897], "characters": "\u2A91" }, + "⥢": { "codepoints": [10594], "characters": "\u2962" }, + "↽": { "codepoints": [8637], "characters": "\u21BD" }, + "↼": { "codepoints": [8636], "characters": "\u21BC" }, + "⥪": { "codepoints": [10602], "characters": "\u296A" }, + "▄": { "codepoints": [9604], "characters": "\u2584" }, + "Љ": { "codepoints": [1033], "characters": "\u0409" }, + "љ": { "codepoints": [1113], "characters": "\u0459" }, + "⇇": { "codepoints": [8647], "characters": "\u21C7" }, + "≪": { "codepoints": [8810], "characters": "\u226A" }, + "⋘": { "codepoints": [8920], "characters": "\u22D8" }, + "⌞": { "codepoints": [8990], "characters": "\u231E" }, + "⇚": { "codepoints": [8666], "characters": "\u21DA" }, + "⥫": { "codepoints": [10603], "characters": "\u296B" }, + "◺": { "codepoints": [9722], "characters": "\u25FA" }, + "Ŀ": { "codepoints": [319], "characters": "\u013F" }, + "ŀ": { "codepoints": [320], "characters": "\u0140" }, + "⎰": { "codepoints": [9136], "characters": "\u23B0" }, + "⎰": { "codepoints": [9136], "characters": "\u23B0" }, + "⪉": { "codepoints": [10889], "characters": "\u2A89" }, + "⪉": { "codepoints": [10889], "characters": "\u2A89" }, + "⪇": { "codepoints": [10887], "characters": "\u2A87" }, + "≨": { "codepoints": [8808], "characters": "\u2268" }, + "⪇": { "codepoints": [10887], "characters": "\u2A87" }, + "≨": { "codepoints": [8808], "characters": "\u2268" }, + "⋦": { "codepoints": [8934], "characters": "\u22E6" }, + "⟬": { "codepoints": [10220], "characters": "\u27EC" }, + "⇽": { "codepoints": [8701], "characters": "\u21FD" }, + "⟦": { "codepoints": [10214], "characters": "\u27E6" }, + "⟵": { "codepoints": [10229], "characters": "\u27F5" }, + "⟵": { "codepoints": [10229], "characters": "\u27F5" }, + "⟸": { "codepoints": [10232], "characters": "\u27F8" }, + "⟷": { "codepoints": [10231], "characters": "\u27F7" }, + "⟷": { "codepoints": [10231], "characters": "\u27F7" }, + "⟺": { "codepoints": [10234], "characters": "\u27FA" }, + "⟼": { "codepoints": [10236], "characters": "\u27FC" }, + "⟶": { "codepoints": [10230], "characters": "\u27F6" }, + "⟶": { "codepoints": [10230], "characters": "\u27F6" }, + "⟹": { "codepoints": [10233], "characters": "\u27F9" }, + "↫": { "codepoints": [8619], "characters": "\u21AB" }, + "↬": { "codepoints": [8620], "characters": "\u21AC" }, + "⦅": { "codepoints": [10629], "characters": "\u2985" }, + "𝕃": { "codepoints": [120131], "characters": "\uD835\uDD43" }, + "𝕝": { "codepoints": [120157], "characters": "\uD835\uDD5D" }, + "⨭": { "codepoints": [10797], "characters": "\u2A2D" }, + "⨴": { "codepoints": [10804], "characters": "\u2A34" }, + "∗": { "codepoints": [8727], "characters": "\u2217" }, + "_": { "codepoints": [95], "characters": "\u005F" }, + "↙": { "codepoints": [8601], "characters": "\u2199" }, + "↘": { "codepoints": [8600], "characters": "\u2198" }, + "◊": { "codepoints": [9674], "characters": "\u25CA" }, + "◊": { "codepoints": [9674], "characters": "\u25CA" }, + "⧫": { "codepoints": [10731], "characters": "\u29EB" }, + "(": { "codepoints": [40], "characters": "\u0028" }, + "⦓": { "codepoints": [10643], "characters": "\u2993" }, + "⇆": { "codepoints": [8646], "characters": "\u21C6" }, + "⌟": { "codepoints": [8991], "characters": "\u231F" }, + "⇋": { "codepoints": [8651], "characters": "\u21CB" }, + "⥭": { "codepoints": [10605], "characters": "\u296D" }, + "‎": { "codepoints": [8206], "characters": "\u200E" }, + "⊿": { "codepoints": [8895], "characters": "\u22BF" }, + "‹": { "codepoints": [8249], "characters": "\u2039" }, + "𝓁": { "codepoints": [120001], "characters": "\uD835\uDCC1" }, + "ℒ": { "codepoints": [8466], "characters": "\u2112" }, + "↰": { "codepoints": [8624], "characters": "\u21B0" }, + "↰": { "codepoints": [8624], "characters": "\u21B0" }, + "≲": { "codepoints": [8818], "characters": "\u2272" }, + "⪍": { "codepoints": [10893], "characters": "\u2A8D" }, + "⪏": { "codepoints": [10895], "characters": "\u2A8F" }, + "[": { "codepoints": [91], "characters": "\u005B" }, + "‘": { "codepoints": [8216], "characters": "\u2018" }, + "‚": { "codepoints": [8218], "characters": "\u201A" }, + "Ł": { "codepoints": [321], "characters": "\u0141" }, + "ł": { "codepoints": [322], "characters": "\u0142" }, + "⪦": { "codepoints": [10918], "characters": "\u2AA6" }, + "⩹": { "codepoints": [10873], "characters": "\u2A79" }, + "<": { "codepoints": [60], "characters": "\u003C" }, + "<": { "codepoints": [60], "characters": "\u003C" }, + "<": { "codepoints": [60], "characters": "\u003C" }, + "<": { "codepoints": [60], "characters": "\u003C" }, + "≪": { "codepoints": [8810], "characters": "\u226A" }, + "⋖": { "codepoints": [8918], "characters": "\u22D6" }, + "⋋": { "codepoints": [8907], "characters": "\u22CB" }, + "⋉": { "codepoints": [8905], "characters": "\u22C9" }, + "⥶": { "codepoints": [10614], "characters": "\u2976" }, + "⩻": { "codepoints": [10875], "characters": "\u2A7B" }, + "◃": { "codepoints": [9667], "characters": "\u25C3" }, + "⊴": { "codepoints": [8884], "characters": "\u22B4" }, + "◂": { "codepoints": [9666], "characters": "\u25C2" }, + "⦖": { "codepoints": [10646], "characters": "\u2996" }, + "⥊": { "codepoints": [10570], "characters": "\u294A" }, + "⥦": { "codepoints": [10598], "characters": "\u2966" }, + "≨︀": { "codepoints": [8808, 65024], "characters": "\u2268\uFE00" }, + "≨︀": { "codepoints": [8808, 65024], "characters": "\u2268\uFE00" }, + "¯": { "codepoints": [175], "characters": "\u00AF" }, + "¯": { "codepoints": [175], "characters": "\u00AF" }, + "♂": { "codepoints": [9794], "characters": "\u2642" }, + "✠": { "codepoints": [10016], "characters": "\u2720" }, + "✠": { "codepoints": [10016], "characters": "\u2720" }, + "⤅": { "codepoints": [10501], "characters": "\u2905" }, + "↦": { "codepoints": [8614], "characters": "\u21A6" }, + "↦": { "codepoints": [8614], "characters": "\u21A6" }, + "↧": { "codepoints": [8615], "characters": "\u21A7" }, + "↤": { "codepoints": [8612], "characters": "\u21A4" }, + "↥": { "codepoints": [8613], "characters": "\u21A5" }, + "▮": { "codepoints": [9646], "characters": "\u25AE" }, + "⨩": { "codepoints": [10793], "characters": "\u2A29" }, + "М": { "codepoints": [1052], "characters": "\u041C" }, + "м": { "codepoints": [1084], "characters": "\u043C" }, + "—": { "codepoints": [8212], "characters": "\u2014" }, + "∺": { "codepoints": [8762], "characters": "\u223A" }, + "∡": { "codepoints": [8737], "characters": "\u2221" }, + " ": { "codepoints": [8287], "characters": "\u205F" }, + "ℳ": { "codepoints": [8499], "characters": "\u2133" }, + "𝔐": { "codepoints": [120080], "characters": "\uD835\uDD10" }, + "𝔪": { "codepoints": [120106], "characters": "\uD835\uDD2A" }, + "℧": { "codepoints": [8487], "characters": "\u2127" }, + "µ": { "codepoints": [181], "characters": "\u00B5" }, + "µ": { "codepoints": [181], "characters": "\u00B5" }, + "*": { "codepoints": [42], "characters": "\u002A" }, + "⫰": { "codepoints": [10992], "characters": "\u2AF0" }, + "∣": { "codepoints": [8739], "characters": "\u2223" }, + "·": { "codepoints": [183], "characters": "\u00B7" }, + "·": { "codepoints": [183], "characters": "\u00B7" }, + "⊟": { "codepoints": [8863], "characters": "\u229F" }, + "−": { "codepoints": [8722], "characters": "\u2212" }, + "∸": { "codepoints": [8760], "characters": "\u2238" }, + "⨪": { "codepoints": [10794], "characters": "\u2A2A" }, + "∓": { "codepoints": [8723], "characters": "\u2213" }, + "⫛": { "codepoints": [10971], "characters": "\u2ADB" }, + "…": { "codepoints": [8230], "characters": "\u2026" }, + "∓": { "codepoints": [8723], "characters": "\u2213" }, + "⊧": { "codepoints": [8871], "characters": "\u22A7" }, + "𝕄": { "codepoints": [120132], "characters": "\uD835\uDD44" }, + "𝕞": { "codepoints": [120158], "characters": "\uD835\uDD5E" }, + "∓": { "codepoints": [8723], "characters": "\u2213" }, + "𝓂": { "codepoints": [120002], "characters": "\uD835\uDCC2" }, + "ℳ": { "codepoints": [8499], "characters": "\u2133" }, + "∾": { "codepoints": [8766], "characters": "\u223E" }, + "Μ": { "codepoints": [924], "characters": "\u039C" }, + "μ": { "codepoints": [956], "characters": "\u03BC" }, + "⊸": { "codepoints": [8888], "characters": "\u22B8" }, + "⊸": { "codepoints": [8888], "characters": "\u22B8" }, + "∇": { "codepoints": [8711], "characters": "\u2207" }, + "Ń": { "codepoints": [323], "characters": "\u0143" }, + "ń": { "codepoints": [324], "characters": "\u0144" }, + "∠⃒": { "codepoints": [8736, 8402], "characters": "\u2220\u20D2" }, + "≉": { "codepoints": [8777], "characters": "\u2249" }, + "⩰̸": { "codepoints": [10864, 824], "characters": "\u2A70\u0338" }, + "≋̸": { "codepoints": [8779, 824], "characters": "\u224B\u0338" }, + "ʼn": { "codepoints": [329], "characters": "\u0149" }, + "≉": { "codepoints": [8777], "characters": "\u2249" }, + "♮": { "codepoints": [9838], "characters": "\u266E" }, + "ℕ": { "codepoints": [8469], "characters": "\u2115" }, + "♮": { "codepoints": [9838], "characters": "\u266E" }, + " ": { "codepoints": [160], "characters": "\u00A0" }, + " ": { "codepoints": [160], "characters": "\u00A0" }, + "≎̸": { "codepoints": [8782, 824], "characters": "\u224E\u0338" }, + "≏̸": { "codepoints": [8783, 824], "characters": "\u224F\u0338" }, + "⩃": { "codepoints": [10819], "characters": "\u2A43" }, + "Ň": { "codepoints": [327], "characters": "\u0147" }, + "ň": { "codepoints": [328], "characters": "\u0148" }, + "Ņ": { "codepoints": [325], "characters": "\u0145" }, + "ņ": { "codepoints": [326], "characters": "\u0146" }, + "≇": { "codepoints": [8775], "characters": "\u2247" }, + "⩭̸": { "codepoints": [10861, 824], "characters": "\u2A6D\u0338" }, + "⩂": { "codepoints": [10818], "characters": "\u2A42" }, + "Н": { "codepoints": [1053], "characters": "\u041D" }, + "н": { "codepoints": [1085], "characters": "\u043D" }, + "–": { "codepoints": [8211], "characters": "\u2013" }, + "⤤": { "codepoints": [10532], "characters": "\u2924" }, + "↗": { "codepoints": [8599], "characters": "\u2197" }, + "⇗": { "codepoints": [8663], "characters": "\u21D7" }, + "↗": { "codepoints": [8599], "characters": "\u2197" }, + "≠": { "codepoints": [8800], "characters": "\u2260" }, + "≐̸": { "codepoints": [8784, 824], "characters": "\u2250\u0338" }, + "​": { "codepoints": [8203], "characters": "\u200B" }, + "​": { "codepoints": [8203], "characters": "\u200B" }, + "​": { "codepoints": [8203], "characters": "\u200B" }, + "​": { "codepoints": [8203], "characters": "\u200B" }, + "≢": { "codepoints": [8802], "characters": "\u2262" }, + "⤨": { "codepoints": [10536], "characters": "\u2928" }, + "≂̸": { "codepoints": [8770, 824], "characters": "\u2242\u0338" }, + "≫": { "codepoints": [8811], "characters": "\u226B" }, + "≪": { "codepoints": [8810], "characters": "\u226A" }, + "
": { "codepoints": [10], "characters": "\u000A" }, + "∄": { "codepoints": [8708], "characters": "\u2204" }, + "∄": { "codepoints": [8708], "characters": "\u2204" }, + "𝔑": { "codepoints": [120081], "characters": "\uD835\uDD11" }, + "𝔫": { "codepoints": [120107], "characters": "\uD835\uDD2B" }, + "≧̸": { "codepoints": [8807, 824], "characters": "\u2267\u0338" }, + "≱": { "codepoints": [8817], "characters": "\u2271" }, + "≱": { "codepoints": [8817], "characters": "\u2271" }, + "≧̸": { "codepoints": [8807, 824], "characters": "\u2267\u0338" }, + "⩾̸": { "codepoints": [10878, 824], "characters": "\u2A7E\u0338" }, + "⩾̸": { "codepoints": [10878, 824], "characters": "\u2A7E\u0338" }, + "⋙̸": { "codepoints": [8921, 824], "characters": "\u22D9\u0338" }, + "≵": { "codepoints": [8821], "characters": "\u2275" }, + "≫⃒": { "codepoints": [8811, 8402], "characters": "\u226B\u20D2" }, + "≯": { "codepoints": [8815], "characters": "\u226F" }, + "≯": { "codepoints": [8815], "characters": "\u226F" }, + "≫̸": { "codepoints": [8811, 824], "characters": "\u226B\u0338" }, + "↮": { "codepoints": [8622], "characters": "\u21AE" }, + "⇎": { "codepoints": [8654], "characters": "\u21CE" }, + "⫲": { "codepoints": [10994], "characters": "\u2AF2" }, + "∋": { "codepoints": [8715], "characters": "\u220B" }, + "⋼": { "codepoints": [8956], "characters": "\u22FC" }, + "⋺": { "codepoints": [8954], "characters": "\u22FA" }, + "∋": { "codepoints": [8715], "characters": "\u220B" }, + "Њ": { "codepoints": [1034], "characters": "\u040A" }, + "њ": { "codepoints": [1114], "characters": "\u045A" }, + "↚": { "codepoints": [8602], "characters": "\u219A" }, + "⇍": { "codepoints": [8653], "characters": "\u21CD" }, + "‥": { "codepoints": [8229], "characters": "\u2025" }, + "≦̸": { "codepoints": [8806, 824], "characters": "\u2266\u0338" }, + "≰": { "codepoints": [8816], "characters": "\u2270" }, + "↚": { "codepoints": [8602], "characters": "\u219A" }, + "⇍": { "codepoints": [8653], "characters": "\u21CD" }, + "↮": { "codepoints": [8622], "characters": "\u21AE" }, + "⇎": { "codepoints": [8654], "characters": "\u21CE" }, + "≰": { "codepoints": [8816], "characters": "\u2270" }, + "≦̸": { "codepoints": [8806, 824], "characters": "\u2266\u0338" }, + "⩽̸": { "codepoints": [10877, 824], "characters": "\u2A7D\u0338" }, + "⩽̸": { "codepoints": [10877, 824], "characters": "\u2A7D\u0338" }, + "≮": { "codepoints": [8814], "characters": "\u226E" }, + "⋘̸": { "codepoints": [8920, 824], "characters": "\u22D8\u0338" }, + "≴": { "codepoints": [8820], "characters": "\u2274" }, + "≪⃒": { "codepoints": [8810, 8402], "characters": "\u226A\u20D2" }, + "≮": { "codepoints": [8814], "characters": "\u226E" }, + "⋪": { "codepoints": [8938], "characters": "\u22EA" }, + "⋬": { "codepoints": [8940], "characters": "\u22EC" }, + "≪̸": { "codepoints": [8810, 824], "characters": "\u226A\u0338" }, + "∤": { "codepoints": [8740], "characters": "\u2224" }, + "⁠": { "codepoints": [8288], "characters": "\u2060" }, + " ": { "codepoints": [160], "characters": "\u00A0" }, + "𝕟": { "codepoints": [120159], "characters": "\uD835\uDD5F" }, + "ℕ": { "codepoints": [8469], "characters": "\u2115" }, + "⫬": { "codepoints": [10988], "characters": "\u2AEC" }, + "¬": { "codepoints": [172], "characters": "\u00AC" }, + "¬": { "codepoints": [172], "characters": "\u00AC" }, + "≢": { "codepoints": [8802], "characters": "\u2262" }, + "≭": { "codepoints": [8813], "characters": "\u226D" }, + "∦": { "codepoints": [8742], "characters": "\u2226" }, + "∉": { "codepoints": [8713], "characters": "\u2209" }, + "≠": { "codepoints": [8800], "characters": "\u2260" }, + "≂̸": { "codepoints": [8770, 824], "characters": "\u2242\u0338" }, + "∄": { "codepoints": [8708], "characters": "\u2204" }, + "≯": { "codepoints": [8815], "characters": "\u226F" }, + "≱": { "codepoints": [8817], "characters": "\u2271" }, + "≧̸": { "codepoints": [8807, 824], "characters": "\u2267\u0338" }, + "≫̸": { "codepoints": [8811, 824], "characters": "\u226B\u0338" }, + "≹": { "codepoints": [8825], "characters": "\u2279" }, + "⩾̸": { "codepoints": [10878, 824], "characters": "\u2A7E\u0338" }, + "≵": { "codepoints": [8821], "characters": "\u2275" }, + "≎̸": { "codepoints": [8782, 824], "characters": "\u224E\u0338" }, + "≏̸": { "codepoints": [8783, 824], "characters": "\u224F\u0338" }, + "∉": { "codepoints": [8713], "characters": "\u2209" }, + "⋵̸": { "codepoints": [8949, 824], "characters": "\u22F5\u0338" }, + "⋹̸": { "codepoints": [8953, 824], "characters": "\u22F9\u0338" }, + "∉": { "codepoints": [8713], "characters": "\u2209" }, + "⋷": { "codepoints": [8951], "characters": "\u22F7" }, + "⋶": { "codepoints": [8950], "characters": "\u22F6" }, + "⧏̸": { "codepoints": [10703, 824], "characters": "\u29CF\u0338" }, + "⋪": { "codepoints": [8938], "characters": "\u22EA" }, + "⋬": { "codepoints": [8940], "characters": "\u22EC" }, + "≮": { "codepoints": [8814], "characters": "\u226E" }, + "≰": { "codepoints": [8816], "characters": "\u2270" }, + "≸": { "codepoints": [8824], "characters": "\u2278" }, + "≪̸": { "codepoints": [8810, 824], "characters": "\u226A\u0338" }, + "⩽̸": { "codepoints": [10877, 824], "characters": "\u2A7D\u0338" }, + "≴": { "codepoints": [8820], "characters": "\u2274" }, + "⪢̸": { "codepoints": [10914, 824], "characters": "\u2AA2\u0338" }, + "⪡̸": { "codepoints": [10913, 824], "characters": "\u2AA1\u0338" }, + "∌": { "codepoints": [8716], "characters": "\u220C" }, + "∌": { "codepoints": [8716], "characters": "\u220C" }, + "⋾": { "codepoints": [8958], "characters": "\u22FE" }, + "⋽": { "codepoints": [8957], "characters": "\u22FD" }, + "⊀": { "codepoints": [8832], "characters": "\u2280" }, + "⪯̸": { "codepoints": [10927, 824], "characters": "\u2AAF\u0338" }, + "⋠": { "codepoints": [8928], "characters": "\u22E0" }, + "∌": { "codepoints": [8716], "characters": "\u220C" }, + "⧐̸": { "codepoints": [10704, 824], "characters": "\u29D0\u0338" }, + "⋫": { "codepoints": [8939], "characters": "\u22EB" }, + "⋭": { "codepoints": [8941], "characters": "\u22ED" }, + "⊏̸": { "codepoints": [8847, 824], "characters": "\u228F\u0338" }, + "⋢": { "codepoints": [8930], "characters": "\u22E2" }, + "⊐̸": { "codepoints": [8848, 824], "characters": "\u2290\u0338" }, + "⋣": { "codepoints": [8931], "characters": "\u22E3" }, + "⊂⃒": { "codepoints": [8834, 8402], "characters": "\u2282\u20D2" }, + "⊈": { "codepoints": [8840], "characters": "\u2288" }, + "⊁": { "codepoints": [8833], "characters": "\u2281" }, + "⪰̸": { "codepoints": [10928, 824], "characters": "\u2AB0\u0338" }, + "⋡": { "codepoints": [8929], "characters": "\u22E1" }, + "≿̸": { "codepoints": [8831, 824], "characters": "\u227F\u0338" }, + "⊃⃒": { "codepoints": [8835, 8402], "characters": "\u2283\u20D2" }, + "⊉": { "codepoints": [8841], "characters": "\u2289" }, + "≁": { "codepoints": [8769], "characters": "\u2241" }, + "≄": { "codepoints": [8772], "characters": "\u2244" }, + "≇": { "codepoints": [8775], "characters": "\u2247" }, + "≉": { "codepoints": [8777], "characters": "\u2249" }, + "∤": { "codepoints": [8740], "characters": "\u2224" }, + "∦": { "codepoints": [8742], "characters": "\u2226" }, + "∦": { "codepoints": [8742], "characters": "\u2226" }, + "⫽⃥": { "codepoints": [11005, 8421], "characters": "\u2AFD\u20E5" }, + "∂̸": { "codepoints": [8706, 824], "characters": "\u2202\u0338" }, + "⨔": { "codepoints": [10772], "characters": "\u2A14" }, + "⊀": { "codepoints": [8832], "characters": "\u2280" }, + "⋠": { "codepoints": [8928], "characters": "\u22E0" }, + "⊀": { "codepoints": [8832], "characters": "\u2280" }, + "⪯̸": { "codepoints": [10927, 824], "characters": "\u2AAF\u0338" }, + "⪯̸": { "codepoints": [10927, 824], "characters": "\u2AAF\u0338" }, + "⤳̸": { "codepoints": [10547, 824], "characters": "\u2933\u0338" }, + "↛": { "codepoints": [8603], "characters": "\u219B" }, + "⇏": { "codepoints": [8655], "characters": "\u21CF" }, + "↝̸": { "codepoints": [8605, 824], "characters": "\u219D\u0338" }, + "↛": { "codepoints": [8603], "characters": "\u219B" }, + "⇏": { "codepoints": [8655], "characters": "\u21CF" }, + "⋫": { "codepoints": [8939], "characters": "\u22EB" }, + "⋭": { "codepoints": [8941], "characters": "\u22ED" }, + "⊁": { "codepoints": [8833], "characters": "\u2281" }, + "⋡": { "codepoints": [8929], "characters": "\u22E1" }, + "⪰̸": { "codepoints": [10928, 824], "characters": "\u2AB0\u0338" }, + "𝒩": { "codepoints": [119977], "characters": "\uD835\uDCA9" }, + "𝓃": { "codepoints": [120003], "characters": "\uD835\uDCC3" }, + "∤": { "codepoints": [8740], "characters": "\u2224" }, + "∦": { "codepoints": [8742], "characters": "\u2226" }, + "≁": { "codepoints": [8769], "characters": "\u2241" }, + "≄": { "codepoints": [8772], "characters": "\u2244" }, + "≄": { "codepoints": [8772], "characters": "\u2244" }, + "∤": { "codepoints": [8740], "characters": "\u2224" }, + "∦": { "codepoints": [8742], "characters": "\u2226" }, + "⋢": { "codepoints": [8930], "characters": "\u22E2" }, + "⋣": { "codepoints": [8931], "characters": "\u22E3" }, + "⊄": { "codepoints": [8836], "characters": "\u2284" }, + "⫅̸": { "codepoints": [10949, 824], "characters": "\u2AC5\u0338" }, + "⊈": { "codepoints": [8840], "characters": "\u2288" }, + "⊂⃒": { "codepoints": [8834, 8402], "characters": "\u2282\u20D2" }, + "⊈": { "codepoints": [8840], "characters": "\u2288" }, + "⫅̸": { "codepoints": [10949, 824], "characters": "\u2AC5\u0338" }, + "⊁": { "codepoints": [8833], "characters": "\u2281" }, + "⪰̸": { "codepoints": [10928, 824], "characters": "\u2AB0\u0338" }, + "⊅": { "codepoints": [8837], "characters": "\u2285" }, + "⫆̸": { "codepoints": [10950, 824], "characters": "\u2AC6\u0338" }, + "⊉": { "codepoints": [8841], "characters": "\u2289" }, + "⊃⃒": { "codepoints": [8835, 8402], "characters": "\u2283\u20D2" }, + "⊉": { "codepoints": [8841], "characters": "\u2289" }, + "⫆̸": { "codepoints": [10950, 824], "characters": "\u2AC6\u0338" }, + "≹": { "codepoints": [8825], "characters": "\u2279" }, + "Ñ": { "codepoints": [209], "characters": "\u00D1" }, + "Ñ": { "codepoints": [209], "characters": "\u00D1" }, + "ñ": { "codepoints": [241], "characters": "\u00F1" }, + "ñ": { "codepoints": [241], "characters": "\u00F1" }, + "≸": { "codepoints": [8824], "characters": "\u2278" }, + "⋪": { "codepoints": [8938], "characters": "\u22EA" }, + "⋬": { "codepoints": [8940], "characters": "\u22EC" }, + "⋫": { "codepoints": [8939], "characters": "\u22EB" }, + "⋭": { "codepoints": [8941], "characters": "\u22ED" }, + "Ν": { "codepoints": [925], "characters": "\u039D" }, + "ν": { "codepoints": [957], "characters": "\u03BD" }, + "#": { "codepoints": [35], "characters": "\u0023" }, + "№": { "codepoints": [8470], "characters": "\u2116" }, + " ": { "codepoints": [8199], "characters": "\u2007" }, + "≍⃒": { "codepoints": [8781, 8402], "characters": "\u224D\u20D2" }, + "⊬": { "codepoints": [8876], "characters": "\u22AC" }, + "⊭": { "codepoints": [8877], "characters": "\u22AD" }, + "⊮": { "codepoints": [8878], "characters": "\u22AE" }, + "⊯": { "codepoints": [8879], "characters": "\u22AF" }, + "≥⃒": { "codepoints": [8805, 8402], "characters": "\u2265\u20D2" }, + ">⃒": { "codepoints": [62, 8402], "characters": "\u003E\u20D2" }, + "⤄": { "codepoints": [10500], "characters": "\u2904" }, + "⧞": { "codepoints": [10718], "characters": "\u29DE" }, + "⤂": { "codepoints": [10498], "characters": "\u2902" }, + "≤⃒": { "codepoints": [8804, 8402], "characters": "\u2264\u20D2" }, + "<⃒": { "codepoints": [60, 8402], "characters": "\u003C\u20D2" }, + "⊴⃒": { "codepoints": [8884, 8402], "characters": "\u22B4\u20D2" }, + "⤃": { "codepoints": [10499], "characters": "\u2903" }, + "⊵⃒": { "codepoints": [8885, 8402], "characters": "\u22B5\u20D2" }, + "∼⃒": { "codepoints": [8764, 8402], "characters": "\u223C\u20D2" }, + "⤣": { "codepoints": [10531], "characters": "\u2923" }, + "↖": { "codepoints": [8598], "characters": "\u2196" }, + "⇖": { "codepoints": [8662], "characters": "\u21D6" }, + "↖": { "codepoints": [8598], "characters": "\u2196" }, + "⤧": { "codepoints": [10535], "characters": "\u2927" }, + "Ó": { "codepoints": [211], "characters": "\u00D3" }, + "Ó": { "codepoints": [211], "characters": "\u00D3" }, + "ó": { "codepoints": [243], "characters": "\u00F3" }, + "ó": { "codepoints": [243], "characters": "\u00F3" }, + "⊛": { "codepoints": [8859], "characters": "\u229B" }, + "Ô": { "codepoints": [212], "characters": "\u00D4" }, + "Ô": { "codepoints": [212], "characters": "\u00D4" }, + "ô": { "codepoints": [244], "characters": "\u00F4" }, + "ô": { "codepoints": [244], "characters": "\u00F4" }, + "⊚": { "codepoints": [8858], "characters": "\u229A" }, + "О": { "codepoints": [1054], "characters": "\u041E" }, + "о": { "codepoints": [1086], "characters": "\u043E" }, + "⊝": { "codepoints": [8861], "characters": "\u229D" }, + "Ő": { "codepoints": [336], "characters": "\u0150" }, + "ő": { "codepoints": [337], "characters": "\u0151" }, + "⨸": { "codepoints": [10808], "characters": "\u2A38" }, + "⊙": { "codepoints": [8857], "characters": "\u2299" }, + "⦼": { "codepoints": [10684], "characters": "\u29BC" }, + "Œ": { "codepoints": [338], "characters": "\u0152" }, + "œ": { "codepoints": [339], "characters": "\u0153" }, + "⦿": { "codepoints": [10687], "characters": "\u29BF" }, + "𝔒": { "codepoints": [120082], "characters": "\uD835\uDD12" }, + "𝔬": { "codepoints": [120108], "characters": "\uD835\uDD2C" }, + "˛": { "codepoints": [731], "characters": "\u02DB" }, + "Ò": { "codepoints": [210], "characters": "\u00D2" }, + "Ò": { "codepoints": [210], "characters": "\u00D2" }, + "ò": { "codepoints": [242], "characters": "\u00F2" }, + "ò": { "codepoints": [242], "characters": "\u00F2" }, + "⧁": { "codepoints": [10689], "characters": "\u29C1" }, + "⦵": { "codepoints": [10677], "characters": "\u29B5" }, + "Ω": { "codepoints": [937], "characters": "\u03A9" }, + "∮": { "codepoints": [8750], "characters": "\u222E" }, + "↺": { "codepoints": [8634], "characters": "\u21BA" }, + "⦾": { "codepoints": [10686], "characters": "\u29BE" }, + "⦻": { "codepoints": [10683], "characters": "\u29BB" }, + "‾": { "codepoints": [8254], "characters": "\u203E" }, + "⧀": { "codepoints": [10688], "characters": "\u29C0" }, + "Ō": { "codepoints": [332], "characters": "\u014C" }, + "ō": { "codepoints": [333], "characters": "\u014D" }, + "Ω": { "codepoints": [937], "characters": "\u03A9" }, + "ω": { "codepoints": [969], "characters": "\u03C9" }, + "Ο": { "codepoints": [927], "characters": "\u039F" }, + "ο": { "codepoints": [959], "characters": "\u03BF" }, + "⦶": { "codepoints": [10678], "characters": "\u29B6" }, + "⊖": { "codepoints": [8854], "characters": "\u2296" }, + "𝕆": { "codepoints": [120134], "characters": "\uD835\uDD46" }, + "𝕠": { "codepoints": [120160], "characters": "\uD835\uDD60" }, + "⦷": { "codepoints": [10679], "characters": "\u29B7" }, + "“": { "codepoints": [8220], "characters": "\u201C" }, + "‘": { "codepoints": [8216], "characters": "\u2018" }, + "⦹": { "codepoints": [10681], "characters": "\u29B9" }, + "⊕": { "codepoints": [8853], "characters": "\u2295" }, + "↻": { "codepoints": [8635], "characters": "\u21BB" }, + "⩔": { "codepoints": [10836], "characters": "\u2A54" }, + "∨": { "codepoints": [8744], "characters": "\u2228" }, + "⩝": { "codepoints": [10845], "characters": "\u2A5D" }, + "ℴ": { "codepoints": [8500], "characters": "\u2134" }, + "ℴ": { "codepoints": [8500], "characters": "\u2134" }, + "ª": { "codepoints": [170], "characters": "\u00AA" }, + "ª": { "codepoints": [170], "characters": "\u00AA" }, + "º": { "codepoints": [186], "characters": "\u00BA" }, + "º": { "codepoints": [186], "characters": "\u00BA" }, + "⊶": { "codepoints": [8886], "characters": "\u22B6" }, + "⩖": { "codepoints": [10838], "characters": "\u2A56" }, + "⩗": { "codepoints": [10839], "characters": "\u2A57" }, + "⩛": { "codepoints": [10843], "characters": "\u2A5B" }, + "Ⓢ": { "codepoints": [9416], "characters": "\u24C8" }, + "𝒪": { "codepoints": [119978], "characters": "\uD835\uDCAA" }, + "ℴ": { "codepoints": [8500], "characters": "\u2134" }, + "Ø": { "codepoints": [216], "characters": "\u00D8" }, + "Ø": { "codepoints": [216], "characters": "\u00D8" }, + "ø": { "codepoints": [248], "characters": "\u00F8" }, + "ø": { "codepoints": [248], "characters": "\u00F8" }, + "⊘": { "codepoints": [8856], "characters": "\u2298" }, + "Õ": { "codepoints": [213], "characters": "\u00D5" }, + "Õ": { "codepoints": [213], "characters": "\u00D5" }, + "õ": { "codepoints": [245], "characters": "\u00F5" }, + "õ": { "codepoints": [245], "characters": "\u00F5" }, + "⨶": { "codepoints": [10806], "characters": "\u2A36" }, + "⨷": { "codepoints": [10807], "characters": "\u2A37" }, + "⊗": { "codepoints": [8855], "characters": "\u2297" }, + "Ö": { "codepoints": [214], "characters": "\u00D6" }, + "Ö": { "codepoints": [214], "characters": "\u00D6" }, + "ö": { "codepoints": [246], "characters": "\u00F6" }, + "ö": { "codepoints": [246], "characters": "\u00F6" }, + "⌽": { "codepoints": [9021], "characters": "\u233D" }, + "‾": { "codepoints": [8254], "characters": "\u203E" }, + "⏞": { "codepoints": [9182], "characters": "\u23DE" }, + "⎴": { "codepoints": [9140], "characters": "\u23B4" }, + "⏜": { "codepoints": [9180], "characters": "\u23DC" }, + "¶": { "codepoints": [182], "characters": "\u00B6" }, + "¶": { "codepoints": [182], "characters": "\u00B6" }, + "∥": { "codepoints": [8741], "characters": "\u2225" }, + "∥": { "codepoints": [8741], "characters": "\u2225" }, + "⫳": { "codepoints": [10995], "characters": "\u2AF3" }, + "⫽": { "codepoints": [11005], "characters": "\u2AFD" }, + "∂": { "codepoints": [8706], "characters": "\u2202" }, + "∂": { "codepoints": [8706], "characters": "\u2202" }, + "П": { "codepoints": [1055], "characters": "\u041F" }, + "п": { "codepoints": [1087], "characters": "\u043F" }, + "%": { "codepoints": [37], "characters": "\u0025" }, + ".": { "codepoints": [46], "characters": "\u002E" }, + "‰": { "codepoints": [8240], "characters": "\u2030" }, + "⊥": { "codepoints": [8869], "characters": "\u22A5" }, + "‱": { "codepoints": [8241], "characters": "\u2031" }, + "𝔓": { "codepoints": [120083], "characters": "\uD835\uDD13" }, + "𝔭": { "codepoints": [120109], "characters": "\uD835\uDD2D" }, + "Φ": { "codepoints": [934], "characters": "\u03A6" }, + "φ": { "codepoints": [966], "characters": "\u03C6" }, + "ϕ": { "codepoints": [981], "characters": "\u03D5" }, + "ℳ": { "codepoints": [8499], "characters": "\u2133" }, + "☎": { "codepoints": [9742], "characters": "\u260E" }, + "Π": { "codepoints": [928], "characters": "\u03A0" }, + "π": { "codepoints": [960], "characters": "\u03C0" }, + "⋔": { "codepoints": [8916], "characters": "\u22D4" }, + "ϖ": { "codepoints": [982], "characters": "\u03D6" }, + "ℏ": { "codepoints": [8463], "characters": "\u210F" }, + "ℎ": { "codepoints": [8462], "characters": "\u210E" }, + "ℏ": { "codepoints": [8463], "characters": "\u210F" }, + "⨣": { "codepoints": [10787], "characters": "\u2A23" }, + "⊞": { "codepoints": [8862], "characters": "\u229E" }, + "⨢": { "codepoints": [10786], "characters": "\u2A22" }, + "+": { "codepoints": [43], "characters": "\u002B" }, + "∔": { "codepoints": [8724], "characters": "\u2214" }, + "⨥": { "codepoints": [10789], "characters": "\u2A25" }, + "⩲": { "codepoints": [10866], "characters": "\u2A72" }, + "±": { "codepoints": [177], "characters": "\u00B1" }, + "±": { "codepoints": [177], "characters": "\u00B1" }, + "±": { "codepoints": [177], "characters": "\u00B1" }, + "⨦": { "codepoints": [10790], "characters": "\u2A26" }, + "⨧": { "codepoints": [10791], "characters": "\u2A27" }, + "±": { "codepoints": [177], "characters": "\u00B1" }, + "ℌ": { "codepoints": [8460], "characters": "\u210C" }, + "⨕": { "codepoints": [10773], "characters": "\u2A15" }, + "𝕡": { "codepoints": [120161], "characters": "\uD835\uDD61" }, + "ℙ": { "codepoints": [8473], "characters": "\u2119" }, + "£": { "codepoints": [163], "characters": "\u00A3" }, + "£": { "codepoints": [163], "characters": "\u00A3" }, + "⪷": { "codepoints": [10935], "characters": "\u2AB7" }, + "⪻": { "codepoints": [10939], "characters": "\u2ABB" }, + "≺": { "codepoints": [8826], "characters": "\u227A" }, + "≼": { "codepoints": [8828], "characters": "\u227C" }, + "⪷": { "codepoints": [10935], "characters": "\u2AB7" }, + "≺": { "codepoints": [8826], "characters": "\u227A" }, + "≼": { "codepoints": [8828], "characters": "\u227C" }, + "≺": { "codepoints": [8826], "characters": "\u227A" }, + "⪯": { "codepoints": [10927], "characters": "\u2AAF" }, + "≼": { "codepoints": [8828], "characters": "\u227C" }, + "≾": { "codepoints": [8830], "characters": "\u227E" }, + "⪯": { "codepoints": [10927], "characters": "\u2AAF" }, + "⪹": { "codepoints": [10937], "characters": "\u2AB9" }, + "⪵": { "codepoints": [10933], "characters": "\u2AB5" }, + "⋨": { "codepoints": [8936], "characters": "\u22E8" }, + "⪯": { "codepoints": [10927], "characters": "\u2AAF" }, + "⪳": { "codepoints": [10931], "characters": "\u2AB3" }, + "≾": { "codepoints": [8830], "characters": "\u227E" }, + "′": { "codepoints": [8242], "characters": "\u2032" }, + "″": { "codepoints": [8243], "characters": "\u2033" }, + "ℙ": { "codepoints": [8473], "characters": "\u2119" }, + "⪹": { "codepoints": [10937], "characters": "\u2AB9" }, + "⪵": { "codepoints": [10933], "characters": "\u2AB5" }, + "⋨": { "codepoints": [8936], "characters": "\u22E8" }, + "∏": { "codepoints": [8719], "characters": "\u220F" }, + "∏": { "codepoints": [8719], "characters": "\u220F" }, + "⌮": { "codepoints": [9006], "characters": "\u232E" }, + "⌒": { "codepoints": [8978], "characters": "\u2312" }, + "⌓": { "codepoints": [8979], "characters": "\u2313" }, + "∝": { "codepoints": [8733], "characters": "\u221D" }, + "∝": { "codepoints": [8733], "characters": "\u221D" }, + "∷": { "codepoints": [8759], "characters": "\u2237" }, + "∝": { "codepoints": [8733], "characters": "\u221D" }, + "≾": { "codepoints": [8830], "characters": "\u227E" }, + "⊰": { "codepoints": [8880], "characters": "\u22B0" }, + "𝒫": { "codepoints": [119979], "characters": "\uD835\uDCAB" }, + "𝓅": { "codepoints": [120005], "characters": "\uD835\uDCC5" }, + "Ψ": { "codepoints": [936], "characters": "\u03A8" }, + "ψ": { "codepoints": [968], "characters": "\u03C8" }, + " ": { "codepoints": [8200], "characters": "\u2008" }, + "𝔔": { "codepoints": [120084], "characters": "\uD835\uDD14" }, + "𝔮": { "codepoints": [120110], "characters": "\uD835\uDD2E" }, + "⨌": { "codepoints": [10764], "characters": "\u2A0C" }, + "𝕢": { "codepoints": [120162], "characters": "\uD835\uDD62" }, + "ℚ": { "codepoints": [8474], "characters": "\u211A" }, + "⁗": { "codepoints": [8279], "characters": "\u2057" }, + "𝒬": { "codepoints": [119980], "characters": "\uD835\uDCAC" }, + "𝓆": { "codepoints": [120006], "characters": "\uD835\uDCC6" }, + "ℍ": { "codepoints": [8461], "characters": "\u210D" }, + "⨖": { "codepoints": [10774], "characters": "\u2A16" }, + "?": { "codepoints": [63], "characters": "\u003F" }, + "≟": { "codepoints": [8799], "characters": "\u225F" }, + """: { "codepoints": [34], "characters": "\u0022" }, + """: { "codepoints": [34], "characters": "\u0022" }, + """: { "codepoints": [34], "characters": "\u0022" }, + """: { "codepoints": [34], "characters": "\u0022" }, + "⇛": { "codepoints": [8667], "characters": "\u21DB" }, + "∽̱": { "codepoints": [8765, 817], "characters": "\u223D\u0331" }, + "Ŕ": { "codepoints": [340], "characters": "\u0154" }, + "ŕ": { "codepoints": [341], "characters": "\u0155" }, + "√": { "codepoints": [8730], "characters": "\u221A" }, + "⦳": { "codepoints": [10675], "characters": "\u29B3" }, + "⟩": { "codepoints": [10217], "characters": "\u27E9" }, + "⟫": { "codepoints": [10219], "characters": "\u27EB" }, + "⦒": { "codepoints": [10642], "characters": "\u2992" }, + "⦥": { "codepoints": [10661], "characters": "\u29A5" }, + "⟩": { "codepoints": [10217], "characters": "\u27E9" }, + "»": { "codepoints": [187], "characters": "\u00BB" }, + "»": { "codepoints": [187], "characters": "\u00BB" }, + "⥵": { "codepoints": [10613], "characters": "\u2975" }, + "⇥": { "codepoints": [8677], "characters": "\u21E5" }, + "⤠": { "codepoints": [10528], "characters": "\u2920" }, + "⤳": { "codepoints": [10547], "characters": "\u2933" }, + "→": { "codepoints": [8594], "characters": "\u2192" }, + "↠": { "codepoints": [8608], "characters": "\u21A0" }, + "⇒": { "codepoints": [8658], "characters": "\u21D2" }, + "⤞": { "codepoints": [10526], "characters": "\u291E" }, + "↪": { "codepoints": [8618], "characters": "\u21AA" }, + "↬": { "codepoints": [8620], "characters": "\u21AC" }, + "⥅": { "codepoints": [10565], "characters": "\u2945" }, + "⥴": { "codepoints": [10612], "characters": "\u2974" }, + "⤖": { "codepoints": [10518], "characters": "\u2916" }, + "↣": { "codepoints": [8611], "characters": "\u21A3" }, + "↝": { "codepoints": [8605], "characters": "\u219D" }, + "⤚": { "codepoints": [10522], "characters": "\u291A" }, + "⤜": { "codepoints": [10524], "characters": "\u291C" }, + "∶": { "codepoints": [8758], "characters": "\u2236" }, + "ℚ": { "codepoints": [8474], "characters": "\u211A" }, + "⤍": { "codepoints": [10509], "characters": "\u290D" }, + "⤏": { "codepoints": [10511], "characters": "\u290F" }, + "⤐": { "codepoints": [10512], "characters": "\u2910" }, + "❳": { "codepoints": [10099], "characters": "\u2773" }, + "}": { "codepoints": [125], "characters": "\u007D" }, + "]": { "codepoints": [93], "characters": "\u005D" }, + "⦌": { "codepoints": [10636], "characters": "\u298C" }, + "⦎": { "codepoints": [10638], "characters": "\u298E" }, + "⦐": { "codepoints": [10640], "characters": "\u2990" }, + "Ř": { "codepoints": [344], "characters": "\u0158" }, + "ř": { "codepoints": [345], "characters": "\u0159" }, + "Ŗ": { "codepoints": [342], "characters": "\u0156" }, + "ŗ": { "codepoints": [343], "characters": "\u0157" }, + "⌉": { "codepoints": [8969], "characters": "\u2309" }, + "}": { "codepoints": [125], "characters": "\u007D" }, + "Р": { "codepoints": [1056], "characters": "\u0420" }, + "р": { "codepoints": [1088], "characters": "\u0440" }, + "⤷": { "codepoints": [10551], "characters": "\u2937" }, + "⥩": { "codepoints": [10601], "characters": "\u2969" }, + "”": { "codepoints": [8221], "characters": "\u201D" }, + "”": { "codepoints": [8221], "characters": "\u201D" }, + "↳": { "codepoints": [8627], "characters": "\u21B3" }, + "ℜ": { "codepoints": [8476], "characters": "\u211C" }, + "ℛ": { "codepoints": [8475], "characters": "\u211B" }, + "ℜ": { "codepoints": [8476], "characters": "\u211C" }, + "ℝ": { "codepoints": [8477], "characters": "\u211D" }, + "ℜ": { "codepoints": [8476], "characters": "\u211C" }, + "▭": { "codepoints": [9645], "characters": "\u25AD" }, + "®": { "codepoints": [174], "characters": "\u00AE" }, + "®": { "codepoints": [174], "characters": "\u00AE" }, + "®": { "codepoints": [174], "characters": "\u00AE" }, + "®": { "codepoints": [174], "characters": "\u00AE" }, + "∋": { "codepoints": [8715], "characters": "\u220B" }, + "⇋": { "codepoints": [8651], "characters": "\u21CB" }, + "⥯": { "codepoints": [10607], "characters": "\u296F" }, + "⥽": { "codepoints": [10621], "characters": "\u297D" }, + "⌋": { "codepoints": [8971], "characters": "\u230B" }, + "𝔯": { "codepoints": [120111], "characters": "\uD835\uDD2F" }, + "ℜ": { "codepoints": [8476], "characters": "\u211C" }, + "⥤": { "codepoints": [10596], "characters": "\u2964" }, + "⇁": { "codepoints": [8641], "characters": "\u21C1" }, + "⇀": { "codepoints": [8640], "characters": "\u21C0" }, + "⥬": { "codepoints": [10604], "characters": "\u296C" }, + "Ρ": { "codepoints": [929], "characters": "\u03A1" }, + "ρ": { "codepoints": [961], "characters": "\u03C1" }, + "ϱ": { "codepoints": [1009], "characters": "\u03F1" }, + "⟩": { "codepoints": [10217], "characters": "\u27E9" }, + "⇥": { "codepoints": [8677], "characters": "\u21E5" }, + "→": { "codepoints": [8594], "characters": "\u2192" }, + "→": { "codepoints": [8594], "characters": "\u2192" }, + "⇒": { "codepoints": [8658], "characters": "\u21D2" }, + "⇄": { "codepoints": [8644], "characters": "\u21C4" }, + "↣": { "codepoints": [8611], "characters": "\u21A3" }, + "⌉": { "codepoints": [8969], "characters": "\u2309" }, + "⟧": { "codepoints": [10215], "characters": "\u27E7" }, + "⥝": { "codepoints": [10589], "characters": "\u295D" }, + "⥕": { "codepoints": [10581], "characters": "\u2955" }, + "⇂": { "codepoints": [8642], "characters": "\u21C2" }, + "⌋": { "codepoints": [8971], "characters": "\u230B" }, + "⇁": { "codepoints": [8641], "characters": "\u21C1" }, + "⇀": { "codepoints": [8640], "characters": "\u21C0" }, + "⇄": { "codepoints": [8644], "characters": "\u21C4" }, + "⇌": { "codepoints": [8652], "characters": "\u21CC" }, + "⇉": { "codepoints": [8649], "characters": "\u21C9" }, + "↝": { "codepoints": [8605], "characters": "\u219D" }, + "↦": { "codepoints": [8614], "characters": "\u21A6" }, + "⊢": { "codepoints": [8866], "characters": "\u22A2" }, + "⥛": { "codepoints": [10587], "characters": "\u295B" }, + "⋌": { "codepoints": [8908], "characters": "\u22CC" }, + "⧐": { "codepoints": [10704], "characters": "\u29D0" }, + "⊳": { "codepoints": [8883], "characters": "\u22B3" }, + "⊵": { "codepoints": [8885], "characters": "\u22B5" }, + "⥏": { "codepoints": [10575], "characters": "\u294F" }, + "⥜": { "codepoints": [10588], "characters": "\u295C" }, + "⥔": { "codepoints": [10580], "characters": "\u2954" }, + "↾": { "codepoints": [8638], "characters": "\u21BE" }, + "⥓": { "codepoints": [10579], "characters": "\u2953" }, + "⇀": { "codepoints": [8640], "characters": "\u21C0" }, + "˚": { "codepoints": [730], "characters": "\u02DA" }, + "≓": { "codepoints": [8787], "characters": "\u2253" }, + "⇄": { "codepoints": [8644], "characters": "\u21C4" }, + "⇌": { "codepoints": [8652], "characters": "\u21CC" }, + "‏": { "codepoints": [8207], "characters": "\u200F" }, + "⎱": { "codepoints": [9137], "characters": "\u23B1" }, + "⎱": { "codepoints": [9137], "characters": "\u23B1" }, + "⫮": { "codepoints": [10990], "characters": "\u2AEE" }, + "⟭": { "codepoints": [10221], "characters": "\u27ED" }, + "⇾": { "codepoints": [8702], "characters": "\u21FE" }, + "⟧": { "codepoints": [10215], "characters": "\u27E7" }, + "⦆": { "codepoints": [10630], "characters": "\u2986" }, + "𝕣": { "codepoints": [120163], "characters": "\uD835\uDD63" }, + "ℝ": { "codepoints": [8477], "characters": "\u211D" }, + "⨮": { "codepoints": [10798], "characters": "\u2A2E" }, + "⨵": { "codepoints": [10805], "characters": "\u2A35" }, + "⥰": { "codepoints": [10608], "characters": "\u2970" }, + ")": { "codepoints": [41], "characters": "\u0029" }, + "⦔": { "codepoints": [10644], "characters": "\u2994" }, + "⨒": { "codepoints": [10770], "characters": "\u2A12" }, + "⇉": { "codepoints": [8649], "characters": "\u21C9" }, + "⇛": { "codepoints": [8667], "characters": "\u21DB" }, + "›": { "codepoints": [8250], "characters": "\u203A" }, + "𝓇": { "codepoints": [120007], "characters": "\uD835\uDCC7" }, + "ℛ": { "codepoints": [8475], "characters": "\u211B" }, + "↱": { "codepoints": [8625], "characters": "\u21B1" }, + "↱": { "codepoints": [8625], "characters": "\u21B1" }, + "]": { "codepoints": [93], "characters": "\u005D" }, + "’": { "codepoints": [8217], "characters": "\u2019" }, + "’": { "codepoints": [8217], "characters": "\u2019" }, + "⋌": { "codepoints": [8908], "characters": "\u22CC" }, + "⋊": { "codepoints": [8906], "characters": "\u22CA" }, + "▹": { "codepoints": [9657], "characters": "\u25B9" }, + "⊵": { "codepoints": [8885], "characters": "\u22B5" }, + "▸": { "codepoints": [9656], "characters": "\u25B8" }, + "⧎": { "codepoints": [10702], "characters": "\u29CE" }, + "⧴": { "codepoints": [10740], "characters": "\u29F4" }, + "⥨": { "codepoints": [10600], "characters": "\u2968" }, + "℞": { "codepoints": [8478], "characters": "\u211E" }, + "Ś": { "codepoints": [346], "characters": "\u015A" }, + "ś": { "codepoints": [347], "characters": "\u015B" }, + "‚": { "codepoints": [8218], "characters": "\u201A" }, + "⪸": { "codepoints": [10936], "characters": "\u2AB8" }, + "Š": { "codepoints": [352], "characters": "\u0160" }, + "š": { "codepoints": [353], "characters": "\u0161" }, + "⪼": { "codepoints": [10940], "characters": "\u2ABC" }, + "≻": { "codepoints": [8827], "characters": "\u227B" }, + "≽": { "codepoints": [8829], "characters": "\u227D" }, + "⪰": { "codepoints": [10928], "characters": "\u2AB0" }, + "⪴": { "codepoints": [10932], "characters": "\u2AB4" }, + "Ş": { "codepoints": [350], "characters": "\u015E" }, + "ş": { "codepoints": [351], "characters": "\u015F" }, + "Ŝ": { "codepoints": [348], "characters": "\u015C" }, + "ŝ": { "codepoints": [349], "characters": "\u015D" }, + "⪺": { "codepoints": [10938], "characters": "\u2ABA" }, + "⪶": { "codepoints": [10934], "characters": "\u2AB6" }, + "⋩": { "codepoints": [8937], "characters": "\u22E9" }, + "⨓": { "codepoints": [10771], "characters": "\u2A13" }, + "≿": { "codepoints": [8831], "characters": "\u227F" }, + "С": { "codepoints": [1057], "characters": "\u0421" }, + "с": { "codepoints": [1089], "characters": "\u0441" }, + "⊡": { "codepoints": [8865], "characters": "\u22A1" }, + "⋅": { "codepoints": [8901], "characters": "\u22C5" }, + "⩦": { "codepoints": [10854], "characters": "\u2A66" }, + "⤥": { "codepoints": [10533], "characters": "\u2925" }, + "↘": { "codepoints": [8600], "characters": "\u2198" }, + "⇘": { "codepoints": [8664], "characters": "\u21D8" }, + "↘": { "codepoints": [8600], "characters": "\u2198" }, + "§": { "codepoints": [167], "characters": "\u00A7" }, + "§": { "codepoints": [167], "characters": "\u00A7" }, + ";": { "codepoints": [59], "characters": "\u003B" }, + "⤩": { "codepoints": [10537], "characters": "\u2929" }, + "∖": { "codepoints": [8726], "characters": "\u2216" }, + "∖": { "codepoints": [8726], "characters": "\u2216" }, + "✶": { "codepoints": [10038], "characters": "\u2736" }, + "𝔖": { "codepoints": [120086], "characters": "\uD835\uDD16" }, + "𝔰": { "codepoints": [120112], "characters": "\uD835\uDD30" }, + "⌢": { "codepoints": [8994], "characters": "\u2322" }, + "♯": { "codepoints": [9839], "characters": "\u266F" }, + "Щ": { "codepoints": [1065], "characters": "\u0429" }, + "щ": { "codepoints": [1097], "characters": "\u0449" }, + "Ш": { "codepoints": [1064], "characters": "\u0428" }, + "ш": { "codepoints": [1096], "characters": "\u0448" }, + "↓": { "codepoints": [8595], "characters": "\u2193" }, + "←": { "codepoints": [8592], "characters": "\u2190" }, + "∣": { "codepoints": [8739], "characters": "\u2223" }, + "∥": { "codepoints": [8741], "characters": "\u2225" }, + "→": { "codepoints": [8594], "characters": "\u2192" }, + "↑": { "codepoints": [8593], "characters": "\u2191" }, + "­": { "codepoints": [173], "characters": "\u00AD" }, + "­": { "codepoints": [173], "characters": "\u00AD" }, + "Σ": { "codepoints": [931], "characters": "\u03A3" }, + "σ": { "codepoints": [963], "characters": "\u03C3" }, + "ς": { "codepoints": [962], "characters": "\u03C2" }, + "ς": { "codepoints": [962], "characters": "\u03C2" }, + "∼": { "codepoints": [8764], "characters": "\u223C" }, + "⩪": { "codepoints": [10858], "characters": "\u2A6A" }, + "≃": { "codepoints": [8771], "characters": "\u2243" }, + "≃": { "codepoints": [8771], "characters": "\u2243" }, + "⪞": { "codepoints": [10910], "characters": "\u2A9E" }, + "⪠": { "codepoints": [10912], "characters": "\u2AA0" }, + "⪝": { "codepoints": [10909], "characters": "\u2A9D" }, + "⪟": { "codepoints": [10911], "characters": "\u2A9F" }, + "≆": { "codepoints": [8774], "characters": "\u2246" }, + "⨤": { "codepoints": [10788], "characters": "\u2A24" }, + "⥲": { "codepoints": [10610], "characters": "\u2972" }, + "←": { "codepoints": [8592], "characters": "\u2190" }, + "∘": { "codepoints": [8728], "characters": "\u2218" }, + "∖": { "codepoints": [8726], "characters": "\u2216" }, + "⨳": { "codepoints": [10803], "characters": "\u2A33" }, + "⧤": { "codepoints": [10724], "characters": "\u29E4" }, + "∣": { "codepoints": [8739], "characters": "\u2223" }, + "⌣": { "codepoints": [8995], "characters": "\u2323" }, + "⪪": { "codepoints": [10922], "characters": "\u2AAA" }, + "⪬": { "codepoints": [10924], "characters": "\u2AAC" }, + "⪬︀": { "codepoints": [10924, 65024], "characters": "\u2AAC\uFE00" }, + "Ь": { "codepoints": [1068], "characters": "\u042C" }, + "ь": { "codepoints": [1100], "characters": "\u044C" }, + "⌿": { "codepoints": [9023], "characters": "\u233F" }, + "⧄": { "codepoints": [10692], "characters": "\u29C4" }, + "/": { "codepoints": [47], "characters": "\u002F" }, + "𝕊": { "codepoints": [120138], "characters": "\uD835\uDD4A" }, + "𝕤": { "codepoints": [120164], "characters": "\uD835\uDD64" }, + "♠": { "codepoints": [9824], "characters": "\u2660" }, + "♠": { "codepoints": [9824], "characters": "\u2660" }, + "∥": { "codepoints": [8741], "characters": "\u2225" }, + "⊓": { "codepoints": [8851], "characters": "\u2293" }, + "⊓︀": { "codepoints": [8851, 65024], "characters": "\u2293\uFE00" }, + "⊔": { "codepoints": [8852], "characters": "\u2294" }, + "⊔︀": { "codepoints": [8852, 65024], "characters": "\u2294\uFE00" }, + "√": { "codepoints": [8730], "characters": "\u221A" }, + "⊏": { "codepoints": [8847], "characters": "\u228F" }, + "⊑": { "codepoints": [8849], "characters": "\u2291" }, + "⊏": { "codepoints": [8847], "characters": "\u228F" }, + "⊑": { "codepoints": [8849], "characters": "\u2291" }, + "⊐": { "codepoints": [8848], "characters": "\u2290" }, + "⊒": { "codepoints": [8850], "characters": "\u2292" }, + "⊐": { "codepoints": [8848], "characters": "\u2290" }, + "⊒": { "codepoints": [8850], "characters": "\u2292" }, + "□": { "codepoints": [9633], "characters": "\u25A1" }, + "□": { "codepoints": [9633], "characters": "\u25A1" }, + "⊓": { "codepoints": [8851], "characters": "\u2293" }, + "⊏": { "codepoints": [8847], "characters": "\u228F" }, + "⊑": { "codepoints": [8849], "characters": "\u2291" }, + "⊐": { "codepoints": [8848], "characters": "\u2290" }, + "⊒": { "codepoints": [8850], "characters": "\u2292" }, + "⊔": { "codepoints": [8852], "characters": "\u2294" }, + "▪": { "codepoints": [9642], "characters": "\u25AA" }, + "□": { "codepoints": [9633], "characters": "\u25A1" }, + "▪": { "codepoints": [9642], "characters": "\u25AA" }, + "→": { "codepoints": [8594], "characters": "\u2192" }, + "𝒮": { "codepoints": [119982], "characters": "\uD835\uDCAE" }, + "𝓈": { "codepoints": [120008], "characters": "\uD835\uDCC8" }, + "∖": { "codepoints": [8726], "characters": "\u2216" }, + "⌣": { "codepoints": [8995], "characters": "\u2323" }, + "⋆": { "codepoints": [8902], "characters": "\u22C6" }, + "⋆": { "codepoints": [8902], "characters": "\u22C6" }, + "☆": { "codepoints": [9734], "characters": "\u2606" }, + "★": { "codepoints": [9733], "characters": "\u2605" }, + "ϵ": { "codepoints": [1013], "characters": "\u03F5" }, + "ϕ": { "codepoints": [981], "characters": "\u03D5" }, + "¯": { "codepoints": [175], "characters": "\u00AF" }, + "⊂": { "codepoints": [8834], "characters": "\u2282" }, + "⋐": { "codepoints": [8912], "characters": "\u22D0" }, + "⪽": { "codepoints": [10941], "characters": "\u2ABD" }, + "⫅": { "codepoints": [10949], "characters": "\u2AC5" }, + "⊆": { "codepoints": [8838], "characters": "\u2286" }, + "⫃": { "codepoints": [10947], "characters": "\u2AC3" }, + "⫁": { "codepoints": [10945], "characters": "\u2AC1" }, + "⫋": { "codepoints": [10955], "characters": "\u2ACB" }, + "⊊": { "codepoints": [8842], "characters": "\u228A" }, + "⪿": { "codepoints": [10943], "characters": "\u2ABF" }, + "⥹": { "codepoints": [10617], "characters": "\u2979" }, + "⊂": { "codepoints": [8834], "characters": "\u2282" }, + "⋐": { "codepoints": [8912], "characters": "\u22D0" }, + "⊆": { "codepoints": [8838], "characters": "\u2286" }, + "⫅": { "codepoints": [10949], "characters": "\u2AC5" }, + "⊆": { "codepoints": [8838], "characters": "\u2286" }, + "⊊": { "codepoints": [8842], "characters": "\u228A" }, + "⫋": { "codepoints": [10955], "characters": "\u2ACB" }, + "⫇": { "codepoints": [10951], "characters": "\u2AC7" }, + "⫕": { "codepoints": [10965], "characters": "\u2AD5" }, + "⫓": { "codepoints": [10963], "characters": "\u2AD3" }, + "⪸": { "codepoints": [10936], "characters": "\u2AB8" }, + "≻": { "codepoints": [8827], "characters": "\u227B" }, + "≽": { "codepoints": [8829], "characters": "\u227D" }, + "≻": { "codepoints": [8827], "characters": "\u227B" }, + "⪰": { "codepoints": [10928], "characters": "\u2AB0" }, + "≽": { "codepoints": [8829], "characters": "\u227D" }, + "≿": { "codepoints": [8831], "characters": "\u227F" }, + "⪰": { "codepoints": [10928], "characters": "\u2AB0" }, + "⪺": { "codepoints": [10938], "characters": "\u2ABA" }, + "⪶": { "codepoints": [10934], "characters": "\u2AB6" }, + "⋩": { "codepoints": [8937], "characters": "\u22E9" }, + "≿": { "codepoints": [8831], "characters": "\u227F" }, + "∋": { "codepoints": [8715], "characters": "\u220B" }, + "∑": { "codepoints": [8721], "characters": "\u2211" }, + "∑": { "codepoints": [8721], "characters": "\u2211" }, + "♪": { "codepoints": [9834], "characters": "\u266A" }, + "¹": { "codepoints": [185], "characters": "\u00B9" }, + "¹": { "codepoints": [185], "characters": "\u00B9" }, + "²": { "codepoints": [178], "characters": "\u00B2" }, + "²": { "codepoints": [178], "characters": "\u00B2" }, + "³": { "codepoints": [179], "characters": "\u00B3" }, + "³": { "codepoints": [179], "characters": "\u00B3" }, + "⊃": { "codepoints": [8835], "characters": "\u2283" }, + "⋑": { "codepoints": [8913], "characters": "\u22D1" }, + "⪾": { "codepoints": [10942], "characters": "\u2ABE" }, + "⫘": { "codepoints": [10968], "characters": "\u2AD8" }, + "⫆": { "codepoints": [10950], "characters": "\u2AC6" }, + "⊇": { "codepoints": [8839], "characters": "\u2287" }, + "⫄": { "codepoints": [10948], "characters": "\u2AC4" }, + "⊃": { "codepoints": [8835], "characters": "\u2283" }, + "⊇": { "codepoints": [8839], "characters": "\u2287" }, + "⟉": { "codepoints": [10185], "characters": "\u27C9" }, + "⫗": { "codepoints": [10967], "characters": "\u2AD7" }, + "⥻": { "codepoints": [10619], "characters": "\u297B" }, + "⫂": { "codepoints": [10946], "characters": "\u2AC2" }, + "⫌": { "codepoints": [10956], "characters": "\u2ACC" }, + "⊋": { "codepoints": [8843], "characters": "\u228B" }, + "⫀": { "codepoints": [10944], "characters": "\u2AC0" }, + "⊃": { "codepoints": [8835], "characters": "\u2283" }, + "⋑": { "codepoints": [8913], "characters": "\u22D1" }, + "⊇": { "codepoints": [8839], "characters": "\u2287" }, + "⫆": { "codepoints": [10950], "characters": "\u2AC6" }, + "⊋": { "codepoints": [8843], "characters": "\u228B" }, + "⫌": { "codepoints": [10956], "characters": "\u2ACC" }, + "⫈": { "codepoints": [10952], "characters": "\u2AC8" }, + "⫔": { "codepoints": [10964], "characters": "\u2AD4" }, + "⫖": { "codepoints": [10966], "characters": "\u2AD6" }, + "⤦": { "codepoints": [10534], "characters": "\u2926" }, + "↙": { "codepoints": [8601], "characters": "\u2199" }, + "⇙": { "codepoints": [8665], "characters": "\u21D9" }, + "↙": { "codepoints": [8601], "characters": "\u2199" }, + "⤪": { "codepoints": [10538], "characters": "\u292A" }, + "ß": { "codepoints": [223], "characters": "\u00DF" }, + "ß": { "codepoints": [223], "characters": "\u00DF" }, + "	": { "codepoints": [9], "characters": "\u0009" }, + "⌖": { "codepoints": [8982], "characters": "\u2316" }, + "Τ": { "codepoints": [932], "characters": "\u03A4" }, + "τ": { "codepoints": [964], "characters": "\u03C4" }, + "⎴": { "codepoints": [9140], "characters": "\u23B4" }, + "Ť": { "codepoints": [356], "characters": "\u0164" }, + "ť": { "codepoints": [357], "characters": "\u0165" }, + "Ţ": { "codepoints": [354], "characters": "\u0162" }, + "ţ": { "codepoints": [355], "characters": "\u0163" }, + "Т": { "codepoints": [1058], "characters": "\u0422" }, + "т": { "codepoints": [1090], "characters": "\u0442" }, + "⃛": { "codepoints": [8411], "characters": "\u20DB" }, + "⌕": { "codepoints": [8981], "characters": "\u2315" }, + "𝔗": { "codepoints": [120087], "characters": "\uD835\uDD17" }, + "𝔱": { "codepoints": [120113], "characters": "\uD835\uDD31" }, + "∴": { "codepoints": [8756], "characters": "\u2234" }, + "∴": { "codepoints": [8756], "characters": "\u2234" }, + "∴": { "codepoints": [8756], "characters": "\u2234" }, + "Θ": { "codepoints": [920], "characters": "\u0398" }, + "θ": { "codepoints": [952], "characters": "\u03B8" }, + "ϑ": { "codepoints": [977], "characters": "\u03D1" }, + "ϑ": { "codepoints": [977], "characters": "\u03D1" }, + "≈": { "codepoints": [8776], "characters": "\u2248" }, + "∼": { "codepoints": [8764], "characters": "\u223C" }, + "  ": { "codepoints": [8287, 8202], "characters": "\u205F\u200A" }, + " ": { "codepoints": [8201], "characters": "\u2009" }, + " ": { "codepoints": [8201], "characters": "\u2009" }, + "≈": { "codepoints": [8776], "characters": "\u2248" }, + "∼": { "codepoints": [8764], "characters": "\u223C" }, + "Þ": { "codepoints": [222], "characters": "\u00DE" }, + "Þ": { "codepoints": [222], "characters": "\u00DE" }, + "þ": { "codepoints": [254], "characters": "\u00FE" }, + "þ": { "codepoints": [254], "characters": "\u00FE" }, + "˜": { "codepoints": [732], "characters": "\u02DC" }, + "∼": { "codepoints": [8764], "characters": "\u223C" }, + "≃": { "codepoints": [8771], "characters": "\u2243" }, + "≅": { "codepoints": [8773], "characters": "\u2245" }, + "≈": { "codepoints": [8776], "characters": "\u2248" }, + "⨱": { "codepoints": [10801], "characters": "\u2A31" }, + "⊠": { "codepoints": [8864], "characters": "\u22A0" }, + "×": { "codepoints": [215], "characters": "\u00D7" }, + "×": { "codepoints": [215], "characters": "\u00D7" }, + "⨰": { "codepoints": [10800], "characters": "\u2A30" }, + "∭": { "codepoints": [8749], "characters": "\u222D" }, + "⤨": { "codepoints": [10536], "characters": "\u2928" }, + "⌶": { "codepoints": [9014], "characters": "\u2336" }, + "⫱": { "codepoints": [10993], "characters": "\u2AF1" }, + "⊤": { "codepoints": [8868], "characters": "\u22A4" }, + "𝕋": { "codepoints": [120139], "characters": "\uD835\uDD4B" }, + "𝕥": { "codepoints": [120165], "characters": "\uD835\uDD65" }, + "⫚": { "codepoints": [10970], "characters": "\u2ADA" }, + "⤩": { "codepoints": [10537], "characters": "\u2929" }, + "‴": { "codepoints": [8244], "characters": "\u2034" }, + "™": { "codepoints": [8482], "characters": "\u2122" }, + "™": { "codepoints": [8482], "characters": "\u2122" }, + "▵": { "codepoints": [9653], "characters": "\u25B5" }, + "▿": { "codepoints": [9663], "characters": "\u25BF" }, + "◃": { "codepoints": [9667], "characters": "\u25C3" }, + "⊴": { "codepoints": [8884], "characters": "\u22B4" }, + "≜": { "codepoints": [8796], "characters": "\u225C" }, + "▹": { "codepoints": [9657], "characters": "\u25B9" }, + "⊵": { "codepoints": [8885], "characters": "\u22B5" }, + "◬": { "codepoints": [9708], "characters": "\u25EC" }, + "≜": { "codepoints": [8796], "characters": "\u225C" }, + "⨺": { "codepoints": [10810], "characters": "\u2A3A" }, + "⃛": { "codepoints": [8411], "characters": "\u20DB" }, + "⨹": { "codepoints": [10809], "characters": "\u2A39" }, + "⧍": { "codepoints": [10701], "characters": "\u29CD" }, + "⨻": { "codepoints": [10811], "characters": "\u2A3B" }, + "⏢": { "codepoints": [9186], "characters": "\u23E2" }, + "𝒯": { "codepoints": [119983], "characters": "\uD835\uDCAF" }, + "𝓉": { "codepoints": [120009], "characters": "\uD835\uDCC9" }, + "Ц": { "codepoints": [1062], "characters": "\u0426" }, + "ц": { "codepoints": [1094], "characters": "\u0446" }, + "Ћ": { "codepoints": [1035], "characters": "\u040B" }, + "ћ": { "codepoints": [1115], "characters": "\u045B" }, + "Ŧ": { "codepoints": [358], "characters": "\u0166" }, + "ŧ": { "codepoints": [359], "characters": "\u0167" }, + "≬": { "codepoints": [8812], "characters": "\u226C" }, + "↞": { "codepoints": [8606], "characters": "\u219E" }, + "↠": { "codepoints": [8608], "characters": "\u21A0" }, + "Ú": { "codepoints": [218], "characters": "\u00DA" }, + "Ú": { "codepoints": [218], "characters": "\u00DA" }, + "ú": { "codepoints": [250], "characters": "\u00FA" }, + "ú": { "codepoints": [250], "characters": "\u00FA" }, + "↑": { "codepoints": [8593], "characters": "\u2191" }, + "↟": { "codepoints": [8607], "characters": "\u219F" }, + "⇑": { "codepoints": [8657], "characters": "\u21D1" }, + "⥉": { "codepoints": [10569], "characters": "\u2949" }, + "Ў": { "codepoints": [1038], "characters": "\u040E" }, + "ў": { "codepoints": [1118], "characters": "\u045E" }, + "Ŭ": { "codepoints": [364], "characters": "\u016C" }, + "ŭ": { "codepoints": [365], "characters": "\u016D" }, + "Û": { "codepoints": [219], "characters": "\u00DB" }, + "Û": { "codepoints": [219], "characters": "\u00DB" }, + "û": { "codepoints": [251], "characters": "\u00FB" }, + "û": { "codepoints": [251], "characters": "\u00FB" }, + "У": { "codepoints": [1059], "characters": "\u0423" }, + "у": { "codepoints": [1091], "characters": "\u0443" }, + "⇅": { "codepoints": [8645], "characters": "\u21C5" }, + "Ű": { "codepoints": [368], "characters": "\u0170" }, + "ű": { "codepoints": [369], "characters": "\u0171" }, + "⥮": { "codepoints": [10606], "characters": "\u296E" }, + "⥾": { "codepoints": [10622], "characters": "\u297E" }, + "𝔘": { "codepoints": [120088], "characters": "\uD835\uDD18" }, + "𝔲": { "codepoints": [120114], "characters": "\uD835\uDD32" }, + "Ù": { "codepoints": [217], "characters": "\u00D9" }, + "Ù": { "codepoints": [217], "characters": "\u00D9" }, + "ù": { "codepoints": [249], "characters": "\u00F9" }, + "ù": { "codepoints": [249], "characters": "\u00F9" }, + "⥣": { "codepoints": [10595], "characters": "\u2963" }, + "↿": { "codepoints": [8639], "characters": "\u21BF" }, + "↾": { "codepoints": [8638], "characters": "\u21BE" }, + "▀": { "codepoints": [9600], "characters": "\u2580" }, + "⌜": { "codepoints": [8988], "characters": "\u231C" }, + "⌜": { "codepoints": [8988], "characters": "\u231C" }, + "⌏": { "codepoints": [8975], "characters": "\u230F" }, + "◸": { "codepoints": [9720], "characters": "\u25F8" }, + "Ū": { "codepoints": [362], "characters": "\u016A" }, + "ū": { "codepoints": [363], "characters": "\u016B" }, + "¨": { "codepoints": [168], "characters": "\u00A8" }, + "¨": { "codepoints": [168], "characters": "\u00A8" }, + "_": { "codepoints": [95], "characters": "\u005F" }, + "⏟": { "codepoints": [9183], "characters": "\u23DF" }, + "⎵": { "codepoints": [9141], "characters": "\u23B5" }, + "⏝": { "codepoints": [9181], "characters": "\u23DD" }, + "⋃": { "codepoints": [8899], "characters": "\u22C3" }, + "⊎": { "codepoints": [8846], "characters": "\u228E" }, + "Ų": { "codepoints": [370], "characters": "\u0172" }, + "ų": { "codepoints": [371], "characters": "\u0173" }, + "𝕌": { "codepoints": [120140], "characters": "\uD835\uDD4C" }, + "𝕦": { "codepoints": [120166], "characters": "\uD835\uDD66" }, + "⤒": { "codepoints": [10514], "characters": "\u2912" }, + "↑": { "codepoints": [8593], "characters": "\u2191" }, + "↑": { "codepoints": [8593], "characters": "\u2191" }, + "⇑": { "codepoints": [8657], "characters": "\u21D1" }, + "⇅": { "codepoints": [8645], "characters": "\u21C5" }, + "↕": { "codepoints": [8597], "characters": "\u2195" }, + "↕": { "codepoints": [8597], "characters": "\u2195" }, + "⇕": { "codepoints": [8661], "characters": "\u21D5" }, + "⥮": { "codepoints": [10606], "characters": "\u296E" }, + "↿": { "codepoints": [8639], "characters": "\u21BF" }, + "↾": { "codepoints": [8638], "characters": "\u21BE" }, + "⊎": { "codepoints": [8846], "characters": "\u228E" }, + "↖": { "codepoints": [8598], "characters": "\u2196" }, + "↗": { "codepoints": [8599], "characters": "\u2197" }, + "υ": { "codepoints": [965], "characters": "\u03C5" }, + "ϒ": { "codepoints": [978], "characters": "\u03D2" }, + "ϒ": { "codepoints": [978], "characters": "\u03D2" }, + "Υ": { "codepoints": [933], "characters": "\u03A5" }, + "υ": { "codepoints": [965], "characters": "\u03C5" }, + "↥": { "codepoints": [8613], "characters": "\u21A5" }, + "⊥": { "codepoints": [8869], "characters": "\u22A5" }, + "⇈": { "codepoints": [8648], "characters": "\u21C8" }, + "⌝": { "codepoints": [8989], "characters": "\u231D" }, + "⌝": { "codepoints": [8989], "characters": "\u231D" }, + "⌎": { "codepoints": [8974], "characters": "\u230E" }, + "Ů": { "codepoints": [366], "characters": "\u016E" }, + "ů": { "codepoints": [367], "characters": "\u016F" }, + "◹": { "codepoints": [9721], "characters": "\u25F9" }, + "𝒰": { "codepoints": [119984], "characters": "\uD835\uDCB0" }, + "𝓊": { "codepoints": [120010], "characters": "\uD835\uDCCA" }, + "⋰": { "codepoints": [8944], "characters": "\u22F0" }, + "Ũ": { "codepoints": [360], "characters": "\u0168" }, + "ũ": { "codepoints": [361], "characters": "\u0169" }, + "▵": { "codepoints": [9653], "characters": "\u25B5" }, + "▴": { "codepoints": [9652], "characters": "\u25B4" }, + "⇈": { "codepoints": [8648], "characters": "\u21C8" }, + "Ü": { "codepoints": [220], "characters": "\u00DC" }, + "Ü": { "codepoints": [220], "characters": "\u00DC" }, + "ü": { "codepoints": [252], "characters": "\u00FC" }, + "ü": { "codepoints": [252], "characters": "\u00FC" }, + "⦧": { "codepoints": [10663], "characters": "\u29A7" }, + "⦜": { "codepoints": [10652], "characters": "\u299C" }, + "ϵ": { "codepoints": [1013], "characters": "\u03F5" }, + "ϰ": { "codepoints": [1008], "characters": "\u03F0" }, + "∅": { "codepoints": [8709], "characters": "\u2205" }, + "ϕ": { "codepoints": [981], "characters": "\u03D5" }, + "ϖ": { "codepoints": [982], "characters": "\u03D6" }, + "∝": { "codepoints": [8733], "characters": "\u221D" }, + "↕": { "codepoints": [8597], "characters": "\u2195" }, + "⇕": { "codepoints": [8661], "characters": "\u21D5" }, + "ϱ": { "codepoints": [1009], "characters": "\u03F1" }, + "ς": { "codepoints": [962], "characters": "\u03C2" }, + "⊊︀": { "codepoints": [8842, 65024], "characters": "\u228A\uFE00" }, + "⫋︀": { "codepoints": [10955, 65024], "characters": "\u2ACB\uFE00" }, + "⊋︀": { "codepoints": [8843, 65024], "characters": "\u228B\uFE00" }, + "⫌︀": { "codepoints": [10956, 65024], "characters": "\u2ACC\uFE00" }, + "ϑ": { "codepoints": [977], "characters": "\u03D1" }, + "⊲": { "codepoints": [8882], "characters": "\u22B2" }, + "⊳": { "codepoints": [8883], "characters": "\u22B3" }, + "⫨": { "codepoints": [10984], "characters": "\u2AE8" }, + "⫫": { "codepoints": [10987], "characters": "\u2AEB" }, + "⫩": { "codepoints": [10985], "characters": "\u2AE9" }, + "В": { "codepoints": [1042], "characters": "\u0412" }, + "в": { "codepoints": [1074], "characters": "\u0432" }, + "⊢": { "codepoints": [8866], "characters": "\u22A2" }, + "⊨": { "codepoints": [8872], "characters": "\u22A8" }, + "⊩": { "codepoints": [8873], "characters": "\u22A9" }, + "⊫": { "codepoints": [8875], "characters": "\u22AB" }, + "⫦": { "codepoints": [10982], "characters": "\u2AE6" }, + "⊻": { "codepoints": [8891], "characters": "\u22BB" }, + "∨": { "codepoints": [8744], "characters": "\u2228" }, + "⋁": { "codepoints": [8897], "characters": "\u22C1" }, + "≚": { "codepoints": [8794], "characters": "\u225A" }, + "⋮": { "codepoints": [8942], "characters": "\u22EE" }, + "|": { "codepoints": [124], "characters": "\u007C" }, + "‖": { "codepoints": [8214], "characters": "\u2016" }, + "|": { "codepoints": [124], "characters": "\u007C" }, + "‖": { "codepoints": [8214], "characters": "\u2016" }, + "∣": { "codepoints": [8739], "characters": "\u2223" }, + "|": { "codepoints": [124], "characters": "\u007C" }, + "❘": { "codepoints": [10072], "characters": "\u2758" }, + "≀": { "codepoints": [8768], "characters": "\u2240" }, + " ": { "codepoints": [8202], "characters": "\u200A" }, + "𝔙": { "codepoints": [120089], "characters": "\uD835\uDD19" }, + "𝔳": { "codepoints": [120115], "characters": "\uD835\uDD33" }, + "⊲": { "codepoints": [8882], "characters": "\u22B2" }, + "⊂⃒": { "codepoints": [8834, 8402], "characters": "\u2282\u20D2" }, + "⊃⃒": { "codepoints": [8835, 8402], "characters": "\u2283\u20D2" }, + "𝕍": { "codepoints": [120141], "characters": "\uD835\uDD4D" }, + "𝕧": { "codepoints": [120167], "characters": "\uD835\uDD67" }, + "∝": { "codepoints": [8733], "characters": "\u221D" }, + "⊳": { "codepoints": [8883], "characters": "\u22B3" }, + "𝒱": { "codepoints": [119985], "characters": "\uD835\uDCB1" }, + "𝓋": { "codepoints": [120011], "characters": "\uD835\uDCCB" }, + "⫋︀": { "codepoints": [10955, 65024], "characters": "\u2ACB\uFE00" }, + "⊊︀": { "codepoints": [8842, 65024], "characters": "\u228A\uFE00" }, + "⫌︀": { "codepoints": [10956, 65024], "characters": "\u2ACC\uFE00" }, + "⊋︀": { "codepoints": [8843, 65024], "characters": "\u228B\uFE00" }, + "⊪": { "codepoints": [8874], "characters": "\u22AA" }, + "⦚": { "codepoints": [10650], "characters": "\u299A" }, + "Ŵ": { "codepoints": [372], "characters": "\u0174" }, + "ŵ": { "codepoints": [373], "characters": "\u0175" }, + "⩟": { "codepoints": [10847], "characters": "\u2A5F" }, + "∧": { "codepoints": [8743], "characters": "\u2227" }, + "⋀": { "codepoints": [8896], "characters": "\u22C0" }, + "≙": { "codepoints": [8793], "characters": "\u2259" }, + "℘": { "codepoints": [8472], "characters": "\u2118" }, + "𝔚": { "codepoints": [120090], "characters": "\uD835\uDD1A" }, + "𝔴": { "codepoints": [120116], "characters": "\uD835\uDD34" }, + "𝕎": { "codepoints": [120142], "characters": "\uD835\uDD4E" }, + "𝕨": { "codepoints": [120168], "characters": "\uD835\uDD68" }, + "℘": { "codepoints": [8472], "characters": "\u2118" }, + "≀": { "codepoints": [8768], "characters": "\u2240" }, + "≀": { "codepoints": [8768], "characters": "\u2240" }, + "𝒲": { "codepoints": [119986], "characters": "\uD835\uDCB2" }, + "𝓌": { "codepoints": [120012], "characters": "\uD835\uDCCC" }, + "⋂": { "codepoints": [8898], "characters": "\u22C2" }, + "◯": { "codepoints": [9711], "characters": "\u25EF" }, + "⋃": { "codepoints": [8899], "characters": "\u22C3" }, + "▽": { "codepoints": [9661], "characters": "\u25BD" }, + "𝔛": { "codepoints": [120091], "characters": "\uD835\uDD1B" }, + "𝔵": { "codepoints": [120117], "characters": "\uD835\uDD35" }, + "⟷": { "codepoints": [10231], "characters": "\u27F7" }, + "⟺": { "codepoints": [10234], "characters": "\u27FA" }, + "Ξ": { "codepoints": [926], "characters": "\u039E" }, + "ξ": { "codepoints": [958], "characters": "\u03BE" }, + "⟵": { "codepoints": [10229], "characters": "\u27F5" }, + "⟸": { "codepoints": [10232], "characters": "\u27F8" }, + "⟼": { "codepoints": [10236], "characters": "\u27FC" }, + "⋻": { "codepoints": [8955], "characters": "\u22FB" }, + "⨀": { "codepoints": [10752], "characters": "\u2A00" }, + "𝕏": { "codepoints": [120143], "characters": "\uD835\uDD4F" }, + "𝕩": { "codepoints": [120169], "characters": "\uD835\uDD69" }, + "⨁": { "codepoints": [10753], "characters": "\u2A01" }, + "⨂": { "codepoints": [10754], "characters": "\u2A02" }, + "⟶": { "codepoints": [10230], "characters": "\u27F6" }, + "⟹": { "codepoints": [10233], "characters": "\u27F9" }, + "𝒳": { "codepoints": [119987], "characters": "\uD835\uDCB3" }, + "𝓍": { "codepoints": [120013], "characters": "\uD835\uDCCD" }, + "⨆": { "codepoints": [10758], "characters": "\u2A06" }, + "⨄": { "codepoints": [10756], "characters": "\u2A04" }, + "△": { "codepoints": [9651], "characters": "\u25B3" }, + "⋁": { "codepoints": [8897], "characters": "\u22C1" }, + "⋀": { "codepoints": [8896], "characters": "\u22C0" }, + "Ý": { "codepoints": [221], "characters": "\u00DD" }, + "Ý": { "codepoints": [221], "characters": "\u00DD" }, + "ý": { "codepoints": [253], "characters": "\u00FD" }, + "ý": { "codepoints": [253], "characters": "\u00FD" }, + "Я": { "codepoints": [1071], "characters": "\u042F" }, + "я": { "codepoints": [1103], "characters": "\u044F" }, + "Ŷ": { "codepoints": [374], "characters": "\u0176" }, + "ŷ": { "codepoints": [375], "characters": "\u0177" }, + "Ы": { "codepoints": [1067], "characters": "\u042B" }, + "ы": { "codepoints": [1099], "characters": "\u044B" }, + "¥": { "codepoints": [165], "characters": "\u00A5" }, + "¥": { "codepoints": [165], "characters": "\u00A5" }, + "𝔜": { "codepoints": [120092], "characters": "\uD835\uDD1C" }, + "𝔶": { "codepoints": [120118], "characters": "\uD835\uDD36" }, + "Ї": { "codepoints": [1031], "characters": "\u0407" }, + "ї": { "codepoints": [1111], "characters": "\u0457" }, + "𝕐": { "codepoints": [120144], "characters": "\uD835\uDD50" }, + "𝕪": { "codepoints": [120170], "characters": "\uD835\uDD6A" }, + "𝒴": { "codepoints": [119988], "characters": "\uD835\uDCB4" }, + "𝓎": { "codepoints": [120014], "characters": "\uD835\uDCCE" }, + "Ю": { "codepoints": [1070], "characters": "\u042E" }, + "ю": { "codepoints": [1102], "characters": "\u044E" }, + "ÿ": { "codepoints": [255], "characters": "\u00FF" }, + "ÿ": { "codepoints": [255], "characters": "\u00FF" }, + "Ÿ": { "codepoints": [376], "characters": "\u0178" }, + "Ź": { "codepoints": [377], "characters": "\u0179" }, + "ź": { "codepoints": [378], "characters": "\u017A" }, + "Ž": { "codepoints": [381], "characters": "\u017D" }, + "ž": { "codepoints": [382], "characters": "\u017E" }, + "З": { "codepoints": [1047], "characters": "\u0417" }, + "з": { "codepoints": [1079], "characters": "\u0437" }, + "Ż": { "codepoints": [379], "characters": "\u017B" }, + "ż": { "codepoints": [380], "characters": "\u017C" }, + "ℨ": { "codepoints": [8488], "characters": "\u2128" }, + "​": { "codepoints": [8203], "characters": "\u200B" }, + "Ζ": { "codepoints": [918], "characters": "\u0396" }, + "ζ": { "codepoints": [950], "characters": "\u03B6" }, + "𝔷": { "codepoints": [120119], "characters": "\uD835\uDD37" }, + "ℨ": { "codepoints": [8488], "characters": "\u2128" }, + "Ж": { "codepoints": [1046], "characters": "\u0416" }, + "ж": { "codepoints": [1078], "characters": "\u0436" }, + "⇝": { "codepoints": [8669], "characters": "\u21DD" }, + "𝕫": { "codepoints": [120171], "characters": "\uD835\uDD6B" }, + "ℤ": { "codepoints": [8484], "characters": "\u2124" }, + "𝒵": { "codepoints": [119989], "characters": "\uD835\uDCB5" }, + "𝓏": { "codepoints": [120015], "characters": "\uD835\uDCCF" }, + "‍": { "codepoints": [8205], "characters": "\u200D" }, + "‌": { "codepoints": [8204], "characters": "\u200C" } +}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/common/form-submission.py b/third_party/WebKit/LayoutTests/imported/wpt/common/form-submission.py index 78f96fe..4678754 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/common/form-submission.py +++ b/third_party/WebKit/LayoutTests/imported/wpt/common/form-submission.py
@@ -1,17 +1,10 @@ def main(request, response): if request.headers.get('Content-Type') == 'application/x-www-form-urlencoded': - if request.body == 'foo=bara': - return 'OK' - else: - return 'FAIL' + result = request.body == 'foo=bara' elif request.headers.get('Content-Type') == 'text/plain': - if request.body == 'qux=baz\r\n': - return 'OK' - else: - return 'FAIL' + result = request.body == 'qux=baz\r\n' else: - if request.POST.first('foo') == 'bar': - return 'OK' - else: - return 'FAIL' + result = request.POST.first('foo') == 'bar' + return ([("Content-Type", "text/plain")], + "OK" if result else "FAIL")
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/dom/nodes/Document-createEvent-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/dom/nodes/Document-createEvent-expected.txt index 2b16dc3..157dd2d1 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/dom/nodes/Document-createEvent-expected.txt +++ b/third_party/WebKit/LayoutTests/imported/wpt/dom/nodes/Document-createEvent-expected.txt
@@ -1,4 +1,3 @@ -CONSOLE WARNING: line 13: 'SVGZoomEvent' is deprecated and will be removed in M52, around July 2016. See https://www.chromestatus.com/features/5760883808534528 for more details. This is a testharness.js-based test. PASS AnimationEvent should be an alias for AnimationEvent. PASS createEvent('AnimationEvent') should be initialized correctly. @@ -164,14 +163,14 @@ FAIL createEvent('svgevents') should be initialized correctly. Cannot read property 'type' of undefined FAIL SVGEVENTS should be an alias for Event. Failed to execute 'createEvent' on 'Document': The provided event type ('SVGEVENTS') is invalid. FAIL createEvent('SVGEVENTS') should be initialized correctly. Cannot read property 'type' of undefined -PASS SVGZoomEvent should be an alias for SVGZoomEvent. -PASS createEvent('SVGZoomEvent') should be initialized correctly. +FAIL SVGZoomEvent should be an alias for SVGZoomEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('SVGZoomEvent') is invalid. +FAIL createEvent('SVGZoomEvent') should be initialized correctly. Cannot read property 'type' of undefined FAIL svgzoomevent should be an alias for SVGZoomEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('svgzoomevent') is invalid. FAIL createEvent('svgzoomevent') should be initialized correctly. Cannot read property 'type' of undefined FAIL SVGZOOMEVENT should be an alias for SVGZoomEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('SVGZOOMEVENT') is invalid. FAIL createEvent('SVGZOOMEVENT') should be initialized correctly. Cannot read property 'type' of undefined -PASS SVGZoomEvents should be an alias for SVGZoomEvent. -PASS createEvent('SVGZoomEvents') should be initialized correctly. +FAIL SVGZoomEvents should be an alias for SVGZoomEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('SVGZoomEvents') is invalid. +FAIL createEvent('SVGZoomEvents') should be initialized correctly. Cannot read property 'type' of undefined FAIL svgzoomevents should be an alias for SVGZoomEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('svgzoomevents') is invalid. FAIL createEvent('svgzoomevents') should be initialized correctly. Cannot read property 'type' of undefined FAIL SVGZOOMEVENTS should be an alias for SVGZoomEvent. Failed to execute 'createEvent' on 'Document': The provided event type ('SVGZOOMEVENTS') is invalid.
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/document-without-browsing-context-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/document-without-browsing-context-expected.txt new file mode 100644 index 0000000..782baefd --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/document-without-browsing-context-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +FAIL Create a document, adopt the node assert_equals: expected "1" but got "def main(request, response):\n try:\n count = int(request.server.stash.take(request.GET[\"id\"]))\n except:\n count = 0\n if \"count\" in request.GET:\n return str(count)\n request.server.stash.put(request.GET[\"id\"], str(count + 1))\n return 'body { color: red }'\n" +FAIL Create a stylesheet in innerHTML document assert_equals: expected "1" but got "def main(request, response):\n try:\n count = int(request.server.stash.take(request.GET[\"id\"]))\n except:\n count = 0\n if \"count\" in request.GET:\n return str(count)\n request.server.stash.put(request.GET[\"id\"], str(count + 1))\n return 'body { color: red }'\n" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/document-without-browsing-context.html b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/document-without-browsing-context.html new file mode 100644 index 0000000..127b253 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/document-without-browsing-context.html
@@ -0,0 +1,35 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Documents without browsing contexts should not load stylesheets</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> +<body> +<script> + function count(id, t) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', 'stylesheet.py?count=1&id=' + id); + xhr.onload = t.step_func_done(function() { + assert_equals(xhr.responseText, "1"); + }); + xhr.onerror = t.unreached_func(); + xhr.send(); + } + + async_test(function(t) { + var id = token(); + var doc = (new DOMParser()).parseFromString('<link rel="stylesheet" href="stylesheet.py?id=' + id + '"></link>', 'text/html'); + var link = doc.querySelector('link'); + document.head.appendChild(link); + t.step_timeout(function() { count(id, t) }, 500); + }, 'Create a document, adopt the node'); + + async_test(function(t) { + var id = token(); + var d = document.createElement('div'); + document.body.appendChild(d); + d.innerHTML = '<link rel="stylesheet" href="stylesheet.py?id=' + id + '"></link>'; + t.step_timeout(function() { count(id, t) }, 500); + }, 'Create a stylesheet in innerHTML document'); +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/link-style-error-01.html b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/link-style-error-01.html index ce35e03..0460846 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/link-style-error-01.html +++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/link-style-error-01.html
@@ -7,17 +7,32 @@ <div id="log"></div> <div id="test"> <script> -//var t404 = async_test("Should get an error event for a 404 error.") -//t404.step(function() { -// var elt = document.createElement("link"); -// elt.onerror = t404.step_func(function() { -// assert_true(true, "Got error event for 404 error.") -// t404.done() -// }) -// elt.rel = "stylesheet"; -// elt.href = 404 error; -// document.getElementsByTagName("head")[0].appendChild(elt); -//}) +var t404 = async_test("Should get an error event for a 404 error.") +t404.step(function() { + var elt = document.createElement("link"); + elt.onerror = t404.step_func(function() { + assert_true(true, "Got error event for 404 error.") + t404.step_timeout(function() { t404.done() }, 0); + }) + elt.onload = t404.unreached_func("load event should not be fired"); + elt.rel = "stylesheet"; + elt.href = "nonexistent_stylesheet.css"; + document.getElementsByTagName("head")[0].appendChild(elt); +}) + +var tUnsupported = async_test("Should get an error event for an unsupported URL.") +tUnsupported.step(function() { + var elt = document.createElement("link"); + elt.onerror = tUnsupported.step_func(function() { + assert_true(true, "Got error event for unsupported URL.") + tUnsupported.step_timeout(function() { tUnsupported.done() }, 0); + }) + elt.onload = tUnsupported.unreached_func("load event should not be fired"); + elt.rel = "stylesheet"; + elt.href = "nonexistent:stylesheet.css"; + document.getElementsByTagName("head")[0].appendChild(elt); +}) + var tText = async_test("Should get an error event for a text/plain response.") tText.step(function() { var elt = document.createElement("link");
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/stylesheet.py b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/stylesheet.py new file mode 100644 index 0000000..a312e9e8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/document-metadata/the-link-element/stylesheet.py
@@ -0,0 +1,9 @@ +def main(request, response): + try: + count = int(request.server.stash.take(request.GET["id"])) + except: + count = 0 + if "count" in request.GET: + return str(count) + request.server.stash.put(request.GET["id"], str(count + 1)) + return 'body { color: red }'
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues.html b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues.html index 11d33b77..4b7808c9 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues.html +++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues.html
@@ -79,7 +79,7 @@ var video = document.createElement('video'); var t1 = video.addTextTrack('subtitles'); var t1_cues = t1.cues; - t1.mode = 'showing'; + t1.mode = 'hidden'; var track = document.createElement('track'); track['default'] = true; video.appendChild(track); // queues a task to "honor user preferences...", media element event task source
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/the-img-element/invalid-src.html b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/the-img-element/invalid-src.html new file mode 100644 index 0000000..a4323da --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/embedded-content/the-img-element/invalid-src.html
@@ -0,0 +1,21 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Loading a non-parsing URL as an image should silently fail; triggering appropriate events</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<img id=myimg /> +<script> +async_test(function(t) { + var img = document.getElementById("myimg"); + img.src = "http://also a broken url"; + var errorevent = false; + + // The errors should be queued in the event loop, so they should only trigger + // after this block of code finishes, not during the img.src setter itself + img.addEventListener('error', t.step_func(function(){errorevent = true;})); + img.addEventListener('loadend', t.step_func_done(function() { + assert_true(errorevent, "error event fired"); + })); +}); + +</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html index 5f52573..60d591ba 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html +++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html
@@ -32,6 +32,18 @@ },'input setSelectionRange(0,input.value.length+1)'); test(function() { + input.setSelectionRange(input.value.length+1,input.value.length+1) + assert_equals(input.selectionStart, input.value.length, "Arguments (start) greater than the length of the value of the text field must be treated as pointing at the end of the text field"); + assert_equals(input.selectionEnd, input.value.length, "Arguments (end) greater than the length of the value of the text field must be treated as pointing at the end of the text field"); + },'input setSelectionRange(input.value.length+1,input.value.length+1)'); + + test(function() { + input.setSelectionRange(input.value.length+1,1) + assert_equals(input.selectionStart, 1, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end"); + assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1"); + },'input setSelectionRange(input.value.length+1,input.value.length+1)'); + + test(function() { input.setSelectionRange(2,2) assert_equals(input.selectionStart, 2, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end"); assert_equals(input.selectionEnd, 2, "If end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end"); @@ -74,6 +86,18 @@ },'input direction of setSelectionRange(0,1)'); test(function() { + input.setSelectionRange(1,-1); + assert_equals(input.selectionStart, 1, "element.selectionStart should be 1"); + assert_equals(input.selectionEnd, input.value.length, "ECMAScript conversion to unsigned long"); + },'input setSelectionRange(1,-1)'); + + test(function() { + input.setSelectionRange(-1,1); + assert_equals(input.selectionStart, 1, "ECMAScript conversion to unsigned long + if end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end"); + assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1"); + },'input setSelectionRange(-1,1)'); + + test(function() { input.setSelectionRange("string",1); assert_equals(input.selectionStart, 0, "element.selectionStart should be 0"); assert_equals(input.selectionEnd, 1, "element.selectionEnd should be 1");
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.html b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.html new file mode 100644 index 0000000..704e8ed --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.html
@@ -0,0 +1,18 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Script is not executed after script thread is shutdown</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe id="testiframe" src="script-not-executed-after-shutdown-child.html"></iframe> +<script> +async_test(function(t) { + window.script_executed = t.unreached_func("script executed in removed iframe"); + let iframe = document.getElementById("testiframe"); + iframe.onload = function() { + iframe.parentNode.removeChild(iframe); + }; + setTimeout(function() { + t.done(); + }, 5000); +}); +</script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.js b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.js new file mode 100644 index 0000000..ccdf14c0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.js
@@ -0,0 +1 @@ +script_executed();
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/html/the-xhtml-syntax/parsing-xhtml-documents/xhtml-mathml-dtd-entity-support.htm b/third_party/WebKit/LayoutTests/imported/wpt/html/the-xhtml-syntax/parsing-xhtml-documents/xhtml-mathml-dtd-entity-support.htm index 4494f7f3..6d19229 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/html/the-xhtml-syntax/parsing-xhtml-documents/xhtml-mathml-dtd-entity-support.htm +++ b/third_party/WebKit/LayoutTests/imported/wpt/html/the-xhtml-syntax/parsing-xhtml-documents/xhtml-mathml-dtd-entity-support.htm
@@ -35,8 +35,7 @@ setup(function() {}, {explicit_done: true}); var xhr = new XMLHttpRequest(); - //xhr.open("GET", "entities.json"); - xhr.open("GET", "https://w3c.github.io/html/entities.json"); + xhr.open("GET", "/common/entities.json"); xhr.onload = function () { // Note: for proper XML parsing of the Doctype, Edge requires a non-empty string for url part var entitiesJSON = JSON.parse(xhr.response);
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/README.md b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/README.md index 07004cf..0cc01909 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/README.md +++ b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/README.md
@@ -1,6 +1,6 @@ Directory for Pointer Events Tests -Latest Editor's Draft: https://dvcs.w3.org/hg/pointerevents/raw-file/tip/pointerEvents.html +Latest Editor's Draft: https://w3c.github.io/pointerevents/ Latest W3C Technical Report: http://www.w3.org/TR/pointerevents/
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_button_attribute_mouse-manual.html b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_button_attribute_mouse-manual.html deleted file mode 100644 index a31e53d..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_button_attribute_mouse-manual.html +++ /dev/null
@@ -1,57 +0,0 @@ -<!doctype html> -<html> - <head> - <title>Button and buttons attribute test for mouse</title> - <meta name="viewport" content="width=device-width"> - <link rel="stylesheet" type="text/css" href="pointerevent_styles.css"> - <script src="/resources/testharness.js"></script> - <script src="/resources/testharnessreport.js"></script> - <script type="text/javascript" src="pointerevent_support.js"></script> - </head> - <body onload="run()"> - <h1>Button attribute test for mouse</h1> - <h2>This test is for mouse only</h2> - <h4> - Test Description: This test checks if button attribute for mouse handled properly. - <p>Put your mouse over the black rectangle</p> - </h4> - <p> - <div id="target0" style="background:black"></div> - <script> - var eventTested = false; - var detected_pointertypes = {}; - - setup({ explicit_done: true }); - add_completion_callback(showPointerTypes); - - function run() { - var target0 = document.getElementById("target0"); - - // If pointerType is "mouse" and no mouse button is depressed, then the button attribute of the pointermove event must be -1 and the buttons attribute must be 0. - // TA: 5.8 - on_event(target0, "pointerover", function (event) { - detected_pointertypes[event.pointerType] = true; - if(event.pointerType != "mouse") { - alert("Use mouse for this test please!"); - return; - } - if (eventTested == false) { - test(function() { - assert_true(event.button == -1, "If mouse buttons are released button attribute is -1") - }, "If mouse buttons are released button attribute is -1"); - test(function() { - assert_true(event.buttons == 0, "If mouse buttons are released buttons attribute is 0") - }, "If mouse buttons are released buttons attribute is 0"); - eventTested = true; - done(); - } - }); - } - </script> - <h1>Pointer Events button attribute test for mouse test</h1> - <div id="complete-notice"> - <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p> - </div> - <div id="log"></div> - </body> -</html> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_properties_mouse-manual.html b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_properties_mouse-manual.html deleted file mode 100644 index adea65b2..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_properties_mouse-manual.html +++ /dev/null
@@ -1,76 +0,0 @@ -<!doctype html> -<html> - <head> - <title>Pointer Events properties tests</title> - <meta name="viewport" content="width=device-width"> - <link rel="stylesheet" type="text/css" href="pointerevent_styles.css"> - <script src="/resources/testharness.js"></script> - <script src="/resources/testharnessreport.js"></script> - <!-- Additional helper script for common checks across event types --> - <script type="text/javascript" src="pointerevent_support.js"></script> - <script> - var detected_pointertypes = {}; - var detected_eventTypes = {}; - var test_pointerEvent = async_test("pointerdown event received"); - // showPointerTypes is defined in pointerevent_support.js - // Requirements: the callback function will reference the test_pointerEvent object and - // will fail unless the async_test is created with the var name "test_pointerEvent". - add_completion_callback(showPointerTypes); - - function run() { - var square1 = document.getElementById("square1"); - var rectSquare1 = square1.getBoundingClientRect(); - var pointerover_event; - - var eventList = ['pointerenter', 'pointerover', 'pointermove', 'pointerdown', 'pointerup', 'pointerout', 'pointerleave']; - eventList.forEach(function(eventName) { - on_event(square1, eventName, function (event) { - if (detected_eventTypes[event.type]) - return; - detected_pointertypes[event.pointerType] = true; - test(function () { - assert_equals(event.pointerType, 'mouse', 'pointerType should be mouse'); - }, event.type + ".pointerType attribute is correct."); - - if (event.type != 'pointerout' && event.type != 'pointerleave' ) { - test(function () { - assert_true(event.clientX >= rectSquare1.left && event.clientX < rectSquare1.right, "ClientX should be in the boundaries of the black box"); - }, event.type + ".clientX attribute is correct."); - test(function () { - assert_true(event.clientY >= rectSquare1.top && event.clientY < rectSquare1.bottom, "ClientY should be in the boundaries of the black box"); - }, event.type + ".clientY attribute is correct."); - } else { - test(function () { - assert_true(event.clientX < rectSquare1.left || event.clientX > rectSquare1.right - 1 || event.clientY < rectSquare1.top || event.clientY > rectSquare1.bottom - 1, "ClientX/Y should be out of the boundaries of the black box"); - }, event.type + "'s ClientX and ClientY attributes are correct."); - } - - test(function () { - assert_equals(event.isPrimary, true, "isPrimary should be true"); - }, event.type + ".isPrimary attribute is correct."); - - check_PointerEvent(event); - detected_eventTypes[event.type] = true; - if (Object.keys(detected_eventTypes).length == eventList.length) - test_pointerEvent.done(); - }); - }); - } - </script> - </head> - <body onload="run()"> - <h1>Pointer Events pointerdown tests</h1> - <h4> - Test Description: This test checks the properties of mouse pointer events. Move your mouse over the black square and click on it. Then move it off the black square. - </h4> - Test passes if the proper behavior of the events is observed. - <div id="square1" class="square"></div> - <div class="spacer"></div> - <div id="complete-notice"> - <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p> - <p>Refresh the page to run the tests again with a different pointer type.</p> - </div> - <div id="log"></div> - </body> -</html> -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_styles.css b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_styles.css index 70b037a9..d2acf94 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_styles.css +++ b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_styles.css
@@ -31,6 +31,17 @@ overflow-x: auto; } +.touchActionNone { +touch-action: none; +} + +#innerframe { +width: 90%; +margin: 10px; +margin-left: 10%; +height: 200px; +} + .scroller { width: 700px; height: 430px; @@ -66,6 +77,10 @@ font-weight: bold; } +#event-log { +font-weight: bold; +} + #listener { background: orange; border: 1px solid orange;
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_support.js b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_support.js index b3fb661..6f399706 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_support.js +++ b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_support.js
@@ -105,6 +105,14 @@ complete_notice.style.display = "block"; } +function showLoggedEvents() { + var event_log_elem = document.getElementById("event-log"); + event_log_elem.innerHTML = event_log.length ? event_log.join(", ") : "(none)"; + + var complete_notice = document.getElementById("complete-notice"); + complete_notice.style.display = "block"; +} + function log(msg, el) { if (++count > 10){ count = 0; @@ -167,4 +175,4 @@ } catch(e) { } -} \ No newline at end of file +}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_suppress_compat_events_on_click.html b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_suppress_compat_events_on_click.html new file mode 100644 index 0000000..71b8a082 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_suppress_compat_events_on_click.html
@@ -0,0 +1,101 @@ +<!doctype html> +<html> + <head> + <title>Pointer Event: Suppress compatibility mouse events on click</title> + <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/> + <link rel="author" title="Google" href="http://www.google.com "/> + <meta name="assert" content="When a pointerdown is canceled, a click/tap shouldn't fire any compatibility mouse events."/> + <link rel="stylesheet" type="text/css" href="pointerevent_styles.css"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script type="text/javascript" src="pointerevent_support.js"></script> + <script type="text/javascript"> + var test_pointerEvent = async_test("Suppress compat mouse events on click"); + add_completion_callback(end_of_test); + + var detected_pointertypes = {}; + var event_log = []; + + function end_of_test() { + showLoggedEvents(); + showPointerTypes(); + } + + function end_of_interaction() { + test(function () { + assert_equals(event_log.join(", "), + "mousedown@target1, mouseup@target1"); + }, "Event log"); + + test_pointerEvent.done(); // complete test + } + + function run() { + on_event(document.getElementById("done"), "click", end_of_interaction); + + var target_list = ["target0", "target1"]; + var pointer_event_list = ["pointerdown"]; + var mouse_event_list = ["mousedown", "mouseup"]; + + target_list.forEach(function(targetId) { + var target = document.getElementById(targetId); + + pointer_event_list.forEach(function(eventName) { + on_event(target, eventName, function (event) { + detected_pointertypes[event.pointerType] = true; + var label = event.type + "@" + targetId; + + test(function () { + assert_true(event.isPrimary); + }, "primary pointer " + label); + + if (label === "pointerdown@target0") + event.preventDefault(); + }); + }); + + mouse_event_list.forEach(function(eventName) { + on_event(target, eventName, function (event) { + event_log.push(event.type + "@" + targetId); + }); + }); + }); + } + </script> + <style> + #target0, #target1 { + margin: 20px; + } + + #done { + margin: 20px; + border: 2px solid black; + } + </style> + </head> + <body onload="run()"> + <h1>Pointer Event: Suppress compatibility mouse events on click</h1> + <h4> + When a pointerdown is canceled, a click/tap shouldn't fire any compatibility mouse events. + </h4> + <ol> + <li> Click or tap on Target0.</li> + <li> Click or tap on Target1.</li> + <li> Click Done.</li> + </ol> + <div id="target0"> + Target0 + </div> + <div id="target1"> + Target1 + </div> + <div id="done"> + Done + </div> + <div id="complete-notice"> + <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p> + <p>The following events were logged: <span id="event-log"></span>.</p> + </div> + <div id="log"></div> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse.html b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse.html new file mode 100644 index 0000000..02bca85 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/pointerevent_suppress_compat_events_on_drag_mouse.html
@@ -0,0 +1,114 @@ +<!doctype html> +<html> + <head> + <title>Pointer Event: Suppress compatibility mouse events on drag</title> + <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/> + <link rel="author" title="Google" href="http://www.google.com "/> + <meta name="assert" content="When a pointerdown is canceled, a mouse drag shouldn't fire any compatibility mouse events."/> + <link rel="stylesheet" type="text/css" href="pointerevent_styles.css"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script type="text/javascript" src="pointerevent_support.js"></script> + <script type="text/javascript"> + var test_pointerEvent = async_test("Suppress compat mouse events on drag"); + add_completion_callback(end_of_test); + + var detected_pointertypes = {}; + var event_log = []; + + function end_of_test() { + showLoggedEvents(); + showPointerTypes(); + } + + var include_next_mousemove = false; + + // Limits logging/testing of mousemove. + function drop_event(event_type) { + return (event_type == "mousemove" && !include_next_mousemove); + } + + function end_of_interaction() { + test(function () { + assert_equals(event_log.join(", "), + "mousedown@target1, mousemove@target1, mouseup@target1"); + }, "Event log"); + + test_pointerEvent.done(); // complete test + } + + function run() { + on_event(document.getElementById("done"), "click", end_of_interaction); + + var target_list = ["target0", "target1"]; + var pointer_event_list = ["pointerdown"]; + var mouse_event_list = ["mousedown", "mouseup", "mousemove"]; + + target_list.forEach(function(targetId) { + var target = document.getElementById(targetId); + + pointer_event_list.forEach(function(eventName) { + on_event(target, eventName, function (event) { + detected_pointertypes[event.pointerType] = true; + var label = event.type + "@" + targetId; + + test(function () { + assert_true(event.isPrimary); + }, "primary pointer " + label); + + if (label === "pointerdown@target0") + event.preventDefault(); + }); + }); + + mouse_event_list.forEach(function(eventName) { + on_event(target, eventName, function (event) { + if (drop_event(event.type)) + return; + + event_log.push(event.type + "@" + targetId); + + include_next_mousemove = (event.type == "mousedown"); + }); + }); + }); + } + </script> + <style> + #target0, #target1 { + margin: 20px; + touch-action: none; + } + + #done { + margin: 20px; + border: 2px solid black; + } + </style> + </head> + <body onload="run()"> + <h1>Pointer Event: Suppress compatibility mouse events on drag</h1> + <h4> + When a pointerdown is canceled, a mouse drag shouldn't fire any compatibility mouse events. + </h4> + <ol> + <li> Drag mouse within Target0 & release.</li> + <li> Drag mouse within Target1 & release.</li> + <li> Click Done.</li> + </ol> + <div id="target0"> + Target0 + </div> + <div id="target1"> + Target1 + </div> + <div id="done"> + Done + </div> + <div id="complete-notice"> + <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p> + <p>The following events were logged: <span id="event-log"></span>.</p> + </div> + <div id="log"></div> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/resources/pointerevent_pointerId_scope-iframe.html b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/resources/pointerevent_pointerId_scope-iframe.html new file mode 100644 index 0000000..ad1a57f --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt/pointerevents/resources/pointerevent_pointerId_scope-iframe.html
@@ -0,0 +1,37 @@ +<!doctype html> +<html> + <!-- +Test cases for Pointer Events v1 spec +This document references Test Assertions (abbrev TA below) written by Cathy Chan +http://www.w3.org/wiki/PointerEvents/TestAssertions +--> + <head> + <title>Pointer Events pointerdown tests</title> + <meta name="viewport" content="width=device-width"> + <link rel="stylesheet" type="text/css" href="../pointerevent_styles.css"> + <script> + function run() { + var target1 = document.getElementById("target1"); + var pointerover_event; + var ponterId = null; + + var eventList = ['pointerenter', 'pointerover', 'pointermove', 'pointerout', 'pointerleave']; + + eventList.forEach(function(eventName) { + target1.addEventListener(eventName, function (event) { + var pass_data = { + 'pointerId' : event.pointerId, + 'type' : event.type, + 'pointerType' : event.pointerType + }; + top.postMessage(JSON.stringify(pass_data), "*"); + }); + }); + } + </script> + </head> + <body onload="run()"> + <div id="target1" class="touchActionNone"> + </div> + </body> +</html>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/resources/idlharness.js b/third_party/WebKit/LayoutTests/imported/wpt/resources/idlharness.js index b6a16af..5002ec5 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/resources/idlharness.js +++ b/third_party/WebKit/LayoutTests/imported/wpt/resources/idlharness.js
@@ -307,6 +307,28 @@ return ret; }; +function exposed_in(globals) { + if ('document' in self) { + return globals.indexOf("Window") >= 0; + } + if ('DedicatedWorkerGlobalScope' in self && + self instanceof DedicatedWorkerGlobalScope) { + return globals.indexOf("Worker") >= 0 || + globals.indexOf("DedicatedWorker") >= 0; + } + if ('SharedWorkerGlobalScope' in self && + self instanceof SharedWorkerGlobalScope) { + return globals.indexOf("Worker") >= 0 || + globals.indexOf("SharedWorker") >= 0; + } + if ('ServiceWorkerGlobalScope' in self && + self instanceof ServiceWorkerGlobalScope) { + return globals.indexOf("Worker") >= 0 || + globals.indexOf("ServiceWorker") >= 0; + } + throw "Unexpected global object"; +} + //@} IdlArray.prototype.test = function() //@{ @@ -353,6 +375,23 @@ } this["implements"] = {}; + Object.getOwnPropertyNames(this.members).forEach(function(memberName) { + var member = this.members[memberName]; + if (!(member instanceof IdlInterface)) { + return; + } + + var exposed = member.extAttrs.filter(function(a) { return a.name == "Exposed" }); + if (exposed.length > 1) { + throw "Unexpected Exposed extended attributes on " + memberName + ": " + exposed; + } + + var globals = exposed.length === 1 + ? exposed[0].rhs.value + : ["Window"]; + member.exposed = exposed_in(globals); + }.bind(this)); + // Now run test() on every member, and test_object() for every object. for (var name in this.members) { @@ -678,6 +717,13 @@ return; } + if (!this.exposed) { + test(function() { + assert_false(this.name in self); + }.bind(this), this.name + " interface: existence and properties of interface object"); + return; + } + if (!this.untested) { // First test things to do with the exception/interface object and @@ -701,7 +747,6 @@ test(function() { // This function tests WebIDL as of 2015-01-13. - // TODO: Consider [Exposed]. // "For every interface that is exposed in a given ECMAScript global // environment and:
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/resources/testharness.js b/third_party/WebKit/LayoutTests/imported/wpt/resources/testharness.js index ceb3a4b..91dfab5 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/resources/testharness.js +++ b/third_party/WebKit/LayoutTests/imported/wpt/resources/testharness.js
@@ -471,6 +471,11 @@ self instanceof ServiceWorkerGlobalScope) { return new ServiceWorkerTestEnvironment(); } + if ('WorkerGlobalScope' in self && + self instanceof WorkerGlobalScope) { + return new DedicatedWorkerTestEnvironment(); + } + throw new Error("Unsupported test environment"); }
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/resources/testharnessreport.js b/third_party/WebKit/LayoutTests/imported/wpt/resources/testharnessreport.js index 0dba6f20..15a0710 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/resources/testharnessreport.js +++ b/third_party/WebKit/LayoutTests/imported/wpt/resources/testharnessreport.js
@@ -79,7 +79,7 @@ document.head.appendChild(common_script); } - path = path.replace(/imported\/wpt\/(.*)\.html$/, "imported/wpt_automation/$1-input.js"); + path = path.replace(/imported\/wpt\/(.*)\.html$/, "imported/wpt_automation/$1-automation.js"); var input_script = document.createElement('script'); input_script.setAttribute('src', path); document.head.appendChild(input_script);
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/Document-prototype-currentScript-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/Document-prototype-currentScript-expected.txt index a100343..adb48a0 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/Document-prototype-currentScript-expected.txt +++ b/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/Document-prototype-currentScript-expected.txt
@@ -1,7 +1,7 @@ -CONSOLE ERROR: line 2440: Uncaught Error: assert_equals: expected Element node <script id="outerScriptElement"> +CONSOLE ERROR: line 2445: Uncaught Error: assert_equals: expected Element node <script id="outerScriptElement"> var outerScriptElement ... but got null -CONSOLE ERROR: line 2440: Uncaught Error: assert_equals: expected Element node <script id="outerScriptElement"> +CONSOLE ERROR: line 2445: Uncaught Error: assert_equals: expected Element node <script id="outerScriptElement"> var outerScriptElement ... but got null This is a testharness.js-based test.
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/leaktests/html-collection.html b/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/leaktests/html-collection.html index 4f864fd..d156569 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/leaktests/html-collection.html +++ b/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/leaktests/html-collection.html
@@ -11,7 +11,6 @@ <template id='collection-template'> <img> <embed></embed> - <plugin></plugin> <applet></applet> <object type='application/x-java-applet'></object> <a href='http://example.com'></a>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-001.html b/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-001.html deleted file mode 100644 index 94f7d1b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-001.html +++ /dev/null
@@ -1,86 +0,0 @@ -<!DOCTYPE html> -<!-- -Distributed under both the W3C Test Suite License [1] and the W3C -3-clause BSD License [2]. To contribute to a W3C Test Suite, see the -policies and contribution forms [3]. - -[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license -[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license -[3] http://www.w3.org/2004/10/27-testcases ---> -<html> -<head> -<title>Shadow DOM Test: A_07_02_01</title> -<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> -<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#focus-navigation"> -<meta name="assert" content="User Interaction: The navigation order within a shadow tree must be computed as a list of focusable elements in tree order as-rendered"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="../../../../html/resources/common.js"></script> -<script src="../../../resources/shadow-dom-utils.js"></script> -</head> -<body> -<div id="log"></div> -<script> -var A_07_02_01_T01 = async_test('A_07_02_01_T01'); - -A_07_02_01_T01.step(unit(function (ctx) { - - var counter = 0; - - var d = newRenderedHTMLDocument(ctx); - - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - chb1.setAttribute('id', 'chb1'); - chb1.addEventListener('focus', A_07_02_01_T01.step_func(function(event) { - assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); - }), false); - d.body.appendChild(chb1); - - var host = d.createElement('div'); - d.body.appendChild(host); - var s = host.attachShadow({mode: 'open'}); - - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - inp1.setAttribute('value', 'Input 1'); - inp1.addEventListener('focus', A_07_02_01_T01.step_func(function(event) { - assert_equals(counter++, 1, 'Point 2: wrong focus navigation order'); - }), false); - s.appendChild(inp1); - - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - inp2.setAttribute('value', 'Input 2'); - inp2.addEventListener('focus', A_07_02_01_T01.step_func(function(event) { - assert_equals(counter++, 2, 'Point 3: wrong focus navigation order'); - }), false); - s.appendChild(inp2); - - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - chb2.addEventListener('focus', A_07_02_01_T01.step_func(function(event) { - assert_equals(counter++, 3, 'Point 4: wrong focus navigation order'); - }), false); - d.body.appendChild(chb2); - - chb1.focus(); - - //simulate TAB clicks - fireKeyboardEvent(d, chb1, 'U+0009'); - - fireKeyboardEvent(d, inp1, 'U+0009'); - - fireKeyboardEvent(d, inp2, 'U+0009'); - - fireKeyboardEvent(d, chb2, 'U+0009'); - - A_07_02_01_T01.done(); -})); -</script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html b/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html deleted file mode 100644 index 14c3219..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-002.html +++ /dev/null
@@ -1,238 +0,0 @@ -<!DOCTYPE html> -<!-- -Distributed under both the W3C Test Suite License [1] and the W3C -3-clause BSD License [2]. To contribute to a W3C Test Suite, see the -policies and contribution forms [3]. - -[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license -[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license -[3] http://www.w3.org/2004/10/27-testcases ---> -<html> -<head> -<title>Shadow DOM Test: A_07_02_02</title> -<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> -<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#focus-navigation"> -<meta name="assert" content="User Interaction: The navigation order within a shadow tree must be computed as a list of focusable elements in tree order as-rendered with the exception of any elements, distributed its insertion points, and is called shadow DOM navigation order."> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="../../../../html/resources/common.js"></script> -<script src="../../../resources/shadow-dom-utils.js"></script> -</head> -<body> -<div id="log"></div> -<script> -var A_07_02_02_T01 = async_test('A_07_02_02_T01'); -var A_07_02_02_T02 = async_test('A_07_02_02_T02'); - -A_07_02_02_T01.step(unit(function (ctx) { - - var counter = 0; - - var expectations = []; - - var d = newRenderedHTMLDocument(ctx); - - var host = d.createElement('div'); - d.body.appendChild(host); - - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - chb1.setAttribute('id', 'chb1'); - chb1.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { - assert_true(false, 'Element shouldn\'t be rendered'); - }), false); - host.appendChild(chb1); - - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - chb2.setAttribute('slot', 'shadow'); - chb2.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { - assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); - expectations[1] = true; - }), false); - expectations[1] = false; - host.appendChild(chb2); - - var chb3 = d.createElement('input'); - chb3.setAttribute('type', 'checkbox'); - chb3.setAttribute('id', 'chb3'); - chb3.setAttribute('slot', 'shadow'); - chb3.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { - assert_equals(counter++, 1, 'Point 2: wrong focus navigation order'); - expectations[2] = true; - }), false); - expectations[2] = false; - host.appendChild(chb3); - - var s = host.attachShadow({mode: 'open'}); - - var div = d.createElement('div'); - div.innerHTML = '<slot name="shadow"></slot>'; - s.appendChild(div); - - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - inp1.setAttribute('value', 'Input 1'); - inp1.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { - expectations[3] = false; - }), false); - expectations[3] = true; - s.appendChild(inp1); - - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - inp2.setAttribute('value', 'Input 2'); - inp2.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { - expectations[4] = false; - }), false); - expectations[4] = true; - s.appendChild(inp2); - - var chb4 = d.createElement('input'); - chb4.setAttribute('type', 'checkbox'); - chb4.setAttribute('id', 'chb4'); - chb4.addEventListener('focus', A_07_02_02_T01.step_func(function(event) { - assert_equals(counter++, 2, 'Point 5: wrong focus navigation order'); - expectations[5] = true; - }), false); - expectations[5] = false; - d.body.appendChild(chb4); - - chb2.focus(); - - //simulate TAB clicks - fireKeyboardEvent(d, chb2, 'U+0009'); - - fireKeyboardEvent(d, chb3, 'U+0009'); - - fireKeyboardEvent(d, inp1, 'U+0009'); - - fireKeyboardEvent(d, inp2, 'U+0009'); - - fireKeyboardEvent(d, chb4, 'U+0009'); - - for (var i = 1; i < expectations.length; i++) { - if (!expectations[i]) { - assert_true(false, 'Point ' + i + ' event listener was not invoked'); - } - } - - A_07_02_02_T01.done(); -})); - - - -A_07_02_02_T02.step(unit(function (ctx) { - - var counter = 0; - - var expectations = []; - - var d = newRenderedHTMLDocument(ctx); - - var chb0 = d.createElement('input'); - chb0.setAttribute('type', 'checkbox'); - chb0.setAttribute('id', 'chb0'); - d.body.appendChild(chb0); - - - var host = d.createElement('div'); - d.body.appendChild(host); - - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - chb1.setAttribute('id', 'chb1'); - chb1.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { - assert_true(false, 'Element shouldn\'t be rendered'); - }), false); - host.appendChild(chb1); - - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - chb2.setAttribute('slot', 'shadow'); - chb2.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { - assert_equals(counter++, 2, 'Point 3: wrong focus navigation order'); - expectations[1] = true; - }), false); - expectations[1] = false; - host.appendChild(chb2); - - var chb3 = d.createElement('input'); - chb3.setAttribute('type', 'checkbox'); - chb3.setAttribute('id', 'chb3'); - chb3.setAttribute('slot', 'shadow'); - chb3.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { - assert_equals(counter++, 3, 'Point 4: wrong focus navigation order'); - expectations[2] = true; - }), false); - expectations[2] = false; - host.appendChild(chb3); - - var s = host.attachShadow({mode: 'open'}); - - var div = d.createElement('div'); - div.innerHTML = '<slot name="shadow"></slot>'; - s.appendChild(div); - - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - inp1.setAttribute('value', 'Input 1'); - inp1.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { - assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); - - expectations[3] = true; - }), false); - expectations[3] = false; - s.appendChild(inp1); - - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - inp2.setAttribute('value', 'Input 2'); - inp2.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { - assert_equals(counter++, 1, 'Point 2: wrong focus navigation order'); - expectations[4] = true; - }), false); - expectations[4] = false; - s.appendChild(inp2); - - var chb4 = d.createElement('input'); - chb4.setAttribute('type', 'checkbox'); - chb4.setAttribute('id', 'chb4'); - chb4.addEventListener('focus', A_07_02_02_T02.step_func(function(event) { - assert_equals(counter++, 4, 'Point 5: wrong focus navigation order'); - expectations[5] = true; - }), false); - expectations[5] = false; - d.body.appendChild(chb4); - - chb0.focus(); - - //simulate TAB clicks - fireKeyboardEvent(d, inp1, 'U+0009'); - - fireKeyboardEvent(d, inp2, 'U+0009'); - - fireKeyboardEvent(d, chb2, 'U+0009'); - - fireKeyboardEvent(d, chb3, 'U+0009'); - - fireKeyboardEvent(d, chb4, 'U+0009'); - - for (var i = 1; i < expectations.length; i++) { - if (!expectations[i]) { - assert_true(false, 'Point ' + i + ' event listener was not invoked'); - } - } - - A_07_02_02_T02.done(); -})); -</script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html b/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html deleted file mode 100644 index eec7620..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-003.html +++ /dev/null
@@ -1,237 +0,0 @@ -<!DOCTYPE html> -<!-- -Distributed under both the W3C Test Suite License [1] and the W3C -3-clause BSD License [2]. To contribute to a W3C Test Suite, see the -policies and contribution forms [3]. - -[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license -[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license -[3] http://www.w3.org/2004/10/27-testcases ---> -<html> -<head> -<title>Shadow DOM Test: A_07_02_03</title> -<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> -<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#focus-navigation"> -<meta name="assert" content="User Interaction: For sequential focus navigation, the shadow DOM navigation order sequence must be inserted into the document navigation order in place of the shadow host as if the shadow host were assigned the value of auto for determining its position and shadow host is not focusable"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="../../../../html/resources/common.js"></script> -<script src="../../../resources/shadow-dom-utils.js"></script> -</head> -<body> -<div id="log"></div> -<script> -var A_07_02_03_T01 = async_test('A_07_02_03_T01'); - -A_07_02_03_T01.step(unit(function (ctx) { - - var counter = 0; - - var invoked = []; - - var d = newRenderedHTMLDocument(ctx); - - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - // TODO according CSS3 nav-index is a replacement for tabindex - //chb1.setAttribute('nav-index', '4'); - chb1.setAttribute('tabindex', '4'); - chb1.setAttribute('id', 'chb1'); - chb1.addEventListener('focus', A_07_02_03_T01.step_func(function(event) { - assert_equals(counter++, 1, 'Point 1: wrong focus navigation order'); - invoked[1] = true; - }), false); - invoked[1] = false; - d.body.appendChild(chb1); - - var host = d.createElement('div'); - d.body.appendChild(host); - var s = host.attachShadow({mode: 'open'}); - - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - //inp1.setAttribute('nav-index', '3'); - inp1.setAttribute('tabindex', '3'); - inp1.setAttribute('value', 'Input 1'); - inp1.addEventListener('focus', A_07_02_03_T01.step_func(function(event) { - assert_equals(counter++, 4, 'Point 2: wrong focus navigation order'); - invoked[2] = true; - }), false); - invoked[2] = false; - s.appendChild(inp1); - - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - //inp2.setAttribute('nav-index', '2'); - inp2.setAttribute('tabindex', '2'); - inp2.setAttribute('value', 'Input 2'); - inp2.addEventListener('focus', A_07_02_03_T01.step_func(function(event) { - assert_equals(counter++, 3, 'Point 3: wrong focus navigation order'); - invoked[3] = true; - }), false); - invoked[3] = false; - s.appendChild(inp2); - - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - //chb2.setAttribute('nav-index', '1'); - chb2.setAttribute('tabindex', '1'); - chb2.addEventListener('focus', A_07_02_03_T01.step_func(function(event) { - assert_equals(counter++, 0, 'Point 4: wrong focus navigation order'); - invoked[4] = true; - }), false); - invoked[4] = false; - d.body.appendChild(chb2); - - var chb3 = d.createElement('input'); - chb3.setAttribute('type', 'checkbox'); - chb3.setAttribute('id', 'chb3'); - //chb3.setAttribute('nav-index', '5'); - chb3.setAttribute('tabindex', '5'); - chb3.addEventListener('focus', A_07_02_03_T01.step_func(function(event) { - assert_equals(counter++, 2, 'Point 5: wrong focus navigation order'); - invoked[5] = true; - }), false); - invoked[5] = false; - d.body.appendChild(chb3); - - chb2.focus(); - - //simulate TAB clicks. Expected order: chb2, chb1, chb3, inp2, inp1 - fireKeyboardEvent(d, chb2, 'U+0009'); - - fireKeyboardEvent(d, chb1, 'U+0009'); - - fireKeyboardEvent(d, chb3, 'U+0009'); - - fireKeyboardEvent(d, inp2, 'U+0009'); - - fireKeyboardEvent(d, inp1, 'U+0009'); - - for (var i = 1; i < invoked.length; i++) { - if (!invoked[i]) { - assert_true(false, 'Piont ' + i + ' event listener was not invoked'); - } - } - - A_07_02_03_T01.done(); -})); - -// test nodes, distributed into insertion points -var A_07_02_03_T02 = async_test('A_07_02_03_T02'); - -A_07_02_03_T02.step(unit(function (ctx) { - - var counter = 0; - - var invoked = []; - - var d = newRenderedHTMLDocument(ctx); - - var host = d.createElement('div'); - d.body.appendChild(host); - - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - chb1.setAttribute('id', 'chb1'); - chb1.setAttribute('tabindex', '1'); - chb1.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { - assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); - invoked[1] = true; - }), false); - invoked[1] = false; - d.body.appendChild(chb1); - - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - chb2.setAttribute('slot', 'shadow'); - chb2.setAttribute('tabindex', '3'); - chb2.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { - assert_equals(counter++, 2, 'Point 2: wrong focus navigation order'); - invoked[2] = true; - }), false); - invoked[2] = false; - host.appendChild(chb2); - - var chb3 = d.createElement('input'); - chb3.setAttribute('type', 'checkbox'); - chb3.setAttribute('id', 'chb3'); - chb3.setAttribute('slot', 'shadow'); - chb3.setAttribute('tabindex', '2'); - chb3.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { - assert_equals(counter++, 1, 'Point 3: wrong focus navigation order'); - invoked[3] = true; - }), false); - invoked[3] = false; - host.appendChild(chb3); - - var s = host.attachShadow({mode: 'open'}); - - var div = d.createElement('div'); - div.innerHTML = '<slot name="shadow"></slot>'; - s.appendChild(div); - - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - inp1.setAttribute('value', 'Input 1'); - inp1.setAttribute('tabindex', '4'); - inp1.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { - assert_equals(counter++, 4, 'Point 4: wrong focus navigation order'); - invoked[4] = true; - }), false); - invoked[4] = false; - s.appendChild(inp1); - - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - inp2.setAttribute('value', 'Input 2'); - inp2.setAttribute('tabindex', '5'); - inp2.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { - assert_equals(counter++, 5, 'Point 5: wrong focus navigation order'); - invoked[5] = true; - }), false); - invoked[5] = false; - s.appendChild(inp2); - - var chb4 = d.createElement('input'); - chb4.setAttribute('type', 'checkbox'); - chb4.setAttribute('id', 'chb4'); - chb4.setAttribute('tabindex', '6'); - chb4.addEventListener('focus', A_07_02_03_T02.step_func(function(event) { - assert_equals(counter++, 3, 'Point 6: wrong focus navigation order'); - invoked[6] = true; - }), false); - invoked[6] = false; - d.body.appendChild(chb4); - - chb1.focus(); - - //simulate TAB clicks - //Expected order: chb1, chb3, chb2, chb4, inp1, inp2 - fireKeyboardEvent(d, chb1, 'U+0009'); - fireKeyboardEvent(d, chb3, 'U+0009'); - fireKeyboardEvent(d, chb2, 'U+0009'); - fireKeyboardEvent(d, chb4, 'U+0009'); - fireKeyboardEvent(d, inp1, 'U+0009'); - fireKeyboardEvent(d, inp2, 'U+0009'); - - - - for (var i = 1; i < invoked.length; i++) { - if (!invoked[i]) { - assert_true(false, 'Piont ' + i + ' event listener was not invoked'); - } - } - - A_07_02_03_T02.done(); -})); -</script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html b/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html deleted file mode 100644 index 29e02bd..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/shadow-dom/untriaged/user-interaction/focus-navigation/test-004.html +++ /dev/null
@@ -1,427 +0,0 @@ -<!DOCTYPE html> -<!-- -Distributed under both the W3C Test Suite License [1] and the W3C -3-clause BSD License [2]. To contribute to a W3C Test Suite, see the -policies and contribution forms [3]. - -[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license -[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license -[3] http://www.w3.org/2004/10/27-testcases ---> -<html> -<head> -<title>Shadow DOM Test: A_07_02_04</title> -<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> -<link rel="help" href="http://www.w3.org/TR/2013/WD-shadow-dom-20130514/#focus-navigation"> -<meta name="assert" content="User Interaction: For sequential focus navigation, the shadow DOM navigation order sequence must be inserted into the document navigation order immediately after the shadow host, if the shadow host is focusable;"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="../../../../html/resources/common.js"></script> -<script src="../../../resources/shadow-dom-utils.js"></script> -</head> -<body> -<div id="log"></div> -<script> -var A_07_02_04_T01 = async_test('A_07_02_04_T01'); - -A_07_02_04_T01.step(unit(function (ctx) { - - var counter = 0; - - var invoked = []; - - var d = newRenderedHTMLDocument(ctx); - - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - // TODO according CSS3 nav-index is a replacement for tabindex - //chb1.setAttribute('nav-index', '4'); - chb1.setAttribute('tabindex', '1'); - chb1.setAttribute('id', 'chb1'); - chb1.addEventListener('focus', A_07_02_04_T01.step_func(function(event) { - assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); - invoked[1] = true; - }), false); - invoked[1] = false; - d.body.appendChild(chb1); - - var host = d.createElement('div'); - //make shadow host focusable - host.setAttribute('tabindex', '3'); - d.body.appendChild(host); - var s = host.attachShadow({mode: 'open'}); - - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - //inp1.setAttribute('nav-index', '3'); - inp1.setAttribute('tabindex', '2'); - inp1.setAttribute('value', 'Input 1'); - inp1.addEventListener('focus', A_07_02_04_T01.step_func(function(event) { - assert_equals(counter++, 3, 'Point 2: wrong focus navigation order'); - invoked[2] = true; - }), false); - invoked[2] = false; - s.appendChild(inp1); - - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - //inp2.setAttribute('nav-index', '2'); - inp2.setAttribute('tabindex', '1'); - inp2.setAttribute('value', 'Input 2'); - inp2.addEventListener('focus', A_07_02_04_T01.step_func(function(event) { - assert_equals(counter++, 2, 'Point 3: wrong focus navigation order'); - invoked[3] = true; - }), false); - invoked[3] = false; - s.appendChild(inp2); - - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - //chb2.setAttribute('nav-index', '1'); - chb2.setAttribute('tabindex', '2'); - chb2.addEventListener('focus', A_07_02_04_T01.step_func(function(event) { - assert_equals(counter++, 1, 'Point 4: wrong focus navigation order'); - invoked[4] = true; - }), false); - invoked[4] = false; - d.body.appendChild(chb2); - - var chb3 = d.createElement('input'); - chb3.setAttribute('type', 'checkbox'); - chb3.setAttribute('id', 'chb3'); - //chb3.setAttribute('nav-index', '5'); - chb3.setAttribute('tabindex', '4'); - chb3.addEventListener('focus', A_07_02_04_T01.step_func(function(event) { - assert_equals(counter++, 4, 'Point 5: wrong focus navigation order'); - invoked[5] = true; - }), false); - invoked[5] = false; - d.body.appendChild(chb3); - - chb1.focus(); - - //simulate TAB clicks. Expected order: chb1, chb2, inp2, inp1, chb3 - fireKeyboardEvent(d, chb1, 'U+0009'); - - fireKeyboardEvent(d, chb2, 'U+0009'); - - fireKeyboardEvent(d, inp2, 'U+0009'); - - fireKeyboardEvent(d, inp1, 'U+0009'); - - fireKeyboardEvent(d, chb3, 'U+0009'); - - for (var i = 1; i < invoked.length; i++) { - if (!invoked[i]) { - assert_true(false, 'Piont ' + i + ' event listener was not invoked'); - } - } - - A_07_02_04_T01.done(); -})); - - - -// test nodes, distributed into insertion points -var A_07_02_04_T02 = async_test('A_07_02_04_T02'); - -A_07_02_04_T02.step(unit(function (ctx) { - - var counter = 0; - - var invoked = []; - - var d = newRenderedHTMLDocument(ctx); - - var host = d.createElement('div'); - host.setAttribute('tabindex', '3'); - d.body.appendChild(host); - - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - chb1.setAttribute('id', 'chb1'); - chb1.setAttribute('tabindex', '1'); - chb1.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { - assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); - invoked[1] = true; - }), false); - invoked[1] = false; - d.body.appendChild(chb1); - - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - chb2.setAttribute('slot', 'shadow'); - chb2.setAttribute('tabindex', '3'); - chb2.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { - assert_equals(counter++, 4, 'Point 2: wrong focus navigation order'); - invoked[2] = true; - }), false); - invoked[2] = false; - host.appendChild(chb2); - - var chb3 = d.createElement('input'); - chb3.setAttribute('type', 'checkbox'); - chb3.setAttribute('id', 'chb3'); - chb3.setAttribute('slot', 'shadow'); - chb3.setAttribute('tabindex', '2'); - chb3.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { - assert_equals(counter++, 1, 'Point 3: wrong focus navigation order'); - invoked[3] = true; - }), false); - invoked[3] = false; - host.appendChild(chb3); - - var s = host.attachShadow({mode: 'open'}); - - var div = d.createElement('div'); - div.innerHTML = '<slot name="shadow"></slot>'; - s.appendChild(div); - - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - inp1.setAttribute('value', 'Input 1'); - inp1.setAttribute('tabindex', '4'); - inp1.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { - assert_equals(counter++, 3, 'Point 4: wrong focus navigation order'); - invoked[4] = true; - }), false); - invoked[4] = false; - s.appendChild(inp1); - - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - inp2.setAttribute('value', 'Input 2'); - inp2.setAttribute('tabindex', '4'); - inp2.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { - assert_equals(counter++, 5, 'Point 5: wrong focus navigation order'); - invoked[5] = true; - }), false); - invoked[5] = false; - d.body.appendChild(inp2); - - var chb4 = d.createElement('input'); - chb4.setAttribute('type', 'checkbox'); - chb4.setAttribute('id', 'chb4'); - chb4.setAttribute('tabindex', '2'); - chb4.addEventListener('focus', A_07_02_04_T02.step_func(function(event) { - assert_equals(counter++, 2, 'Point 6: wrong focus navigation order'); - invoked[6] = true; - }), false); - invoked[6] = false; - d.body.appendChild(chb4); - - chb1.focus(); - - //simulate TAB clicks - //Expected order: chb1, chb3, chb4, chb2, inp1, inp2 - fireKeyboardEvent(d, chb1, 'U+0009'); - fireKeyboardEvent(d, chb3, 'U+0009'); - fireKeyboardEvent(d, chb4, 'U+0009'); - fireKeyboardEvent(d, chb2, 'U+0009'); - fireKeyboardEvent(d, inp1, 'U+0009'); - fireKeyboardEvent(d, inp2, 'U+0009'); - - - - for (var i = 1; i < invoked.length; i++) { - if (!invoked[i]) { - assert_true(false, 'Point ' + i + ' event listener was not invoked'); - } - } - - A_07_02_04_T02.done(); -})); - - - -// Shadow root is the first in nav order -var A_07_02_04_T03 = async_test('A_07_02_04_T03'); - -A_07_02_04_T03.step(unit(function (ctx) { - - var counter = 0; - - var invoked = []; - - var d = newRenderedHTMLDocument(ctx); - - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - chb1.setAttribute('tabindex', '3'); - chb1.setAttribute('id', 'chb1'); - chb1.addEventListener('focus', A_07_02_04_T03.step_func(function(event) { - assert_equals(counter++, 4, 'Point 1: wrong focus navigation order'); - invoked[1] = true; - }), false); - invoked[1] = false; - d.body.appendChild(chb1); - - var host = d.createElement('div'); - host.setAttribute('tabindex', '1'); - d.body.appendChild(host); - var s = host.attachShadow({mode: 'open'}); - - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - inp1.setAttribute('tabindex', '2'); - inp1.setAttribute('value', 'Input 1'); - inp1.addEventListener('focus', A_07_02_04_T03.step_func(function(event) { - assert_equals(counter++, 1, 'Point 2: wrong focus navigation order'); - invoked[2] = true; - }), false); - invoked[2] = false; - s.appendChild(inp1); - - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - inp2.setAttribute('tabindex', '1'); - inp2.setAttribute('value', 'Input 2'); - inp2.addEventListener('focus', A_07_02_04_T03.step_func(function(event) { - assert_equals(counter++, 0, 'Point 3: wrong focus navigation order'); - invoked[3] = true; - }), false); - invoked[3] = false; - s.appendChild(inp2); - - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - chb2.setAttribute('tabindex', '3'); - chb2.addEventListener('focus', A_07_02_04_T03.step_func(function(event) { - assert_equals(counter++, 2, 'Point 4: wrong focus navigation order'); - invoked[4] = true; - }), false); - invoked[4] = false; - s.appendChild(chb2); - - var chb3 = d.createElement('input'); - chb3.setAttribute('type', 'checkbox'); - chb3.setAttribute('id', 'chb3'); - chb3.setAttribute('tabindex', '2'); - chb3.addEventListener('focus', A_07_02_04_T03.step_func(function(event) { - assert_equals(counter++, 3, 'Point 5: wrong focus navigation order'); - invoked[5] = true; - }), false); - invoked[5] = false; - d.body.appendChild(chb3); - - host.focus(); - - //simulate TAB clicks. Expected order: inp2, inp1, chb2, chb3, chb1 - fireKeyboardEvent(d, inp2, 'U+0009'); - fireKeyboardEvent(d, inp1, 'U+0009'); - fireKeyboardEvent(d, chb2, 'U+0009'); - fireKeyboardEvent(d, chb3, 'U+0009'); - fireKeyboardEvent(d, chb1, 'U+0009'); - - for (var i = 1; i < invoked.length; i++) { - if (!invoked[i]) { - assert_true(false, 'Piont ' + i + ' event listener was not invoked'); - } - } - - A_07_02_04_T03.done(); -})); - - -//Shadow root is the last in nav order -var A_07_02_04_T04 = async_test('A_07_02_04_T04'); - -A_07_02_04_T04.step(unit(function (ctx) { - - var counter = 0; - - var invoked = []; - - var d = newRenderedHTMLDocument(ctx); - - var chb1 = d.createElement('input'); - chb1.setAttribute('type', 'checkbox'); - chb1.setAttribute('tabindex', '1'); - chb1.setAttribute('id', 'chb1'); - chb1.addEventListener('focus', A_07_02_04_T04.step_func(function(event) { - assert_equals(counter++, 0, 'Point 1: wrong focus navigation order'); - invoked[1] = true; - }), false); - invoked[1] = false; - d.body.appendChild(chb1); - - var host = d.createElement('div'); - host.setAttribute('tabindex', '3'); - d.body.appendChild(host); - var s = host.attachShadow({mode: 'open'}); - - var inp1 = d.createElement('input'); - inp1.setAttribute('type', 'text'); - inp1.setAttribute('id', 'shInp1'); - inp1.setAttribute('tabindex', '2'); - inp1.setAttribute('value', 'Input 1'); - inp1.addEventListener('focus', A_07_02_04_T04.step_func(function(event) { - assert_equals(counter++, 3, 'Point 2: wrong focus navigation order'); - invoked[2] = true; - }), false); - invoked[2] = false; - s.appendChild(inp1); - - var inp2 = d.createElement('input'); - inp2.setAttribute('type', 'text'); - inp2.setAttribute('id', 'shInp2'); - inp2.setAttribute('tabindex', '1'); - inp2.setAttribute('value', 'Input 2'); - inp2.addEventListener('focus', A_07_02_04_T04.step_func(function(event) { - assert_equals(counter++, 2, 'Point 3: wrong focus navigation order'); - invoked[3] = true; - }), false); - invoked[3] = false; - s.appendChild(inp2); - - var chb2 = d.createElement('input'); - chb2.setAttribute('type', 'checkbox'); - chb2.setAttribute('id', 'chb2'); - chb2.setAttribute('tabindex', '3'); - chb2.addEventListener('focus', A_07_02_04_T04.step_func(function(event) { - assert_equals(counter++, 4, 'Point 4: wrong focus navigation order'); - invoked[4] = true; - }), false); - invoked[4] = false; - s.appendChild(chb2); - - var chb3 = d.createElement('input'); - chb3.setAttribute('type', 'checkbox'); - chb3.setAttribute('id', 'chb3'); - chb3.setAttribute('tabindex', '2'); - chb3.addEventListener('focus', A_07_02_04_T04.step_func(function(event) { - assert_equals(counter++, 1, 'Point 5: wrong focus navigation order'); - invoked[5] = true; - }), false); - invoked[5] = false; - d.body.appendChild(chb3); - - chb1.focus(); - - //simulate TAB clicks. Expected order: inp2, inp1, chb2, chb3, chb1 - fireKeyboardEvent(d, chb1, 'U+0009'); - fireKeyboardEvent(d, chb3, 'U+0009'); - fireKeyboardEvent(d, inp2, 'U+0009'); - fireKeyboardEvent(d, inp1, 'U+0009'); - fireKeyboardEvent(d, chb2, 'U+0009'); - - for (var i = 1; i < invoked.length; i++) { - if (!invoked[i]) { - assert_true(false, 'Piont ' + i + ' event listener was not invoked'); - } - } - - A_07_02_04_T04.done(); -})); -</script> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/uievents/keyboard/key-manual.css b/third_party/WebKit/LayoutTests/imported/wpt/uievents/keyboard/key-manual.css deleted file mode 100644 index b2add2a..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/uievents/keyboard/key-manual.css +++ /dev/null
@@ -1,118 +0,0 @@ -.keyboard { - display: table; - border-collapse: separate; - border-spacing: 2px; - width: 800px; - border: 2px solid black; - border-radius: 10px; - padding: 5px; -} - -.key-row { - display: table; - margin: 0; - padding: 0; -} - -.key { - display: table-cell; - border: 2px solid black; - border-radius: 8px; - width: 50px; - height: 40px; - vertical-align: middle; - text-align: center; - margin: 0; - padding: 0; -} - -.wide1 { - width: 70px; -} - -.wide2 { - width: 90px; -} - -.wide3 { - width: 110px; -} - -.wide4 { - width: 130px; -} - -.wide5 { - width: 300px; -} - -.nextKey { - background-color: yellow; -} - -.goodKey { - background-color: #80ff08; -} - -.badKey { - background-color: #ff8080; -} - -.activeModifierKey { - background-color: #a0a0ff; -} - -.skippedKey { - background-color: #e0e0e0; -} - -#options { - display: none; - margin: 20px; -} - -#optionstoggle, #helptoggle { - font-size: 10pt; -} - -.opttable { - border: 1px solid black; -} - -.optcell { - vertical-align: top; - padding: 0 10px; -} - -.opttitle { - font-weight: bold; -} - -.error { - border: 1px solid red; - margin: 5px; - padding: 5px; -} - -.error1 { - font-size: 12pt; - margin: 0 0 0 10px; - padding: 0; -} - -.error2 { - font-size: 10pt; - margin: 0 0 0 20px; - padding: 0; -} - -.help { - font-size: 11pt; - margin: 0 0 5px 20px; - padding: 0; -} - -body { - margin: 10px; - padding: 0 20px; -}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/uievents/keyboard/key-manual.js b/third_party/WebKit/LayoutTests/imported/wpt/uievents/keyboard/key-manual.js deleted file mode 100644 index 175258b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt/uievents/keyboard/key-manual.js +++ /dev/null
@@ -1,671 +0,0 @@ -var _testing = false; - -// The index into _keyTable of the key currently being tested. -var _currKey = 0; - -var _keysTotal = 0; -var _keysGood = 0; -var _keysBad = 0; -var _keysSkipped = 0; - -var _modifierMode = "None"; - -var _keydownCapture = []; -var _keyupCapture = []; - -var CAPTURE_KEYCODE = 0; -var CAPTURE_CODE = 1; -var CAPTURE_KEY = 2; -var CAPTURE_SHIFTKEY = 3; -var CAPTURE_CONTROLKEY = 4; -var CAPTURE_ALTKEY = 5; -var CAPTURE_METAKEY = 6; - -// An array of KeyInfo for each key to be tested. -var _keyTable = []; - -// KeyInfo fields. -var KEYINFO_CODE = 0; // |code| for this key -var KEYINFO_ROW = 1; // Keyboard row -var KEYINFO_TYPE = 2; // Key type (see below) -var KEYINFO_WIDTH = 3; // Width of key: 0=normal -var KEYINFO_KEYCAP = 4; // Keycap string to display -var KEYINFO_KEY = 5; // Unmodified key value -var KEYINFO_KEY_SHIFT = 6; // Shifted key value - -var KEYTYPE_NORMAL = 0; -var KEYTYPE_DISABLED = 1; // Key cannot be tested: e.g., CapsLock -var KEYTYPE_END = 2; // Used to mark end of KeyTable -var KEYTYPE_MODIFIER = 3; // Modifer key - -function clearChildren(e) { - while (e.firstChild !== null) { - e.removeChild(e.firstChild); - } -} - -function setText(e, text) { - clearChildren(e); - e.appendChild(document.createTextNode(text)); -} - -function setUserAgent() { - var userAgent = navigator.userAgent; - uaDiv = document.getElementById("useragent"); - setText(uaDiv, userAgent); -} - -function addEventListener(obj, etype, handler) { - if (obj.addEventListener) { - obj.addEventListener(etype, handler, false); - } else if (obj.attachEvent) { - obj.attachEvent("on"+etype, handler); - } else { - obj["on"+etype] = handler; - } -} - -function addClass(obj, className) { - obj.classList.add(className); -} - -function removeClass(obj, className) { - obj.classList.remove(className); -} - -function addInnerText(obj, text) { - obj.appendChild(document.createTextNode(text)); -} - -function calcLocation(loc) { - if (loc == 1) return "LEFT"; - if (loc == 2) return "RIGHT"; - if (loc == 3) return "NUMPAD"; - return loc; -} - -function isModifierKey(e) { - // Shift, Control, Alt - if (e.keyCode >= 16 && e.keyCode <= 18) { - return true; - } - // Windows, Command or Meta key. - if (e.keyCode == 224 // Right/Left: Gecko - || e.keyCode == 91 // Left: WebKit/Blink - || e.keyCode == 93 // Right: WebKit/Blink - ) { - return true; - } - return false; -} - -function init(title, keytable) { - _keyTable = keytable; - - createBody(title, keytable); - - setUserAgent(); - - var input = document.getElementById("input"); - input.disabled = true; - addEventListener(input, "keydown", onKeyDown); - addEventListener(input, "keyup", onKeyUp); - //addEventListener(input, "beforeInput", onBeforeInput); - //addEventListener(input, "input", onInput); -} - -function onKeyDown(e) { - // Ignore modifier keys when checking modifier combinations. - if (_modifierMode != "None" && isModifierKey(e)) { - return; - } - - _keydownInfo = [e.keyCode, e.code, e.key, e.shiftKey, e.ctrlKey, e.altKey, e.metaKey]; - if (e.keyCode == 9 || e.code == "Tab") { - e.preventDefault(); - } -} - -function onKeyUp(e) { - // Ignore modifier keys when checking modifier combinations. - if (_modifierMode != "None" && isModifierKey(e)) { - return; - } - - _keyupInfo = [e.keyCode, e.code, e.key, e.shiftKey, e.ctrlKey, e.altKey, e.metaKey]; - - if (_testing) { - verifyKey(); - nextKey(); - } -} - -function onBeforeInput(e) { -} - -function onInput(e) { -} - -function addError(elem, str) { - var p = document.createElement('p'); - p.classList.add("error2"); - p.textContent = str; - elem.appendChild(p); -} - -function addErrorIncorrect(elem, eventName, attrName, keyEventInfo, attr, expected) { - addError(elem, "Incorrect " + eventName - + " |" + attrName + "| = " + keyEventInfo[attr] - + " - Expected " + expected); -} - -function verifyKeyEventFields(eventName, keyEventInfo, code, key, error) { - var verifyCode = document.getElementById("opt_attr_code").checked; - var verifyKey = document.getElementById("opt_attr_key").checked; - var verifyModifiers = document.getElementById("opt_attr_modifiers").checked; - var good = true; - - if (!verifyCode && !verifyKey && !verifyModifiers) { - good = false; - addError(error, "Invalid test: At least one attribute must be selected for testing."); - } - if (verifyCode && keyEventInfo[CAPTURE_CODE] != code) { - good = false; - addErrorIncorrect(error, eventName, "code", keyEventInfo, CAPTURE_CODE, code); - } - if (verifyKey && keyEventInfo[CAPTURE_KEY] != key) { - good = false; - addErrorIncorrect(error, eventName, "key", keyEventInfo, CAPTURE_KEY, key); - } - if (verifyModifiers) { - if (keyEventInfo[CAPTURE_SHIFTKEY] != (_modifierMode == "Shift")) { - good = false; - addErrorIncorrect(error, eventName, "shiftKey", keyEventInfo, CAPTURE_SHIFTKEY, false); - } - if (keyEventInfo[CAPTURE_CONTROLKEY]) { - good = false; - addErrorIncorrect(error, eventName, "controlKey", keyEventInfo, CAPTURE_CONTROLKEY, false); - } - if (keyEventInfo[CAPTURE_ALTKEY]) { - good = false; - addErrorIncorrect(error, eventName, "altKey", keyEventInfo, CAPTURE_ALTKEY, false); - } - if (keyEventInfo[CAPTURE_METAKEY]) { - good = false; - addErrorIncorrect(error, eventName, "metaKey", keyEventInfo, CAPTURE_METAKEY, false); - } - } - - return good; -} - -function verifyKey() { - _keysTotal++; - - var keyInfo = _keyTable[_currKey]; - var code = keyInfo[KEYINFO_CODE]; - var key = keyInfo[KEYINFO_KEY]; - var keyShift = keyInfo[KEYINFO_KEY_SHIFT]; - - var keyCheck = key; - if (_modifierMode == "Shift") { - keyCheck = keyShift; - } - - var verifyKeydown = document.getElementById("opt_event_keydown").checked; - var verifyKeyup = document.getElementById("opt_event_keyup").checked; - - var error = document.createElement('div'); - error.classList.add("error"); - var good = true; - - if (verifyKeydown) { - good = verifyKeyEventFields("keydown", _keydownInfo, code, keyCheck, error); - } - if (verifyKeyup) { - good = verifyKeyEventFields("keyup", _keyupInfo, code, keyCheck, error); - } - - if (!verifyKeydown && !verifyKeyup) { - good = false; - addError(error, "Invalid test: At least one event must be selected for testing."); - } - - // Allow Escape key to skip the current key. - var skipped = false; - if (_keydownInfo[CAPTURE_KEYCODE] == 27 || _keydownInfo[CAPTURE_CODE] == "Escape") { - good = true; - skipped = true; - } - - if (!good) { - var p = document.createElement('p'); - p.classList.add("error1"); - p.textContent = "Error : " + code; - error.insertBefore(p, error.firstChild); - } - - removeNextKeyHilight(); - if (skipped) { - _keysSkipped++; - document.getElementById(code).classList.add("skippedKey") - } else if (good) { - _keysGood++; - document.getElementById(code).classList.add("goodKey") - } else { - _keysBad++; - document.getElementById(code).classList.add("badKey") - } - updateTestSummary(good ? null : error); -} - -function updateTestSummary(error) { - document.getElementById("keys-total").textContent = _keysTotal; - document.getElementById("keys-good").textContent = _keysGood; - document.getElementById("keys-bad").textContent = _keysBad; - document.getElementById("keys-skipped").textContent = _keysSkipped; - - if (error) { - var errors = document.getElementById("errors"); - errors.insertBefore(error, errors.firstChild); - } -} - -function resetTest() { - _keysTotal = 0; - _keysGood = 0; - _keysBad = 0; - - _currKey = -1; - nextKey(); - - updateTestSummary(); - - // Remove previous test results. - clearChildren(document.getElementById("errors")); - - // Remove highlighting from keys. - for (var i = 0; i < _keyTable.length; i++) { - var code = _keyTable[i][KEYINFO_CODE]; - var type = _keyTable[i][KEYINFO_TYPE]; - if (type != KEYTYPE_END) { - var key = document.getElementById(code); - key.classList.remove("goodKey"); - key.classList.remove("badKey"); - key.classList.remove("skippedKey"); - } - } -} - -function startTest() { - if (_testing) { - // Cancel the currently running test. - endTest(); - return; - } - - resetTest(); - _testing = true; - document.getElementById("start").value = "Stop Test" - - var input = document.getElementById("input"); - input.value = ""; - input.disabled = false; - input.focus(); - - // Show test instructions and info. - document.getElementById("test-info").style.display = 'block'; - document.getElementById("instructions").style.display = 'block'; - document.getElementById("test-done").style.display = 'none'; -} - -function endTest() { - _testing = false; - removeNextKeyHilight(); - document.getElementById("start").value = "Restart Test" - document.getElementById("input").disabled = true; - document.getElementById("instructions").style.display = 'none'; - document.getElementById("test-done").style.display = 'block'; -} - -function removeNextKeyHilight() { - var curr = document.getElementById(_keyTable[_currKey][KEYINFO_CODE]); - if (curr) { - removeClass(curr, "nextKey") - } -} - -function addNextKeyHilight() { - var curr = document.getElementById(_keyTable[_currKey][KEYINFO_CODE]); - if (curr) { - addClass(curr, "nextKey") - } -} - -function nextKey() { - var keyInfo; - var keepLooking = true; - do { - _currKey++; - keyInfo = _keyTable[_currKey]; - var type = keyInfo[KEYINFO_TYPE]; - - // Skip over disabled keys. - keepLooking = (type == KEYTYPE_DISABLED); - - // Skip over modifier keys if we're testing modifier combinations. - if (_modifierMode != "None" && type == KEYTYPE_MODIFIER) { - keepLooking = true; - } - - // Skip over keys in disabled rows. - if (type != KEYTYPE_END) { - var row = keyInfo[KEYINFO_ROW]; - var rowEnabled = document.getElementById("opt_row_" + row).checked; - keepLooking = keepLooking || !rowEnabled; - } - } while (keepLooking); - - if (keyInfo[KEYINFO_TYPE] == KEYTYPE_END) { - endTest(); - } else { - addNextKeyHilight(); - } -} - -function toggleOptions() { - var link = document.getElementById("optionstoggle"); - var options = document.getElementById("options"); - clearChildren(link); - if (options.style.display == "block") { - options.style.display = "none"; - addInnerText(link, "Show Options"); - } - else { - options.style.display = "block"; - addInnerText(link, "Hide Options"); - } -} - -function toggleHelp() { - var link = document.getElementById("helptoggle"); - var help = document.getElementById("help"); - clearChildren(link); - if (help.style.display == "block") { - help.style.display = "none"; - addInnerText(link, "Show Help"); - } - else { - help.style.display = "block"; - addInnerText(link, "Hide Help"); - } -} - -function createBody(title, keytable) { - var body = document.getElementsByTagName("body")[0]; - var p; - var span; - - var h1 = document.createElement('h1'); - h1.textContent = "Keyboard Event Manual Test - " + title; - body.appendChild(h1); - - // Display useragent. - p = document.createElement('p'); - p.textContent = "UserAgent: "; - var useragent = document.createElement('span'); - useragent.id = "useragent"; - p.appendChild(useragent); - body.appendChild(p); - - // Display input textedit. - p = document.createElement('p'); - p.textContent = "Test Input: "; - var input1 = document.createElement('input'); - input1.id = "input"; - input1.type = "text"; - input1.size = 80; - p.appendChild(input1); - p.appendChild(document.createTextNode(" ")); - var input2 = document.createElement('input'); - input2.id = "start"; - input2.type = "button"; - input2.onclick = function() { startTest(); return false; } - input2.value = "Start Test"; - p.appendChild(input2); - p.appendChild(document.createTextNode(" ")); - var optionsToggle = document.createElement('a'); - optionsToggle.id = "optionstoggle"; - optionsToggle.href = "javascript:toggleOptions()"; - optionsToggle.textContent = "Show Options"; - p.appendChild(optionsToggle); - p.appendChild(document.createTextNode(" ")); - var helpToggle = document.createElement('a'); - helpToggle.id = "helptoggle"; - helpToggle.href = "javascript:toggleHelp()"; - helpToggle.textContent = "Show Help"; - p.appendChild(helpToggle); - body.appendChild(p); - - createOptions(body); - - createHelp(body); - - createKeyboard(body, keytable); - - // Test info and summary. - var test_info = document.createElement('div'); - test_info.id = "test-info"; - test_info.style.display = "none"; - - var instructions = document.createElement('div'); - instructions.id = "instructions"; - p = document.createElement('p'); - p.textContent = "Press the highlighted key."; - instructions.appendChild(p); - test_info.appendChild(instructions); - - var test_done = document.createElement('div'); - test_done.id = "test-done"; - p = document.createElement('p'); - p.textContent = "Test complete!"; - test_done.appendChild(p); - test_info.appendChild(test_done); - - var summary = document.createElement('div'); - summary.id = "summary"; - p = document.createElement('p'); - summary.appendChild(document.createTextNode("Keys Tested: ")); - span = document.createElement('span'); - span.id = "keys-total"; - span.textContent = 0; - summary.appendChild(span); - summary.appendChild(document.createTextNode("; Passed ")); - span = document.createElement('span'); - span.id = "keys-good"; - span.textContent = 0; - summary.appendChild(span); - summary.appendChild(document.createTextNode("; Failed ")); - span = document.createElement('span'); - span.id = "keys-bad"; - span.textContent = 0; - summary.appendChild(span); - summary.appendChild(document.createTextNode("; Skipped ")); - span = document.createElement('span'); - span.id = "keys-skipped"; - span.textContent = 0; - summary.appendChild(span); - test_info.appendChild(summary); - - var errors = document.createElement('div'); - errors.id = "errors"; - test_info.appendChild(errors); - - body.appendChild(test_info); -} - -function addOptionTitle(cell, title) { - var span = document.createElement('span'); - span.classList.add("opttitle"); - span.textContent = title; - cell.appendChild(span); - cell.appendChild(document.createElement("br")); -} - -function addOptionCheckbox(cell, id, text) { - var label = document.createElement("label"); - - var input = document.createElement("input"); - input.type = "checkbox"; - input.id = id; - input.checked = true; - label.appendChild(input); - - label.appendChild(document.createTextNode(" " + text)); - cell.appendChild(label); - - cell.appendChild(document.createElement("br")); -} - -function addOptionRadio(cell, group, text, handler, checked) { - var label = document.createElement("label"); - - var input = document.createElement("input"); - input.type = "radio"; - input.name = group; - input.value = text; - input.onclick = handler; - input.checked = checked; - label.appendChild(input); - - label.appendChild(document.createTextNode(" " + text)); - cell.appendChild(label); - - cell.appendChild(document.createElement("br")); -} - -function handleModifierGroup() { - var radio = document.querySelector("input[name=opt_modifier]:checked"); - var oldMode = _modifierMode; - _modifierMode = radio.value; - - if (oldMode == "Shift") { - document.getElementById("ShiftLeft").classList.remove("activeModifierKey"); - document.getElementById("ShiftRight").classList.remove("activeModifierKey"); - } - - if (_modifierMode == "Shift") { - document.getElementById("ShiftLeft").classList.add("activeModifierKey"); - document.getElementById("ShiftRight").classList.add("activeModifierKey"); - } -} - -function createOptions(body) { - var options = document.createElement('div'); - options.id = "options"; - options.style.display = "none"; - - var table = document.createElement('table'); - table.classList.add("opttable"); - var row = document.createElement('tr'); - var cell; - - cell = document.createElement('td'); - cell.classList.add("optcell"); - addOptionTitle(cell, "Keyboard Rows"); - addOptionCheckbox(cell, "opt_row_0", "Row E (top)"); - addOptionCheckbox(cell, "opt_row_1", "Row D"); - addOptionCheckbox(cell, "opt_row_2", "Row C"); - addOptionCheckbox(cell, "opt_row_3", "Row B"); - addOptionCheckbox(cell, "opt_row_4", "Row A (bottom)"); - row.appendChild(cell); - - cell = document.createElement('td'); - cell.classList.add("optcell"); - addOptionTitle(cell, "Events"); - addOptionCheckbox(cell, "opt_event_keydown", "keydown"); - addOptionCheckbox(cell, "opt_event_keyup", "keyup"); - row.appendChild(cell); - - cell = document.createElement('td'); - cell.classList.add("optcell"); - addOptionTitle(cell, "Attributes"); - addOptionCheckbox(cell, "opt_attr_code", "code"); - addOptionCheckbox(cell, "opt_attr_key", "key"); - addOptionCheckbox(cell, "opt_attr_modifiers", "modifiers"); - row.appendChild(cell); - - cell = document.createElement('td'); - cell.classList.add("optcell"); - addOptionTitle(cell, "Modifiers"); - addOptionRadio(cell, "opt_modifier", "None", handleModifierGroup, true); - addOptionRadio(cell, "opt_modifier", "Shift", handleModifierGroup, false); - row.appendChild(cell); - - table.appendChild(row); - options.appendChild(table); - - body.appendChild(options); -} - -function addHelpText(div, text) { - var p = document.createElement('p'); - p.classList.add("help"); - p.textContent = text; - div.appendChild(p); -} - -function createHelp(body) { - var help = document.createElement('div'); - help.id = "help"; - help.style.display = "none"; - - addHelpText(help, "Click on the \"Start Test\" button to begin testing."); - addHelpText(help, "Press the hilighted key to test it."); - addHelpText(help, "Clicking anywhere outside the \"Test Input\" editbox will pause testing. To resume, click back inside the editbox."); - addHelpText(help, "To skip a key while testing, press Escape."); - addHelpText(help, "When testing with modifier keys, the modifier must be pressed before the keydown and released after the keyup of the key being tested."); - - body.appendChild(help); -} - -function createKeyboard(body, keytable) { - var keyboard = document.createElement('div'); - keyboard.classList.add("keyboard"); - - var currRow = 0; - var row = document.createElement('div'); - row.classList.add("key-row"); - - for (var i = 0; i < keytable.length; i++) { - var code = keytable[i][KEYINFO_CODE]; - var rowId = keytable[i][KEYINFO_ROW]; - var type = keytable[i][KEYINFO_TYPE]; - var width = keytable[i][KEYINFO_WIDTH]; - var keyCap = keytable[i][KEYINFO_KEYCAP]; - - if (type == KEYTYPE_END) { - continue; - } - - if (rowId != currRow) { - keyboard.appendChild(row); - row = document.createElement('div'); - row.classList.add("key-row"); - currRow = rowId; - } - - var key = document.createElement('div'); - key.id = code; - key.classList.add("key"); - if (width != 0) { - key.classList.add("wide" + width); - } - key.textContent = keyCap; - - row.appendChild(key); - } - - keyboard.appendChild(row); - body.appendChild(keyboard); -}
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/README.md b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/README.md index ca01178a..c6d7c72 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/README.md +++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/README.md
@@ -12,17 +12,17 @@ For example, if you want to test setting the start time, you might be tempted to put all the tests in: - > `/web-animations/Animation/startTime.html` + > `/web-animations/interfaces/Animation/startTime.html` However, in the spec most of the logic is in the “Set the animation start time“ procedure in the “Timing model” section. Instead, try something like: - > * `/web-animations/timing-model/animation/set-the-animation-start-time.html`<br> + > * `/web-animations/timing-model/animations/set-the-animation-start-time.html`<br> > Tests all the branches and inputs to the procedure as defined in the > spec (using the `Animation.startTime` API). - > * `/web-animations/Animation/startTime.html`<br> + > * `/web-animations/interfaces/Animation/startTime.html`<br> > Tests API-layer specific issues like mapping unresolved values to > null, etc.
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/animation-model/keyframe-effects/spacing-keyframes-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/animation-model/keyframe-effects/spacing-keyframes-expected.txt new file mode 100644 index 0000000..b814546 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/animation-model/keyframe-effects/spacing-keyframes-expected.txt
@@ -0,0 +1,19 @@ +This is a testharness.js-based test. +FAIL Test distribute spacing anim.effect.getKeyframes is not a function +FAIL Test distribute spacing with specific offsets anim.effect.getKeyframes is not a function +FAIL Test paced spacing without any keyframe anim.effect.getKeyframes is not a function +FAIL Test paced spacing anim.effect.getKeyframes is not a function +FAIL Test paced spacing with specific offsets anim.effect.getKeyframes is not a function +FAIL Test paced spacing if some paced property values are equal anim.effect.getKeyframes is not a function +FAIL Test falling back to distribute spacing if all paced property value are equal anim.effect.getKeyframes is not a function +FAIL Test paced spacing if there a keyframe without the paced property anim.effect.getKeyframes is not a function +FAIL Test paced spacing if a paced property that appears on only some keyframes anim.effect.getKeyframes is not a function +FAIL Test paced spacing if a paced property that appears on only some keyframes and there is a specific offset anim.effect.getKeyframes is not a function +FAIL Test paced spacing where there are some keyframes without offsets and without the paced property before the first paceable keyframe and after the last paceable keyframe anim.effect.getKeyframes is not a function +FAIL Test paced spacing for using shorthand property anim.effect.getKeyframes is not a function +FAIL Test paced spacing using shorthand property where only the longhand components are specified anim.effect.getKeyframes is not a function +FAIL Test falling back to distribute spacing if all keyframe miss some components anim.effect.getKeyframes is not a function +FAIL Test paced spacing only for keyframes specifying all longhand components, and falling back to distribute spacing for the reset anim.effect.getKeyframes is not a function +FAIL Test paced spacing only for keyframes specifying all some components, and falling back to distribute spacing for the reset with some specific offsets anim.effect.getKeyframes is not a function +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/animation-model/keyframe-effects/spacing-keyframes.html b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/animation-model/keyframe-effects/spacing-keyframes.html new file mode 100644 index 0000000..14dc32b --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/animation-model/keyframe-effects/spacing-keyframes.html
@@ -0,0 +1,328 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Keyframe spacing tests</title> +<link rel="help" href="https://w3c.github.io/web-animations/#spacing-keyframes"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> +"use strict"; + +test(function(t) { + var anim = createDiv(t).animate([ { marginLeft: '0px' }, + { marginLeft: '-20px' }, + { marginLeft: '100px' }, + { marginLeft: '50px' } ], + { duration: 100 * MS_PER_SEC }); + + var frames = anim.effect.getKeyframes(); + var slots = frames.length - 1; + assert_equals(frames[0].computedOffset, 0.0, '1st frame offset'); + assert_equals(frames[1].computedOffset, 1.0 / slots, '2nd frame offset'); + assert_equals(frames[2].computedOffset, 2.0 / slots, '3rd frame offset'); + assert_equals(frames[3].computedOffset, 1.0, 'last frame offset'); +}, 'Test distribute spacing'); + +test(function(t) { + var anim = createDiv(t).animate([ { marginLeft: '0px' }, + { marginLeft: '-20px' }, + { marginLeft: '100px', offset: 0.5 }, + { marginLeft: '50px' } ], + { duration: 100 * MS_PER_SEC, + spacing: 'distribute' }); + + var frames = anim.effect.getKeyframes(); + assert_equals(frames[0].computedOffset, 0.0, '1st frame offset'); + assert_equals(frames[1].computedOffset, 0.5 * 1 / 2, '2nd frame offset'); + assert_equals(frames[2].computedOffset, 0.5, '3rd frame offset'); + assert_equals(frames[3].computedOffset, 1.0, 'last frame offset'); +}, 'Test distribute spacing with specific offsets'); + +test(function(t) { + var anim = createDiv(t).animate(null, + { duration: 100 * MS_PER_SEC, + spacing: 'paced(margin-left)' }); + + var frames = anim.effect.getKeyframes(); + assert_equals(frames.length, 0, "empty keyframe list"); +}, 'Test paced spacing without any keyframe'); + + +test(function(t) { + var anim = createDiv(t).animate([ { marginLeft: '0px' }, + { marginLeft: '-20px' }, + { marginLeft: '100px' }, + { marginLeft: '50px' } ], + { duration: 100 * MS_PER_SEC, + spacing: 'paced(margin-left)' }); + + var frames = anim.effect.getKeyframes(); + var cumDist = [0, 20, 140, 190]; + assert_equals(frames[0].computedOffset, 0.0, + '1st frame offset'); + assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3], + '2nd frame offset'); + assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3], + '3rd frame offset'); + assert_equals(frames[3].computedOffset, 1.0, + 'last frame offset'); +}, 'Test paced spacing'); + +test(function(t) { + var anim = createDiv(t).animate([ { marginLeft: '0px' }, + { marginLeft: '-20px' }, + { marginLeft: '100px', offset: 0.5 }, + { marginLeft: '120px' }, + { marginLeft: '50px' } ], + { duration: 100 * MS_PER_SEC, + spacing: 'paced(margin-left)' }); + + var frames = anim.effect.getKeyframes(); + var cumDist1 = [ 0, 20, 140 ]; + var cumDist2 = [ 0, 20, 90 ]; + assert_equals(frames[1].computedOffset, 0.5 * cumDist1[1] / cumDist1[2], + '2nd frame offset'); + assert_equals(frames[2].computedOffset, 0.5, + '3rd frame offset'); + assert_equals(frames[3].computedOffset, 0.5 + 0.5 * cumDist2[1] / cumDist2[2], + '4th frame offset'); +}, 'Test paced spacing with specific offsets'); + +test(function(t) { + var anim = createDiv(t).animate([ { marginLeft: '0px' }, + { marginLeft: '0px' }, + { marginLeft: '100px' }, + { marginLeft: '50px' } ], + { duration: 100 * MS_PER_SEC, + spacing: 'paced(margin-left)' }); + + var frames = anim.effect.getKeyframes(); + var cumDist = [0, 0, 100, 150]; + assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3], + '2nd frame offset'); + assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3], + '3rd frame offset'); +}, 'Test paced spacing if some paced property values are equal'); + +test(function(t) { + var anim = createDiv(t).animate([ { marginLeft: '0px' }, + { marginLeft: '0px' }, + { marginLeft: '0px' }, + { marginLeft: '0px' } ], + { duration: 100 * MS_PER_SEC, + spacing: 'paced(margin-left)' }); + + var frames = anim.effect.getKeyframes(); + var slots = frames.length - 1; + assert_equals(frames[1].computedOffset, 1.0 / slots, '2nd frame offset'); + assert_equals(frames[2].computedOffset, 2.0 / slots, '3rd frame offset'); +}, 'Test falling back to distribute spacing if all paced property value ' + + 'are equal'); + +test(function(t) { + var anim = createDiv(t).animate([ { margin: '0px' }, + { marginTop: '-20px' }, + { marginLeft: '100px' }, + { margin: '50px' } ], + { duration: 100 * MS_PER_SEC, + spacing: 'paced(margin-left)' }); + + var frames = anim.effect.getKeyframes(); + assert_equals(frames[1].computedOffset, frames[2].computedOffset * 1 / 2, + '2nd frame offset using distribute spacing'); + assert_equals(frames[2].computedOffset, 100 / 150, + '3rd frame offset using paced spacing'); +}, 'Test paced spacing if there a keyframe without the paced property'); + +test(function(t) { + var anim = createDiv(t).animate([ { margin: '0px' }, + { marginTop: '40px' }, + { marginTop: '-20px' }, + { marginLeft: '40px' }, + { marginTop: '60px' }, + { margin: '10px' } ], + { duration: 100 * MS_PER_SEC, + spacing: 'paced(margin-left)' }); + + var frames = anim.effect.getKeyframes(); + var cumDist = [0, 0, 0, 40, 40, 70]; + assert_equals(frames[1].computedOffset, frames[3].computedOffset * 1 / 3, + '2nd frame offset using distribute spacing'); + assert_equals(frames[2].computedOffset, frames[3].computedOffset * 2 / 3, + '3rd frame offset using distribute spacing'); + assert_equals(frames[3].computedOffset, cumDist[3] / cumDist[5], + '4th frame offset using paced spacing'); + assert_equals(frames[4].computedOffset, + frames[3].computedOffset + + (1 - frames[3].computedOffset) * 1 / 2, + '5th frame offset using distribute spacing'); +}, 'Test paced spacing if a paced property that appears on only some ' + + 'keyframes'); + +test(function(t) { + var anim = createDiv(t).animate([ { margin: '0px' }, + { marginTop: '-20px', offset: 0.5 }, + { marginLeft: '40px' }, + { marginLeft: '100px' }, + { margin: '50px' } ], + { duration: 100 * MS_PER_SEC, + spacing: 'paced(margin-left)' }); + + var frames = anim.effect.getKeyframes(); + assert_equals(frames[2].computedOffset, 0.5 + 0.5 * 1 / 3, + '3rd frame offset using distribute spacing because it is the ' + + 'first paceable keyframe'); + assert_equals(frames[3].computedOffset, + frames[2].computedOffset + + (1.0 - frames[2].computedOffset) * 60 / 110, + '4th frame offset using paced spacing'); +}, 'Test paced spacing if a paced property that appears on only some ' + + 'keyframes and there is a specific offset'); + +test(function(t) { + var anim = createDiv(t).animate([ { margin: '0px' }, + { marginTop: '20px', offset: 0.2 }, + { marginTop: '40px' }, + { marginTop: '-20px' }, + { marginLeft: '-20px' }, + { marginLeft: '40px' }, + { marginTop: '60px' }, + { marginLeft: '100px' }, + { marginTop: '50px' }, + { marginTop: '100px', offset: 0.8 }, + { margin: '0px' } ], + { duration: 100 * MS_PER_SEC, + spacing: 'paced(margin-left)' }); + var frames = anim.effect.getKeyframes(); + // Test distribute spacing in (A, Paced A] and [Paced B, frame B). + var slots = frames.length - 3; + var start = 0.2; + var diff = 0.8 - start; + assert_equals(frames[2].computedOffset, start + diff * 1.0 / slots, + '3nd frame offset using distribute spacing'); + assert_equals(frames[3].computedOffset, start + diff * 2.0 / slots, + '4rd frame offset using distribute spacing'); + assert_equals(frames[4].computedOffset, start + diff * 3.0 / slots, + '5th frame offset using distribute spacing because it is ' + + 'the first paceable keyframe'); + assert_equals(frames[7].computedOffset, start + diff * 6.0 / slots, + '8th frame offset using distribute spacing because it is ' + + 'the last paceable keyframe'); + assert_equals(frames[8].computedOffset, start + diff * 7.0 / slots, + '9th frame offset using distribute spacing'); + // Test paced spacing and other null computed offsets in (Paced A, Paced B). + var cumDist = [0, 60, 60, 120]; + assert_equals(frames[5].computedOffset, + frames[4].computedOffset + cumDist[2] / cumDist[3] * + (frames[7].computedOffset - frames[4].computedOffset), + '6th frame offset using paced spacing'); + assert_equals(frames[6].computedOffset, + frames[5].computedOffset + 1.0 / 2.0 * + (frames[7].computedOffset - frames[5].computedOffset), + '7th frame offset using distribute spacing'); +}, 'Test paced spacing where there are some keyframes without offsets and ' + + 'without the paced property before the first paceable keyframe and ' + + 'after the last paceable keyframe'); + +test(function(t) { + var anim = createDiv(t).animate([ { margin: '0px' }, + { margin: '-20px' }, + { margin: '100px' }, + { margin: '50px' } ], + { duration: 100 * MS_PER_SEC, + spacing: 'paced(margin)' }); + + var frames = anim.effect.getKeyframes(); + var cumDist = [0, 20, 140, 190]; + assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3], + '2nd frame offset'); + assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3], + '3rd frame offset'); +}, 'Test paced spacing for using shorthand property'); + +test(function(t) { + var anim = + createDiv(t).animate([ { marginLeft: '0px', marginRight: '0px', + marginTop: '10px', marginBottom: '10px' }, + { marginLeft: '-20px', marginRight: '-20px', + marginTop: '0px', marginBottom: '0px' }, + { marginLeft: '100px', marginRight: '100px', + marginTop: '-50px', marginBottom: '-50px' }, + { marginLeft: '50px', marginRight: '50px', + marginTop: '80px', marginBottom: '80px' } ], + { duration: 100 * MS_PER_SEC, + spacing: 'paced(margin)' }); + + var frames = anim.effect.getKeyframes(); + var dist = [ 0, + Math.sqrt(20 * 20 * 2 + 10 * 10 * 2), + Math.sqrt(120 * 120 * 2 + 50 * 50 * 2), + Math.sqrt(50 * 50 * 2 + 130 * 130 * 2) ]; + var cumDist = []; + dist.reduce(function(prev, curr, i) { return cumDist[i] = prev + curr; }, 0); + assert_approx_equals(frames[1].computedOffset, cumDist[1] / cumDist[3], + 0.0001, '2nd frame offset'); + assert_approx_equals(frames[2].computedOffset, cumDist[2] / cumDist[3], + 0.0001, '3rd frame offset'); +}, 'Test paced spacing using shorthand property where only the longhand ' + + 'components are specified'); + +test(function(t) { + var anim = createDiv(t).animate([ { marginLeft: '0px', marginTop: '0px' }, + { marginLeft: '-20px', marginTop: '-20px' }, + { marginLeft: '100px', marginTop: '100px' }, + { marginLeft: '50px', marginTop: '50px' } ], + { duration: 100 * MS_PER_SEC, + spacing: 'paced(margin)' }); + + var frames = anim.effect.getKeyframes(); + var slots = frames.length - 1; + assert_equals(frames[1].computedOffset, 1 / slots, '2nd frame offset'); + assert_equals(frames[2].computedOffset, 2 / slots, '3rd frame offset'); +}, 'Test falling back to distribute spacing if all keyframe miss some ' + + 'components'); + +test(function(t) { + var anim = createDiv(t).animate([ { margin: '0px' }, + { marginLeft: '-20px' }, + { marginTop: '40px' }, + { margin: '100px' }, + { margin: '50px' } ], + { duration: 100 * MS_PER_SEC, + spacing: 'paced(margin)' }); + + var frames = anim.effect.getKeyframes(); + assert_equals(frames[1].computedOffset, frames[3].computedOffset * 1 / 3, + '2nd frame offset using distribute spacing'); + assert_equals(frames[2].computedOffset, frames[3].computedOffset * 2 / 3, + '3rd frame offset using distribute spacing'); + assert_equals(frames[3].computedOffset, 100 / 150, + '4th frame offset using paced spacing'); +}, 'Test paced spacing only for keyframes specifying all longhand ' + + 'components, and falling back to distribute spacing for the reset'); + +test(function(t) { + var anim = createDiv(t).animate([ { margin: '0px' }, + { marginLeft: '-20px' }, + { marginTop: '40px', offset: 0.5 }, + { margin: '100px' }, + { margin: '50px' } ], + { duration: 100 * MS_PER_SEC, + spacing: 'paced(margin)' }); + + var frames = anim.effect.getKeyframes(); + assert_equals(frames[1].computedOffset, 0.5 * 1 / 2, + '2nd frame offset using distribute spacing'); + assert_equals(frames[3].computedOffset, 0.5 + 0.5 * 1 / 2, + '4th frame offset using distribute spacing because it is the ' + + 'first paceable keyframe from a non-null offset keyframe'); +}, 'Test paced spacing only for keyframes specifying all some components, ' + + 'and falling back to distribute spacing for the reset with some specific ' + + 'offsets'); + +// Bug 1276193: Test for mixing percent and pixel values. + +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/Animation/cancel.html b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/Animation/cancel.html index 73f05ee..d7b0df2 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/Animation/cancel.html +++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/Animation/cancel.html
@@ -13,7 +13,7 @@ promise_test(function(t) { var div = createDiv(t); - var animation = div.animate({transform: ['none', 'translate(100px)']}, + var animation = div.animate({transform: ['translate(100px)', 'translate(100px)']}, 100 * MS_PER_SEC); return animation.ready.then(function() { assert_not_equals(getComputedStyle(div).transform, 'none', @@ -26,7 +26,7 @@ test(function(t) { var div = createDiv(t); - var animation = div.animate({marginLeft: ['0px', '100px']}, + var animation = div.animate({marginLeft: ['100px', '200px']}, 100 * MS_PER_SEC); animation.effect.timing.easing = 'linear'; animation.cancel(); @@ -34,7 +34,7 @@ 'margin-left style is not animated after cancelling'); animation.currentTime = 50 * MS_PER_SEC; - assert_equals(getComputedStyle(div).marginLeft, '50px', + assert_equals(getComputedStyle(div).marginLeft, '150px', 'margin-left style is updated when cancelled animation is' + ' seeked'); }, 'After cancelling an animation, it can still be seeked');
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/document-timeline.html b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/document-timeline.html index e4f5133f..0f782f50 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/document-timeline.html +++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/document-timeline.html
@@ -1,6 +1,7 @@ <!doctype html> <meta charset=utf-8> -<title>Web Animations API: DocumentTimeline tests</title> +<title>Default document timeline tests</title> +<link rel="help" href="https://w3c.github.io/web-animations/#the-documents-default-timeline"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <div id="log"></div> @@ -16,15 +17,9 @@ 'document.timeline returns a different object for each document'); assert_not_equals(iframe.contentDocument.timeline, null, 'document.timeline on an iframe is not null'); -}, -'document.timeline identity tests', -{ - help: 'http://dev.w3.org/fxtf/web-animations/#the-document-timeline', - assert: [ 'Each document has a timeline called the document timeline' ], - author: 'Brian Birtles' -}); +}, 'document.timeline identity tests'); -async_test(function(t) { +promise_test(function(t) { assert_true(document.timeline.currentTime > 0, 'document.timeline.currentTime is positive'); // document.timeline.currentTime should be set even before document @@ -40,31 +35,14 @@ // We can't just compare document.timeline.currentTime to // window.performance.now() because currentTime is only updated on a sample // so we use requestAnimationFrame instead. - window.requestAnimationFrame(t.step_func(function(rafTime) { + return window.requestAnimationFrame(t.step_func(function(rafTime) { assert_equals(document.timeline.currentTime, rafTime, 'document.timeline.currentTime matches' + ' requestAnimationFrame time'); - t.done(); })); -}, -'document.timeline.currentTime value tests', -{ - help: [ - 'http://dev.w3.org/fxtf/web-animations/#the-global-clock', - 'http://dev.w3.org/fxtf/web-animations/#the-document-timeline' - ], - assert: [ - 'The global clock is a source of monotonically increasing time values', - 'The time values of the document timeline are calculated as a fixed' + - ' offset from the global clock', - 'the zero time corresponds to the navigationStart moment', - 'the time value of each document timeline must be equal to the time ' + - 'passed to animation frame request callbacks for that browsing context' - ], - author: 'Brian Birtles' -}); +}, 'document.timeline.currentTime value tests'); -async_test(function(t) { +promise_test(function(t) { var valueAtStart = document.timeline.currentTime; var timeAtStart = window.performance.now(); while (window.performance.now() - timeAtStart < 100) { @@ -72,18 +50,10 @@ } assert_equals(document.timeline.currentTime, valueAtStart, 'document.timeline.currentTime does not change within a script block'); - window.requestAnimationFrame(t.step_func(function() { + return window.requestAnimationFrame(t.step_func(function() { assert_true(document.timeline.currentTime > valueAtStart, 'document.timeline.currentTime increases between script blocks'); - t.done(); })); -}, -'document.timeline.currentTime liveness tests', -{ - help: 'http://dev.w3.org/fxtf/web-animations/#script-execution-and-live-updates-to-the-model', - assert: [ 'The value returned by the currentTime attribute of a' + - ' document timeline will not change within a script block' ], - author: 'Brian Birtles' -}); +}, 'document.timeline.currentTime liveness tests'); </script>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/idlharness-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/idlharness-expected.txt index 977c872..5cb30a0 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/idlharness-expected.txt +++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/idlharness-expected.txt
@@ -1,11 +1,5 @@ This is a testharness.js-based test. PASS Web Animations API: DocumentTimeline tests -PASS AnimationTimeline interface: existence and properties of interface object -PASS AnimationTimeline interface object length -PASS AnimationTimeline interface object name -FAIL AnimationTimeline interface: existence and properties of interface prototype object assert_equals: class string of AnimationTimeline.prototype expected "[object AnimationTimelinePrototype]" but got "[object AnimationTimeline]" -PASS AnimationTimeline interface: existence and properties of interface prototype object's "constructor" property -FAIL AnimationTimeline interface: attribute currentTime assert_equals: setter must be undefined for readonly attributes expected (undefined) undefined but got (function) function "function () { [native code] }" FAIL DocumentTimeline interface: existence and properties of interface object assert_own_property: self does not have own property "DocumentTimeline" expected property "DocumentTimeline" missing FAIL DocumentTimeline interface object length assert_own_property: self does not have own property "DocumentTimeline" expected property "DocumentTimeline" missing FAIL DocumentTimeline interface object name assert_own_property: self does not have own property "DocumentTimeline" expected property "DocumentTimeline" missing
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/idlharness.html b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/idlharness.html index 9a489086..04afcada 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/idlharness.html +++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/AnimationTimeline/idlharness.html
@@ -6,11 +6,13 @@ <script src="/resources/WebIDLParser.js"></script> <script src="/resources/idlharness.js"></script> <div id="log"></div> -<script type="text/plain" id="DocumentTimeline-IDL"> +<script type="text/plain" id="AnimationTimeline-IDL"> interface AnimationTimeline { readonly attribute double? currentTime; }; - +</script> +<script type="text/plain" id="DocumentTimeline-IDL"> +[Constructor (DOMHighResTimeStamp originTime)] interface DocumentTimeline : AnimationTimeline { }; </script> @@ -20,6 +22,8 @@ var idlArray; test(function() { idlArray = new IdlArray(); + idlArray.add_untested_idls( + document.getElementById('AnimationTimeline-IDL').textContent); idlArray.add_idls( document.getElementById('DocumentTimeline-IDL').textContent); idlArray.add_objects( { DocumentTimeline: ['document.timeline'] } );
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/DocumentTimeline/constructor-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/DocumentTimeline/constructor-expected.txt new file mode 100644 index 0000000..e443eb4d --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/DocumentTimeline/constructor-expected.txt
@@ -0,0 +1,6 @@ +This is a testharness.js-based test. +FAIL zero origin time DocumentTimeline is not defined +FAIL positive origin time DocumentTimeline is not defined +FAIL negative origin time DocumentTimeline is not defined +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/DocumentTimeline/constructor.html b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/DocumentTimeline/constructor.html new file mode 100644 index 0000000..efdf1118 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/DocumentTimeline/constructor.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>DocumentTimeline constructor tests</title> +<link rel="help" href="https://w3c.github.io/web-animations/#the-documenttimeline-interface"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> +"use strict"; + +test(function(t) { + var timeline = new DocumentTimeline(0); + + assert_times_equal(timeline.currentTime, document.timeline.currentTime); +}, 'zero origin time'); + +test(function(t) { + var timeline = new DocumentTimeline(10 * MS_PER_SEC); + + assert_times_equal(timeline.currentTime, + (document.timeline.currentTime - 10 * MS_PER_SEC)); +}, 'positive origin time'); + +test(function(t) { + var timeline = new DocumentTimeline(-10 * MS_PER_SEC); + + assert_times_equal(timeline.currentTime, + (document.timeline.currentTime + 10 * MS_PER_SEC)); +}, 'negative origin time'); + +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffect/setTarget-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffect/setTarget-expected.txt index 271de512..421c9d96 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffect/setTarget-expected.txt +++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffect/setTarget-expected.txt
@@ -3,5 +3,8 @@ FAIL Test setting target from null to a valid target Animation is not defined FAIL Test setting target from a valid target to null assert_equals: Value after clearing the target expected "10px" but got "50px" FAIL Test setting target from a valid target to another target assert_equals: Value of 1st element (currently not targeted) after changing the effect target expected "10px" but got "50px" +FAIL Test falling back to distribute spacing mode after setting null target anim.effect.getKeyframes is not a function +FAIL Test falling back to distribute spacing mode if there is no context element effect.getKeyframes is not a function +FAIL Test paced spacing mode after setting a new target anim.effect.getKeyframes is not a function Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffect/setTarget.html b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffect/setTarget.html index 49ef8402..2b07d3de 100644 --- a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffect/setTarget.html +++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffect/setTarget.html
@@ -85,5 +85,76 @@ 'changing the animation current time.'); }, 'Test setting target from a valid target to another target'); +test(function(t) { + var anim = createDiv(t).animate([ { marginLeft: '0px' }, + { marginLeft: '-20px' }, + { marginLeft: '100px' }, + { marginLeft: '50px' } ], + { duration: 100 * MS_PER_SEC, + spacing: 'paced(margin-left)' }); + + anim.effect.target = null; + + var frames = anim.effect.getKeyframes(); + var slots = frames.length - 1; + assert_equals(frames[0].computedOffset, 0.0, '1st frame offset'); + assert_equals(frames[1].computedOffset, 1.0 / slots, '2nd frame offset'); + assert_equals(frames[2].computedOffset, 2.0 / slots, '3rd frame offset'); + assert_equals(frames[3].computedOffset, 1.0, 'last frame offset'); +}, 'Test falling back to distribute spacing mode after setting null target'); + +test(function(t) { + var effect = new KeyframeEffect(null, + [ { marginLeft: '0px' }, + { marginLeft: '-20px' }, + { marginLeft: '100px' }, + { marginLeft: '50px' } ], + { duration: 100 * MS_PER_SEC, + spacing: 'paced(margin-left)' }); + var frames = effect.getKeyframes(); + var slots = frames.length - 1; + assert_equals(frames[1].computedOffset, 1.0 / slots, '2nd frame offset'); + assert_equals(frames[2].computedOffset, 2.0 / slots, '3rd frame offset'); +}, 'Test falling back to distribute spacing mode if there is no context ' + + 'element'); + +test(function(t) { + var div1 = createDiv(t); + var div2 = createDiv(t); + div1.style.marginLeft = '-20px'; + div2.style.marginLeft = '-50px'; + var child1 = document.createElement('div'); + var child2 = document.createElement('div'); + div1.appendChild(child1); + div2.appendChild(child2); + // body + // / \ + // div1 div2 + // (-20px) (-50px) + // | | + // child1 child2 + var anim = child1.animate([ { marginLeft: '0px' }, + { marginLeft: 'inherit' }, + { marginLeft: '100px' }, + { marginLeft: '50px' } ], + { duration: 100 * MS_PER_SEC, + spacing: 'paced(margin-left)' }); + + var frames = anim.effect.getKeyframes(); + var cumDist = [0, 20, 140, 190]; + assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3], + '2nd frame offset'); + assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3], + '3rd frame offset'); + + anim.effect.target = child2; + frames = anim.effect.getKeyframes(); + cumDist = [0, 50, 200, 250]; + assert_equals(frames[1].computedOffset, cumDist[1] / cumDist[3], + '2nd frame offset after setting a new target'); + assert_equals(frames[2].computedOffset, cumDist[2] / cumDist[3], + '3rd frame offset after setting a new target'); +}, 'Test paced spacing mode after setting a new target'); + </script> </body>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffectReadOnly/spacing-expected.txt b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffectReadOnly/spacing-expected.txt new file mode 100644 index 0000000..f876ed2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffectReadOnly/spacing-expected.txt
@@ -0,0 +1,84 @@ +This is a testharness.js-based test. +FAIL Test throwing TypeError if using empty string assert_throws: function "function () { + createDiv(t).animate(null, { spacing: '' }); + }" did not throw +FAIL Test throwing TypeError if not using the correct keyword assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'dist' }); + }" did not throw +FAIL Test throwing TypeError if adding leading spaces assert_throws: function "function () { + createDiv(t).animate(null, { spacing: ' paced(margin-left)' }); + }" did not throw +FAIL Test throwing TypeError if adding trailing spaces assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(margin-left) ' }); + }" did not throw +FAIL Test throwing TypeError if adding leading spaces before the paced property assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced( margin-left)' }); + }" did not throw +FAIL Test throwing TypeError if adding trailing spaces after the paced property assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(margin-left )' }); + }" did not throw +FAIL Test throwing TypeError if these is no paced property assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced()' }); + }" did not throw +FAIL Test throwing TypeError if using a non-ident started string assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(.margin)' }); + }" did not throw +FAIL Test throwing TypeError if using a non-ident started string assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(1margin)' }); + }" did not throw +FAIL Test throwing TypeError if using a non-ident started string with an invalid escape assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(\\)' }); + }" did not throw +FAIL Test throwing TypeError if using a non-ident started string with an invalid escape (FF) assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(\\\fmargin)' }); + }" did not throw +FAIL Test throwing TypeError if using a non-ident started string with an invalid escape (CR) assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(\\\rmargin)' }); + }" did not throw +FAIL Test throwing TypeError if using a non-ident started string with an invalid escape (LF) assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(\\\nmargin)' }); + }" did not throw +FAIL Test throwing TypeError if using a non-ident started string with a leading minus and an invalid name-start code point assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(- )' }); + }" did not throw +FAIL Test throwing TypeError if using a non-ident started string with a leading minus and an invalid escape assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(-\\)' }); + }" did not throw +FAIL Test throwing TypeError if using a non-ident started string with a leading minus and an invalid escape (FF) assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(-\\\fmargin)' }); + }" did not throw +FAIL Test throwing TypeError if using a non-ident started string with a leading minus and an invalid escape (CR) assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(-\\\rmargin)' }); + }" did not throw +FAIL Test throwing TypeError if using a non-ident started string with a leading minus and an invalid escape (LF) assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(-\\\nmargin)' }); + }" did not throw +FAIL Test throwing TypeError if using a non-ident string with an invalid escape assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(--\\)' }); + }" did not throw +FAIL Test throwing TypeError if using a non-ident string with an invalid escape (FF) assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(--\\\fmargin)' }); + }" did not throw +FAIL Test throwing TypeError if using a non-ident string with an invalid escape (CR) assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(--\\\rmargin)' }); + }" did not throw +FAIL Test throwing TypeError if using a non-ident string with an invalid escape (LF) assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(--\\\nmargin)' }); + }" did not throw +FAIL Test throwing TypeError if using a non-ident string with an invalid name code point assert_throws: function "function () { + createDiv(t).animate(null, { spacing: 'paced(margin.left)' }); + }" did not throw +FAIL Test falling back to distribute spacing if using a unrecognized property assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined +FAIL Test falling back to distribute spacing if using a unrecognized property which starts with a valid escape (Full stop) assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined +FAIL Test falling back to distribute spacing if using a unrecognized property which starts with a valid escape (white space) assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined +FAIL Test falling back to distribute spacing if using a unrecognized property which starts with a valid escape (low line) assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined +FAIL Test falling back to distribute spacing if using a unrecognized property which starts with a minus and a low line assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined +FAIL Test falling back to distribute spacing if using a unrecognized property which starts with a minus and a valid escape assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined +FAIL Test falling back to distribute spacing if using CSS variables assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined +FAIL Test falling back to distribute spacing if using a non-animatable shorthand property assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined +FAIL Test falling back to distribute spacing if using a non-animatable property assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined +FAIL Test default value of spacing assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined +FAIL Test spacing value if setting distribute assert_equals: spacing mode expected (string) "distribute" but got (undefined) undefined +FAIL Test spacing value if setting paced assert_equals: spacing mode expected (string) "paced(margin-left)" but got (undefined) undefined +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffectReadOnly/spacing.html b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffectReadOnly/spacing.html new file mode 100644 index 0000000..c83d1ebc --- /dev/null +++ b/third_party/WebKit/LayoutTests/imported/wpt/web-animations/interfaces/KeyframeEffectReadOnly/spacing.html
@@ -0,0 +1,237 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>KeyframeEffectReadOnly spacing attribute tests</title> +<link rel="help" +href="https://w3c.github.io/web-animations/#dom-keyframeeffectreadonly-spacing"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../../testcommon.js"></script> +<body> +<div id="log"></div> +<script> +"use strict"; + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: '' }); + }); +}, 'Test throwing TypeError if using empty string'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'dist' }); + }); +}, 'Test throwing TypeError if not using the correct keyword'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: ' paced(margin-left)' }); + }); +}, 'Test throwing TypeError if adding leading spaces'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(margin-left) ' }); + }); +}, 'Test throwing TypeError if adding trailing spaces'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced( margin-left)' }); + }); +}, 'Test throwing TypeError if adding leading spaces before the ' + + 'paced property'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(margin-left )' }); + }); +}, 'Test throwing TypeError if adding trailing spaces after the ' + + 'paced property'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced()' }); + }); +}, 'Test throwing TypeError if these is no paced property'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(.margin)' }); + }); +}, 'Test throwing TypeError if using a non-ident started string'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(1margin)' }); + }); +}, 'Test throwing TypeError if using a non-ident started string'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(\\)' }); + }); +}, 'Test throwing TypeError if using a non-ident started string with ' + + 'an invalid escape'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(\\\fmargin)' }); + }); +}, 'Test throwing TypeError if using a non-ident started string with ' + + 'an invalid escape (FF)'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(\\\rmargin)' }); + }); +}, 'Test throwing TypeError if using a non-ident started string with ' + + 'an invalid escape (CR)'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(\\\nmargin)' }); + }); +}, 'Test throwing TypeError if using a non-ident started string with ' + + 'an invalid escape (LF)'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(- )' }); + }); +}, 'Test throwing TypeError if using a non-ident started string with ' + + 'a leading minus and an invalid name-start code point'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(-\\)' }); + }); +}, 'Test throwing TypeError if using a non-ident started string with ' + + 'a leading minus and an invalid escape'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(-\\\fmargin)' }); + }); +}, 'Test throwing TypeError if using a non-ident started string with ' + + 'a leading minus and an invalid escape (FF)'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(-\\\rmargin)' }); + }); +}, 'Test throwing TypeError if using a non-ident started string with ' + + 'a leading minus and an invalid escape (CR)'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(-\\\nmargin)' }); + }); +}, 'Test throwing TypeError if using a non-ident started string with ' + + 'a leading minus and an invalid escape (LF)'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(--\\)' }); + }); +}, 'Test throwing TypeError if using a non-ident string with an invalid ' + + 'escape'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(--\\\fmargin)' }); + }); +}, 'Test throwing TypeError if using a non-ident string with an invalid ' + + 'escape (FF)'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(--\\\rmargin)' }); + }); +}, 'Test throwing TypeError if using a non-ident string with an invalid ' + + 'escape (CR)'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(--\\\nmargin)' }); + }); +}, 'Test throwing TypeError if using a non-ident string with an invalid ' + + 'escape (LF)'); + +test(function(t) { + assert_throws(new TypeError, function() { + createDiv(t).animate(null, { spacing: 'paced(margin.left)' }); + }); +}, 'Test throwing TypeError if using a non-ident string with an invalid name ' + + 'code point'); + +test(function(t) { + var anim = createDiv(t).animate(null, { spacing: 'paced(A)' }); + assert_equals(anim.effect.spacing, 'distribute', 'spacing mode'); +}, 'Test falling back to distribute spacing if using a unrecognized property'); + +test(function(t) { + var anim = createDiv(t).animate(null, { spacing: 'paced(\\.margin)' }); + assert_equals(anim.effect.spacing, 'distribute', 'spacing mode'); +}, 'Test falling back to distribute spacing if using a unrecognized property ' + + 'which starts with a valid escape (Full stop)'); + +test(function(t) { + var anim = createDiv(t).animate(null, { spacing: 'paced(\\ margin)' }); + assert_equals(anim.effect.spacing, 'distribute', 'spacing mode'); +}, 'Test falling back to distribute spacing if using a unrecognized property ' + + 'which starts with a valid escape (white space)'); + +test(function(t) { + var anim = createDiv(t).animate(null, { spacing: 'paced(_margin)' }); + assert_equals(anim.effect.spacing, 'distribute', 'spacing mode'); +}, 'Test falling back to distribute spacing if using a unrecognized property ' + + 'which starts with a valid escape (low line)'); + +test(function(t) { + var anim = createDiv(t).animate(null, { spacing: 'paced(-_margin)' }); + assert_equals(anim.effect.spacing, 'distribute', 'spacing mode'); +}, 'Test falling back to distribute spacing if using a unrecognized property ' + + 'which starts with a minus and a low line'); + +test(function(t) { + var anim = createDiv(t).animate(null, { spacing: 'paced(-\\.margin)' }); + assert_equals(anim.effect.spacing, 'distribute', 'spacing mode'); +}, 'Test falling back to distribute spacing if using a unrecognized property ' + + 'which starts with a minus and a valid escape'); + +test(function(t) { + var anim = createDiv(t).animate(null, { spacing: 'paced(--bg-color)' }); + assert_equals(anim.effect.spacing, 'distribute', 'spacing mode'); +}, 'Test falling back to distribute spacing if using CSS variables'); + +test(function(t) { + var anim = createDiv(t).animate(null, { spacing: 'paced(animation)' }); + assert_equals(anim.effect.spacing, 'distribute', 'spacing mode'); +}, 'Test falling back to distribute spacing if using a non-animatable ' + + 'shorthand property'); + +test(function(t) { + var anim = createDiv(t).animate(null, + { spacing: 'paced(animation-duration)' }); + assert_equals(anim.effect.spacing, 'distribute', 'spacing mode'); +}, 'Test falling back to distribute spacing if using a non-animatable ' + + 'property'); + +test(function(t) { + var anim = createDiv(t).animate(null); + assert_equals(anim.effect.spacing, 'distribute', 'spacing mode'); +}, 'Test default value of spacing'); + +test(function(t) { + var anim = createDiv(t).animate(null, { spacing: 'distribute' }); + assert_equals(anim.effect.spacing, 'distribute', 'spacing mode'); +}, 'Test spacing value if setting distribute'); + +test(function(t) { + var anim = createDiv(t).animate(null, { spacing: 'paced(margin-left)' }); + assert_equals(anim.effect.spacing, 'paced(margin-left)', 'spacing mode'); +}, 'Test spacing value if setting paced'); + +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_capture_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_capture_mouse-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_capture_mouse-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_capture_mouse-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_capture_suppressing_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_capture_suppressing_mouse-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_capture_suppressing_mouse-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_capture_suppressing_mouse-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_change-touch-action-onpointerdown_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_gotpointercapture_before_first_pointerevent-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_gotpointercapture_before_first_pointerevent-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_gotpointercapture_before_first_pointerevent-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_gotpointercapture_before_first_pointerevent-manual-input.js deleted file mode 100644 index d8ef5a6..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_gotpointercapture_before_first_pointerevent-manual-input.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - mouseClickInTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_lostpointercapture_for_disconnected_node-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_lostpointercapture_for_disconnected_node-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_lostpointercapture_for_disconnected_node-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_lostpointercapture_for_disconnected_node-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_lostpointercapture_is_first-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_lostpointercapture_is_first-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_lostpointercapture_is_first-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_lostpointercapture_is_first-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointercancel_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointercancel_touch-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointercancel_touch-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointercancel_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerdown-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerdown-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerdown-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerdown-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_does_not_bubble-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_does_not_bubble-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_does_not_bubble-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_does_not_bubble-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointercancel_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointercancel_touch-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual-input.js deleted file mode 100644 index 14dd4b5..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointercancel_touch-manual-input.js +++ /dev/null
@@ -1,7 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchScrollUpInTarget('target0'); -} - -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual-input.js deleted file mode 100644 index 05cf1b1..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_after_pointerup_nohover-manual-input.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchTapInTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_descendant_over-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_descendant_over-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_descendant_over-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_descendant_over-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_descendants-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_descendants-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_descendants-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_descendants-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_does_not_bubble-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_does_not_bubble-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_does_not_bubble-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_does_not_bubble-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_does_not_bubble-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_does_not_bubble-manual-input.js deleted file mode 100644 index 316468b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_does_not_bubble-manual-input.js +++ /dev/null
@@ -1,7 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - mouseMoveIntoTarget('target0'); - mouseMoveToDocument(); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_does_not_bubble-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_mouse-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_does_not_bubble-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_mouse-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_pen-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_pen-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_pen-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_pen-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_touch-manual-input.js deleted file mode 100644 index 05cf1b1..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_touch-manual-input.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchTapInTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove-manual-input.js deleted file mode 100644 index c08ae78..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove-manual-input.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - mouseMoveIntoTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_isprimary_same_as_pointerdown-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_isprimary_same_as_pointerdown-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_isprimary_same_as_pointerdown-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_isprimary_same_as_pointerdown-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_pointertype-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_pointertype-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_pointertype-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_pointertype-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_mouse-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout-manual-input.js deleted file mode 100644 index 316468b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout-manual-input.js +++ /dev/null
@@ -1,7 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - mouseMoveIntoTarget('target0'); - mouseMoveToDocument(); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual-input.js deleted file mode 100644 index 05cf1b1..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_after_pointerup_nohover-manual-input.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchTapInTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_pen-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_pen-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerleave_pen-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_pen-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_pen-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_pen-manual-input.js deleted file mode 100644 index 66bffa4..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_pen-manual-input.js +++ /dev/null
@@ -1,10 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - if (window.eventSender) { - var target0 = document.getElementById('target0'); - penMoveIntoTarget(target0); - eventSender.mouseMoveTo(0, 0, [], "pen", 0); - } -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_does_not_bubble-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_received_once-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_does_not_bubble-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_received_once-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_received_once-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_received_once-manual-input.js deleted file mode 100644 index 316468b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_received_once-manual-input.js +++ /dev/null
@@ -1,7 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - mouseMoveIntoTarget('target0'); - mouseMoveToDocument(); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerover-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerover-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerover-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerover-manual-input.js deleted file mode 100644 index c08ae78..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerover-manual-input.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - mouseMoveIntoTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_mouse-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_mouse-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_mouse-manual-input.js deleted file mode 100644 index d8ef5a6..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_mouse-manual-input.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - mouseClickInTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_pen-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_pen-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_pen-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_pen-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_nohover-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_touch-manual-input.js deleted file mode 100644 index 05cf1b1..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointertype_touch-manual-input.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchTapInTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerdown-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerdown-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup-manual-input.js deleted file mode 100644 index d8ef5a6..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup-manual-input.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - mouseClickInTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup_isprimary_same_as_pointerdown-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup_isprimary_same_as_pointerdown-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup_isprimary_same_as_pointerdown-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup_isprimary_same_as_pointerdown-manual-input.js deleted file mode 100644 index d8ef5a6..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup_isprimary_same_as_pointerdown-manual-input.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - mouseClickInTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup_pointertype-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup_pointertype-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup_pointertype-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup_pointertype-manual-input.js deleted file mode 100644 index d8ef5a6..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerup_pointertype-manual-input.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - mouseClickInTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_isprimary_same_as_pointerdown-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_isprimary_same_as_pointerdown-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual-input.js deleted file mode 100644 index 0c31fb73..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_events_to_original_target-manual-input.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - mouseDragInTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_isprimary_same_as_pointerdown-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_invalid_pointerid-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointermove_isprimary_same_as_pointerdown-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_invalid_pointerid-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_invalid_pointerid-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_invalid_pointerid-manual-input.js deleted file mode 100644 index 0c31fb73..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_invalid_pointerid-manual-input.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - mouseDragInTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerout_after_pointercancel_touch-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual-input.js deleted file mode 100644 index d73a444..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointercancel_touch-manual-input.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchScrollUpInTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointerup_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointerup_mouse-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointerup_mouse-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_releasepointercapture_onpointerup_mouse-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_disconnected-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_disconnected-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_disconnected-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_disconnected-manual-input.js deleted file mode 100644 index d8ef5a6..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_disconnected-manual-input.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - mouseClickInTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_does_not_bubble-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_inactive_button_mouse-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_pointerenter_does_not_bubble-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_inactive_button_mouse-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_inactive_button_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_inactive_button_mouse-manual-input.js deleted file mode 100644 index 316468b..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_inactive_button_mouse-manual-input.js +++ /dev/null
@@ -1,7 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - mouseMoveIntoTarget('target0'); - mouseMoveToDocument(); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_invalid_pointerid-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_button_attribute_mouse-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_invalid_pointerid-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_invalid_pointerid-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_invalid_pointerid-manual-input.js deleted file mode 100644 index d8ef5a6..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_invalid_pointerid-manual-input.js +++ /dev/null
@@ -1,6 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - mouseClickInTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_relatedtarget-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_relatedtarget-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_relatedtarget-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_setpointercapture_relatedtarget-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-auto-css_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-auto-css_touch-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-auto-css_touch-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-auto-css_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual-input.js deleted file mode 100644 index d972b5a3..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual-input.js +++ /dev/null
@@ -1,8 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchScrollUpInTarget('target0'); - touchScrollLeftInTarget('target0'); - touchTapInTarget('btnComplete'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual-input.js deleted file mode 100644 index d972b5a3..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-none_touch-manual-input.js +++ /dev/null
@@ -1,8 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchScrollUpInTarget('target0'); - touchScrollLeftInTarget('target0'); - touchTapInTarget('btnComplete'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual-input.js deleted file mode 100644 index d972b5a3..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual-input.js +++ /dev/null
@@ -1,8 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchScrollUpInTarget('target0'); - touchScrollLeftInTarget('target0'); - touchTapInTarget('btnComplete'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual-input.js deleted file mode 100644 index d972b5a3..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual-input.js +++ /dev/null
@@ -1,8 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchScrollUpInTarget('target0'); - touchScrollLeftInTarget('target0'); - touchTapInTarget('btnComplete'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-auto-css_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-auto-css_touch-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual-input.js deleted file mode 100644 index 4fffdcf..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch-manual-input.js +++ /dev/null
@@ -1,7 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchScrollUpInTarget('target0'); - touchScrollLeftInTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual-input.js deleted file mode 100644 index d972b5a3..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual-input.js +++ /dev/null
@@ -1,8 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchScrollUpInTarget('target0'); - touchScrollLeftInTarget('target0'); - touchTapInTarget('btnComplete'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-keyboard-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-keyboard-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-keyboard-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-keyboard-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-mouse-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-mouse-manual-automation.js similarity index 100% rename from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-mouse-manual-input.js rename to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-mouse-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-none-css_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-none-css_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-none-css_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-none-css_touch-manual-input.js deleted file mode 100644 index d972b5a3..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-none-css_touch-manual-input.js +++ /dev/null
@@ -1,8 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchScrollUpInTarget('target0'); - touchScrollLeftInTarget('target0'); - touchTapInTarget('btnComplete'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-css_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-css_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-css_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-css_touch-manual-input.js deleted file mode 100644 index d972b5a3..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-css_touch-manual-input.js +++ /dev/null
@@ -1,8 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchScrollUpInTarget('target0'); - touchScrollLeftInTarget('target0'); - touchTapInTarget('btnComplete'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual-input.js deleted file mode 100644 index d972b5a3..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual-input.js +++ /dev/null
@@ -1,8 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchScrollUpInTarget('target0'); - touchScrollLeftInTarget('target0'); - touchTapInTarget('btnComplete'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-auto-css_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-auto-css_touch-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual-input.js deleted file mode 100644 index 4fffdcf..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch-manual-input.js +++ /dev/null
@@ -1,7 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchScrollUpInTarget('target0'); - touchScrollLeftInTarget('target0'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual-input.js deleted file mode 100644 index d972b5a3..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-pan-y-css_touch-manual-input.js +++ /dev/null
@@ -1,8 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchScrollUpInTarget('target0'); - touchScrollLeftInTarget('target0'); - touchTapInTarget('btnComplete'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-span-test_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-span-test_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-span-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-span-test_touch-manual-input.js deleted file mode 100644 index d972b5a3..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-span-test_touch-manual-input.js +++ /dev/null
@@ -1,8 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchScrollUpInTarget('target0'); - touchScrollLeftInTarget('target0'); - touchTapInTarget('btnComplete'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-svg-test_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-svg-test_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-svg-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-svg-test_touch-manual-input.js deleted file mode 100644 index d972b5a3..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-svg-test_touch-manual-input.js +++ /dev/null
@@ -1,8 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchScrollUpInTarget('target0'); - touchScrollLeftInTarget('target0'); - touchTapInTarget('btnComplete'); -} -
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-table-test_touch-manual-automation.js similarity index 100% copy from third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-button-test_touch-manual-input.js copy to third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-table-test_touch-manual-automation.js
diff --git a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-table-test_touch-manual-input.js b/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-table-test_touch-manual-input.js deleted file mode 100644 index d972b5a3..0000000 --- a/third_party/WebKit/LayoutTests/imported/wpt_automation/pointerevents/pointerevent_touch-action-table-test_touch-manual-input.js +++ /dev/null
@@ -1,8 +0,0 @@ -importAutomationScript('/pointerevents/pointerevent_common_input.js'); - -function inject_input() { - touchScrollUpInTarget('target0'); - touchScrollLeftInTarget('target0'); - touchTapInTarget('btnComplete'); -} -
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/console/console-line-and-column-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/console/console-line-and-column-expected.txt index 0713d4f..f38b264 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/console/console-line-and-column-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/console/console-line-and-column-expected.txt
@@ -8,9 +8,9 @@ stack : { callFrames : [ [0] : { - columnNumber : 9 + columnNumber : 8 functionName : - lineNumber : 1 + lineNumber : 0 scriptId : 0 url : } @@ -28,9 +28,9 @@ stack : { callFrames : [ [0] : { - columnNumber : 3 + columnNumber : 2 functionName : - lineNumber : 2 + lineNumber : 1 scriptId : 0 url : }
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation.html index 18168c82..dec791a 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation.html +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/continueToLocation.html
@@ -23,13 +23,17 @@ function callbackEvalFunctionObject(response) { var functionObjectId = response.result.result.objectId; - InspectorTest.sendCommand("Debugger.getFunctionDetails", { functionId: functionObjectId }, callbackFunctionDetails); + InspectorTest.sendCommand("Runtime.getProperties", { objectId: functionObjectId }, callbackFunctionDetails); } function callbackFunctionDetails(response) { var result = response.result; - var scriptId = result.details.location.scriptId; + var scriptId; + for (var prop of result.internalProperties) { + if (prop.name === "[[FunctionLocation]]") + scriptId = prop.value.value.scriptId; + } nextScenarioStep(0);
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource.html b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource.html index ff34b440..3bec1c92 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource.html +++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/setScriptSource.html
@@ -9,7 +9,7 @@ // A general-purpose engine for sending a sequence of protocol commands. // The clients provide requests and response handlers, while the engine catches // errors and makes sure that once there's nothing to do completeTest() is called. - // @param step is an object with command, params and callback fields + // @param step is an object with command, params and callback fields function runRequestSeries(step) { processStep(step); @@ -21,7 +21,7 @@ InspectorTest.completeTest(); } } - + function processStepOrFail(currentStep) { if (!currentStep) { InspectorTest.completeTest(); @@ -64,7 +64,7 @@ InspectorTest.sendCommand(currentStep.command, currentStep.params, innerCallback); } } - + function logEqualsCheck(actual, expected) { if (actual == expected) { @@ -77,57 +77,63 @@ { InspectorTest.log(description + ": " + (success ? "PASS" : "FAIL")); } - + var firstStep = { callback: enableDebugger }; runRequestSeries(firstStep); - + function enableDebugger() { return { command: "Debugger.enable", params: {}, callback: evalFunction }; } - + function evalFunction(response) { var expression = "TestExpression(2, 4)"; return { command: "Runtime.evaluate", params: { expression: expression }, callback: callbackEvalFunction }; } - + function callbackEvalFunction(result) { InspectorTest.log("Function evaluate: " + JSON.stringify(result.result)); logEqualsCheck(result.result.value, 6); return { command: "Runtime.evaluate", params: { expression: "TestExpression" }, callback: callbackEvalFunctionObject }; } - + function callbackEvalFunctionObject(result) { - return { command: "Debugger.getFunctionDetails", params: { functionId: result.result.objectId }, callback: callbackFunctionDetails }; - } - - function callbackFunctionDetails(result) { - return createScriptManipulationArc(result.details.location.scriptId, null); + return { command: "Runtime.getProperties", params: { objectId: result.result.objectId }, callback: callbackFunctionDetails }; } - // Several steps with scriptId in context. + function callbackFunctionDetails(result) + { + var scriptId; + for (var prop of result.internalProperties) { + if (prop.name === "[[FunctionLocation]]") + scriptId = prop.value.value.scriptId; + } + return createScriptManipulationArc(scriptId, null); + } + + // Several steps with scriptId in context. function createScriptManipulationArc(scriptId, next) { return { command: "Debugger.getScriptSource", params: { scriptId: scriptId }, callback: callbackGetScriptSource }; - + var originalText; - + function callbackGetScriptSource(result) { originalText = result.scriptSource; var patched = originalText.replace("a + b", "a * b"); return { command: "Debugger.setScriptSource", params: { scriptId: scriptId, scriptSource: patched }, callback: callbackSetScriptSource }; } - + function callbackSetScriptSource(result) { var expression = "TestExpression(2, 4)"; return { command: "Runtime.evaluate", params: { expression: expression }, callback: callbackEvalFunction2 }; } - + function callbackEvalFunction2(result) { InspectorTest.log("Function evaluate: " + JSON.stringify(result.result)); logEqualsCheck(result.result.value, 8); - + var patched = originalText.replace("a + b", "a # b"); return { command: "Debugger.setScriptSource", params: { scriptId: scriptId, scriptSource: patched }, callback: errorCallbackSetScriptSource2 };
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/network/websocket-initiator-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/network/websocket-initiator-expected.txt index fd18f8e1..b7e73710 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/network/websocket-initiator-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/network/websocket-initiator-expected.txt
@@ -7,5 +7,5 @@ Stack #0 functionName: createSocket url: websocket-initiator.html - lineNumber: 10 + lineNumber: 9
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/resources/worker-console-worker.js b/third_party/WebKit/LayoutTests/inspector-protocol/resources/worker-console-worker.js index 8c5f0035..5151327 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/resources/worker-console-worker.js +++ b/third_party/WebKit/LayoutTests/inspector-protocol/resources/worker-console-worker.js
@@ -1,6 +1,9 @@ self.onmessage = function(event) { - console.log(event.data); + if (event.data.indexOf("throw") === 0) + Promise.reject(event.data); + else + console.log(event.data); self.postMessage(event.data); } self.postMessage("ready");
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-getFunctionDetails-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-getFunctionDetails-expected.txt deleted file mode 100644 index b216bd45..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-getFunctionDetails-expected.txt +++ /dev/null
@@ -1,13 +0,0 @@ - -{ - "details": { - "location": { - "scriptId": "0", - "lineNumber": -1, - "columnNumber": -1 - }, - "functionName": "", - "isGenerator": false - } -} -
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-getFunctionDetails.html b/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-getFunctionDetails.html deleted file mode 100644 index a5dd9c71..0000000 --- a/third_party/WebKit/LayoutTests/inspector-protocol/runtime/runtime-getFunctionDetails.html +++ /dev/null
@@ -1,27 +0,0 @@ -<html> -<head> -<script type="text/javascript" src="../../http/tests/inspector-protocol/inspector-protocol-test.js"></script> -<script> - -function test() -{ - InspectorTest.sendCommand("Debugger.enable", { }); - InspectorTest.sendCommand("Runtime.evaluate", { "expression": "document.querySelector('object')" }, callbackEvaluate); - - function callbackEvaluate(result) - { - InspectorTest.sendCommand("Debugger.getFunctionDetails", { "functionId": result.result.result.objectId }, callbackGetFunctionDetails); - } - - function callbackGetFunctionDetails(result) - { - InspectorTest.log(JSON.stringify(result.result, null, 4)); - InspectorTest.completeTest(); - } -} -</script> -</head> -<body onLoad="runTest();"> -<object type="application/pdf" data="data:text/plain,"></object> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/worker/worker-console-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/worker/worker-console-expected.txt index 6c2d156c..1e54b7d 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/worker/worker-console-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/worker/worker-console-expected.txt
@@ -1,38 +1,46 @@ -CONSOLE MESSAGE: line 3: message0 -CONSOLE MESSAGE: line 3: message1 -CONSOLE MESSAGE: line 3: message2 -CONSOLE MESSAGE: line 3: message3 -CONSOLE MESSAGE: line 3: message4 -CONSOLE MESSAGE: line 3: message5 -CONSOLE MESSAGE: line 3: message6 +CONSOLE MESSAGE: line 6: message0 +CONSOLE MESSAGE: line 6: message1 +CONSOLE MESSAGE: line 6: message2 +CONSOLE ERROR: line 4: Uncaught (in promise) throw1 +CONSOLE MESSAGE: line 6: message3 +CONSOLE MESSAGE: line 6: message4 +CONSOLE MESSAGE: line 6: message5 +CONSOLE MESSAGE: line 6: message6 Starting worker Logging in worker: message0 -Stopping worker Got console message from page: message0 +Stopping worker Starting worker Logging in worker: message1 +Got console message from page: message1 Sending Worker.enable Worker.created Sending Console.enable to worker Got console message from worker: message1 Logging in worker: message2 +Got console message from page: message2 Got console message from worker: message2 +Logging in worker: throw1 +Got console message from page: Uncaught (in promise) throw1 Sending Worker.disable Logging in worker: message3 +Got console message from page: message3 Stopping worker Sending Worker.enable Starting worker Worker.created Logging in worker: message4 +Got console message from page: message4 Sending Console.enable to worker Got console message from worker: message4 Logging in worker: message5 +Got console message from page: message5 Got console message from worker: message5 Stopping worker Starting worker Worker.created Logging in worker: message6 -Stopping worker Got console message from page: message6 +Stopping worker Sending Worker.disable
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/worker/worker-console.html b/third_party/WebKit/LayoutTests/inspector-protocol/worker/worker-console.html index bc201b9..97823329 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/worker/worker-console.html +++ b/third_party/WebKit/LayoutTests/inspector-protocol/worker/worker-console.html
@@ -38,11 +38,10 @@ function test() { - var workerEventHandler = []; - InspectorTest.eventHandler["Console.messageAdded"] = onConsoleMessage.bind(null, false); + var workerEventHandler = {}; InspectorTest.eventHandler["Worker.workerCreated"] = onWorkerCreated; InspectorTest.eventHandler["Worker.dispatchMessageFromWorker"] = onWorkerMessage; - workerEventHandler["Console.messageAdded"] = onConsoleMessage.bind(null, true); + workerEventHandler["Console.messageAdded"] = onConsoleMessageFromWorker; var workerId; @@ -91,20 +90,25 @@ function logInWorker(message, next) { InspectorTest.log("Logging in worker: " + message); - if (next) - InspectorTest.evaluateInPageAsync("logInWorkerFromPage(\"" + message + "\", %callback)", next); - else - InspectorTest.evaluateInPage("logInWorkerFromPage(\"" + message + "\")"); + InspectorTest.eventHandler["Console.messageAdded"] = onConsoleMessage; + InspectorTest.evaluateInPage("logInWorkerFromPage(\"" + message + "\")"); + + function onConsoleMessage(payload) + { + InspectorTest.log("Got console message from page: " + payload.params.message.text); + delete InspectorTest.eventHandler["Console.messageAdded"]; + next(); + } } var gotMessages = []; var waitingForMessage; var waitingForMessageCallback; - function onConsoleMessage(fromWorker, payload) + function onConsoleMessageFromWorker(payload) { var message = payload.params.message.text; - InspectorTest.log("Got console message from " + (fromWorker ? "worker" : "page") + ": " + message); + InspectorTest.log("Got console message from worker: " + message); gotMessages.push(message); if (message === waitingForMessage) waitingForMessageCallback(); @@ -140,8 +144,7 @@ function stop0(next) { InspectorTest.log("Stopping worker"); - waitForMessage("message0", next); - InspectorTest.evaluateInPage("stopWorker()"); + InspectorTest.evaluateInPage("stopWorker()", next); }, function start1(next) @@ -170,8 +173,17 @@ function log2(next) { + logInWorker("message2", next); + }, + + function waitForMessage2(next) + { waitForMessage("message2", next); - logInWorker("message2"); + }, + + function throw1(next) + { + logInWorker("throw1", next); }, function disable1(next) @@ -218,8 +230,12 @@ function log5(next) { + logInWorker("message5", next); + }, + + function waitForMessage5(next) + { waitForMessage("message5", next); - logInWorker("message5"); }, function stop2(next) @@ -242,8 +258,7 @@ function stop3(next) { InspectorTest.log("Stopping worker"); - waitForMessage("message6", next); - InspectorTest.evaluateInPage("stopWorker()"); + InspectorTest.evaluateInPage("stopWorker()", next); }, function disable2(next)
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-dir-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-dir-expected.txt index 679c8f5..a04d1d6 100644 --- a/third_party/WebKit/LayoutTests/inspector/console/console-dir-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/console/console-dir-expected.txt
@@ -40,8 +40,8 @@ name: "" prototype: Object __proto__: () - <function scope> - Global: Window + [[FunctionLocation]]: console-dir.html:19 + [[Scopes]]: Scopes[1] console-dir.html:23 inner __proto__: Object console-dir.html:26 Object @@ -56,8 +56,7 @@ length: 0 name: "get __proto__" __proto__: () - <function scope> - No Scopes + [[FunctionLocation]]: <unknown> console-dir.html:34 Uint8Array[400000000] [0 … 99999999] [100000000 … 199999999]
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-eval-exception-report-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-eval-exception-report-expected.txt index b3775fd..6da5f5d5 100644 --- a/third_party/WebKit/LayoutTests/inspector/console/console-eval-exception-report-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/console/console-eval-exception-report-expected.txt
@@ -10,7 +10,7 @@ } boo(); VM:3 Uncaught Object {a: 239}foo @ VM:3boo @ VM:7(anonymous function) @ VM:9 -call frame:foo at :3 -call frame:boo at :7 -call frame: at :9 +call frame:foo at :2 +call frame:boo at :6 +call frame: at :8
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-native-function-expected.txt b/third_party/WebKit/LayoutTests/inspector/console/console-native-function-expected.txt index 7f259fa..b1b6b62 100644 --- a/third_party/WebKit/LayoutTests/inspector/console/console-native-function-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/console/console-native-function-expected.txt
@@ -2,4 +2,6 @@ Math.random random() { [native code] } +document.appendChild +appendChild() { [native code] }
diff --git a/third_party/WebKit/LayoutTests/inspector/console/console-native-function.html b/third_party/WebKit/LayoutTests/inspector/console/console-native-function.html index 70f932b9..e61a5a5 100644 --- a/third_party/WebKit/LayoutTests/inspector/console/console-native-function.html +++ b/third_party/WebKit/LayoutTests/inspector/console/console-native-function.html
@@ -7,7 +7,12 @@ { InspectorTest.evaluateInConsole("Math.random", step1); - function step1(current, total) + function step1() + { + InspectorTest.evaluateInConsole("document.appendChild", step2); + } + + function step2() { InspectorTest.expandConsoleMessages(onExpanded); }
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/test-ast-editing-1-expected.txt b/third_party/WebKit/LayoutTests/inspector/sass/test-ast-editing-1-expected.txt index 30206fb..bc8ddf7 100644 --- a/third_party/WebKit/LayoutTests/inspector/sass/test-ast-editing-1-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sass/test-ast-editing-1-expected.txt
@@ -38,7 +38,7 @@ div { /* This is a regular comment */ color: red; - position: absolute; + position: absolute; display: block }
diff --git a/third_party/WebKit/LayoutTests/inspector/sass/test-edit-toggle-property-expected.txt b/third_party/WebKit/LayoutTests/inspector/sass/test-edit-toggle-property-expected.txt index 23d24f6..f4e38baf 100644 --- a/third_party/WebKit/LayoutTests/inspector/sass/test-edit-toggle-property-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sass/test-edit-toggle-property-expected.txt
@@ -75,7 +75,7 @@ ===== test-edit-toggle-property.scss ===== @for.$i.from.1.through.3.{ .....box#{$i}.{ - ........color:.red;. + ........color:.red; ........margin:.10px; ....} }
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/execution-context-sorted-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/execution-context-sorted-expected.txt new file mode 100644 index 0000000..2918702 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/execution-context-sorted-expected.txt
@@ -0,0 +1,7 @@ + +Tests how execution context and target are selected. + +top +execution-context-iframe1.html +execution-context-iframe2.html +
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/execution-context-sorted.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/execution-context-sorted.html new file mode 100644 index 0000000..7958d84 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/execution-context-sorted.html
@@ -0,0 +1,24 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script> + +function test() +{ + var contexts = InspectorTest.runtimeModel.executionContexts(); + for (var c of contexts) + InspectorTest.addResult(c.target().resourceTreeModel.frameForId(c.frameId).displayName()); + InspectorTest.completeTest(); +} + +</script> +</head> + +<body onload="runTest()"> + <iframe src="../resources/execution-context-iframe1.html"></iframe> +<p> +Tests how execution context and target are selected. +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-details-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-details-expected.txt index b8809ce..3f34200 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-details-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-details-expected.txt
@@ -8,8 +8,7 @@ columnNumber: 36 scriptId is valid: true functionName: firstLineFunction -isGenerator: false -scopeChain #0: global; <global object properties omitted> +scopeChain #0: Global; <global object properties omitted> Running: testGetNonFirstLineFunctionDetails notFirstLineFunction type = function @@ -18,8 +17,7 @@ columnNumber: 32 scriptId is valid: true functionName: notFirstLineFunction -isGenerator: false -scopeChain #0: global; <global object properties omitted> +scopeChain #0: Global; <global object properties omitted> Running: testGetDetailsOfFunctionWithInferredName obj.m type = function @@ -28,8 +26,7 @@ columnNumber: 15 scriptId is valid: true functionName: m -isGenerator: false -scopeChain #0: global; <global object properties omitted> +scopeChain #0: Global; <global object properties omitted> Running: testGetDetailsOfFunctionWithDisplayName functionWithDisplayName type = function @@ -38,8 +35,7 @@ columnNumber: 32 scriptId is valid: true functionName: user-friendly name -isGenerator: false -scopeChain #0: global; <global object properties omitted> +scopeChain #0: Global; <global object properties omitted> Running: testGetDetailsOfFunctionWithDisplayNameGetter functionWithDisplayNameGetter type = function @@ -48,8 +44,7 @@ columnNumber: 38 scriptId is valid: true functionName: functionWithDisplayNameGetter -isGenerator: false -scopeChain #0: global; <global object properties omitted> +scopeChain #0: Global; <global object properties omitted> Running: testSmallClosure smallClosure type = function @@ -58,9 +53,8 @@ columnNumber: 49 scriptId is valid: true functionName: -isGenerator: false -scopeChain #0: closure; p: "Capybara" -scopeChain #1: global; <global object properties omitted> +scopeChain #0: Closure; p: "Capybara" +scopeChain #1: Global; <global object properties omitted> Running: testBigClosure bigClosure type = function @@ -69,9 +63,18 @@ columnNumber: 27 scriptId is valid: true functionName: -isGenerator: false -scopeChain #0: catch; ex: <no string representation> -scopeChain #1: with; __proto__: <no string representation>,e: 7,f: 5,u: <no value>,v: <no value> -scopeChain #2: closure; p: <no string representation> -scopeChain #3: global; <global object properties omitted> +scopeChain #0: Catch; ex: <no string representation> +scopeChain #1: With Block; __proto__: <no string representation>,e: 7,f: 5,u: <no value>,v: <no value> +scopeChain #2: Closure; p: <no string representation> +scopeChain #3: Global; <global object properties omitted> + +Running: testGenFunction +gen type = function +Function details: +lineNumber: 45 +columnNumber: 13 +scriptId is valid: true +functionName: gen +isGenerator: true +scopeChain #0: Global; <global object properties omitted>
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-details.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-details.html index 10d9760..0e7aa52 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-details.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/function-details.html
@@ -43,16 +43,20 @@ } })({}); +function* gen() { yield [1,2,3] } + function test() { - function dumpFunctionDetails(details) + function dumpFunctionDetails(properties) { + var location = properties.get("[[FunctionLocation]]").value.value; InspectorTest.addResult("Function details: "); - InspectorTest.addResult("lineNumber: " + details.location.lineNumber); - InspectorTest.addResult("columnNumber: " + details.location.columnNumber); - InspectorTest.addResult("scriptId is valid: " + !!details.location.scriptId); - InspectorTest.addResult("functionName: " + details.functionName); - InspectorTest.addResult("isGenerator: " + details.isGenerator); + InspectorTest.addResult("lineNumber: " + location.lineNumber); + InspectorTest.addResult("columnNumber: " + location.columnNumber); + InspectorTest.addResult("scriptId is valid: " + !!location.scriptId); + InspectorTest.addResult("functionName: " + properties.get("name").value.value); + if (properties.has("[[IsGenerator]]")) + InspectorTest.addResult("isGenerator: " + properties.get("[[IsGenerator]]").value.value); } function dumpFunctionNoScopes() @@ -63,7 +67,7 @@ function dumpFunctionScope(pos, type, propertyDescriptors) { var variables; - if (type == "global") { + if (type == "Global") { variables = "<global object properties omitted>"; } else { var varArray = []; @@ -88,28 +92,37 @@ function loadAndDumpScopeObjects(scopeChain, end) { + var scopes = []; function loadScopeObject(pos, next) { - if (pos >= scopeChain.length) { + if (pos >= scopes.length) { next(); return; } - var scopeJson = scopeChain[pos]; - InspectorTest.RuntimeAgent.getProperties(scopeJson.object.objectId, true, didGetProperties); + InspectorTest.RuntimeAgent.getProperties(scopes[pos].objectId, true, didGetProperties); function didGetProperties(error, propertyDescriptors) { - dumpFunctionScope(pos, scopeJson.type, propertyDescriptors); + dumpFunctionScope(pos, scopes[pos].description, propertyDescriptors); loadScopeObject(pos + 1, next); } } if (scopeChain) { - loadScopeObject(0, end); + InspectorTest.RuntimeAgent.getProperties(scopeChain.value.objectId, true, didGetScopes); } else { dumpFunctionNoScopes(); end(); } + + function didGetScopes(error, properties) + { + for (var prop of properties) { + if (String(prop.name >>> 0) === prop.name) + scopes.push(prop.value); + } + loadScopeObject(0, end); + } } function performStandardTestCase(pageExpression, next) @@ -119,12 +132,23 @@ function didEvaluate(remote) { InspectorTest.addResult(pageExpression + " type = " + remote.type); - InspectorTest.DebuggerAgent.getFunctionDetails(remote.objectId, didGetDetails); + InspectorTest.RuntimeAgent.getProperties(remote.objectId, /* isOwnProperty */ false, didGetDetails); } - function didGetDetails(error, response) + function didGetDetails(error, properties, internalProperties) { - dumpFunctionDetails(response); - loadAndDumpScopeObjects(response.scopeChain, next); + var propertiesMap = new Map(); + for (var prop of internalProperties) + propertiesMap.set(prop.name, prop); + for (var prop of properties) { + if (prop.name === "name" && prop.value && prop.value.type === "string") + propertiesMap.set("name", prop); + if (prop.name === "displayName" && prop.value && prop.value.type === "string") { + propertiesMap.set("name", prop); + break; + } + } + dumpFunctionDetails(propertiesMap); + loadAndDumpScopeObjects(propertiesMap.get("[[Scopes]]"), next); } } @@ -156,6 +180,10 @@ function testBigClosure(next) { performStandardTestCase("bigClosure", next); + }, + function testGenFunction(next) + { + performStandardTestCase("gen", next); } ]); };
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/last-execution-context-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/last-execution-context-expected.txt index 65041c9..77541f53 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/last-execution-context-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/last-execution-context-expected.txt
@@ -9,7 +9,7 @@ Adding sw target Removing page main frame -Execution context selected: contentScript1 +Execution context selected: mock-target-page-target:iframe1 Readding page main frame Execution context selected: mock-target-page-target:42
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/last-execution-context.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/last-execution-context.html index 23d3892..939f470 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/last-execution-context.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/last-execution-context.html
@@ -33,7 +33,7 @@ InspectorTest.addResult(""); InspectorTest.addResult("Adding sw target"); - var swTarget = InspectorTest.createMockTarget("sw-target", null, WebInspector.Target.Type.Worker); + var swTarget = InspectorTest.createMockTarget("sw-target", null, WebInspector.Target.Capability.Network | WebInspector.Target.Capability.Worker); swTarget.runtimeModel._executionContextCreated({id: "sw1", isDefault: true, origin: "origin", name: "swContext1Name", frameId: ""}); InspectorTest.addResult(""); @@ -54,7 +54,7 @@ InspectorTest.addResult(""); InspectorTest.addResult("User selected content script"); - context.setFlavor(WebInspector.ExecutionContext, pageTarget.runtimeModel.executionContexts()[0]); + context.setFlavor(WebInspector.ExecutionContext, pageTarget.runtimeModel.executionContexts()[2]); InspectorTest.addResult(""); InspectorTest.addResult("Switching to sw target"); @@ -66,7 +66,7 @@ InspectorTest.addResult(""); InspectorTest.addResult("User selected iframe1"); - context.setFlavor(WebInspector.ExecutionContext, pageTarget.runtimeModel.executionContexts()[1]); + context.setFlavor(WebInspector.ExecutionContext, pageTarget.runtimeModel.executionContexts()[0]); InspectorTest.addResult(""); InspectorTest.addResult("Switching to sw target");
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/watch-expressions-preserve-expansion-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/watch-expressions-preserve-expansion-expected.txt index aef0c356..0794d3d 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/watch-expressions-preserve-expansion-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/watch-expressions-preserve-expansion-expected.txt
@@ -4,8 +4,8 @@ Watch expressions added. expanded foo [object Object] expanded bar [object Object] -expanded <function scope> -expanded Closure +expanded [[Scopes]] [object Object] +expanded 0 [object Object] expanded a [object Object] expanded [200 .. 299] expanded 299 [object Object] @@ -129,11 +129,12 @@ name: prototype: Object __proto__: function () {} - <function scope> - Closure + [[FunctionLocation]]: Object + [[Scopes]]: Scopes[2] + 0: Closure a: 10 b: 100 - Global: Window + 1: Global Page reloaded. Watch expressions after page reload: globalObject: Object @@ -255,9 +256,10 @@ name: prototype: Object __proto__: function () {} - <function scope> - Closure + [[FunctionLocation]]: Object + [[Scopes]]: Scopes[2] + 0: Closure a: 10 b: 100 - Global: Window + 1: Global
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/watch-expressions-preserve-expansion.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/watch-expressions-preserve-expansion.html index 94349a93..a80c4414 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/watch-expressions-preserve-expansion.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger-ui/watch-expressions-preserve-expansion.html
@@ -38,7 +38,7 @@ { InspectorTest.addResult("Watch expressions added."); var expandArray = expandWatchExpression.bind(null, ["array", "[200 \u2026 299]", "299"], step3); - var expandFunc = expandWatchExpression.bind(null, ["func", "<function scope>", "Closure", "a"], expandArray); + var expandFunc = expandWatchExpression.bind(null, ["func", "[[Scopes]]", "0", "a"], expandArray); expandWatchExpression(["globalObject", "foo", "bar"], expandFunc); }
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/debugger-compile-and-run-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger/debugger-compile-and-run-expected.txt index 878de58c..cb41034 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger/debugger-compile-and-run-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/debugger-compile-and-run-expected.txt
@@ -16,7 +16,7 @@ exceptionDetails stack trace: url: test.js function: - line: 1 + line: 0 Running: testCompileError Compiling script
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special-expected.txt b/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special-expected.txt index 427e428a..36d5ec9 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special-expected.txt
@@ -1,6 +1,7 @@ CONSOLE MESSAGE: line 10: true CONSOLE MESSAGE: line 11: function (a,b) { return a + b; } CONSOLE MESSAGE: line 12: function () { [native code] } +CONSOLE MESSAGE: line 13: function* () { yeild [1,2,3] } Tests how debugger presents special properties of closures, bound functions and object wrappers. properties-special.html:10 Boolean @@ -13,8 +14,9 @@ name: "" prototype: Object __proto__: () - <function scope> -properties-special.html:12 anonymous() + [[FunctionLocation]]: properties-special.html:11 + [[Scopes]]: Scopes[1] +properties-special.html:12 bound () arguments: (...) caller: (...) length: 1 @@ -23,4 +25,14 @@ [[TargetFunction]]: (a,b) [[BoundThis]]: Object [[BoundArgs]]: Array[1] +properties-special.html:13 anonymous() + arguments: (...) + caller: (...) + length: 0 + name: "" + prototype: Generator + __proto__: GeneratorFunction + [[FunctionLocation]]: properties-special.html:13 + [[IsGenerator]]: true + [[Scopes]]: Scopes[1]
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special.html b/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special.html index 4749b20..f87c8164 100644 --- a/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special.html +++ b/third_party/WebKit/LayoutTests/inspector/sources/debugger/properties-special.html
@@ -10,6 +10,7 @@ console.dir(Object(true)); console.dir((function(a,b) { return a + b; })); console.dir((function(a,b) { return a + b; }).bind({}, 2)); + console.dir((function*() { yeild [1,2,3] })); runTest(); }
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/resources/execution-context-iframe1.html b/third_party/WebKit/LayoutTests/inspector/sources/resources/execution-context-iframe1.html new file mode 100644 index 0000000..3b11606 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/sources/resources/execution-context-iframe1.html
@@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> + <head> + </head> + <body> + iframe 1 + <iframe src="execution-context-iframe2.html"></iframe> + </bodY> +</html> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/inspector/sources/resources/execution-context-iframe2.html b/third_party/WebKit/LayoutTests/inspector/sources/resources/execution-context-iframe2.html new file mode 100644 index 0000000..8e28820f --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/sources/resources/execution-context-iframe2.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<html> + <head> + </head> + <body> + iframe 2 + </bodY> +</html> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/compile-script-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/compile-script-expected.txt deleted file mode 100644 index 7d95d51..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/compile-script-expected.txt +++ /dev/null
@@ -1,28 +0,0 @@ -CONSOLE MESSAGE: line 1: SCRIPT TAG -Tests the Timeline instrumentation for CompileScript event. - -v8.compile Properties: -{ - data : { - columnNumber : <number> - lineNumber : <number> - url : - } - endTime : <number> - startTime : <number> - type : "v8.compile" -} -Text details for v8.compile: undefined -v8.compile Properties: -{ - data : { - columnNumber : <number> - lineNumber : <number> - url : .../inspector/tracing/timeline-script-tag-2.js - } - endTime : <number> - startTime : <number> - type : "v8.compile" -} -Text details for v8.compile: timeline-script-tag-2.js:1 -
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/compile-script.html b/third_party/WebKit/LayoutTests/inspector/tracing/compile-script.html deleted file mode 100644 index 37d2017..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/compile-script.html +++ /dev/null
@@ -1,33 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function performActions() -{ - var script = document.createElement("script"); - script.textContent = "function noop1() {} \n//# sourceURL=script-content.js"; - document.body.appendChild(script); - eval("function noop2() {} \n//# sourceURL=script-content.js"); - - script = document.createElement("script"); - script.src = "timeline-script-tag-2.js"; - document.body.appendChild(script); -} - -function test() -{ - InspectorTest.performActionsAndPrint("performActions()", WebInspector.TimelineModel.RecordType.CompileScript); -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline instrumentation for CompileScript event. -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/layer-tree.html b/third_party/WebKit/LayoutTests/inspector/tracing/layer-tree.html deleted file mode 100644 index 79e32b3..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/layer-tree.html +++ /dev/null
@@ -1,55 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script src="../../http/tests/inspector/layers-test.js"></script> -<script src="../tracing-test.js"></script> - -<script> -function doActions(callback) -{ - var div = document.createElement("div"); - div.id = "b4"; - document.getElementById("a").appendChild(div); - - // Make sure to force commit, otherwise some owner nodes will be missing. - var style = document.createElement("style"); - style.textContent = ".layer { transform: translateZ(10px); opacity: 0.8; }"; - document.head.appendChild(style); - generateFrames(3, callback); -} - -function test() -{ - WebInspector.panels.timeline._captureLayersAndPicturesSetting.set(true); - - InspectorTest.invokeAsyncWithTimeline("doActions", step1); - function step1() - { - var frames = InspectorTest.timelineFrameModel().frames(); - var lastFrame = InspectorTest.timelineFrameModel().frames().peekLast(); - var deferredLayerTree = lastFrame.layerTree; - deferredLayerTree.resolve(InspectorTest.safeWrap(layerTreeResolved)); - } - - function layerTreeResolved(layerTree) - { - InspectorTest.layerTreeModel().setLayerTree(layerTree); - InspectorTest.dumpLayerTree(); - InspectorTest.completeTest(); - } -} -</script> - -<body onload="runTestAfterDisplay()"> -Tests that LayerTreeModel successfully imports layers from a trace. -</p> -<div id="a" style="width: 200px; height: 200px" class="layer"> - <div class="layer" id="b1" style="width: 150px; height: 100px"></div> - <div id="b2" class="layer" style="width: 140px; height: 110px"> - <div id="c" class="layer" style="width: 100px; height: 90px"></div> - </div> - <div id="b3" class="layer" style="width: 140px; height: 110px"></div> -</div> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/paint-profiler-update.html b/third_party/WebKit/LayoutTests/inspector/tracing/paint-profiler-update.html deleted file mode 100644 index 7a320e9..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/paint-profiler-update.html +++ /dev/null
@@ -1,84 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function performActions(callback) -{ - var square = document.getElementById("square"); - step1(); - - function step1() - { - square.style.backgroundColor = "red"; - testRunner.layoutAndPaintAsyncThen(step2); - } - - function step2() - { - square.style.backgroundColor = "black"; - testRunner.layoutAndPaintAsyncThen(callback); - } -} - -function test() -{ - var panel = WebInspector.panels.timeline; - - panel._captureLayersAndPicturesSetting.set(true); - panel._onModeChanged(); - - InspectorTest.invokeAsyncWithTimeline("performActions", onRecordingDone); - var paintEvents = []; - function onRecordingDone() - { - var events = InspectorTest.timelineModel()._mainThreadEvents; - for (var event of events) { - if (event.name === WebInspector.TimelineModel.RecordType.Paint) { - paintEvents.push(event); - if (!event.picture) - InspectorTest.addResult("Event without picture at " + paintEvents.length); - } - } - - if (paintEvents.length < 2) - throw new Error("FAIL: Expect at least two paint events"); - - InspectorTest.addSniffer(panel, "_appendDetailsTabsForTraceEventAndShowDetails", onRecordDetailsReady, false); - panel.select(WebInspector.TimelineSelection.fromTraceEvent(paintEvents[0]), WebInspector.TimelinePanel.DetailsTab.PaintProfiler); - } - - function onRecordDetailsReady() - { - var updateCount = 0; - var paintProfilerView = panel._lazyPaintProfilerView._paintProfilerView; - InspectorTest.addSniffer(paintProfilerView, "_update", onPaintProfilerUpdate, true); - - function onPaintProfilerUpdate() - { - // No snapshot, not a real update yet -- wait for another update! - if (!paintProfilerView._snapshot) - return; - var logSize = paintProfilerView._log && paintProfilerView._log.length ? ">0" : "0"; - InspectorTest.addResult("Paint " + updateCount + " log size: " + logSize); - if (updateCount++) - InspectorTest.completeTest(); - else - panel.select(WebInspector.TimelineSelection.fromTraceEvent(paintEvents[1]), WebInspector.TimelinePanel.DetailsTab.PaintProfiler); - } - } - -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests that paint profiler is properly update when an event is selected in Flame Chart -</p> - -<div id="square" style="width: 40px; height: 40px"></div> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/parse-author-style-sheet.html b/third_party/WebKit/LayoutTests/inspector/tracing/parse-author-style-sheet.html deleted file mode 100644 index 51e6b66..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/parse-author-style-sheet.html +++ /dev/null
@@ -1,41 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script src="../tracing-test.js"></script> -<script> - -function importStyle(onComplete) -{ - var link = document.createElement('link'); - link.setAttribute('rel', 'stylesheet'); - link.type = 'text/css'; - link.href = 'resources/style.css'; - document.head.appendChild(link); - link.onload = onComplete.bind(this, null); -} - -function test() -{ - InspectorTest.invokeWithTracing("importStyle", processTracingEvents); - - function processTracingEvents() - { - var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.ParseAuthorStyleSheet); - if (record) - InspectorTest.addResult("SUCCESS: found ParseAuthorStyleSheet record"); - else - InspectorTest.addResult("FAIL: ParseAuthorStyleSheet record not found"); - InspectorTest.completeTest(); - } -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests that ParseAuthorStyleSheet trace event is recorded. -</p> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-aggregated-details.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-aggregated-details.html deleted file mode 100644 index 43dc84dd..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-aggregated-details.html +++ /dev/null
@@ -1,620 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function test() -{ - var sessionId = "6.23"; - var rawTraceEvents = [ - { - "args": { - "name": "Renderer" - }, - "cat": "__metadata", - "name": "process_name", - "ph": "M", - "pid": 17851, - "tid": 23, - "ts": 0 - }, - { - "args": { - "name": "CrRendererMain" - }, - "cat": "__metadata", - "name": "thread_name", - "ph": "M", - "pid": 17851, - "tid": 23, - "ts": 0 - }, - { - "args": { - "sessionId": sessionId - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "TracingStartedInPage", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 100000, - "tts": 606543 - }, - { - "args": {}, - "cat": "disabled-by-default-devtools.timeline", - "name": "Program", - "ph": "B", - "pid": 17851, - "tid": 23, - "ts": 200000, - "tts": 5612442 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "c", "callUID": "c", "scriptId": 1 }, - { "functionName": "b", "callUID": "b", "scriptId": 1 }, - { "functionName": "a", "callUID": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 208000, - "tts": 1758056 - }, - { - "args": {}, - "cat": "disabled-by-default-devtools.timeline", - "name": "FunctionCall", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 210000, - "dur": 30000, - "tts": 5612442 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "c", "callUID": "c", "scriptId": 1 }, - { "functionName": "b", "callUID": "b", "scriptId": 1 }, - { "functionName": "a", "callUID": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 211000, - "tts": 1758056 - }, - { - "args": { - "data": { - "stackTrace": [] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 212000, - "tts": 1758056 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "c", "callUID": "c", "scriptId": 1 }, - { "functionName": "b", "callUID": "b", "scriptId": 1 }, - { "functionName": "a", "callUID": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 219875, - "tts": 1758056 - }, - { - "args": { - "frame": "0x2f7b63884000", - "data": { - "stackTrace": [ - { "functionName": "b", "callUID": "b", "scriptId": 1 }, - { "functionName": "a", "callUID": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "InvalidateLayout", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 220000, - "dur": 7000, - "tts": 1758056 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "c", "callUID": "c", "scriptId": 1 }, - { "functionName": "b", "callUID": "b", "scriptId": 1 }, - { "functionName": "a", "callUID": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 220125, - "tts": 1758056 - }, - { - "args": { - "frame": "0x2f7b63884000", - "data": { - "stackTrace": [ - { "functionName": "b", "callUID": "b", "scriptId": 1 }, - { "functionName": "a", "callUID": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "InvalidateLayout", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 221000, - "dur": 3000, - "tts": 1758056 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "g", "scriptId": 1 }, - { "functionName": "f", "scriptId": 1 }, - { "functionName": "b", "scriptId": 1 }, - { "functionName": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 222000, - "tts": 1758056 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "g", "scriptId": 1 }, - { "functionName": "e", "scriptId": 1 }, - { "functionName": "b", "scriptId": 1 }, - { "functionName": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 227125, - "tts": 1758056 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "g", "scriptId": 1 }, - { "functionName": "e", "scriptId": 1 }, - { "functionName": "b", "scriptId": 1 }, - { "functionName": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 227250, - "tts": 1758056 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "a", "callUID": "a", "scriptId": 1 }, - { "functionName": "l", "callUID": "l", "scriptId": 1 }, - { "functionName": "f", "callUID": "f", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 230000, - "tts": 1758056 - }, - { - "args": { - "beginData": { - "stackTrace": [ - { "functionName": "a", "callUID": "a", "scriptId": 1 }, - { "functionName": "l", "callUID": "l", "scriptId": 1 }, - { "functionName": "f", "callUID": "f", "scriptId": 1 }, - { "functionName": "sin", "callUID": "sin", "scriptId": 2, "url": "native math.js" } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "Layout", - "ph": "X", - "dur": 100, - "pid": 17851, - "tid": 23, - "ts": 230010, - "tts": 1758056 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "a", "callUID": "a", "scriptId": 1 }, - { "functionName": "l", "callUID": "l", "scriptId": 1 }, - { "functionName": "f", "callUID": "f", "scriptId": 1 }, - { "functionName": "sin", "callUID": "sin", "scriptId": 2, "url": "native math.js" } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "TimerInstall", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 230111 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "a", "callUID": "a", "scriptId": 1 }, - { "functionName": "l", "callUID": "l", "scriptId": 1 }, - { "functionName": "f", "callUID": "f", "scriptId": 1 }, - { "functionName": "sin", "callUID": "sin", "scriptId": 2, "url": "native math.js" } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 230125 - }, - { - "args": {}, - "cat": "disabled-by-default-devtools.timeline", - "name": "FunctionCall", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 250000, - "dur": 10000 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "y", "callUID": "y", "scriptId": 1 }, - { "functionName": "x", "callUID": "x", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "FunctionCall", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 251000, - "dur": 1000 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "w", "callUID": "w", "scriptId": 1 }, - { "functionName": "z", "callUID": "z", "scriptId": 1 }, - { "functionName": "y", "callUID": "y", "scriptId": 1 }, - { "functionName": "x", "callUID": "x", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 251000 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "w", "callUID": "w", "scriptId": 1 }, - { "functionName": "z", "callUID": "z", "scriptId": 1 }, - { "functionName": "y", "callUID": "y", "scriptId": 1 }, - { "functionName": "x", "callUID": "x", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 251100 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "w", "scriptId": 1 }, - { "functionName": "y", "callUID": "y", "scriptId": 1 }, - { "functionName": "x", "callUID": "x", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 251200 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "w", "scriptId": 1 }, - { "functionName": "y", "callUID": "y", "scriptId": 1 }, - { "functionName": "x", "callUID": "x", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 251300 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "y", "callUID": "y", "scriptId": 1 }, - { "functionName": "x", "callUID": "x", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 251400 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "recursive_b", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, - { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, - { "functionName": "recursive_b", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, - { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 253000 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, - { "functionName": "recursive_b", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, - { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 253008 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "recursive_b", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, - { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 253012 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 253014 - }, - { - "args": { - "data": { - "stackTrace": [ - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 253015 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "recursive_b", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, - { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 253100 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 253200 - }, - { - "args": { - "data": { - "stackTrace": [ - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 253300 - }, - { - "args": {}, - "cat": "disabled-by-default-devtools.timeline", - "name": "Program", - "ph": "E", - "pid": 17851, - "tid": 23, - "ts": 500000, - "tts": 5612506 - } - ]; - - var timeline = WebInspector.panels.timeline; - InspectorTest.setTraceEvents(InspectorTest.timelineModel(), InspectorTest.tracingModel(), rawTraceEvents); - - timeline.requestWindowTimes(0, Infinity); - for (var grouping in WebInspector.TimelineAggregator.GroupBy) { - var groupingValue = WebInspector.TimelineAggregator.GroupBy[grouping]; - testEventTree(WebInspector.TimelinePanel.DetailsTab.CallTree, groupingValue); - testEventTree(WebInspector.TimelinePanel.DetailsTab.BottomUp, groupingValue); - } - - testEventTree(WebInspector.TimelinePanel.DetailsTab.Events); - InspectorTest.completeTest(); - - function testEventTree(type, grouping) - { - InspectorTest.addResult(""); - timeline._detailsView.selectTab(type, true); - var callTree = timeline._detailsView._rangeDetailViews.get(type); - if (grouping) { - InspectorTest.addResult(type + " Group by: " + grouping); - callTree._groupByCombobox.select(callTree._groupByCombobox.options().find((x) => x.value === grouping)); - callTree._onGroupByChanged(); - } else { - InspectorTest.addResult(type); - } - var rootNode = callTree._dataGrid.rootNode(); - for (var node of rootNode.children) - printEventTree(1, node._profileNode, node._treeView); - } - - function printEventTree(padding, node, treeView) - { - var name; - if (node.isGroupNode()) { - name = treeView._displayInfoForGroupNode(node).name; - } else { - name = node.event.name === WebInspector.TimelineModel.RecordType.JSFrame - ? WebInspector.beautifyFunctionName(node.event.args["data"]["functionName"]) - : WebInspector.TimelineUIUtils.eventTitle(node.event); - } - InspectorTest.addResult(" ".repeat(padding) + name + ": " + [node.selfTime, node.totalTime].map(function (t) { return t.toFixed(3); }).join(" ")); - (node.children || new Map()).forEach(printEventTree.bind(null, padding + 1)); - } -} - -</script> -</head> -<body onload="runTest()"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-animation-frame.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-animation-frame.html deleted file mode 100644 index ddd1ab1..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-animation-frame.html +++ /dev/null
@@ -1,40 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function performActions(callback) -{ - var requestId = window.requestAnimationFrame(animationFrameCallback); - function animationFrameCallback() - { - window.cancelAnimationFrame(requestId); - if (callback) - callback(); - } -} - -function test() -{ - InspectorTest.invokeAsyncWithTimeline("performActions", finish); - - function finish() - { - InspectorTest.printTimelineRecordsWithDetails("RequestAnimationFrame"); - InspectorTest.printTimelineRecordsWithDetails("FireAnimationFrame"); - InspectorTest.printTimelineRecordsWithDetails("CancelAnimationFrame"); - InspectorTest.completeTest(); - } -} - -if (!window.testRunner) - setTimeout(performActions, 2000); -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline events for Animation Frame feature -</p> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-auto-record.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-auto-record.html deleted file mode 100644 index 7f965e1..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-auto-record.html +++ /dev/null
@@ -1,51 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/console-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function test() -{ - var panel = WebInspector.panels.timeline; - - var callbackBarrier = new CallbackBarrier(); - InspectorTest.addSniffer(panel, "recordingStarted", recordingStarted); - InspectorTest.addSniffer(panel, "loadingComplete", callbackBarrier.createCallback()); - - WebInspector.ConsolePanel.show(); - InspectorTest.runWhenPageLoads(step1); - InspectorTest.addResult("Reloading page on console panel"); - panel._millisecondsToRecordAfterLoadEvent = 1; - InspectorTest.resourceTreeModel.reloadPage(); - - function step1() - { - WebInspector.TimelinePanel.show(); - InspectorTest.runWhenPageLoads(callbackBarrier.createCallback()); - callbackBarrier.callWhenDone(recordingStopped); - InspectorTest.addResult("Reloading page on timeline panel"); - InspectorTest.resourceTreeModel.reloadPage(); - } - - function recordingStarted() - { - InspectorTest.addResult("Recording started"); - InspectorTest.addResult("Initiated by user: " + !panel._autoRecordGeneration); - } - - function recordingStopped() - { - InspectorTest.addResult("Recording stopped"); - InspectorTest.completeTest(); - } -} - -</script> -</head> - -<body onload="runTest()"> -<p>Test auto-recording of Timeline.</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-auto-zoom.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-auto-zoom.html deleted file mode 100644 index e4609a7..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-auto-zoom.html +++ /dev/null
@@ -1,56 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function test() -{ - var sessionId = "4.20"; - var mainThread = 1; - var pid = 100; - - var traceEvents = [ - { - "args": { "sessionId": sessionId }, - "cat": "disabled-by-default-devtools.timeline", - "name": "TracingStartedInPage", - "ph": "I", - "pid": pid, - "tid": mainThread, - "ts": 100, - }, - {"name": "Program", "ts": 1000000, "dur":10000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline" }, - {"name": "FunctionCall", "ts": 1000000, "dur": 10000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{}}}, - {"name": "Program", "ts": 2000000, "dur": 500000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline" }, - {"name": "FunctionCall", "ts": 2000000, "dur": 500000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{}}}, - {"name": "Program", "ts": 3000000, "dur": 400000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline"}, - {"name": "FunctionCall", "ts": 3000000, "dur": 400000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{}}}, - {"name": "Program", "ts": 4000000, "dur": 200000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline"}, - {"name": "FunctionCall", "ts": 4000000, "dur": 200000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{}}}, - {"name": "Program", "ts": 5000000, "dur": 1000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline"}, - {"name": "FunctionCall", "ts": 5000000, "dur": 1000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{}}}, - {"name": "Program", "ts": 6000000, "dur": 1000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline"}, - {"name": "FunctionCall", "ts": 6000000, "dur": 1000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{}}} - ]; - - InspectorTest.setTraceEvents(InspectorTest.timelineModel(), InspectorTest.tracingModel(), traceEvents); - var overview = WebInspector.panels.timeline._overviewPane; - var startTime = overview._windowStartTime; - var endTime = overview._windowEndTime; - InspectorTest.assertGreaterOrEqual(startTime, 1010); - InspectorTest.assertGreaterOrEqual(2000, startTime); - InspectorTest.assertGreaterOrEqual(endTime, 4200); - InspectorTest.assertGreaterOrEqual(5000, startTime); - InspectorTest.completeTest(); -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Test auto zoom feature of the timeline. -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-bound-function.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-bound-function.html deleted file mode 100644 index 2c0903a5..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-bound-function.html +++ /dev/null
@@ -1,46 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function original() { } - -function performActions() -{ - var b = document.getElementById("btn"); - var foo = original.bind(); - b.onclick = foo; - b.click(); -} - -function test() -{ - InspectorTest.evaluateWithTimeline("performActions()", finish); - - function finish() - { - function formatter(record) - { - if (record.type() === "FunctionCall") { - var data = record.traceEvent().args["data"]; - var scriptName = data.scriptName; - var scriptNameShort = scriptName.substring(scriptName.lastIndexOf("/") + 1); - InspectorTest.addResult(record.type() + " " + scriptNameShort + ":" + data.scriptLine); - } - } - InspectorTest.printTimelineRecords(null, formatter); - InspectorTest.completeTest(); - } -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests extracting information about original functions from bound ones -</p> -<button id="btn"></button> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-dfs.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-dfs.html deleted file mode 100644 index 979c1fe..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-dfs.html +++ /dev/null
@@ -1,68 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script type="text/javascript"> - -var test = function() -{ - - function dumper(record) - { - InspectorTest.addResult(record.type()); - } - - var sessionId = "4.20"; - var mainThread = 1; - var pid = 100; - - var testData = [ - { - "args": { "sessionId": sessionId }, - "cat": "disabled-by-default-devtools.timeline", - "name": "TracingStartedInPage", - "ph": "I", - "pid": pid, - "tid": mainThread, - "ts": 100, - }, - {"name": "a", "ts": 1000000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args": {}}, - {"name": "aa", "ts": 1000001, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, - {"name": "aaa", "ts": 1200000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, - {"name": "aab", "ts": 1300000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, - {"name": "aa", "ts": 1400000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args": {}}, - {"name": "ab", "ts": 1500001, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, - {"name": "aba", "ts": 1600000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, - {"name": "abb", "ts": 1700000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, - {"name": "ab", "ts": 1800000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args": {}}, - {"name": "a", "ts": 2000000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args": {}}, - {"name": "b", "ts": 3000000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args": {}}, - {"name": "ba", "ts": 3000001, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, - {"name": "baa", "ts": 3200000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, - {"name": "bab", "ts": 3300000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, - {"name": "ba", "ts": 3400000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args": {}}, - {"name": "bb", "ts": 3500001, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, - {"name": "bba", "ts": 3600000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, - {"name": "bbb", "ts": 3700000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, - {"name": "bb", "ts": 3800000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args": {}}, - {"name": "b", "ts": 4000000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args": {}} - ]; - - var model = new WebInspector.TimelineModel(new WebInspector.TimelineModel.Filter()); - InspectorTest.setTraceEvents(model, InspectorTest.createTracingModel(), testData); - - InspectorTest.addResult("DFS preorder:"); - model.forAllRecords(dumper); - InspectorTest.addResult(""); - - InspectorTest.addResult("DFS postorder:"); - model.forAllRecords(null, dumper); - InspectorTest.completeTest(); -} - -</script> -</head> -<body onload="runTest()"> -<p>Tests TimelineModel.forAllRecords function.</p> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-event-causes.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-event-causes.html deleted file mode 100644 index 129820f..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-event-causes.html +++ /dev/null
@@ -1,135 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function test() -{ - function checkStringContains(string, contains) - { - var doesContain = string.indexOf(contains) >= 0; - InspectorTest.check(doesContain, contains + " should be present in " + string); - InspectorTest.addResult("PASS - record contained " + contains); - } - - InspectorTest.runTestSuite([ - function testTimerInstall(next) - { - function setTimeoutFunction(callback) - { - setTimeout(callback, 0); - } - - var source = setTimeoutFunction.toString(); - source += "\n//# sourceURL=setTimeoutFunction.js"; - InspectorTest.evaluateInPage(source); - - InspectorTest.invokeAsyncWithTimeline("setTimeoutFunction", finishAndRunNextTest); - function finishAndRunNextTest() - { - var linkifier = new WebInspector.Linkifier(); - var record = InspectorTest.findFirstTimelineRecord("TimerFire"); - InspectorTest.check(record, "Should receive a TimerFire record."); - var contentHelper = new WebInspector.TimelineDetailsContentHelper(InspectorTest.timelineModel().target(), linkifier, true); - WebInspector.TimelineUIUtils._generateCauses(record.traceEvent(), InspectorTest.timelineModel().target(), null, contentHelper); - var causes = contentHelper.element.deepTextContent(); - InspectorTest.check(causes, "Should generate causes"); - checkStringContains(causes, "Timer InstalledsetTimeoutFunction @ setTimeoutFunction.js:"); - next(); - } - }, - - function testRequestAnimationFrame(next) - { - function requestAnimationFrameFunction(callback) - { - requestAnimationFrame(callback); - } - - var source = requestAnimationFrameFunction.toString(); - source += "\n//# sourceURL=requestAnimationFrameFunction.js"; - InspectorTest.evaluateInPage(source); - - InspectorTest.invokeAsyncWithTimeline("requestAnimationFrameFunction", finishAndRunNextTest); - function finishAndRunNextTest() - { - var linkifier = new WebInspector.Linkifier(); - var record = InspectorTest.findFirstTimelineRecord("FireAnimationFrame"); - InspectorTest.check(record, "Should receive a FireAnimationFrame record."); - var contentHelper = new WebInspector.TimelineDetailsContentHelper(InspectorTest.timelineModel().target(), linkifier, true); - WebInspector.TimelineUIUtils._generateCauses(record.traceEvent(), InspectorTest.timelineModel().target(), null, contentHelper); - var causes = contentHelper.element.deepTextContent(); - InspectorTest.check(causes, "Should generate causes"); - checkStringContains(causes, "Animation Frame RequestedrequestAnimationFrameFunction @ requestAnimationFrameFunction.js:"); - next(); - } - }, - - function testStyleRecalc(next) - { - function styleRecalcFunction() - { - var element = document.getElementById("testElement"); - element.style.backgroundColor = "papayawhip"; - var forceLayout = element.offsetWidth; - } - - var source = styleRecalcFunction.toString(); - source += "\n//# sourceURL=styleRecalcFunction.js"; - InspectorTest.evaluateInPage(source); - - InspectorTest.evaluateWithTimeline("styleRecalcFunction()", finishAndRunNextTest); - function finishAndRunNextTest() - { - var linkifier = new WebInspector.Linkifier(); - var record = InspectorTest.findFirstTimelineRecord("UpdateLayoutTree"); - InspectorTest.check(record, "Should receive a UpdateLayoutTree record."); - var contentHelper = new WebInspector.TimelineDetailsContentHelper(InspectorTest.timelineModel().target(), linkifier, true); - WebInspector.TimelineUIUtils._generateCauses(record.traceEvent(), InspectorTest.timelineModel().target(), null, contentHelper); - var causes = contentHelper.element.deepTextContent(); - InspectorTest.check(causes, "Should generate causes"); - checkStringContains(causes, "First InvalidatedstyleRecalcFunction @ styleRecalcFunction.js:"); - next(); - } - }, - - function testLayout(next) - { - function layoutFunction() - { - var element = document.getElementById("testElement"); - element.style.width = "200px"; - var forceLayout = element.offsetWidth; - } - - var source = layoutFunction.toString(); - source += "\n//# sourceURL=layoutFunction.js"; - InspectorTest.evaluateInPage(source); - - InspectorTest.evaluateWithTimeline("layoutFunction()", finishAndRunNextTest); - function finishAndRunNextTest() - { - var linkifier = new WebInspector.Linkifier(); - var record = InspectorTest.findFirstTimelineRecord("Layout"); - InspectorTest.check(record, "Should receive a Layout record."); - var contentHelper = new WebInspector.TimelineDetailsContentHelper(InspectorTest.timelineModel().target(), linkifier, true); - WebInspector.TimelineUIUtils._generateCauses(record.traceEvent(), InspectorTest.timelineModel().target(), null, contentHelper); - var causes = contentHelper.element.deepTextContent(); - InspectorTest.check(causes, "Should generate causes"); - checkStringContains(causes, "Layout ForcedlayoutFunction @ layoutFunction.js:"); - checkStringContains(causes, "First Layout InvalidationlayoutFunction @ layoutFunction.js:"); - next(); - } - } - ]); -} -</script> -</head> - -<body onload="runTest()"> -<p> -Test that causes are correctly generated for various types of events. -</p> -<div id="testElement"></div> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-event-dispatch.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-event-dispatch.html deleted file mode 100644 index 399fab6..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-event-dispatch.html +++ /dev/null
@@ -1,43 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function handleMouseDown(event) -{ - console.timeStamp("Handling mousedown"); -} - -function performActions() -{ - var target = document.getElementById("testTarget"); - target.addEventListener("mousedown", handleMouseDown, true); - var rect = target.getBoundingClientRect(); - - // Simulate the mouse down over the target to trigger an EventDispatch - if (window.eventSender) { - window.eventSender.mouseMoveTo(rect.left + rect.width / 2, rect.top + rect.height / 2); - window.eventSender.mouseDown(); - } -} - -function test() -{ - InspectorTest.performActionsAndPrint("performActions()", "EventDispatch"); -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline API instrumentation of a DOM Dispatch (mousedown) -</p> - -<div id="testTarget" style="width:400px; height:400px;"> -Test Mouse Target -</div> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-filtering.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-filtering.html deleted file mode 100644 index fcbe482..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-filtering.html +++ /dev/null
@@ -1,93 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function test() -{ - var sessionId = "4.20"; - var mainThread = 1; - var pid = 100; - - var testData = [ - { - "args": { "sessionId": sessionId }, - "cat": "disabled-by-default-devtools.timeline", - "name": "TracingStartedInPage", - "ph": "I", - "pid": pid, - "tid": mainThread, - "ts": 100, - }, - {"name": "top level event name", "ts": 1000000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"toplevel", "args": {}}, - {"name": "TimeStamp", "ts": 1010000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar01"}}}, - {"name": "TimeStamp", "ts": 1020000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar02"}}}, - {"name": "TimeStamp", "ts": 1120000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar03"}}}, - {"name": "TimeStamp", "ts": 1180000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}}, - {"name": "TimeStamp", "ts": 1210000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar04"}}}, - {"name": "TimeStamp", "ts": 1220000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo05"}}}, - {"name": "TimeStamp", "ts": 1320000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar06"}}}, - {"name": "TimeStamp", "ts": 1380000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}}, - {"name": "TimeStamp", "ts": 1410000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar07"}}}, - {"name": "TimeStamp", "ts": 1420000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo08"}}}, - {"name": "TimeStamp", "ts": 1520000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo09"}}}, - {"name": "TimeStamp", "ts": 1580000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}}, - {"name": "top level event name", "ts": 1990000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"toplevel", "args": {}}, - {"name": "Program", "ts": 2000000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}}, - {"name": "TimeStamp", "ts": 2010000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo10"}}}, - {"name": "TimeStamp", "ts": 2020000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar11"}}}, - {"name": "TimeStamp", "ts": 2120000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar12"}}}, - {"name": "TimeStamp", "ts": 2180000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}}, - {"name": "TimeStamp", "ts": 2210000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo13"}}}, - {"name": "TimeStamp", "ts": 2220000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo14"}}}, - {"name": "TimeStamp", "ts": 2320000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar15"}}}, - {"name": "TimeStamp", "ts": 2380000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}}, - {"name": "TimeStamp", "ts": 2410000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo16"}}}, - {"name": "TimeStamp", "ts": 2420000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo17"}}}, - {"name": "TimeStamp", "ts": 2520000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo18"}}}, - {"name": "TimeStamp", "ts": 2580000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}}, - {"name": "Program", "ts": 2590000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}} - ]; - - - var model = InspectorTest.createTimelineModelWithEvents(testData); - var view = new WebInspector.EventsTimelineTreeView(model, WebInspector.panels.timeline._filters, null); - view.updateContents(WebInspector.TimelineSelection.fromRange(model.minimumRecordTime(), model.maximumRecordTime())); - var filtersControl = view._filtersControl; - function printEventMessage(event, level) - { - InspectorTest.addResult(" ".repeat(level) + event.args["data"].message); - } - - function dumpRecords() - { - InspectorTest.walkTimelineEventTreeUnderNode(printEventMessage, view._currentTree); - InspectorTest.addResult(""); - } - - InspectorTest.addResult("Initial:"); - dumpRecords(); - - InspectorTest.addResult("Filtered by 'bar':"); - var textFilterUI = filtersControl._textFilterUI; - textFilterUI.setValue("bar"); - dumpRecords(); - - InspectorTest.addResult("Filtered by 'foo':"); - textFilterUI.setValue("foo"); - dumpRecords(); - - InspectorTest.completeTest(); -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Test filtering in Timeline Tree View panel.</a> -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-flame-chart-automatically-size-window.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-flame-chart-automatically-size-window.html deleted file mode 100644 index 88ee61d..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-flame-chart-automatically-size-window.html +++ /dev/null
@@ -1,36 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/console-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script src="resources/timeline-data.js"></script> -<script> - -function test() -{ - var timeline = WebInspector.panels.timeline; - timeline._onModeChanged(); - timeline._currentViews[0]._automaticallySizeWindow = true; - - function requestWindowTimesHook(startTime, endTime) - { - if (startTime) - InspectorTest.addResult("time delta: " + (endTime - startTime)); - } - - timeline.requestWindowTimes = requestWindowTimesHook; - InspectorTest.loadTimeline(InspectorTest.timelineData()); - - InspectorTest.completeTest(); -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the TimelineFlameChart automatically sized window. -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-gc-event.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-gc-event.html deleted file mode 100644 index 5c1c2c45..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-gc-event.html +++ /dev/null
@@ -1,38 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function produceGarbageForGCEvents(callback) -{ - if (window.testRunner) { - window.gc(); - testRunner.layoutAndPaintAsyncThen(callback); - } -} - -function test() -{ - InspectorTest.invokeAsyncWithTimeline("produceGarbageForGCEvents", validate); - - function validate() - { - var gcRecord = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.MajorGC) || InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.MinorGC) - if (gcRecord) - InspectorTest.addResult("SUCCESS: Found expected GC event record"); - else - InspectorTest.addResult("FAIL: GC event record wasn't found"); - InspectorTest.completeTest(); - } -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline API instrumentation of a gc event -</p> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-grouped-invalidations-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-grouped-invalidations-expected.txt deleted file mode 100644 index 6f7c92f9..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-grouped-invalidations-expected.txt +++ /dev/null
@@ -1,99 +0,0 @@ -Tests grouped invalidations on the timeline. - -P -A -S -S -paint invalidations[ - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-grouped-invalidations.html:12} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV class='testElement'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-grouped-invalidations.html:13} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV class='testElement'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-grouped-invalidations.html:12} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV class='testElement'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-grouped-invalidations.html:13} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV class='testElement'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-grouped-invalidations.html:12} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV class='testElement'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-grouped-invalidations.html:13} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV class='testElement'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-grouped-invalidations.html:12} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV class='testElement'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-grouped-invalidations.html:13} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV class='testElement'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } -] -PASS - record contained Inline CSS style declaration was mutated for [ DIV class='testElement' ], [ DIV class='testElement' ], and 2 others. (anonymous function) @ timeline-grouped-invalidations.html:12 -PASS - record contained Inline CSS style declaration was mutated for [ DIV class='testElement' ], [ DIV class='testElement' ], and 2 others. (anonymous function) @ timeline-grouped-invalidations.html:13 -
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-grouped-invalidations.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-grouped-invalidations.html deleted file mode 100644 index 9ff0806..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-grouped-invalidations.html +++ /dev/null
@@ -1,55 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function display(callback) -{ - requestAnimationFrame(function() { - var testElements = document.body.getElementsByClassName("testElement"); - for (var i = 0; i < testElements.length; i++) { - testElements[i].style.color = "red"; - testElements[i].style.backgroundColor = "blue"; - } - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function test() -{ - var currentPanel = WebInspector.inspectorView.currentPanel(); - InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); - Runtime.experiments.enableForTest("timelineInvalidationTracking"); - - InspectorTest.invokeAsyncWithTimeline("display", function() { - var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); - InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "paint invalidations"); - - var linkifier = new WebInspector.Linkifier(); - var target = InspectorTest.timelineModel().target(); - var contentHelper = new WebInspector.TimelineDetailsContentHelper(target, linkifier, true); - WebInspector.TimelineUIUtils._generateCauses(record.traceEvent(), target, null, contentHelper); - var invalidationsTree = contentHelper.element.getElementsByClassName("invalidations-tree")[0]; - var invalidations = invalidationsTree.shadowRoot.textContent; - checkStringContains(invalidations, "Inline CSS style declaration was mutated for [ DIV class='testElement' ], [ DIV class='testElement' ], and 2 others. (anonymous function) @ timeline-grouped-invalidations.html:12"); - checkStringContains(invalidations, "Inline CSS style declaration was mutated for [ DIV class='testElement' ], [ DIV class='testElement' ], and 2 others. (anonymous function) @ timeline-grouped-invalidations.html:13"); - InspectorTest.completeTest(); - }); - - function checkStringContains(string, contains) - { - var doesContain = string.indexOf(contains) >= 0; - InspectorTest.check(doesContain, contains + " should be present in " + string); - InspectorTest.addResult("PASS - record contained " + contains); - } -} -</script> -</head> -<body onload="runTest()"> -<p>Tests grouped invalidations on the timeline.</p> -<div class="testElement">P</div><div class="testElement">A</div> -<div class="testElement">S</div><div class="testElement">S</div> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-injected-script-eval.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-injected-script-eval.html deleted file mode 100644 index 9fd6787..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-injected-script-eval.html +++ /dev/null
@@ -1,26 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function performActions() -{ -} - -function test() -{ - WebInspector.panels.timeline._captureJSProfileSetting.set(false); - InspectorTest.performActionsAndPrint("performActions()", "FunctionCall"); -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline API function call is not recorded for InjectedScript.eval. -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-blackboxing.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-blackboxing.html deleted file mode 100644 index 7ecd885..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-blackboxing.html +++ /dev/null
@@ -1,305 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function test() -{ - var sessionId = "6.23"; - var rawTraceEvents = [ - { - "args": { - "name": "Renderer" - }, - "cat": "__metadata", - "name": "process_name", - "ph": "M", - "pid": 17851, - "tid": 23, - "ts": 0 - }, - { - "args": { - "name": "CrRendererMain" - }, - "cat": "__metadata", - "name": "thread_name", - "ph": "M", - "pid": 17851, - "tid": 23, - "ts": 0 - }, - { - "args": { - "sessionId": sessionId - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "TracingStartedInPage", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 100000, - "tts": 606543 - }, - { - "args": {}, - "cat": "disabled-by-default-devtools.timeline", - "name": "Program", - "ph": "B", - "pid": 17851, - "tid": 23, - "ts": 200000, - "tts": 5612442 - }, - { - "args": { - "data": { - "functionName": "level1", - "url": "user_script.js" - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSFrame", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 208000, - "dur": 10000, - "tts": 1758056 - }, - { - "args": { - "data": { - "functionName": "level2", - "url": "user_script.js" - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSFrame", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 208000, - "dur": 10000, - "tts": 1758056 - }, - { - "args": { - "data": { - "functionName": "level3", - "url": "user_script.js" - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSFrame", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 209000, - "dur": 1000, - "tts": 1758056 - }, - { - "args": { - "data": { - "functionName": "level3blackboxed", - "url": "lib_script.js" - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSFrame", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 211000, - "dur": 6000, - "tts": 1758056 - }, - { - "args": { - "data": { - "functionName": "level4user", - "url": "user_script.js" - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSFrame", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 211000, - "dur": 1000, - "tts": 1758056 - }, - { - "args": { - "data": { - "functionName": "level4blackboxed", - "url": "lib_script.js" - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSFrame", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 213000, - "dur": 3000, - "tts": 1758056 - }, - { - "args": { - "data": { - "functionName": "level5blackboxed", - "url": "lib_script.js" - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSFrame", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 213000, - "dur": 3000, - "tts": 1758056 - }, - { - "args": { - "data": { - "functionName": "level6user", - "url": "user_script.js" - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSFrame", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 213000, - "dur": 3000, - "tts": 1758056 - }, - { - "args": { - "data": { - "functionName": "level7blackboxed", - "url": "lib_script.js" - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSFrame", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 213000, - "dur": 3000, - "tts": 1758056 - }, - { - "args": { - "data": { - "functionName": "level8user", - "url": "user_script.js" - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSFrame", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 213000, - "dur": 3000, - "tts": 1758056 - }, - { - "args": { - "data": { - "functionName": "level1blackboxed", - "url": "lib_script.js" - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSFrame", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 230000, - "dur": 3000, - "tts": 1758056 - }, - { - "args": { - "data": { - "functionName": "level1blackboxed", - "url": "lib_script.js" - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSFrame", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 235000, - "dur": 3000, - "tts": 1758056 - }, - { - "args": { - "data": { - "functionName": "level2blackboxed", - "url": "lib_script.js" - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSFrame", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 236000, - "dur": 1000, - "tts": 1758056 - }, - { - "args": {}, - "cat": "disabled-by-default-devtools.timeline", - "name": "Program", - "ph": "E", - "pid": 17851, - "tid": 23, - "ts": 500000, - "tts": 5612506 - } - ]; - - function printTimelineData(dataProvider) - { - dataProvider.reset(); - var timelineData = dataProvider.timelineData(); - for (var i = 0; i < timelineData.entryStartTimes.length; ++i) { - var name = dataProvider.entryTitle(i); - var padding = " ".repeat(timelineData.entryLevels[i] - 1); - InspectorTest.addResult(padding + name + ": " + timelineData.entryTotalTimes[i] + " @ " + timelineData.entryStartTimes[i]); - } - } - - Runtime.experiments.enableForTest("blackboxJSFramesOnTimeline"); - var timelineModel = InspectorTest.createTimelineModelWithEvents(rawTraceEvents); - var frameModel = new WebInspector.TimelineFrameModel(event => WebInspector.TimelineUIUtils.eventStyle(event).category.name); - var dataProvider = new WebInspector.TimelineFlameChartDataProvider(timelineModel, frameModel, new WebInspector.TimelineIRModel(), WebInspector.panels.timeline._filters); - - InspectorTest.addResult("\nBlackboxed url: lib_script.js"); - WebInspector.blackboxManager._blackboxURL("lib_script.js"); - printTimelineData(dataProvider); - - InspectorTest.addResult("\nUnblackboxed url: lib_script.js"); - WebInspector.blackboxManager._unblackboxURL("lib_script.js"); - printTimelineData(dataProvider); - - InspectorTest.completeTest(); -} - -</script> -</head> -<body onload="runTest()"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks.html deleted file mode 100644 index 8f9c2eab..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks.html +++ /dev/null
@@ -1,567 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function test() -{ - var sessionId = "6.23"; - var rawTraceEvents = [ - { - "args": { - "name": "Renderer" - }, - "cat": "__metadata", - "name": "process_name", - "ph": "M", - "pid": 17851, - "tid": 23, - "ts": 0 - }, - { - "args": { - "name": "CrRendererMain" - }, - "cat": "__metadata", - "name": "thread_name", - "ph": "M", - "pid": 17851, - "tid": 23, - "ts": 0 - }, - { - "args": { - "sessionId": sessionId - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "TracingStartedInPage", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 100000, - "tts": 606543 - }, - { - "args": {}, - "cat": "disabled-by-default-devtools.timeline", - "name": "Program", - "ph": "B", - "pid": 17851, - "tid": 23, - "ts": 200000, - "tts": 5612442 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "c", "callUID": "c", "scriptId": 1 }, - { "functionName": "b", "callUID": "b", "scriptId": 1 }, - { "functionName": "a", "callUID": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 208000, - "tts": 1758056 - }, - { - "args": {}, - "cat": "disabled-by-default-devtools.timeline", - "name": "FunctionCall", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 210000, - "dur": 30000, - "tts": 5612442 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "c", "callUID": "c", "scriptId": 1 }, - { "functionName": "b", "callUID": "b", "scriptId": 1 }, - { "functionName": "a", "callUID": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 211000, - "tts": 1758056 - }, - { - "args": { - "data": { - "stackTrace": [] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 212000, - "tts": 1758056 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "c", "callUID": "c", "scriptId": 1 }, - { "functionName": "b", "callUID": "b", "scriptId": 1 }, - { "functionName": "a", "callUID": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 219875, - "tts": 1758056 - }, - { - "args": { - "frame": "0x2f7b63884000", - "data": { - "stackTrace": [ - { "functionName": "b", "callUID": "b", "scriptId": 1 }, - { "functionName": "a", "callUID": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "InvalidateLayout", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 220000, - "dur": 7000, - "tts": 1758056 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "c", "callUID": "c", "scriptId": 1 }, - { "functionName": "b", "callUID": "b", "scriptId": 1 }, - { "functionName": "a", "callUID": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 220125, - "tts": 1758056 - }, - { - "args": { - "frame": "0x2f7b63884000", - "data": { - "stackTrace": [ - { "functionName": "b", "callUID": "b", "scriptId": 1 }, - { "functionName": "a", "callUID": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "InvalidateLayout", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 221000, - "dur": 3000, - "tts": 1758056 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "g", "scriptId": 1 }, - { "functionName": "f", "scriptId": 1 }, - { "functionName": "b", "scriptId": 1 }, - { "functionName": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 222000, - "tts": 1758056 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "g", "scriptId": 1 }, - { "functionName": "e", "scriptId": 1 }, - { "functionName": "b", "scriptId": 1 }, - { "functionName": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 227125, - "tts": 1758056 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "g", "scriptId": 1 }, - { "functionName": "e", "scriptId": 1 }, - { "functionName": "b", "scriptId": 1 }, - { "functionName": "a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 227250, - "tts": 1758056 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "a", "callUID": "a", "scriptId": 1 }, - { "functionName": "l", "callUID": "l", "scriptId": 1 }, - { "functionName": "f", "callUID": "f", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 230000, - "tts": 1758056 - }, - { - "args": { - "beginData": { - "stackTrace": [ - { "functionName": "a", "callUID": "a", "scriptId": 1 }, - { "functionName": "l", "callUID": "l", "scriptId": 1 }, - { "functionName": "f", "callUID": "f", "scriptId": 1 }, - { "functionName": "sin", "callUID": "sin", "scriptId": 2, "url": "native math.js" } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "Layout", - "ph": "X", - "dur": 100, - "pid": 17851, - "tid": 23, - "ts": 230010, - "tts": 1758056 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "a", "callUID": "a", "scriptId": 1 }, - { "functionName": "l", "callUID": "l", "scriptId": 1 }, - { "functionName": "f", "callUID": "f", "scriptId": 1 }, - { "functionName": "sin", "callUID": "sin", "scriptId": 2, "url": "native math.js" } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 230125, - "tts": 1758056 - }, - { - "args": {}, - "cat": "disabled-by-default-devtools.timeline", - "name": "FunctionCall", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 250000, - "dur": 10000 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "y", "callUID": "y", "scriptId": 1 }, - { "functionName": "x", "callUID": "x", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "FunctionCall", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 251000, - "dur": 1000 - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "w", "callUID": "w", "scriptId": 1 }, - { "functionName": "z", "callUID": "z", "scriptId": 1 }, - { "functionName": "y", "callUID": "y", "scriptId": 1 }, - { "functionName": "x", "callUID": "x", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 251000, - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "w", "callUID": "w", "scriptId": 1 }, - { "functionName": "z", "callUID": "z", "scriptId": 1 }, - { "functionName": "y", "callUID": "y", "scriptId": 1 }, - { "functionName": "x", "callUID": "x", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 251100, - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "w", "scriptId": 1 }, - { "functionName": "y", "callUID": "y", "scriptId": 1 }, - { "functionName": "x", "callUID": "x", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 251200, - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "w", "scriptId": 1 }, - { "functionName": "y", "callUID": "y", "scriptId": 1 }, - { "functionName": "x", "callUID": "x", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 251300, - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "y", "callUID": "y", "scriptId": 1 }, - { "functionName": "x", "callUID": "x", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 251400, - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "recursive_b", "scriptId": 1 }, - { "functionName": "recursive_a", "scriptId": 1 }, - { "functionName": "recursive_b", "scriptId": 1 }, - { "functionName": "recursive_a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 253000, - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "recursive_a", "scriptId": 1 }, - { "functionName": "recursive_b", "scriptId": 1 }, - { "functionName": "recursive_a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 253008, - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "recursive_b", "scriptId": 1 }, - { "functionName": "recursive_a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 253012, - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "recursive_a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 253014, - }, - { - "args": { - "data": { - "stackTrace": [ - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 253015, - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "recursive_b", "scriptId": 1 }, - { "functionName": "recursive_a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 253100, - }, - { - "args": { - "data": { - "stackTrace": [ - { "functionName": "recursive_a", "scriptId": 1 } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 253200, - }, - { - "args": { - "data": { - "stackTrace": [ - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "JSSample", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 253300, - }, - { - "args": {}, - "cat": "disabled-by-default-devtools.timeline", - "name": "Program", - "ph": "E", - "pid": 17851, - "tid": 23, - "ts": 500000, - "tts": 5612506 - } - ]; - - var tracingTimelineModel = InspectorTest.createTimelineModelWithEvents(rawTraceEvents); - var events = WebInspector.TimelineJSProfileProcessor.generateJSFrameEvents(tracingTimelineModel.mainThreadEvents()); - events = events.mergeOrdered(tracingTimelineModel.mainThreadEvents(), WebInspector.TracingModel.Event.orderedCompareStartTime); - events.filter(function(e) { return e.duration; }).forEach(function(e) { - InspectorTest.addResult(e.name + ": " + e.startTime.toFixed(3) + " / " + (e.duration.toFixed(3) || 0) + " " + (e.args.data && e.args.data.functionName || "")); - }); - - InspectorTest.completeTest(); -} - -</script> -</head> -<body onload="runTest()"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-line-level-profile.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-line-level-profile.html deleted file mode 100644 index 9f3ad55..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-line-level-profile.html +++ /dev/null
@@ -1,81 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/debugger-test.js"></script> -<script src="resources/timeline-data.js"></script> -<script> -function test() -{ - var cpuProfile = { - startTime: 10, - endTime: 20, - head: { - functionName: "(root)", - hitCount: 0, - children: [ - { - functionName: "foo1", - hitCount: 100, - positionTicks: [{line:1, ticks:10}, {line:2, ticks:20}, {line:3, ticks:30}, {line:4, ticks:40}], - children: [] - }, - { - functionName: "foo2", - hitCount: 200, - positionTicks: [{line:100, ticks:1}, {line:102, ticks:190}], - children: [] - }, - { - functionName: "null", - hitCount: 0, - positionTicks: [], - children: [ - { - functionName: "bar", - hitCount: 300, - positionTicks: [{line:55, ticks:22}], - children: [] - }, - { - functionName: "baz", - hitCount: 400, - // no positionTicks for the node. - children: [] - } - ] - } - ] - } - }; - - InspectorTest.addSniffer(WebInspector.CodeMirrorTextEditor.prototype, "setGutterDecoration", decorationAdded, true); - InspectorTest.showScriptSource("timeline-data.js", frameRevealed); - - function decorationAdded(line, type, element) - { - InspectorTest.addResult(`${line} ${type} ${element.textContent} ${element.style.backgroundColor}`); - } - - function setUrls(url, node) - { - node.url = url; - node.children.forEach(setUrls.bind(null, url)); - } - - function frameRevealed(frame) - { - var url = frame.uiSourceCode().url(); - InspectorTest.addResult(InspectorTest.formatters.formatAsURL(url)); - setUrls(url, cpuProfile.head); - var lineProfile = new WebInspector.LineLevelProfile.instance(); - lineProfile.appendCPUProfile(new WebInspector.CPUProfileDataModel(cpuProfile)); - setTimeout(() => InspectorTest.completeTest(), 0); - } -} - -</script> -</head> -<body onload="runTest()"> -Tests that a line-level CPU profile is shown in the text editor. -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-samping-codeobject-names.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-samping-codeobject-names.html deleted file mode 100644 index 8e50ee1..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-samping-codeobject-names.html +++ /dev/null
@@ -1,41 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../tracing-test.js"></script> -<script> -function test() -{ - Runtime.experiments.enableForTest("timelineTracingJSProfile"); - var rawNames = [ - "", - "Script:", - "Script:http://example.com/alina?", - "Script:http://example.com/:1", - "Script:http://example.com/:1:2", - "Script:http://example.com/:1:2:3", - "Script:http://example.com/:1:2:3x:4", - "Builtin:~foo1 http://url.com/foo.js", - "Builtin:~foo2 native http://url.com/foo.js:11", - "Builtin:*foo3 http://url.com/foo.js:11:22", - "Builtin:foo4 http://url.com/foo.js:11:22:33", - "Builtin:~ http://url.com/anonymous.js:123", - "Builtin:~ native http://url.com/anonymous.js:123", - "Builtin:~function name with spaces http://url.com/bar:123", - "Builtin:~native function name with spaces native http://url.com/bar.js:123", - "Builtin:~user_function_that_is_not_native http://url.com/bar.js:123", - "Builtin:~native http://url.com/bar.js:123" - ]; - - for (var name of rawNames) { - var frame = WebInspector.TimelineJSProfileProcessor._buildCallFrame(name, "456"); - InspectorTest.addResult(name + " => " + [frame.functionName, frame.url, frame.scriptId, frame.lineNumber, frame.columnNumber, frame.isNative].join(",")); - } - - InspectorTest.completeTest(); -} - -</script> -</head> -<body onload="runTest()"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-samping-tracing.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-samping-tracing.html deleted file mode 100644 index 68c403c..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-samping-tracing.html +++ /dev/null
@@ -1,479 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function test() -{ - var sessionId = "6.23"; - var rawTraceEvents = [ - { - "args": { - "name": "Renderer" - }, - "cat": "__metadata", - "name": "process_name", - "ph": "M", - "pid": 17851, - "tid": 23, - "ts": 0 - }, - { - "args": { - "name": "CrRendererMain" - }, - "cat": "__metadata", - "name": "thread_name", - "ph": "M", - "pid": 17851, - "tid": 23, - "ts": 0 - }, - { - "args": { - "sessionId": sessionId - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "TracingStartedInPage", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 100000, - "tts": 606543 - }, - { - "args": { - "data": { - "code_start": "0xa000", - "code_len": 100, - "name": "LazyCompile:~a file:///script1.js:12", - "script_id": 1 - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "JitCodeAdded", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 190000, - "tts": 5610000 - }, - { - "args": { - "data": { - "code_start": "0xb000", - "code_len": 100, - "name": "LazyCompile:~b file:///script1.js:12", - "script_id": 1 - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "JitCodeAdded", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 190000, - "tts": 5610000 - }, - { - "args": { - "data": { - "code_start": "0xc000", - "code_len": 100, - "name": "LazyCompile:~c file:///script1.js:12", - "script_id": 1 - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "JitCodeAdded", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 190000, - "tts": 5610000 - }, - { - "args": { - "data": { - "code_start": "0xd000", - "code_len": 100, - "name": "LazyCompile:~d file:///script1.js:12", - "script_id": 1 - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "JitCodeAdded", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 190000, - "tts": 5610000 - }, - { - "args": { - "data": { - "code_start": "0x1e000", - "code_len": 100, - "name": "LazyCompile:~e file:///script1.js:12", - "script_id": 1 - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "JitCodeAdded", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 190000, - "tts": 5610000 - }, - { - "args": { - "data": { - "code_start": "0x1e000", - "new_code_start": "0xe000", - "code_len": 100 - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "JitCodeMoved", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 190000, - "tts": 5610000 - }, - { - "args": { - "data": { - "code_start": "0xf000", - "code_len": 100, - "name": "LazyCompile:~f file:///script1.js:12", - "script_id": 1 - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "JitCodeAdded", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 190000, - "tts": 5610000 - }, - { - "args": { - "data": { - "code_start": "0xf200", - "code_len": 100, - "name": "LazyCompile:*f file:///script1.js:12", - "script_id": 1 - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "JitCodeAdded", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 190000, - "tts": 5610000 - }, - { - "args": { - "data": { - "code_start": "0x8000", - "code_len": 100, - "name": "LazyCompile:~g file:///script1.js:12", - "script_id": 1 - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "JitCodeAdded", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 190000, - "tts": 5610000 - }, - { - "args": { - "data": { - "code_start": "0x1000", - "code_len": 100, - "name": "LazyCompile:~l file:///script1.js:12", - "script_id": 1 - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "JitCodeAdded", - "ph": "I", - "pid": 17851, - "tid": 23, - "ts": 190000, - "tts": 5610000 - }, - { - "args": {}, - "cat": "disabled-by-default-devtools.timeline", - "name": "Program", - "ph": "B", - "pid": 17851, - "tid": 23, - "ts": 200000, - "tts": 5612442 - }, - { - "args": { - "data": { - "stack": [ - "0xc000", - "0xb000", - "0xa000" - ] - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "V8Sample", - "ph": "P", - "pid": 17851, - "tid": 23, - "ts": 208000, - "tts": 1758056 - }, - { - "args": {}, - "cat": "disabled-by-default-devtools.timeline", - "name": "FunctionCall", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 210000, - "dur": 30000, - "tts": 5612442 - }, - { - "args": { - "data": { - "stack": [ - "0xc000", - "0xb000", - "0xa000" - ] - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "V8Sample", - "ph": "P", - "pid": 17851, - "tid": 23, - "ts": 211000, - "tts": 1758056 - }, - { - "args": { - "data": { - "stack": [] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "V8Sample", - "ph": "P", - "pid": 17851, - "tid": 23, - "ts": 212000, - "tts": 1758056 - }, - { - "args": { - "data": { - "stack": [ - "0xc000", - "0xb000", - "0xa000" - ] - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "V8Sample", - "ph": "P", - "pid": 17851, - "tid": 23, - "ts": 220000, - "tts": 1758056 - }, - { - "args": { - "frame": "0x2f7b63884000", - "data": { - "stackTrace": [ - { "functionName": "b", "callUID": "b", "scriptId": "1" }, - { "functionName": "a", "callUID": "a", "scriptId": "1" } - ] - } - }, - "cat": "disabled-by-default-devtools.timeline", - "name": "InvalidateLayout", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 221000, - "dur": 7000, - "tts": 1758056 - }, - { - "args": { - "data": { - "stack": [ - "0xc000", - "0xb000", - "0xa000" - ] - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "V8Sample", - "ph": "P", - "pid": 17851, - "tid": 23, - "ts": 221125, - "tts": 1758056 - }, - { - "args": { - "frame": "0x2f7b63884000", - "data": { - "stackTrace": [ - { "functionName": "e", "callUID": "e", "scriptId": "1" }, - { "functionName": "d", "callUID": "d", "scriptId": "1" }, - { "functionName": "b", "callUID": "b", "scriptId": "1" }, - { "functionName": "a", "callUID": "a", "scriptId": "1" } - ] - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "InvalidateLayout", - "ph": "X", - "pid": 17851, - "tid": 23, - "ts": 222000, - "dur": 3000, - "tts": 1758056 - }, - { - "args": { - "data": { - "stack": [ - "0x8000", - "0xf000", - "0xb000", - "0xa000" - ] - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "V8Sample", - "ph": "P", - "pid": 17851, - "tid": 23, - "ts": 225500, - "tts": 1758056 - }, - { - "args": { - "data": { - "stack": [ - "0x8000", - "0xe000", - "0xb000", - "0xa000" - ] - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "V8Sample", - "ph": "P", - "pid": 17851, - "tid": 23, - "ts": 228125, - "tts": 1758056 - }, - { - "args": { - "data": { - "stack": [ - "0x8000", - "0xe000", - "0xb000", - "0xa000" - ] - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "V8Sample", - "ph": "P", - "pid": 17851, - "tid": 23, - "ts": 228250, - "tts": 1758056 - }, - { - "args": { - "data": { - "stack": [ - "0xa000", - "0x1000", - "0xf000" - ] - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "V8Sample", - "ph": "P", - "pid": 17851, - "tid": 23, - "ts": 230000, - "tts": 1758056 - }, - { - "args": { - "data": { - "stack": [ - "0xa000", - "0x1000", - "0xf210" - ] - } - }, - "cat": "disabled-by-default-v8.cpu_profile", - "name": "V8Sample", - "ph": "P", - "pid": 17851, - "tid": 23, - "ts": 230125, - "tts": 1758056 - }, - { - "args": {}, - "cat": "disabled-by-default-devtools.timeline", - "name": "Program", - "ph": "E", - "pid": 17851, - "tid": 23, - "ts": 500000, - "tts": 5612506 - } - ]; - - Runtime.experiments.enableForTest("timelineTracingJSProfile"); - var tracingTimelineModel = InspectorTest.createTimelineModelWithEvents(rawTraceEvents); - var events = tracingTimelineModel.mainThreadEvents(); - events.filter(function(e) { return e.name === "JSFrame"; }).forEach(function(e) { - InspectorTest.addResult(e.name + ": " + e.startTime.toFixed(3) + " / " + (e.duration.toFixed(3) || 0) + " " + e.args.data.functionName); - }); - - InspectorTest.completeTest(); -} - -</script> -</head> -<body onload="runTest()"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/compile-script-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/compile-script-expected.txt new file mode 100644 index 0000000..1ed50256 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/compile-script-expected.txt
@@ -0,0 +1,28 @@ +CONSOLE MESSAGE: line 1: SCRIPT TAG +Tests the Timeline instrumentation for CompileScript event. + +v8.compile Properties: +{ + data : { + columnNumber : <number> + lineNumber : <number> + url : + } + endTime : <number> + startTime : <number> + type : "v8.compile" +} +Text details for v8.compile: undefined +v8.compile Properties: +{ + data : { + columnNumber : <number> + lineNumber : <number> + url : .../inspector/tracing/timeline-js/timeline-script-tag-2.js + } + endTime : <number> + startTime : <number> + type : "v8.compile" +} +Text details for v8.compile: timeline-script-tag-2.js:1 +
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/compile-script.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/compile-script.html new file mode 100644 index 0000000..b8029f8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/compile-script.html
@@ -0,0 +1,33 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function performActions() +{ + var script = document.createElement("script"); + script.textContent = "function noop1() {} \n//# sourceURL=script-content.js"; + document.body.appendChild(script); + eval("function noop2() {} \n//# sourceURL=script-content.js"); + + script = document.createElement("script"); + script.src = "timeline-script-tag-2.js"; + document.body.appendChild(script); +} + +function test() +{ + InspectorTest.performActionsAndPrint("performActions()", WebInspector.TimelineModel.RecordType.CompileScript); +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline instrumentation for CompileScript event. +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-gc-event-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-gc-event-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-gc-event-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-gc-event-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-gc-event.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-gc-event.html new file mode 100644 index 0000000..bf1d5cd --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-gc-event.html
@@ -0,0 +1,38 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function produceGarbageForGCEvents(callback) +{ + if (window.testRunner) { + window.gc(); + testRunner.layoutAndPaintAsyncThen(callback); + } +} + +function test() +{ + InspectorTest.invokeAsyncWithTimeline("produceGarbageForGCEvents", validate); + + function validate() + { + var gcRecord = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.MajorGC) || InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.MinorGC) + if (gcRecord) + InspectorTest.addResult("SUCCESS: Found expected GC event record"); + else + InspectorTest.addResult("FAIL: GC event record wasn't found"); + InspectorTest.completeTest(); + } +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline API instrumentation of a gc event +</p> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-injected-script-eval-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-injected-script-eval-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-injected-script-eval-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-injected-script-eval-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-injected-script-eval.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-injected-script-eval.html new file mode 100644 index 0000000..6eb5192 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-injected-script-eval.html
@@ -0,0 +1,26 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function performActions() +{ +} + +function test() +{ + WebInspector.panels.timeline._captureJSProfileSetting.set(false); + InspectorTest.performActionsAndPrint("performActions()", "FunctionCall"); +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline API function call is not recorded for InjectedScript.eval. +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-blackboxing-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-blackboxing-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-blackboxing-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-blackboxing-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-blackboxing.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-blackboxing.html new file mode 100644 index 0000000..6425684 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-blackboxing.html
@@ -0,0 +1,305 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function test() +{ + var sessionId = "6.23"; + var rawTraceEvents = [ + { + "args": { + "name": "Renderer" + }, + "cat": "__metadata", + "name": "process_name", + "ph": "M", + "pid": 17851, + "tid": 23, + "ts": 0 + }, + { + "args": { + "name": "CrRendererMain" + }, + "cat": "__metadata", + "name": "thread_name", + "ph": "M", + "pid": 17851, + "tid": 23, + "ts": 0 + }, + { + "args": { + "sessionId": sessionId + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "TracingStartedInPage", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 100000, + "tts": 606543 + }, + { + "args": {}, + "cat": "disabled-by-default-devtools.timeline", + "name": "Program", + "ph": "B", + "pid": 17851, + "tid": 23, + "ts": 200000, + "tts": 5612442 + }, + { + "args": { + "data": { + "functionName": "level1", + "url": "user_script.js" + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSFrame", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 208000, + "dur": 10000, + "tts": 1758056 + }, + { + "args": { + "data": { + "functionName": "level2", + "url": "user_script.js" + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSFrame", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 208000, + "dur": 10000, + "tts": 1758056 + }, + { + "args": { + "data": { + "functionName": "level3", + "url": "user_script.js" + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSFrame", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 209000, + "dur": 1000, + "tts": 1758056 + }, + { + "args": { + "data": { + "functionName": "level3blackboxed", + "url": "lib_script.js" + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSFrame", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 211000, + "dur": 6000, + "tts": 1758056 + }, + { + "args": { + "data": { + "functionName": "level4user", + "url": "user_script.js" + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSFrame", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 211000, + "dur": 1000, + "tts": 1758056 + }, + { + "args": { + "data": { + "functionName": "level4blackboxed", + "url": "lib_script.js" + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSFrame", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 213000, + "dur": 3000, + "tts": 1758056 + }, + { + "args": { + "data": { + "functionName": "level5blackboxed", + "url": "lib_script.js" + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSFrame", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 213000, + "dur": 3000, + "tts": 1758056 + }, + { + "args": { + "data": { + "functionName": "level6user", + "url": "user_script.js" + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSFrame", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 213000, + "dur": 3000, + "tts": 1758056 + }, + { + "args": { + "data": { + "functionName": "level7blackboxed", + "url": "lib_script.js" + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSFrame", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 213000, + "dur": 3000, + "tts": 1758056 + }, + { + "args": { + "data": { + "functionName": "level8user", + "url": "user_script.js" + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSFrame", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 213000, + "dur": 3000, + "tts": 1758056 + }, + { + "args": { + "data": { + "functionName": "level1blackboxed", + "url": "lib_script.js" + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSFrame", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 230000, + "dur": 3000, + "tts": 1758056 + }, + { + "args": { + "data": { + "functionName": "level1blackboxed", + "url": "lib_script.js" + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSFrame", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 235000, + "dur": 3000, + "tts": 1758056 + }, + { + "args": { + "data": { + "functionName": "level2blackboxed", + "url": "lib_script.js" + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSFrame", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 236000, + "dur": 1000, + "tts": 1758056 + }, + { + "args": {}, + "cat": "disabled-by-default-devtools.timeline", + "name": "Program", + "ph": "E", + "pid": 17851, + "tid": 23, + "ts": 500000, + "tts": 5612506 + } + ]; + + function printTimelineData(dataProvider) + { + dataProvider.reset(); + var timelineData = dataProvider.timelineData(); + for (var i = 0; i < timelineData.entryStartTimes.length; ++i) { + var name = dataProvider.entryTitle(i); + var padding = " ".repeat(timelineData.entryLevels[i] - 1); + InspectorTest.addResult(padding + name + ": " + timelineData.entryTotalTimes[i] + " @ " + timelineData.entryStartTimes[i]); + } + } + + Runtime.experiments.enableForTest("blackboxJSFramesOnTimeline"); + var timelineModel = InspectorTest.createTimelineModelWithEvents(rawTraceEvents); + var frameModel = new WebInspector.TimelineFrameModel(event => WebInspector.TimelineUIUtils.eventStyle(event).category.name); + var dataProvider = new WebInspector.TimelineFlameChartDataProvider(timelineModel, frameModel, new WebInspector.TimelineIRModel(), WebInspector.panels.timeline._filters); + + InspectorTest.addResult("\nBlackboxed url: lib_script.js"); + WebInspector.blackboxManager._blackboxURL("lib_script.js"); + printTimelineData(dataProvider); + + InspectorTest.addResult("\nUnblackboxed url: lib_script.js"); + WebInspector.blackboxManager._unblackboxURL("lib_script.js"); + printTimelineData(dataProvider); + + InspectorTest.completeTest(); +} + +</script> +</head> +<body onload="runTest()"> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-callstacks-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-callstacks-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-callstacks-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-callstacks.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-callstacks.html new file mode 100644 index 0000000..30a3846d --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-callstacks.html
@@ -0,0 +1,567 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function test() +{ + var sessionId = "6.23"; + var rawTraceEvents = [ + { + "args": { + "name": "Renderer" + }, + "cat": "__metadata", + "name": "process_name", + "ph": "M", + "pid": 17851, + "tid": 23, + "ts": 0 + }, + { + "args": { + "name": "CrRendererMain" + }, + "cat": "__metadata", + "name": "thread_name", + "ph": "M", + "pid": 17851, + "tid": 23, + "ts": 0 + }, + { + "args": { + "sessionId": sessionId + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "TracingStartedInPage", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 100000, + "tts": 606543 + }, + { + "args": {}, + "cat": "disabled-by-default-devtools.timeline", + "name": "Program", + "ph": "B", + "pid": 17851, + "tid": 23, + "ts": 200000, + "tts": 5612442 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "c", "callUID": "c", "scriptId": 1 }, + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 208000, + "tts": 1758056 + }, + { + "args": {}, + "cat": "disabled-by-default-devtools.timeline", + "name": "FunctionCall", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 210000, + "dur": 30000, + "tts": 5612442 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "c", "callUID": "c", "scriptId": 1 }, + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 211000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 212000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "c", "callUID": "c", "scriptId": 1 }, + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 219875, + "tts": 1758056 + }, + { + "args": { + "frame": "0x2f7b63884000", + "data": { + "stackTrace": [ + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "InvalidateLayout", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 220000, + "dur": 7000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "c", "callUID": "c", "scriptId": 1 }, + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 220125, + "tts": 1758056 + }, + { + "args": { + "frame": "0x2f7b63884000", + "data": { + "stackTrace": [ + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "InvalidateLayout", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 221000, + "dur": 3000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "g", "scriptId": 1 }, + { "functionName": "f", "scriptId": 1 }, + { "functionName": "b", "scriptId": 1 }, + { "functionName": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 222000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "g", "scriptId": 1 }, + { "functionName": "e", "scriptId": 1 }, + { "functionName": "b", "scriptId": 1 }, + { "functionName": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 227125, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "g", "scriptId": 1 }, + { "functionName": "e", "scriptId": 1 }, + { "functionName": "b", "scriptId": 1 }, + { "functionName": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 227250, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "a", "callUID": "a", "scriptId": 1 }, + { "functionName": "l", "callUID": "l", "scriptId": 1 }, + { "functionName": "f", "callUID": "f", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 230000, + "tts": 1758056 + }, + { + "args": { + "beginData": { + "stackTrace": [ + { "functionName": "a", "callUID": "a", "scriptId": 1 }, + { "functionName": "l", "callUID": "l", "scriptId": 1 }, + { "functionName": "f", "callUID": "f", "scriptId": 1 }, + { "functionName": "sin", "callUID": "sin", "scriptId": 2, "url": "native math.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "Layout", + "ph": "X", + "dur": 100, + "pid": 17851, + "tid": 23, + "ts": 230010, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "a", "callUID": "a", "scriptId": 1 }, + { "functionName": "l", "callUID": "l", "scriptId": 1 }, + { "functionName": "f", "callUID": "f", "scriptId": 1 }, + { "functionName": "sin", "callUID": "sin", "scriptId": 2, "url": "native math.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 230125, + "tts": 1758056 + }, + { + "args": {}, + "cat": "disabled-by-default-devtools.timeline", + "name": "FunctionCall", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 250000, + "dur": 10000 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "FunctionCall", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 251000, + "dur": 1000 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "w", "callUID": "w", "scriptId": 1 }, + { "functionName": "z", "callUID": "z", "scriptId": 1 }, + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 251000, + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "w", "callUID": "w", "scriptId": 1 }, + { "functionName": "z", "callUID": "z", "scriptId": 1 }, + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 251100, + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "w", "scriptId": 1 }, + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 251200, + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "w", "scriptId": 1 }, + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 251300, + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 251400, + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_b", "scriptId": 1 }, + { "functionName": "recursive_a", "scriptId": 1 }, + { "functionName": "recursive_b", "scriptId": 1 }, + { "functionName": "recursive_a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253000, + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_a", "scriptId": 1 }, + { "functionName": "recursive_b", "scriptId": 1 }, + { "functionName": "recursive_a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253008, + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_b", "scriptId": 1 }, + { "functionName": "recursive_a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253012, + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253014, + }, + { + "args": { + "data": { + "stackTrace": [ + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253015, + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_b", "scriptId": 1 }, + { "functionName": "recursive_a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253100, + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253200, + }, + { + "args": { + "data": { + "stackTrace": [ + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253300, + }, + { + "args": {}, + "cat": "disabled-by-default-devtools.timeline", + "name": "Program", + "ph": "E", + "pid": 17851, + "tid": 23, + "ts": 500000, + "tts": 5612506 + } + ]; + + var tracingTimelineModel = InspectorTest.createTimelineModelWithEvents(rawTraceEvents); + var events = WebInspector.TimelineJSProfileProcessor.generateJSFrameEvents(tracingTimelineModel.mainThreadEvents()); + events = events.mergeOrdered(tracingTimelineModel.mainThreadEvents(), WebInspector.TracingModel.Event.orderedCompareStartTime); + events.filter(function(e) { return e.duration; }).forEach(function(e) { + InspectorTest.addResult(e.name + ": " + e.startTime.toFixed(3) + " / " + (e.duration.toFixed(3) || 0) + " " + (e.args.data && e.args.data.functionName || "")); + }); + + InspectorTest.completeTest(); +} + +</script> +</head> +<body onload="runTest()"> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-line-level-profile-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-line-level-profile-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-line-level-profile-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-line-level-profile-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-line-level-profile.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-line-level-profile.html new file mode 100644 index 0000000..027fa46c --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-line-level-profile.html
@@ -0,0 +1,81 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/debugger-test.js"></script> +<script src="../resources/timeline-data.js"></script> +<script> +function test() +{ + var cpuProfile = { + startTime: 10, + endTime: 20, + head: { + functionName: "(root)", + hitCount: 0, + children: [ + { + functionName: "foo1", + hitCount: 100, + positionTicks: [{line:1, ticks:10}, {line:2, ticks:20}, {line:3, ticks:30}, {line:4, ticks:40}], + children: [] + }, + { + functionName: "foo2", + hitCount: 200, + positionTicks: [{line:100, ticks:1}, {line:102, ticks:190}], + children: [] + }, + { + functionName: "null", + hitCount: 0, + positionTicks: [], + children: [ + { + functionName: "bar", + hitCount: 300, + positionTicks: [{line:55, ticks:22}], + children: [] + }, + { + functionName: "baz", + hitCount: 400, + // no positionTicks for the node. + children: [] + } + ] + } + ] + } + }; + + InspectorTest.addSniffer(WebInspector.CodeMirrorTextEditor.prototype, "setGutterDecoration", decorationAdded, true); + InspectorTest.showScriptSource("timeline-data.js", frameRevealed); + + function decorationAdded(line, type, element) + { + InspectorTest.addResult(`${line} ${type} ${element.textContent} ${element.style.backgroundColor}`); + } + + function setUrls(url, node) + { + node.url = url; + node.children.forEach(setUrls.bind(null, url)); + } + + function frameRevealed(frame) + { + var url = frame.uiSourceCode().url(); + InspectorTest.addResult(InspectorTest.formatters.formatAsURL(url)); + setUrls(url, cpuProfile.head); + var lineProfile = new WebInspector.LineLevelProfile.instance(); + lineProfile.appendCPUProfile(new WebInspector.CPUProfileDataModel(cpuProfile)); + setTimeout(() => InspectorTest.completeTest(), 0); + } +} + +</script> +</head> +<body onload="runTest()"> +Tests that a line-level CPU profile is shown in the text editor. +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-samping-codeobject-names-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-samping-codeobject-names-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-samping-codeobject-names-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-samping-codeobject-names-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-samping-codeobject-names.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-samping-codeobject-names.html new file mode 100644 index 0000000..4de9aab7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-samping-codeobject-names.html
@@ -0,0 +1,41 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../tracing-test.js"></script> +<script> +function test() +{ + Runtime.experiments.enableForTest("timelineTracingJSProfile"); + var rawNames = [ + "", + "Script:", + "Script:http://example.com/alina?", + "Script:http://example.com/:1", + "Script:http://example.com/:1:2", + "Script:http://example.com/:1:2:3", + "Script:http://example.com/:1:2:3x:4", + "Builtin:~foo1 http://url.com/foo.js", + "Builtin:~foo2 native http://url.com/foo.js:11", + "Builtin:*foo3 http://url.com/foo.js:11:22", + "Builtin:foo4 http://url.com/foo.js:11:22:33", + "Builtin:~ http://url.com/anonymous.js:123", + "Builtin:~ native http://url.com/anonymous.js:123", + "Builtin:~function name with spaces http://url.com/bar:123", + "Builtin:~native function name with spaces native http://url.com/bar.js:123", + "Builtin:~user_function_that_is_not_native http://url.com/bar.js:123", + "Builtin:~native http://url.com/bar.js:123" + ]; + + for (var name of rawNames) { + var frame = WebInspector.TimelineJSProfileProcessor._buildCallFrame(name, "456"); + InspectorTest.addResult(name + " => " + [frame.functionName, frame.url, frame.scriptId, frame.lineNumber, frame.columnNumber, frame.isNative].join(",")); + } + + InspectorTest.completeTest(); +} + +</script> +</head> +<body onload="runTest()"> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-samping-tracing-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-samping-tracing-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-js-samping-tracing-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-samping-tracing-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-samping-tracing.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-samping-tracing.html new file mode 100644 index 0000000..645820c5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-js-samping-tracing.html
@@ -0,0 +1,479 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function test() +{ + var sessionId = "6.23"; + var rawTraceEvents = [ + { + "args": { + "name": "Renderer" + }, + "cat": "__metadata", + "name": "process_name", + "ph": "M", + "pid": 17851, + "tid": 23, + "ts": 0 + }, + { + "args": { + "name": "CrRendererMain" + }, + "cat": "__metadata", + "name": "thread_name", + "ph": "M", + "pid": 17851, + "tid": 23, + "ts": 0 + }, + { + "args": { + "sessionId": sessionId + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "TracingStartedInPage", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 100000, + "tts": 606543 + }, + { + "args": { + "data": { + "code_start": "0xa000", + "code_len": 100, + "name": "LazyCompile:~a file:///script1.js:12", + "script_id": 1 + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "JitCodeAdded", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 190000, + "tts": 5610000 + }, + { + "args": { + "data": { + "code_start": "0xb000", + "code_len": 100, + "name": "LazyCompile:~b file:///script1.js:12", + "script_id": 1 + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "JitCodeAdded", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 190000, + "tts": 5610000 + }, + { + "args": { + "data": { + "code_start": "0xc000", + "code_len": 100, + "name": "LazyCompile:~c file:///script1.js:12", + "script_id": 1 + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "JitCodeAdded", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 190000, + "tts": 5610000 + }, + { + "args": { + "data": { + "code_start": "0xd000", + "code_len": 100, + "name": "LazyCompile:~d file:///script1.js:12", + "script_id": 1 + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "JitCodeAdded", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 190000, + "tts": 5610000 + }, + { + "args": { + "data": { + "code_start": "0x1e000", + "code_len": 100, + "name": "LazyCompile:~e file:///script1.js:12", + "script_id": 1 + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "JitCodeAdded", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 190000, + "tts": 5610000 + }, + { + "args": { + "data": { + "code_start": "0x1e000", + "new_code_start": "0xe000", + "code_len": 100 + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "JitCodeMoved", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 190000, + "tts": 5610000 + }, + { + "args": { + "data": { + "code_start": "0xf000", + "code_len": 100, + "name": "LazyCompile:~f file:///script1.js:12", + "script_id": 1 + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "JitCodeAdded", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 190000, + "tts": 5610000 + }, + { + "args": { + "data": { + "code_start": "0xf200", + "code_len": 100, + "name": "LazyCompile:*f file:///script1.js:12", + "script_id": 1 + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "JitCodeAdded", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 190000, + "tts": 5610000 + }, + { + "args": { + "data": { + "code_start": "0x8000", + "code_len": 100, + "name": "LazyCompile:~g file:///script1.js:12", + "script_id": 1 + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "JitCodeAdded", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 190000, + "tts": 5610000 + }, + { + "args": { + "data": { + "code_start": "0x1000", + "code_len": 100, + "name": "LazyCompile:~l file:///script1.js:12", + "script_id": 1 + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "JitCodeAdded", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 190000, + "tts": 5610000 + }, + { + "args": {}, + "cat": "disabled-by-default-devtools.timeline", + "name": "Program", + "ph": "B", + "pid": 17851, + "tid": 23, + "ts": 200000, + "tts": 5612442 + }, + { + "args": { + "data": { + "stack": [ + "0xc000", + "0xb000", + "0xa000" + ] + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "V8Sample", + "ph": "P", + "pid": 17851, + "tid": 23, + "ts": 208000, + "tts": 1758056 + }, + { + "args": {}, + "cat": "disabled-by-default-devtools.timeline", + "name": "FunctionCall", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 210000, + "dur": 30000, + "tts": 5612442 + }, + { + "args": { + "data": { + "stack": [ + "0xc000", + "0xb000", + "0xa000" + ] + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "V8Sample", + "ph": "P", + "pid": 17851, + "tid": 23, + "ts": 211000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stack": [] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "V8Sample", + "ph": "P", + "pid": 17851, + "tid": 23, + "ts": 212000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stack": [ + "0xc000", + "0xb000", + "0xa000" + ] + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "V8Sample", + "ph": "P", + "pid": 17851, + "tid": 23, + "ts": 220000, + "tts": 1758056 + }, + { + "args": { + "frame": "0x2f7b63884000", + "data": { + "stackTrace": [ + { "functionName": "b", "callUID": "b", "scriptId": "1" }, + { "functionName": "a", "callUID": "a", "scriptId": "1" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "InvalidateLayout", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 221000, + "dur": 7000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stack": [ + "0xc000", + "0xb000", + "0xa000" + ] + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "V8Sample", + "ph": "P", + "pid": 17851, + "tid": 23, + "ts": 221125, + "tts": 1758056 + }, + { + "args": { + "frame": "0x2f7b63884000", + "data": { + "stackTrace": [ + { "functionName": "e", "callUID": "e", "scriptId": "1" }, + { "functionName": "d", "callUID": "d", "scriptId": "1" }, + { "functionName": "b", "callUID": "b", "scriptId": "1" }, + { "functionName": "a", "callUID": "a", "scriptId": "1" } + ] + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "InvalidateLayout", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 222000, + "dur": 3000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stack": [ + "0x8000", + "0xf000", + "0xb000", + "0xa000" + ] + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "V8Sample", + "ph": "P", + "pid": 17851, + "tid": 23, + "ts": 225500, + "tts": 1758056 + }, + { + "args": { + "data": { + "stack": [ + "0x8000", + "0xe000", + "0xb000", + "0xa000" + ] + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "V8Sample", + "ph": "P", + "pid": 17851, + "tid": 23, + "ts": 228125, + "tts": 1758056 + }, + { + "args": { + "data": { + "stack": [ + "0x8000", + "0xe000", + "0xb000", + "0xa000" + ] + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "V8Sample", + "ph": "P", + "pid": 17851, + "tid": 23, + "ts": 228250, + "tts": 1758056 + }, + { + "args": { + "data": { + "stack": [ + "0xa000", + "0x1000", + "0xf000" + ] + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "V8Sample", + "ph": "P", + "pid": 17851, + "tid": 23, + "ts": 230000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stack": [ + "0xa000", + "0x1000", + "0xf210" + ] + } + }, + "cat": "disabled-by-default-v8.cpu_profile", + "name": "V8Sample", + "ph": "P", + "pid": 17851, + "tid": 23, + "ts": 230125, + "tts": 1758056 + }, + { + "args": {}, + "cat": "disabled-by-default-devtools.timeline", + "name": "Program", + "ph": "E", + "pid": 17851, + "tid": 23, + "ts": 500000, + "tts": 5612506 + } + ]; + + Runtime.experiments.enableForTest("timelineTracingJSProfile"); + var tracingTimelineModel = InspectorTest.createTimelineModelWithEvents(rawTraceEvents); + var events = tracingTimelineModel.mainThreadEvents(); + events.filter(function(e) { return e.name === "JSFrame"; }).forEach(function(e) { + InspectorTest.addResult(e.name + ": " + e.startTime.toFixed(3) + " / " + (e.duration.toFixed(3) || 0) + " " + e.args.data.functionName); + }); + + InspectorTest.completeTest(); +} + +</script> +</head> +<body onload="runTest()"> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-id-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-id-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-id-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-id-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-id.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-id.html new file mode 100644 index 0000000..cdea0cc --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-id.html
@@ -0,0 +1,70 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function test() +{ + function performActions(callback) + { + var timerOne = setTimeout("1 + 1", 10); + var timerTwo = setInterval(intervalTimerWork, 20); + var iteration = 0; + + function intervalTimerWork() + { + if (++iteration < 2) + return; + clearInterval(timerTwo); + callback(); + } + } + + var source = performActions.toString(); + source += "\n//# sourceURL=performActions.js"; + InspectorTest.evaluateInPage(source, startTimeline); + + function startTimeline() + { + InspectorTest.invokeAsyncWithTimeline("performActions", finish); + } + + var linkifier = new WebInspector.Linkifier(); + + var recordTypes = new Set(["TimerInstall", "TimerRemove", "FunctionCall"]); + function formatter(event) + { + if (!recordTypes.has(event.name)) + return; + + var detailsText = WebInspector.TimelineUIUtils.buildDetailsTextForTraceEvent(event, InspectorTest.timelineModel().target()); + InspectorTest.addResult("detailsTextContent for " + event.name + " event: '" + detailsText + "'"); + + var details = WebInspector.TimelineUIUtils.buildDetailsNodeForTraceEvent(event, InspectorTest.timelineModel().target(), linkifier); + if (!details) + return; + InspectorTest.addResult("details.textContent for " + event.name + " event: '" + details.textContent.replace(/VM[\d]+/, "VM") + "'"); + } + + function finish() + { + InspectorTest.walkTimelineEventTree(formatter); + InspectorTest.completeTest(); + } +} + +if (!window.testRunner) + setTimeout(performActions, 2000); + +</script> +</head> + +<body onload="runTest()"> +<p> +Test that checks location resolving mechanics for TimerInstall TimerRemove and FunctionCall events with scriptId. +</p><p> +It expects two FunctionCall for InjectedScript, two TimerInstall events, two FunctionCall events and one TimerRemove event to be logged with performActions.js script name and some line number. +</p> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-1-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-tag-1-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-1-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-tag-1-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-tag-1.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-tag-1.html new file mode 100644 index 0000000..931afd5e --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-tag-1.html
@@ -0,0 +1,55 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function performActions() +{ + var iframe = document.createElement("iframe"); + iframe.src = "../resources/timeline-iframe-data.html"; + document.body.appendChild(iframe); +} + +function test() +{ + WebInspector.panels.timeline._captureJSProfileSetting.set(false); + InspectorTest.startTimeline(step1); + function step1() + { + InspectorTest.addConsoleSniffer(step2); + InspectorTest.evaluateInPage("performActions()"); + } + + function step2() + { + InspectorTest.stopTimeline(step3); + } + + function step3() + { + function format(record) + { + if (record.type() === WebInspector.TimelineModel.RecordType.EvaluateScript) { + InspectorTest.dumpTimelineRecord(record, undefined, undefined, [ + "TimeStamp", + ]); + InspectorTest.printTimelineRecordProperties(record); + } + } + + InspectorTest.printTimelineRecords(null, InspectorTest.safeWrap(format)); + InspectorTest.completeTest(); + } +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline API instrumentation of an HTML script tag. +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-tag-2-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-tag-2-expected.txt new file mode 100644 index 0000000..a7feeef9 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-tag-2-expected.txt
@@ -0,0 +1,17 @@ +CONSOLE MESSAGE: line 1: SCRIPT TAG +Tests the Timeline API instrumentation of a script tag with an external script. + +EvaluateScript Properties: +{ + data : { + columnNumber : <number> + frame : <string> + lineNumber : <number> + url : .../inspector/tracing/timeline-js/timeline-script-tag-2.js + } + endTime : <number> + frameId : <string> + startTime : <number> + type : "EvaluateScript" +} +
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-tag-2.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-tag-2.html new file mode 100644 index 0000000..659a8de3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-tag-2.html
@@ -0,0 +1,44 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function performActions() +{ + var script = document.createElement("script"); + script.src = "timeline-script-tag-2.js"; + document.body.appendChild(script); +} + +function test() +{ + InspectorTest.startTimeline(step1); + function step1() + { + InspectorTest.addConsoleSniffer(step2); + InspectorTest.evaluateInPage("performActions()"); + } + + function step2() + { + InspectorTest.stopTimeline(step3); + } + + function step3() + { + InspectorTest.printTimelineRecords("EvaluateScript"); + InspectorTest.completeTest(); + } +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline API instrumentation of a script tag with an external script. +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-2.js b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-tag-2.js similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-2.js rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-js/timeline-script-tag-2.js
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout-reason.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout-reason.html deleted file mode 100644 index 2370d19..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout-reason.html +++ /dev/null
@@ -1,50 +0,0 @@ -<html> -<style> -.test { height: 20px; } -</style> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function invalidateStyle() -{ - var element = document.getElementById("test"); - element.className = "test"; -} - -function forceLayout() -{ - var element = document.getElementById("test"); - var unused = element.offsetHeight; -} - -function performActions() -{ - invalidateStyle(); - forceLayout(); -} - -function test() -{ - InspectorTest.evaluateWithTimeline("performActions()", onTimelineRecorded); - function onTimelineRecorded() - { - var layoutRecord = InspectorTest.findFirstTimelineRecord("Layout"); - InspectorTest.addResult("layout invalidated: " + layoutRecord.traceEvent().initiator.stackTrace[0].functionName); - InspectorTest.addResult("layout forced: " + layoutRecord.traceEvent().stackTrace[0].functionName); - InspectorTest.completeTest(); - } -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests that Layout record has correct locations of layout being invalidated and forced. -</p> -<div id="test"></div> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout-with-invalidations-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout-with-invalidations-expected.txt deleted file mode 100644 index a58b1de..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout-with-invalidations-expected.txt +++ /dev/null
@@ -1,61 +0,0 @@ -Tests the Timeline API instrumentation of layout events with invalidations. - -PASS - - -Running: testLocalFrame -first layout invalidations[ - { - cause : {reason: Style changed, stackTrace: .../inspector/tracing/timeline-layout-with-invalidations.html:11} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElement'" - selectorPart : undefined - type : "LayoutInvalidationTracking" - } -] -second layout invalidations[ - { - cause : {reason: Style changed, stackTrace: .../inspector/tracing/timeline-layout-with-invalidations.html:13} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElement'" - selectorPart : undefined - type : "LayoutInvalidationTracking" - } -] - -Running: testSubframe -first layout invalidations[ - { - cause : {reason: Style changed, stackTrace: .../inspector/tracing/timeline-layout-with-invalidations.html:23} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV" - selectorPart : undefined - type : "LayoutInvalidationTracking" - } -] -second layout invalidations[ - { - cause : {reason: Style changed, stackTrace: .../inspector/tracing/timeline-layout-with-invalidations.html:25} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV" - selectorPart : undefined - type : "LayoutInvalidationTracking" - } -] -
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout-with-invalidations.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout-with-invalidations.html deleted file mode 100644 index 02ff6c3b..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout-with-invalidations.html +++ /dev/null
@@ -1,72 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function display(callback) -{ - requestAnimationFrame(function() { - document.getElementById("testElement").style.width = "100px"; - var forceLayout1 = document.body.offsetTop; - document.getElementById("testElement").style.width = "110px"; - var forceLayout2 = document.body.offsetTop; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function updateSubframeAndDisplay(callback) -{ - requestAnimationFrame(function() { - frames[0].document.body.children[0].style.width = "10px"; - var forceLayout1 = frames[0].document.body.offsetTop; - frames[0].document.body.children[0].style.width = "20px"; - var forceLayout2 = frames[0].document.body.offsetTop; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function test() -{ - var currentPanel = WebInspector.inspectorView.currentPanel(); - InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); - Runtime.experiments.enableForTest("timelineInvalidationTracking"); - - InspectorTest.runTestSuite([ - function testLocalFrame(next) - { - InspectorTest.invokeAsyncWithTimeline("display", function() { - var firstLayoutRecord = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Layout); - InspectorTest.addArray(firstLayoutRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first layout invalidations"); - - var secondLayoutRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.Layout, 1); - InspectorTest.addArray(secondLayoutRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second layout invalidations"); - - next(); - }); - }, - - function testSubframe(next) - { - InspectorTest.invokeAsyncWithTimeline("updateSubframeAndDisplay", function() { - var firstLayoutRecord = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Layout); - InspectorTest.addArray(firstLayoutRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first layout invalidations"); - - var secondLayoutRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.Layout, 1); - InspectorTest.addArray(secondLayoutRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second layout invalidations"); - - next(); - }); - } - ]); -} -</script> -</head> -<body onload="runTest()"> -<p>Tests the Timeline API instrumentation of layout events with invalidations.</p> -<div id="outerTestElement" style="display: inline-block;"><div id="testElement">PASS</div></div> -<iframe src="resources/timeline-iframe-paint.html" style="position: absolute; left: 40px; top: 40px; width: 100px; height: 100px; border: none"></iframe> -</body> -</html> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout.html deleted file mode 100644 index 7c2ed83..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout.html +++ /dev/null
@@ -1,55 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<style> -.relayout-boundary { - overflow: hidden; - width: 100px; - height: 100px; -} -</style> -<script> - -function invalidateAndForceLayout(element) -{ - element.style.marginTop = "10px"; - var unused = element.offsetHeight; -} - -function performActions() -{ - wrapCallFunctionForTimeline(() => invalidateAndForceLayout(document.getElementById("invalidate1"))); - wrapCallFunctionForTimeline(() => invalidateAndForceLayout(document.getElementById("invalidate2"))); -} - -function test() -{ - InspectorTest.performActionsAndPrint("performActions()", "Layout"); -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline API instrumentation of a Layout event -</p> -<div class="relayout-boundary"> - <div>text</div> - <div></div> - <div> - <div id="invalidate1"><div>text</div></div> - </div> -</div> -<div class="relayout-boundary"> - <div></div> - <div>text</div> - <div id="invalidate2"><div>text</div></div> - <div></div> - <div></div> - <div>text</div> -</div> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout/timeline-layout-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout/timeline-layout-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout-reason-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout/timeline-layout-reason-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout-reason-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout/timeline-layout-reason-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout/timeline-layout-reason.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout/timeline-layout-reason.html new file mode 100644 index 0000000..0d64406 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout/timeline-layout-reason.html
@@ -0,0 +1,50 @@ +<html> +<style> +.test { height: 20px; } +</style> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function invalidateStyle() +{ + var element = document.getElementById("test"); + element.className = "test"; +} + +function forceLayout() +{ + var element = document.getElementById("test"); + var unused = element.offsetHeight; +} + +function performActions() +{ + invalidateStyle(); + forceLayout(); +} + +function test() +{ + InspectorTest.evaluateWithTimeline("performActions()", onTimelineRecorded); + function onTimelineRecorded() + { + var layoutRecord = InspectorTest.findFirstTimelineRecord("Layout"); + InspectorTest.addResult("layout invalidated: " + layoutRecord.traceEvent().initiator.stackTrace[0].functionName); + InspectorTest.addResult("layout forced: " + layoutRecord.traceEvent().stackTrace[0].functionName); + InspectorTest.completeTest(); + } +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests that Layout record has correct locations of layout being invalidated and forced. +</p> +<div id="test"></div> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout/timeline-layout-with-invalidations-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout/timeline-layout-with-invalidations-expected.txt new file mode 100644 index 0000000..4ddcd95 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout/timeline-layout-with-invalidations-expected.txt
@@ -0,0 +1,61 @@ +Tests the Timeline API instrumentation of layout events with invalidations. + +PASS + + +Running: testLocalFrame +first layout invalidations[ + { + cause : {reason: Style changed, stackTrace: .../inspector/tracing/timeline-layout/timeline-layout-with-invalidations.html:11} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElement'" + selectorPart : undefined + type : "LayoutInvalidationTracking" + } +] +second layout invalidations[ + { + cause : {reason: Style changed, stackTrace: .../inspector/tracing/timeline-layout/timeline-layout-with-invalidations.html:13} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElement'" + selectorPart : undefined + type : "LayoutInvalidationTracking" + } +] + +Running: testSubframe +first layout invalidations[ + { + cause : {reason: Style changed, stackTrace: .../inspector/tracing/timeline-layout/timeline-layout-with-invalidations.html:23} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV" + selectorPart : undefined + type : "LayoutInvalidationTracking" + } +] +second layout invalidations[ + { + cause : {reason: Style changed, stackTrace: .../inspector/tracing/timeline-layout/timeline-layout-with-invalidations.html:25} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV" + selectorPart : undefined + type : "LayoutInvalidationTracking" + } +] +
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout/timeline-layout-with-invalidations.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout/timeline-layout-with-invalidations.html new file mode 100644 index 0000000..0c16a28 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout/timeline-layout-with-invalidations.html
@@ -0,0 +1,72 @@ +<!DOCTYPE HTML> +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function display(callback) +{ + requestAnimationFrame(function() { + document.getElementById("testElement").style.width = "100px"; + var forceLayout1 = document.body.offsetTop; + document.getElementById("testElement").style.width = "110px"; + var forceLayout2 = document.body.offsetTop; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function updateSubframeAndDisplay(callback) +{ + requestAnimationFrame(function() { + frames[0].document.body.children[0].style.width = "10px"; + var forceLayout1 = frames[0].document.body.offsetTop; + frames[0].document.body.children[0].style.width = "20px"; + var forceLayout2 = frames[0].document.body.offsetTop; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function test() +{ + var currentPanel = WebInspector.inspectorView.currentPanel(); + InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); + Runtime.experiments.enableForTest("timelineInvalidationTracking"); + + InspectorTest.runTestSuite([ + function testLocalFrame(next) + { + InspectorTest.invokeAsyncWithTimeline("display", function() { + var firstLayoutRecord = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Layout); + InspectorTest.addArray(firstLayoutRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first layout invalidations"); + + var secondLayoutRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.Layout, 1); + InspectorTest.addArray(secondLayoutRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second layout invalidations"); + + next(); + }); + }, + + function testSubframe(next) + { + InspectorTest.invokeAsyncWithTimeline("updateSubframeAndDisplay", function() { + var firstLayoutRecord = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Layout); + InspectorTest.addArray(firstLayoutRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first layout invalidations"); + + var secondLayoutRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.Layout, 1); + InspectorTest.addArray(secondLayoutRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second layout invalidations"); + + next(); + }); + } + ]); +} +</script> +</head> +<body onload="runTest()"> +<p>Tests the Timeline API instrumentation of layout events with invalidations.</p> +<div id="outerTestElement" style="display: inline-block;"><div id="testElement">PASS</div></div> +<iframe src="../resources/timeline-iframe-paint.html" style="position: absolute; left: 40px; top: 40px; width: 100px; height: 100px; border: none"></iframe> +</body> +</html> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout/timeline-layout.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout/timeline-layout.html new file mode 100644 index 0000000..8636a33 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-layout/timeline-layout.html
@@ -0,0 +1,55 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<style> +.relayout-boundary { + overflow: hidden; + width: 100px; + height: 100px; +} +</style> +<script> + +function invalidateAndForceLayout(element) +{ + element.style.marginTop = "10px"; + var unused = element.offsetHeight; +} + +function performActions() +{ + wrapCallFunctionForTimeline(() => invalidateAndForceLayout(document.getElementById("invalidate1"))); + wrapCallFunctionForTimeline(() => invalidateAndForceLayout(document.getElementById("invalidate2"))); +} + +function test() +{ + InspectorTest.performActionsAndPrint("performActions()", "Layout"); +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline API instrumentation of a Layout event +</p> +<div class="relayout-boundary"> + <div>text</div> + <div></div> + <div> + <div id="invalidate1"><div>text</div></div> + </div> +</div> +<div class="relayout-boundary"> + <div></div> + <div>text</div> + <div id="invalidate2"><div>text</div></div> + <div></div> + <div></div> + <div>text</div> +</div> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-load-event.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-load-event.html deleted file mode 100644 index c1efcb0..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-load-event.html +++ /dev/null
@@ -1,59 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function display(callback) -{ - if (window.testRunner) - testRunner.setCanOpenWindows(true); - var popup = window.open("data:text/html,<b>Hello, world</b>"); - popup.onload = function() - { - requestAnimationFrame(testRunner.capturePixelsAsyncThen.bind(testRunner, callback)); - } -} - -function test() -{ - WebInspector.panels.timeline._captureJSProfileSetting.set(false); - InspectorTest.startTimeline(function() { InspectorTest.reloadPage(pageReloaded); }); - - function pageReloaded() - { - InspectorTest.invokePageFunctionAsync("display", displayDone); - } - - function displayDone() - { - InspectorTest.stopTimeline(InspectorTest.safeWrap(finish)) - } - - function finish() - { - InspectorTest.addResult("Model records:"); - InspectorTest.printTimelineRecords("MarkDOMContent"); - InspectorTest.printTimelineRecords("MarkLoad"); - InspectorTest.addResult("Timestamp records:"); - InspectorTest.printTimestampRecords("MarkDOMContent"); - InspectorTest.printTimestampRecords("MarkLoad"); - InspectorTest.printTimestampRecords("MarkFirstPaint"); - - var eventDividers = InspectorTest.timelineModel().eventDividerRecords(); - for (var i = 1; i < eventDividers.length; ++i) - InspectorTest.assertGreaterOrEqual(eventDividers[i], eventDividers[i - 1], "Event divider timestamps should be monotonically non-decreasing"); - - InspectorTest.completeTest(); - } -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the load event. -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-mark-timeline.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-mark-timeline.html deleted file mode 100644 index 837bd5e..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-mark-timeline.html +++ /dev/null
@@ -1,26 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function performActions() -{ - console.markTimeline("MARK TIMELINE"); -} - -function test() -{ - InspectorTest.performActionsAndPrint("performActions()", "TimeStamp"); -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline API mark feature -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-aggregated-details-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-aggregated-details-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-aggregated-details-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-aggregated-details-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-aggregated-details.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-aggregated-details.html new file mode 100644 index 0000000..19e58429 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-aggregated-details.html
@@ -0,0 +1,620 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function test() +{ + var sessionId = "6.23"; + var rawTraceEvents = [ + { + "args": { + "name": "Renderer" + }, + "cat": "__metadata", + "name": "process_name", + "ph": "M", + "pid": 17851, + "tid": 23, + "ts": 0 + }, + { + "args": { + "name": "CrRendererMain" + }, + "cat": "__metadata", + "name": "thread_name", + "ph": "M", + "pid": 17851, + "tid": 23, + "ts": 0 + }, + { + "args": { + "sessionId": sessionId + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "TracingStartedInPage", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 100000, + "tts": 606543 + }, + { + "args": {}, + "cat": "disabled-by-default-devtools.timeline", + "name": "Program", + "ph": "B", + "pid": 17851, + "tid": 23, + "ts": 200000, + "tts": 5612442 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "c", "callUID": "c", "scriptId": 1 }, + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 208000, + "tts": 1758056 + }, + { + "args": {}, + "cat": "disabled-by-default-devtools.timeline", + "name": "FunctionCall", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 210000, + "dur": 30000, + "tts": 5612442 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "c", "callUID": "c", "scriptId": 1 }, + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 211000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 212000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "c", "callUID": "c", "scriptId": 1 }, + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 219875, + "tts": 1758056 + }, + { + "args": { + "frame": "0x2f7b63884000", + "data": { + "stackTrace": [ + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "InvalidateLayout", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 220000, + "dur": 7000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "c", "callUID": "c", "scriptId": 1 }, + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 220125, + "tts": 1758056 + }, + { + "args": { + "frame": "0x2f7b63884000", + "data": { + "stackTrace": [ + { "functionName": "b", "callUID": "b", "scriptId": 1 }, + { "functionName": "a", "callUID": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "InvalidateLayout", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 221000, + "dur": 3000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "g", "scriptId": 1 }, + { "functionName": "f", "scriptId": 1 }, + { "functionName": "b", "scriptId": 1 }, + { "functionName": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 222000, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "g", "scriptId": 1 }, + { "functionName": "e", "scriptId": 1 }, + { "functionName": "b", "scriptId": 1 }, + { "functionName": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 227125, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "g", "scriptId": 1 }, + { "functionName": "e", "scriptId": 1 }, + { "functionName": "b", "scriptId": 1 }, + { "functionName": "a", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 227250, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "a", "callUID": "a", "scriptId": 1 }, + { "functionName": "l", "callUID": "l", "scriptId": 1 }, + { "functionName": "f", "callUID": "f", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 230000, + "tts": 1758056 + }, + { + "args": { + "beginData": { + "stackTrace": [ + { "functionName": "a", "callUID": "a", "scriptId": 1 }, + { "functionName": "l", "callUID": "l", "scriptId": 1 }, + { "functionName": "f", "callUID": "f", "scriptId": 1 }, + { "functionName": "sin", "callUID": "sin", "scriptId": 2, "url": "native math.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "Layout", + "ph": "X", + "dur": 100, + "pid": 17851, + "tid": 23, + "ts": 230010, + "tts": 1758056 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "a", "callUID": "a", "scriptId": 1 }, + { "functionName": "l", "callUID": "l", "scriptId": 1 }, + { "functionName": "f", "callUID": "f", "scriptId": 1 }, + { "functionName": "sin", "callUID": "sin", "scriptId": 2, "url": "native math.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "TimerInstall", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 230111 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "a", "callUID": "a", "scriptId": 1 }, + { "functionName": "l", "callUID": "l", "scriptId": 1 }, + { "functionName": "f", "callUID": "f", "scriptId": 1 }, + { "functionName": "sin", "callUID": "sin", "scriptId": 2, "url": "native math.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 230125 + }, + { + "args": {}, + "cat": "disabled-by-default-devtools.timeline", + "name": "FunctionCall", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 250000, + "dur": 10000 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "FunctionCall", + "ph": "X", + "pid": 17851, + "tid": 23, + "ts": 251000, + "dur": 1000 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "w", "callUID": "w", "scriptId": 1 }, + { "functionName": "z", "callUID": "z", "scriptId": 1 }, + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 251000 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "w", "callUID": "w", "scriptId": 1 }, + { "functionName": "z", "callUID": "z", "scriptId": 1 }, + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 251100 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "w", "scriptId": 1 }, + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 251200 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "w", "scriptId": 1 }, + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 251300 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "y", "callUID": "y", "scriptId": 1 }, + { "functionName": "x", "callUID": "x", "scriptId": 1 } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 251400 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_b", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, + { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, + { "functionName": "recursive_b", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, + { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253000 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, + { "functionName": "recursive_b", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, + { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253008 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_b", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, + { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253012 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253014 + }, + { + "args": { + "data": { + "stackTrace": [ + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253015 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_b", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" }, + { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253100 + }, + { + "args": { + "data": { + "stackTrace": [ + { "functionName": "recursive_a", "scriptId": 1, "url": "http://xyz.abc.com/rec.js" } + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253200 + }, + { + "args": { + "data": { + "stackTrace": [ + ] + } + }, + "cat": "disabled-by-default-devtools.timeline", + "name": "JSSample", + "ph": "I", + "pid": 17851, + "tid": 23, + "ts": 253300 + }, + { + "args": {}, + "cat": "disabled-by-default-devtools.timeline", + "name": "Program", + "ph": "E", + "pid": 17851, + "tid": 23, + "ts": 500000, + "tts": 5612506 + } + ]; + + var timeline = WebInspector.panels.timeline; + InspectorTest.setTraceEvents(InspectorTest.timelineModel(), InspectorTest.tracingModel(), rawTraceEvents); + + timeline.requestWindowTimes(0, Infinity); + for (var grouping in WebInspector.TimelineAggregator.GroupBy) { + var groupingValue = WebInspector.TimelineAggregator.GroupBy[grouping]; + testEventTree(WebInspector.TimelinePanel.DetailsTab.CallTree, groupingValue); + testEventTree(WebInspector.TimelinePanel.DetailsTab.BottomUp, groupingValue); + } + + testEventTree(WebInspector.TimelinePanel.DetailsTab.Events); + InspectorTest.completeTest(); + + function testEventTree(type, grouping) + { + InspectorTest.addResult(""); + timeline._detailsView.selectTab(type, true); + var callTree = timeline._detailsView._rangeDetailViews.get(type); + if (grouping) { + InspectorTest.addResult(type + " Group by: " + grouping); + callTree._groupByCombobox.select(callTree._groupByCombobox.options().find((x) => x.value === grouping)); + callTree._onGroupByChanged(); + } else { + InspectorTest.addResult(type); + } + var rootNode = callTree._dataGrid.rootNode(); + for (var node of rootNode.children) + printEventTree(1, node._profileNode, node._treeView); + } + + function printEventTree(padding, node, treeView) + { + var name; + if (node.isGroupNode()) { + name = treeView._displayInfoForGroupNode(node).name; + } else { + name = node.event.name === WebInspector.TimelineModel.RecordType.JSFrame + ? WebInspector.beautifyFunctionName(node.event.args["data"]["functionName"]) + : WebInspector.TimelineUIUtils.eventTitle(node.event); + } + InspectorTest.addResult(" ".repeat(padding) + name + ": " + [node.selfTime, node.totalTime].map(function (t) { return t.toFixed(3); }).join(" ")); + (node.children || new Map()).forEach(printEventTree.bind(null, padding + 1)); + } +} + +</script> +</head> +<body onload="runTest()"> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-animation-frame-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-animation-frame-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-animation-frame-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-animation-frame-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-animation-frame.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-animation-frame.html new file mode 100644 index 0000000..6556301 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-animation-frame.html
@@ -0,0 +1,40 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function performActions(callback) +{ + var requestId = window.requestAnimationFrame(animationFrameCallback); + function animationFrameCallback() + { + window.cancelAnimationFrame(requestId); + if (callback) + callback(); + } +} + +function test() +{ + InspectorTest.invokeAsyncWithTimeline("performActions", finish); + + function finish() + { + InspectorTest.printTimelineRecordsWithDetails("RequestAnimationFrame"); + InspectorTest.printTimelineRecordsWithDetails("FireAnimationFrame"); + InspectorTest.printTimelineRecordsWithDetails("CancelAnimationFrame"); + InspectorTest.completeTest(); + } +} + +if (!window.testRunner) + setTimeout(performActions, 2000); +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline events for Animation Frame feature +</p> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-auto-record-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-auto-record-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-auto-record-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-auto-record-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-auto-record.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-auto-record.html new file mode 100644 index 0000000..8516b7c --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-auto-record.html
@@ -0,0 +1,51 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/console-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function test() +{ + var panel = WebInspector.panels.timeline; + + var callbackBarrier = new CallbackBarrier(); + InspectorTest.addSniffer(panel, "recordingStarted", recordingStarted); + InspectorTest.addSniffer(panel, "loadingComplete", callbackBarrier.createCallback()); + + WebInspector.ConsolePanel.show(); + InspectorTest.runWhenPageLoads(step1); + InspectorTest.addResult("Reloading page on console panel"); + panel._millisecondsToRecordAfterLoadEvent = 1; + InspectorTest.resourceTreeModel.reloadPage(); + + function step1() + { + WebInspector.TimelinePanel.show(); + InspectorTest.runWhenPageLoads(callbackBarrier.createCallback()); + callbackBarrier.callWhenDone(recordingStopped); + InspectorTest.addResult("Reloading page on timeline panel"); + InspectorTest.resourceTreeModel.reloadPage(); + } + + function recordingStarted() + { + InspectorTest.addResult("Recording started"); + InspectorTest.addResult("Initiated by user: " + !panel._autoRecordGeneration); + } + + function recordingStopped() + { + InspectorTest.addResult("Recording stopped"); + InspectorTest.completeTest(); + } +} + +</script> +</head> + +<body onload="runTest()"> +<p>Test auto-recording of Timeline.</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-auto-zoom-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-auto-zoom-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-auto-zoom-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-auto-zoom-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-auto-zoom.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-auto-zoom.html new file mode 100644 index 0000000..3c95eddd --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-auto-zoom.html
@@ -0,0 +1,56 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function test() +{ + var sessionId = "4.20"; + var mainThread = 1; + var pid = 100; + + var traceEvents = [ + { + "args": { "sessionId": sessionId }, + "cat": "disabled-by-default-devtools.timeline", + "name": "TracingStartedInPage", + "ph": "I", + "pid": pid, + "tid": mainThread, + "ts": 100, + }, + {"name": "Program", "ts": 1000000, "dur":10000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline" }, + {"name": "FunctionCall", "ts": 1000000, "dur": 10000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{}}}, + {"name": "Program", "ts": 2000000, "dur": 500000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline" }, + {"name": "FunctionCall", "ts": 2000000, "dur": 500000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{}}}, + {"name": "Program", "ts": 3000000, "dur": 400000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline"}, + {"name": "FunctionCall", "ts": 3000000, "dur": 400000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{}}}, + {"name": "Program", "ts": 4000000, "dur": 200000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline"}, + {"name": "FunctionCall", "ts": 4000000, "dur": 200000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{}}}, + {"name": "Program", "ts": 5000000, "dur": 1000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline"}, + {"name": "FunctionCall", "ts": 5000000, "dur": 1000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{}}}, + {"name": "Program", "ts": 6000000, "dur": 1000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline"}, + {"name": "FunctionCall", "ts": 6000000, "dur": 1000, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default-devtools.timeline", "args":{"data":{}}} + ]; + + InspectorTest.setTraceEvents(InspectorTest.timelineModel(), InspectorTest.tracingModel(), traceEvents); + var overview = WebInspector.panels.timeline._overviewPane; + var startTime = overview._windowStartTime; + var endTime = overview._windowEndTime; + InspectorTest.assertGreaterOrEqual(startTime, 1010); + InspectorTest.assertGreaterOrEqual(2000, startTime); + InspectorTest.assertGreaterOrEqual(endTime, 4200); + InspectorTest.assertGreaterOrEqual(5000, startTime); + InspectorTest.completeTest(); +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Test auto zoom feature of the timeline. +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-bound-function-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-bound-function-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-bound-function-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-bound-function-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-bound-function.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-bound-function.html new file mode 100644 index 0000000..b154407 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-bound-function.html
@@ -0,0 +1,46 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function original() { } + +function performActions() +{ + var b = document.getElementById("btn"); + var foo = original.bind(); + b.onclick = foo; + b.click(); +} + +function test() +{ + InspectorTest.evaluateWithTimeline("performActions()", finish); + + function finish() + { + function formatter(record) + { + if (record.type() === "FunctionCall") { + var data = record.traceEvent().args["data"]; + var scriptName = data.scriptName; + var scriptNameShort = scriptName.substring(scriptName.lastIndexOf("/") + 1); + InspectorTest.addResult(record.type() + " " + scriptNameShort + ":" + data.scriptLine); + } + } + InspectorTest.printTimelineRecords(null, formatter); + InspectorTest.completeTest(); + } +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests extracting information about original functions from bound ones +</p> +<button id="btn"></button> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-dfs-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-dfs-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-dfs-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-dfs-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-dfs.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-dfs.html new file mode 100644 index 0000000..e748b6e1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-dfs.html
@@ -0,0 +1,68 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script type="text/javascript"> + +var test = function() +{ + + function dumper(record) + { + InspectorTest.addResult(record.type()); + } + + var sessionId = "4.20"; + var mainThread = 1; + var pid = 100; + + var testData = [ + { + "args": { "sessionId": sessionId }, + "cat": "disabled-by-default-devtools.timeline", + "name": "TracingStartedInPage", + "ph": "I", + "pid": pid, + "tid": mainThread, + "ts": 100, + }, + {"name": "a", "ts": 1000000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args": {}}, + {"name": "aa", "ts": 1000001, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, + {"name": "aaa", "ts": 1200000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, + {"name": "aab", "ts": 1300000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, + {"name": "aa", "ts": 1400000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args": {}}, + {"name": "ab", "ts": 1500001, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, + {"name": "aba", "ts": 1600000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, + {"name": "abb", "ts": 1700000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, + {"name": "ab", "ts": 1800000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args": {}}, + {"name": "a", "ts": 2000000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args": {}}, + {"name": "b", "ts": 3000000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args": {}}, + {"name": "ba", "ts": 3000001, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, + {"name": "baa", "ts": 3200000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, + {"name": "bab", "ts": 3300000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, + {"name": "ba", "ts": 3400000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args": {}}, + {"name": "bb", "ts": 3500001, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, + {"name": "bba", "ts": 3600000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, + {"name": "bbb", "ts": 3700000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args":{}}, + {"name": "bb", "ts": 3800000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args": {}}, + {"name": "b", "ts": 4000000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default.devtools.timeline", "args": {}} + ]; + + var model = new WebInspector.TimelineModel(new WebInspector.TimelineModel.Filter()); + InspectorTest.setTraceEvents(model, InspectorTest.createTracingModel(), testData); + + InspectorTest.addResult("DFS preorder:"); + model.forAllRecords(dumper); + InspectorTest.addResult(""); + + InspectorTest.addResult("DFS postorder:"); + model.forAllRecords(null, dumper); + InspectorTest.completeTest(); +} + +</script> +</head> +<body onload="runTest()"> +<p>Tests TimelineModel.forAllRecords function.</p> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-event-causes-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-event-causes-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-event-causes-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-event-causes-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-event-causes.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-event-causes.html new file mode 100644 index 0000000..d5862525 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-event-causes.html
@@ -0,0 +1,135 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function test() +{ + function checkStringContains(string, contains) + { + var doesContain = string.indexOf(contains) >= 0; + InspectorTest.check(doesContain, contains + " should be present in " + string); + InspectorTest.addResult("PASS - record contained " + contains); + } + + InspectorTest.runTestSuite([ + function testTimerInstall(next) + { + function setTimeoutFunction(callback) + { + setTimeout(callback, 0); + } + + var source = setTimeoutFunction.toString(); + source += "\n//# sourceURL=setTimeoutFunction.js"; + InspectorTest.evaluateInPage(source); + + InspectorTest.invokeAsyncWithTimeline("setTimeoutFunction", finishAndRunNextTest); + function finishAndRunNextTest() + { + var linkifier = new WebInspector.Linkifier(); + var record = InspectorTest.findFirstTimelineRecord("TimerFire"); + InspectorTest.check(record, "Should receive a TimerFire record."); + var contentHelper = new WebInspector.TimelineDetailsContentHelper(InspectorTest.timelineModel().target(), linkifier, true); + WebInspector.TimelineUIUtils._generateCauses(record.traceEvent(), InspectorTest.timelineModel().target(), null, contentHelper); + var causes = contentHelper.element.deepTextContent(); + InspectorTest.check(causes, "Should generate causes"); + checkStringContains(causes, "Timer InstalledsetTimeoutFunction @ setTimeoutFunction.js:"); + next(); + } + }, + + function testRequestAnimationFrame(next) + { + function requestAnimationFrameFunction(callback) + { + requestAnimationFrame(callback); + } + + var source = requestAnimationFrameFunction.toString(); + source += "\n//# sourceURL=requestAnimationFrameFunction.js"; + InspectorTest.evaluateInPage(source); + + InspectorTest.invokeAsyncWithTimeline("requestAnimationFrameFunction", finishAndRunNextTest); + function finishAndRunNextTest() + { + var linkifier = new WebInspector.Linkifier(); + var record = InspectorTest.findFirstTimelineRecord("FireAnimationFrame"); + InspectorTest.check(record, "Should receive a FireAnimationFrame record."); + var contentHelper = new WebInspector.TimelineDetailsContentHelper(InspectorTest.timelineModel().target(), linkifier, true); + WebInspector.TimelineUIUtils._generateCauses(record.traceEvent(), InspectorTest.timelineModel().target(), null, contentHelper); + var causes = contentHelper.element.deepTextContent(); + InspectorTest.check(causes, "Should generate causes"); + checkStringContains(causes, "Animation Frame RequestedrequestAnimationFrameFunction @ requestAnimationFrameFunction.js:"); + next(); + } + }, + + function testStyleRecalc(next) + { + function styleRecalcFunction() + { + var element = document.getElementById("testElement"); + element.style.backgroundColor = "papayawhip"; + var forceLayout = element.offsetWidth; + } + + var source = styleRecalcFunction.toString(); + source += "\n//# sourceURL=styleRecalcFunction.js"; + InspectorTest.evaluateInPage(source); + + InspectorTest.evaluateWithTimeline("styleRecalcFunction()", finishAndRunNextTest); + function finishAndRunNextTest() + { + var linkifier = new WebInspector.Linkifier(); + var record = InspectorTest.findFirstTimelineRecord("UpdateLayoutTree"); + InspectorTest.check(record, "Should receive a UpdateLayoutTree record."); + var contentHelper = new WebInspector.TimelineDetailsContentHelper(InspectorTest.timelineModel().target(), linkifier, true); + WebInspector.TimelineUIUtils._generateCauses(record.traceEvent(), InspectorTest.timelineModel().target(), null, contentHelper); + var causes = contentHelper.element.deepTextContent(); + InspectorTest.check(causes, "Should generate causes"); + checkStringContains(causes, "First InvalidatedstyleRecalcFunction @ styleRecalcFunction.js:"); + next(); + } + }, + + function testLayout(next) + { + function layoutFunction() + { + var element = document.getElementById("testElement"); + element.style.width = "200px"; + var forceLayout = element.offsetWidth; + } + + var source = layoutFunction.toString(); + source += "\n//# sourceURL=layoutFunction.js"; + InspectorTest.evaluateInPage(source); + + InspectorTest.evaluateWithTimeline("layoutFunction()", finishAndRunNextTest); + function finishAndRunNextTest() + { + var linkifier = new WebInspector.Linkifier(); + var record = InspectorTest.findFirstTimelineRecord("Layout"); + InspectorTest.check(record, "Should receive a Layout record."); + var contentHelper = new WebInspector.TimelineDetailsContentHelper(InspectorTest.timelineModel().target(), linkifier, true); + WebInspector.TimelineUIUtils._generateCauses(record.traceEvent(), InspectorTest.timelineModel().target(), null, contentHelper); + var causes = contentHelper.element.deepTextContent(); + InspectorTest.check(causes, "Should generate causes"); + checkStringContains(causes, "Layout ForcedlayoutFunction @ layoutFunction.js:"); + checkStringContains(causes, "First Layout InvalidationlayoutFunction @ layoutFunction.js:"); + next(); + } + } + ]); +} +</script> +</head> + +<body onload="runTest()"> +<p> +Test that causes are correctly generated for various types of events. +</p> +<div id="testElement"></div> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-event-dispatch-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-event-dispatch-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-event-dispatch-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-event-dispatch-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-event-dispatch.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-event-dispatch.html new file mode 100644 index 0000000..74ee7ad --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-event-dispatch.html
@@ -0,0 +1,43 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function handleMouseDown(event) +{ + console.timeStamp("Handling mousedown"); +} + +function performActions() +{ + var target = document.getElementById("testTarget"); + target.addEventListener("mousedown", handleMouseDown, true); + var rect = target.getBoundingClientRect(); + + // Simulate the mouse down over the target to trigger an EventDispatch + if (window.eventSender) { + window.eventSender.mouseMoveTo(rect.left + rect.width / 2, rect.top + rect.height / 2); + window.eventSender.mouseDown(); + } +} + +function test() +{ + InspectorTest.performActionsAndPrint("performActions()", "EventDispatch"); +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline API instrumentation of a DOM Dispatch (mousedown) +</p> + +<div id="testTarget" style="width:400px; height:400px;"> +Test Mouse Target +</div> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-filtering-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-filtering-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-filtering-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-filtering-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-filtering.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-filtering.html new file mode 100644 index 0000000..5143296 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-filtering.html
@@ -0,0 +1,93 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function test() +{ + var sessionId = "4.20"; + var mainThread = 1; + var pid = 100; + + var testData = [ + { + "args": { "sessionId": sessionId }, + "cat": "disabled-by-default-devtools.timeline", + "name": "TracingStartedInPage", + "ph": "I", + "pid": pid, + "tid": mainThread, + "ts": 100, + }, + {"name": "top level event name", "ts": 1000000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"toplevel", "args": {}}, + {"name": "TimeStamp", "ts": 1010000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar01"}}}, + {"name": "TimeStamp", "ts": 1020000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar02"}}}, + {"name": "TimeStamp", "ts": 1120000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar03"}}}, + {"name": "TimeStamp", "ts": 1180000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}}, + {"name": "TimeStamp", "ts": 1210000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar04"}}}, + {"name": "TimeStamp", "ts": 1220000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo05"}}}, + {"name": "TimeStamp", "ts": 1320000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar06"}}}, + {"name": "TimeStamp", "ts": 1380000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}}, + {"name": "TimeStamp", "ts": 1410000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar07"}}}, + {"name": "TimeStamp", "ts": 1420000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo08"}}}, + {"name": "TimeStamp", "ts": 1520000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo09"}}}, + {"name": "TimeStamp", "ts": 1580000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}}, + {"name": "top level event name", "ts": 1990000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"toplevel", "args": {}}, + {"name": "Program", "ts": 2000000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}}, + {"name": "TimeStamp", "ts": 2010000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo10"}}}, + {"name": "TimeStamp", "ts": 2020000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar11"}}}, + {"name": "TimeStamp", "ts": 2120000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar12"}}}, + {"name": "TimeStamp", "ts": 2180000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}}, + {"name": "TimeStamp", "ts": 2210000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo13"}}}, + {"name": "TimeStamp", "ts": 2220000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo14"}}}, + {"name": "TimeStamp", "ts": 2320000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"bar15"}}}, + {"name": "TimeStamp", "ts": 2380000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}}, + {"name": "TimeStamp", "ts": 2410000, "ph": "B", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo16"}}}, + {"name": "TimeStamp", "ts": 2420000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo17"}}}, + {"name": "TimeStamp", "ts": 2520000, "ph": "I", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {"data":{"message":"foo18"}}}, + {"name": "TimeStamp", "ts": 2580000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}}, + {"name": "Program", "ts": 2590000, "ph": "E", "tid": mainThread, "pid": pid, "cat":"disabled-by-default-devtools.timeline", "args": {}} + ]; + + + var model = InspectorTest.createTimelineModelWithEvents(testData); + var view = new WebInspector.EventsTimelineTreeView(model, WebInspector.panels.timeline._filters, null); + view.updateContents(WebInspector.TimelineSelection.fromRange(model.minimumRecordTime(), model.maximumRecordTime())); + var filtersControl = view._filtersControl; + function printEventMessage(event, level) + { + InspectorTest.addResult(" ".repeat(level) + event.args["data"].message); + } + + function dumpRecords() + { + InspectorTest.walkTimelineEventTreeUnderNode(printEventMessage, view._currentTree); + InspectorTest.addResult(""); + } + + InspectorTest.addResult("Initial:"); + dumpRecords(); + + InspectorTest.addResult("Filtered by 'bar':"); + var textFilterUI = filtersControl._textFilterUI; + textFilterUI.setValue("bar"); + dumpRecords(); + + InspectorTest.addResult("Filtered by 'foo':"); + textFilterUI.setValue("foo"); + dumpRecords(); + + InspectorTest.completeTest(); +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Test filtering in Timeline Tree View panel.</a> +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-flame-chart-automatically-size-window-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-flame-chart-automatically-size-window-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-flame-chart-automatically-size-window-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-flame-chart-automatically-size-window-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-flame-chart-automatically-size-window.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-flame-chart-automatically-size-window.html new file mode 100644 index 0000000..ae7bb8ff --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-flame-chart-automatically-size-window.html
@@ -0,0 +1,36 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/console-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script src="../resources/timeline-data.js"></script> +<script> + +function test() +{ + var timeline = WebInspector.panels.timeline; + timeline._onModeChanged(); + timeline._currentViews[0]._automaticallySizeWindow = true; + + function requestWindowTimesHook(startTime, endTime) + { + if (startTime) + InspectorTest.addResult("time delta: " + (endTime - startTime)); + } + + timeline.requestWindowTimes = requestWindowTimesHook; + InspectorTest.loadTimeline(InspectorTest.timelineData()); + + InspectorTest.completeTest(); +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the TimelineFlameChart automatically sized window. +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-grouped-invalidations-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-grouped-invalidations-expected.txt new file mode 100644 index 0000000..2b3be27 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-grouped-invalidations-expected.txt
@@ -0,0 +1,99 @@ +Tests grouped invalidations on the timeline. + +P +A +S +S +paint invalidations[ + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-misc/timeline-grouped-invalidations.html:12} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV class='testElement'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-misc/timeline-grouped-invalidations.html:13} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV class='testElement'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-misc/timeline-grouped-invalidations.html:12} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV class='testElement'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-misc/timeline-grouped-invalidations.html:13} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV class='testElement'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-misc/timeline-grouped-invalidations.html:12} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV class='testElement'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-misc/timeline-grouped-invalidations.html:13} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV class='testElement'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-misc/timeline-grouped-invalidations.html:12} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV class='testElement'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-misc/timeline-grouped-invalidations.html:13} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV class='testElement'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } +] +PASS - record contained Inline CSS style declaration was mutated for [ DIV class='testElement' ], [ DIV class='testElement' ], and 2 others. (anonymous function) @ timeline-grouped-invalidations.html:12 +PASS - record contained Inline CSS style declaration was mutated for [ DIV class='testElement' ], [ DIV class='testElement' ], and 2 others. (anonymous function) @ timeline-grouped-invalidations.html:13 +
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-grouped-invalidations.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-grouped-invalidations.html new file mode 100644 index 0000000..10bcbfc --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-grouped-invalidations.html
@@ -0,0 +1,55 @@ +<!DOCTYPE HTML> +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function display(callback) +{ + requestAnimationFrame(function() { + var testElements = document.body.getElementsByClassName("testElement"); + for (var i = 0; i < testElements.length; i++) { + testElements[i].style.color = "red"; + testElements[i].style.backgroundColor = "blue"; + } + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function test() +{ + var currentPanel = WebInspector.inspectorView.currentPanel(); + InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); + Runtime.experiments.enableForTest("timelineInvalidationTracking"); + + InspectorTest.invokeAsyncWithTimeline("display", function() { + var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); + InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "paint invalidations"); + + var linkifier = new WebInspector.Linkifier(); + var target = InspectorTest.timelineModel().target(); + var contentHelper = new WebInspector.TimelineDetailsContentHelper(target, linkifier, true); + WebInspector.TimelineUIUtils._generateCauses(record.traceEvent(), target, null, contentHelper); + var invalidationsTree = contentHelper.element.getElementsByClassName("invalidations-tree")[0]; + var invalidations = invalidationsTree.shadowRoot.textContent; + checkStringContains(invalidations, "Inline CSS style declaration was mutated for [ DIV class='testElement' ], [ DIV class='testElement' ], and 2 others. (anonymous function) @ timeline-grouped-invalidations.html:12"); + checkStringContains(invalidations, "Inline CSS style declaration was mutated for [ DIV class='testElement' ], [ DIV class='testElement' ], and 2 others. (anonymous function) @ timeline-grouped-invalidations.html:13"); + InspectorTest.completeTest(); + }); + + function checkStringContains(string, contains) + { + var doesContain = string.indexOf(contains) >= 0; + InspectorTest.check(doesContain, contains + " should be present in " + string); + InspectorTest.addResult("PASS - record contained " + contains); + } +} +</script> +</head> +<body onload="runTest()"> +<p>Tests grouped invalidations on the timeline.</p> +<div class="testElement">P</div><div class="testElement">A</div> +<div class="testElement">S</div><div class="testElement">S</div> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-load-event-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-load-event-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-load-event-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-load-event-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-load-event.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-load-event.html new file mode 100644 index 0000000..f059bb51 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-load-event.html
@@ -0,0 +1,59 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function display(callback) +{ + if (window.testRunner) + testRunner.setCanOpenWindows(true); + var popup = window.open("data:text/html,<b>Hello, world</b>"); + popup.onload = function() + { + requestAnimationFrame(testRunner.capturePixelsAsyncThen.bind(testRunner, callback)); + } +} + +function test() +{ + WebInspector.panels.timeline._captureJSProfileSetting.set(false); + InspectorTest.startTimeline(function() { InspectorTest.reloadPage(pageReloaded); }); + + function pageReloaded() + { + InspectorTest.invokePageFunctionAsync("display", displayDone); + } + + function displayDone() + { + InspectorTest.stopTimeline(InspectorTest.safeWrap(finish)) + } + + function finish() + { + InspectorTest.addResult("Model records:"); + InspectorTest.printTimelineRecords("MarkDOMContent"); + InspectorTest.printTimelineRecords("MarkLoad"); + InspectorTest.addResult("Timestamp records:"); + InspectorTest.printTimestampRecords("MarkDOMContent"); + InspectorTest.printTimestampRecords("MarkLoad"); + InspectorTest.printTimestampRecords("MarkFirstPaint"); + + var eventDividers = InspectorTest.timelineModel().eventDividerRecords(); + for (var i = 1; i < eventDividers.length; ++i) + InspectorTest.assertGreaterOrEqual(eventDividers[i], eventDividers[i - 1], "Event divider timestamps should be monotonically non-decreasing"); + + InspectorTest.completeTest(); + } +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the load event. +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-mark-timeline-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-mark-timeline-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-mark-timeline-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-mark-timeline-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-mark-timeline.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-mark-timeline.html new file mode 100644 index 0000000..2202c32 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-mark-timeline.html
@@ -0,0 +1,26 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function performActions() +{ + console.markTimeline("MARK TIMELINE"); +} + +function test() +{ + InspectorTest.performActionsAndPrint("performActions()", "TimeStamp"); +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline API mark feature +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-model-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-model-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-model-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-model-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-model.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-model.html new file mode 100644 index 0000000..3973c64 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-model.html
@@ -0,0 +1,73 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function test() +{ + var sessionId = "4.20"; + var mainThread = 1; + var pid = 100; + + var commonMetadata = [ + { + "args": { "sessionId": sessionId }, + "cat": "disabled-by-default-devtools.timeline", + "name": "TracingStartedInPage", + "ph": "I", + "pid": pid, + "tid": mainThread, + "ts": 100, + }, + { + "args": { "layerTreeId": 17, "sessionId": sessionId }, + "cat": "disabled-by-default-devtools.timeline", + "name": "SetLayerTreeId", + "ph": "I", + "pid": pid, + "tid": mainThread, + "ts": 101, + } + ]; + + var traceEvents = [ + {"name": "Program", "ts": 1000000, "dur": 9999, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline" }, + {"name": "FunctionCall", "ts": 1000001, "dur": 9998, "ph": "X", args: {"data":{}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline" }, + {"name": "ResourceSendRequest", "ts": 1000002, "ph": "I", args: {"data":{"requestId": 1, "url": "http://example.com", "requestMethod": "GET"}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline" }, + {"name": "RecalculateStyles", "ts": 1001003, "dur": 997, "ph": "X", args: {data: {}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, + {"name": "Layout", "ts": 1002001, "ph": "B", args: {beginData: {}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, + {"name": "Layout", "ts": 1003000, "ph": "E", args: {endData: {}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, + + {"name": "Program", "ts": 2000000, "ph": "B", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline" }, + {"name": "FunctionCall", "ts": 2000001, "ph": "B", args: {"data":{}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline" }, + {"name": "ResourceSendRequest", "ts": 2000002, "ph": "I", args: {"data":{"requestId": 1, "url": "http://example.com", "requestMethod": "GET"}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline" }, + {"name": "RecalculateStyles", "ts": 2001003, "ph": "B", args: {beginData: {}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, + {"name": "RecalculateStyles", "ts": 2002000, "ph": "E", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, + {"name": "Layout", "ts": 2002101, "ph": "B", args: {beginData: {}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, + {"name": "Layout", "ts": 2003001, "ph": "E", args: {endData: {}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, + {"name": "ParseHTML", "ts": 2004000, "ph": "B", args: {"beginData": {"url": "http://example.com", "startLine": 777}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, + {"name": "ParseHTML", "ts": 2004100, "ph": "E", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, + {"name": "FunctionCall", "ts": 2009999, "ph": "E", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline" }, + {"name": "Program", "ts": 2009999, "ph": "E", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"} + ]; + + var tracingTimelineModel = InspectorTest.createTimelineModelWithEvents(commonMetadata.concat(traceEvents)); + var records = tracingTimelineModel.records(); + var topLevelRecordsCount = 2; + InspectorTest.assertEquals(topLevelRecordsCount, records.length); + for (var i = 0; i < records.length; ++i) { + InspectorTest.dumpTimelineModelRecord(records[i]); + } + InspectorTest.completeTest(); +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Test trace-specific implementation of timeline model +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-node-reference-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-node-reference-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-node-reference-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-node-reference-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-node-reference.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-node-reference.html new file mode 100644 index 0000000..844e3c35 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-node-reference.html
@@ -0,0 +1,78 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/elements-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<style> +.relayout-boundary { + overflow: hidden; + width: 100px; + height: 100px; +} +</style> +<script> + +function performActions() +{ + var element = document.getElementById("invalidate1"); + element.style.marginTop = "10px"; + var unused = element.offsetHeight; +} + +function test() +{ + InspectorTest.evaluateInPage("var unused = document.body.offsetWidth;", function() { + InspectorTest.evaluateWithTimeline("performActions()", onTimelineRecorded); + }); + + function clickValueLink(record, row) + { + var panel = WebInspector.panels.timeline; + WebInspector.TimelineUIUtils.buildTraceEventDetails(record.traceEvent(), panel._model, new WebInspector.Linkifier(), true, onDetailsContentReady); + + function onDetailsContentReady(element) + { + var rows = element.querySelectorAll(".timeline-details-view-row"); + for (var i = 0; i < rows.length; ++i) { + if (rows[i].firstChild.textContent.indexOf(row) !== -1) { + rows[i].lastChild.firstChild.shadowRoot.lastChild.click(); + return; + } + } + } + } + + function onTimelineRecorded(records) + { + var layoutRecord = InspectorTest.findFirstTimelineRecord("Layout"); + WebInspector.notifications.addEventListener(WebInspector.NotificationService.Events.SelectedNodeChanged, onSelectedNodeChanged); + clickValueLink(layoutRecord, "Layout root"); + } + + function onSelectedNodeChanged() + { + var node = WebInspector.panels.elements.selectedDOMNode(); + // We may first get an old selected node while switching to the Elements panel. + if (node.nodeName() === "BODY") + return; + WebInspector.notifications.removeEventListener(WebInspector.NotificationService.Events.SelectedNodeChanged, onSelectedNodeChanged); + InspectorTest.addResult("Layout root node id: " + node.getAttribute("id")); + InspectorTest.completeTest(); + } +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline API instrumentation of a Layout event +</p> +<div id="boundary" class="relayout-boundary"> + <div> + <div id="invalidate1"><div>text</div></div> + </div> +</div> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-parse-html-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-parse-html-expected.txt new file mode 100644 index 0000000..5270887 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-parse-html-expected.txt
@@ -0,0 +1,44 @@ +Tests the Timeline API instrumentation of ParseHTML + +Test data +ParseHTML Properties: +{ + data : { + beginData : { + frame : <string> + stackTrace : <object> + startLine : 0 + url : .../inspector/tracing/timeline-misc/timeline-parse-html.html + } + endData : { + endLine : -1 + } + } + endTime : <number> + frameId : <string> + stackTrace : <object> + startTime : <number> + type : "ParseHTML" +} +Text details for ParseHTML: timeline-parse-html.html [1…] +ParseHTML Properties: +{ + data : { + beginData : { + frame : <string> + stackTrace : <object> + startLine : 0 + url : .../inspector/tracing/timeline-misc/timeline-parse-html.html + } + endData : { + endLine : -1 + } + } + endTime : <number> + frameId : <string> + stackTrace : <object> + startTime : <number> + type : "ParseHTML" +} +Text details for ParseHTML: timeline-parse-html.html [1…] +
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-parse-html.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-parse-html.html new file mode 100644 index 0000000..ea73002f --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-parse-html.html
@@ -0,0 +1,31 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function performActions() +{ + var element = document.createElement("div"); + element.innerHTML = "Test data"; + document.body.appendChild(element); +} + +function test() +{ + InspectorTest.performActionsAndPrint("performActions()", "ParseHTML"); +} + +if (!window.testRunner) + setTimeout(performActions, 2000); + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline API instrumentation of ParseHTML +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-receive-response-event-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-receive-response-event-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-receive-response-event-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-receive-response-event-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-receive-response-event.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-receive-response-event.html new file mode 100644 index 0000000..0b7ede9b --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-receive-response-event.html
@@ -0,0 +1,61 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function performActions(callback) +{ + var image = new Image(); + image.onload = bar; + image.src = "../resources/anImage.png"; + + function bar() + { + var image = new Image(); + image.onload = function(event) { callback(); } // do not pass event argument to the callback. + image.src = "../resources/anotherImage.png"; + } +} + +function test() +{ + WebInspector.TimelinePanel.show(); + WebInspector.panels.timeline._model._currentTarget = WebInspector.targetManager.mainTarget(); + WebInspector.panels.timeline._captureJSProfileSetting.set(false); + InspectorTest.invokeAsyncWithTimeline("performActions", finish); + + function finish() + { + var recordTypes = WebInspector.TimelineModel.RecordType; + var typesToDump = new Set([recordTypes.ResourceSendRequest, recordTypes.ResourceReceiveResponse, recordTypes.ResourceReceivedData, recordTypes.ResourceFinish, + recordTypes.EventDispatch, recordTypes.FunctionCall]); + function dumpEvent(traceEvent, level) + { + // Ignore stray paint & rendering events for better stability. + var categoryName = WebInspector.TimelineUIUtils.eventStyle(traceEvent).category.name; + if (categoryName !== "loading" && categoryName !== "scripting") + return; + // Here and below: pretend coalesced record are just not there, as coalescation is time dependent and, hence, not stable. + // Filter out InjectedScript function call because they happen out of sync. + if (typesToDump.has(traceEvent.name) && (traceEvent.name !== "FunctionCall" || traceEvent.args["data"].scriptName)) + InspectorTest.addResult(" ".repeat(level - 1) + traceEvent.name); + } + InspectorTest.walkTimelineEventTree(dumpEvent); + InspectorTest.completeTest(); + } +} + +if (!window.testRunner) + setTimeout(performActions, 3000); + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline API instrumentation of a SendRequest, ReceiveResponse etc. +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-sampling-codemap-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-sampling-codemap-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-sampling-codemap-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-sampling-codemap-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-sampling-codemap.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-sampling-codemap.html new file mode 100644 index 0000000..5f0b8ac --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-sampling-codemap.html
@@ -0,0 +1,64 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../tracing-test.js"></script> +<script> +function test() +{ + var codemap = new WebInspector.TimelineJSProfileProcessor.CodeMap(); + for (var i = 0; i < 10; i++) { + var address = i * 0x100 + 0x77000; + codemap.addEntry("0x" + address.toString(16), 0x80, "frame" + i); + } + + codemap.addEntry( "0x77010", 0x10, "frame1killer"); + codemap.addEntry( "0x77090", 0x200, "frames234killer"); + codemap.moveEntry("0x77090", "0x55000", 0x300); + codemap.moveEntry("0x77500", "0xfffffffffffff000", 0x80); + codemap.moveEntry("0x77600", "0x77700", 0x80); + + // fedcba9876543210 + // bank -> BBBAAAAAAAAAAAAA <- address + codemap.addEntry("0xffffffffffffff00", 2, "frameA"); + codemap.addEntry("0xffffffffffffff02", 2, "frameB"); + codemap.addEntry("0xffffffffffffff04", 2, "frameC"); + codemap.addEntry("0xffffffffffffff06", 2, "frameD"); + codemap.addEntry("0xffffffffffffff01", 5, "frameE"); + + InspectorTest.addResult("Lookup test:"); + var addresses = [ + "0x0", + "0x7700f", + "0x77010", + "0x77011", + "0x7701f", + "0x77020", + "0x77800", + "0x55007", + "0x88000", + "0xffffffffffffff00", + "0xffffffffffffff01", + "0xffffffffffffff02", + "0xffffffffffffff07", + "0xffffffffffffff08", + ]; + for (var i = 0; i < addresses.length; ++i) + InspectorTest.addResult(" " + addresses[i] + " -> " + codemap.lookupEntry(addresses[i])); + + InspectorTest.addResult(""); + for (var bankName of codemap._banks.keysArray()) { + InspectorTest.addResult("Bank \"" + bankName + "\":"); + var bank = codemap._banks.get(bankName); + for (var i = 0; i < bank._entries.length; ++i) { + var entry = bank._entries[i]; + InspectorTest.addResult(" 0x" + entry.address.toString(16) + " / " + entry.size + " : " + entry.callFrame); + } + } + InspectorTest.completeTest(); +} + +</script> +</head> +<body onload="runTest()"> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-trivial-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-trivial-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-trivial-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-trivial-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-trivial.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-trivial.html new file mode 100644 index 0000000..de2b482 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-trivial.html
@@ -0,0 +1,27 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function test() { + /* This test seems silly, but originally it tickled bug 31080 */ + function callback() + { + InspectorTest.addResult("Timeline started"); + InspectorTest.completeTest(); + } + InspectorTest.startTimeline(callback); +} + + +</script> +</head> + +<body onload="runTest()"> +<p> +Trivial use of inspector frontend tests +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-window-filter-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-window-filter-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-window-filter-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-window-filter-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-window-filter.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-window-filter.html new file mode 100644 index 0000000..67b0780 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-misc/timeline-window-filter.html
@@ -0,0 +1,66 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script src="../resources/timeline-data.js"></script> +<script> + +function test() +{ + var timeline = WebInspector.panels.timeline; + var overviewPane = timeline._overviewPane; + + InspectorTest.loadTimeline(InspectorTest.timelineData()); + + timeline._currentViews[0].refreshRecords(); + + overviewPane._update(); + InspectorTest.addResult("OverviewPane:"); + overviewPane._overviewCalculator.setDisplayWindow(450); + dumpDividers(overviewPane._overviewCalculator); + InspectorTest.addResult(""); + + function dumpFlameChartRecordsCountForRange(windowLeft, windowRight) + { + var mainView = timeline._currentViews[0]._mainView; + mainView._muteAnimation = true; + overviewPane._overviewGrid.setWindow(windowLeft, windowRight); + mainView.update(); + InspectorTest.addResult("range = " + windowLeft + " - " + windowRight); + InspectorTest.addResult("time range = " + mainView._timeWindowLeft + " - " + mainView._timeWindowRight); + InspectorTest.addResult(""); + } + + function dumpDividers(calculator) + { + var dividers = WebInspector.TimelineGrid.calculateDividerOffsets(calculator).offsets; + for (var i = 0; i < dividers.length; ++i) + dividers[i] -= calculator.zeroTime(); + InspectorTest.addResult("divider offsets: [" + dividers.join(", ") + "]. We are expecting round numbers."); + } + + dumpFlameChartRecordsCountForRange(0, 1); + dumpFlameChartRecordsCountForRange(0.25, 0.75); + dumpFlameChartRecordsCountForRange(0.33, 0.66); + + overviewPane._overviewGrid.setWindow(0.1, 0.9); + + InspectorTest.addResult("--------------------------------------------------------"); + InspectorTest.addResult("time range = " + timeline._windowStartTime + " - " + timeline._windowEndTime); + InspectorTest.completeTest(); +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline window filter. +</p> + +<p> +It applies different ranges to the OverviewGrid and expects that current view reflects the change. +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-model.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-model.html deleted file mode 100644 index 1824a5f..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-model.html +++ /dev/null
@@ -1,73 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function test() -{ - var sessionId = "4.20"; - var mainThread = 1; - var pid = 100; - - var commonMetadata = [ - { - "args": { "sessionId": sessionId }, - "cat": "disabled-by-default-devtools.timeline", - "name": "TracingStartedInPage", - "ph": "I", - "pid": pid, - "tid": mainThread, - "ts": 100, - }, - { - "args": { "layerTreeId": 17, "sessionId": sessionId }, - "cat": "disabled-by-default-devtools.timeline", - "name": "SetLayerTreeId", - "ph": "I", - "pid": pid, - "tid": mainThread, - "ts": 101, - } - ]; - - var traceEvents = [ - {"name": "Program", "ts": 1000000, "dur": 9999, "ph": "X", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline" }, - {"name": "FunctionCall", "ts": 1000001, "dur": 9998, "ph": "X", args: {"data":{}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline" }, - {"name": "ResourceSendRequest", "ts": 1000002, "ph": "I", args: {"data":{"requestId": 1, "url": "http://example.com", "requestMethod": "GET"}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline" }, - {"name": "RecalculateStyles", "ts": 1001003, "dur": 997, "ph": "X", args: {data: {}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, - {"name": "Layout", "ts": 1002001, "ph": "B", args: {beginData: {}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, - {"name": "Layout", "ts": 1003000, "ph": "E", args: {endData: {}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, - - {"name": "Program", "ts": 2000000, "ph": "B", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline" }, - {"name": "FunctionCall", "ts": 2000001, "ph": "B", args: {"data":{}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline" }, - {"name": "ResourceSendRequest", "ts": 2000002, "ph": "I", args: {"data":{"requestId": 1, "url": "http://example.com", "requestMethod": "GET"}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline" }, - {"name": "RecalculateStyles", "ts": 2001003, "ph": "B", args: {beginData: {}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, - {"name": "RecalculateStyles", "ts": 2002000, "ph": "E", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, - {"name": "Layout", "ts": 2002101, "ph": "B", args: {beginData: {}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, - {"name": "Layout", "ts": 2003001, "ph": "E", args: {endData: {}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, - {"name": "ParseHTML", "ts": 2004000, "ph": "B", args: {"beginData": {"url": "http://example.com", "startLine": 777}}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, - {"name": "ParseHTML", "ts": 2004100, "ph": "E", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"}, - {"name": "FunctionCall", "ts": 2009999, "ph": "E", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline" }, - {"name": "Program", "ts": 2009999, "ph": "E", args: {}, "tid": mainThread, "pid": 100, "cat":"disabled-by-default.devtools.timeline"} - ]; - - var tracingTimelineModel = InspectorTest.createTimelineModelWithEvents(commonMetadata.concat(traceEvents)); - var records = tracingTimelineModel.records(); - var topLevelRecordsCount = 2; - InspectorTest.assertEquals(topLevelRecordsCount, records.length); - for (var i = 0; i < records.length; ++i) { - InspectorTest.dumpTimelineModelRecord(records[i]); - } - InspectorTest.completeTest(); -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Test trace-specific implementation of timeline model -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-received-data.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-received-data.html deleted file mode 100644 index a7372e6..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-received-data.html +++ /dev/null
@@ -1,58 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function performActions(callback) -{ - function onImageLoad() - { - window._imageLoaded = true; - if (window._scriptEvaluated) - callback(); - } - - function scriptEvaluated() - { - window._scriptEvaluated = true; - if (window._imageLoaded) - callback(); - } - - var image = new Image(); - image.onload = onImageLoad; - image.src = "resources/anImage.png"; - var script = document.createElement("script"); - script.src = "timeline-network-resource.js"; - document.body.appendChild(script); - - window.timelineNetworkResourceEvaluated = scriptEvaluated; -} - -function test() -{ - InspectorTest.invokeAsyncWithTimeline("performActions", done); - - function done() - { - InspectorTest.addResult("Script evaluated."); - var record = InspectorTest.findFirstTimelineRecord("ResourceReceivedData"); - if (record) { - var data = record.traceEvent().args["data"]; - if (data && typeof data.encodedDataLength === "number") - InspectorTest.addResult("Resource received data has length, test passed."); - } - InspectorTest.completeTest(); - } -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline API instrumentation of a network resource received data -</p> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource-details.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource-details.html deleted file mode 100644 index d39c6ac6..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource-details.html +++ /dev/null
@@ -1,64 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function performActions(callback) -{ - function onRequestFinished() - { - if (!--requestsPending) - callback(); - } - - var requestsPending = 2; - var image = new Image(); - image.onload = onRequestFinished; - image.src = "resources/anImage.png"; - - var script = document.createElement("script"); - script.src = "timeline-network-resource.js"; - document.body.appendChild(script); - window.timelineNetworkResourceEvaluated = onRequestFinished; -} - -function test() -{ - var model = WebInspector.panels.timeline._model; - - InspectorTest.invokeAsyncWithTimeline("performActions", finish); - - function finish() - { - var linkifier = new WebInspector.Linkifier(); - function printRequestDetails(request) - { - return WebInspector.TimelineUIUtils.buildNetworkRequestDetails(request, model, linkifier).then(printElement); - } - function printElement(element) - { - var rows = element.querySelectorAll(".timeline-details-view-row"); - for (var i = 0; i < rows.length; ++i) { - var title = rows[i].firstChild.firstChild.textContent; - var value = rows[i].lastChild.firstChild.textContent; - if (title === "Duration" || title === "Mime Type") - value = typeof value; - if (/^file:\/\//.test(value)) - value = /[^/]*$/.exec(value)[0]; - InspectorTest.addResult(title + ": " + value); - } - } - Promise.all(model.networkRequests().map(printRequestDetails)).then(InspectorTest.completeTest); - } -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline UI API for network requests. -</p> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource-expected.txt deleted file mode 100644 index aca4f68..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource-expected.txt +++ /dev/null
@@ -1,50 +0,0 @@ -Tests the Timeline API instrumentation of a network resource load - -Script resource loaded - -ResourceSendRequest Properties: -{ - data : { - frame : <string> - priority : "Low" - requestId : <string> - requestMethod : "GET" - stackTrace : <object> - url : .../inspector/tracing/timeline-network-resource.js - } - endTime : <number> - frameId : <string> - stackTrace : <object> - startTime : <number> - type : "ResourceSendRequest" -} -Text details for ResourceSendRequest: timeline-network-resource.js - -ResourceReceiveResponse Properties: -{ - data : { - frame : <string> - mimeType : <string> - requestId : <string> - statusCode : 0 - } - endTime : <number> - frameId : <string> - startTime : <number> - type : "ResourceReceiveResponse" -} -Text details for ResourceReceiveResponse: timeline-network-resource.js - -ResourceFinish Properties: -{ - data : { - didFail : false - networkTime : <number> - requestId : <string> - } - endTime : <number> - startTime : <number> - type : "ResourceFinish" -} -Text details for ResourceFinish: timeline-network-resource.js -
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource.html deleted file mode 100644 index c3011d8f..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource.html +++ /dev/null
@@ -1,89 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -var scriptUrl = "timeline-network-resource.js"; - -function performActions(callback) -{ - window.timelineNetworkResourceEvaluated = callback; - var script = document.createElement("script"); - script.src = scriptUrl; - document.body.appendChild(script); -} - -function test() -{ - var requestId; - var scriptUrl = "timeline-network-resource.js"; - - var model = WebInspector.panels.timeline._model; - - InspectorTest.invokeAsyncWithTimeline("performActions", finish); - - function finish() - { - var lastRecordStartTime; - function format(record) - { - if (record.type() === WebInspector.TimelineModel.RecordType.ResourceSendRequest) - printSend(record); - else if (record.type() === WebInspector.TimelineModel.RecordType.ResourceReceiveResponse) - printReceive(record); - else if (record.type() === WebInspector.TimelineModel.RecordType.ResourceFinish) - printFinish(record); - } - model.forAllRecords(format); - InspectorTest.completeTest(); - } - - function printRecord(record) - { - InspectorTest.addResult(""); - InspectorTest.printTimelineRecordProperties(record); - InspectorTest.addResult("Text details for " + record.type() + ": " + WebInspector.TimelineUIUtils.buildDetailsTextForTraceEvent(record.traceEvent())); - } - - function printSend(record) - { - printRecord(record); - var data = record.traceEvent().args["data"]; - requestId = data.requestId; - if (data.url === undefined) - InspectorTest.addResult("* No 'url' property in record"); - else if (data.url.indexOf(scriptUrl) === -1) - InspectorTest.addResult("* Didn't find URL: " + scriptUrl); - } - - function printReceive(record) - { - printRecord(record); - var data = record.traceEvent().args["data"]; - if (requestId !== data.requestId) - InspectorTest.addResult("Didn't find matching requestId: " + requestId); - if (data.statusCode !== 0) - InspectorTest.addResult("Response received status: " + data.statusCode); - } - - function printFinish(record) - { - printRecord(record); - var data = record.traceEvent().args["data"]; - if (requestId !== data.requestId) - InspectorTest.addResult("Didn't find matching requestId: " + requestId); - if (data.didFail) - InspectorTest.addResult("Request failed."); - } -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline API instrumentation of a network resource load -</p> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-received-data-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-received-data-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-received-data-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-received-data-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-received-data.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-received-data.html new file mode 100644 index 0000000..34954c0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-received-data.html
@@ -0,0 +1,58 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function performActions(callback) +{ + function onImageLoad() + { + window._imageLoaded = true; + if (window._scriptEvaluated) + callback(); + } + + function scriptEvaluated() + { + window._scriptEvaluated = true; + if (window._imageLoaded) + callback(); + } + + var image = new Image(); + image.onload = onImageLoad; + image.src = "../resources/anImage.png"; + var script = document.createElement("script"); + script.src = "timeline-network-resource.js"; + document.body.appendChild(script); + + window.timelineNetworkResourceEvaluated = scriptEvaluated; +} + +function test() +{ + InspectorTest.invokeAsyncWithTimeline("performActions", done); + + function done() + { + InspectorTest.addResult("Script evaluated."); + var record = InspectorTest.findFirstTimelineRecord("ResourceReceivedData"); + if (record) { + var data = record.traceEvent().args["data"]; + if (data && typeof data.encodedDataLength === "number") + InspectorTest.addResult("Resource received data has length, test passed."); + } + InspectorTest.completeTest(); + } +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline API instrumentation of a network resource received data +</p> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource-details-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource-details-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource-details-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource-details-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource-details.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource-details.html new file mode 100644 index 0000000..58da539f --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource-details.html
@@ -0,0 +1,64 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function performActions(callback) +{ + function onRequestFinished() + { + if (!--requestsPending) + callback(); + } + + var requestsPending = 2; + var image = new Image(); + image.onload = onRequestFinished; + image.src = "../resources/anImage.png"; + + var script = document.createElement("script"); + script.src = "timeline-network-resource.js"; + document.body.appendChild(script); + window.timelineNetworkResourceEvaluated = onRequestFinished; +} + +function test() +{ + var model = WebInspector.panels.timeline._model; + + InspectorTest.invokeAsyncWithTimeline("performActions", finish); + + function finish() + { + var linkifier = new WebInspector.Linkifier(); + function printRequestDetails(request) + { + return WebInspector.TimelineUIUtils.buildNetworkRequestDetails(request, model, linkifier).then(printElement); + } + function printElement(element) + { + var rows = element.querySelectorAll(".timeline-details-view-row"); + for (var i = 0; i < rows.length; ++i) { + var title = rows[i].firstChild.firstChild.textContent; + var value = rows[i].lastChild.firstChild.textContent; + if (title === "Duration" || title === "Mime Type") + value = typeof value; + if (/^file:\/\//.test(value)) + value = /[^/]*$/.exec(value)[0]; + InspectorTest.addResult(title + ": " + value); + } + } + Promise.all(model.networkRequests().map(printRequestDetails)).then(InspectorTest.completeTest); + } +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline UI API for network requests. +</p> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource-expected.txt new file mode 100644 index 0000000..286fa29c --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource-expected.txt
@@ -0,0 +1,50 @@ +Tests the Timeline API instrumentation of a network resource load + +Script resource loaded + +ResourceSendRequest Properties: +{ + data : { + frame : <string> + priority : "Low" + requestId : <string> + requestMethod : "GET" + stackTrace : <object> + url : .../inspector/tracing/timeline-network/timeline-network-resource.js + } + endTime : <number> + frameId : <string> + stackTrace : <object> + startTime : <number> + type : "ResourceSendRequest" +} +Text details for ResourceSendRequest: timeline-network-resource.js + +ResourceReceiveResponse Properties: +{ + data : { + frame : <string> + mimeType : <string> + requestId : <string> + statusCode : 0 + } + endTime : <number> + frameId : <string> + startTime : <number> + type : "ResourceReceiveResponse" +} +Text details for ResourceReceiveResponse: timeline-network-resource.js + +ResourceFinish Properties: +{ + data : { + didFail : false + networkTime : <number> + requestId : <string> + } + endTime : <number> + startTime : <number> + type : "ResourceFinish" +} +Text details for ResourceFinish: timeline-network-resource.js +
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource.html new file mode 100644 index 0000000..e5de92e0b --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource.html
@@ -0,0 +1,89 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +var scriptUrl = "timeline-network-resource.js"; + +function performActions(callback) +{ + window.timelineNetworkResourceEvaluated = callback; + var script = document.createElement("script"); + script.src = scriptUrl; + document.body.appendChild(script); +} + +function test() +{ + var requestId; + var scriptUrl = "timeline-network-resource.js"; + + var model = WebInspector.panels.timeline._model; + + InspectorTest.invokeAsyncWithTimeline("performActions", finish); + + function finish() + { + var lastRecordStartTime; + function format(record) + { + if (record.type() === WebInspector.TimelineModel.RecordType.ResourceSendRequest) + printSend(record); + else if (record.type() === WebInspector.TimelineModel.RecordType.ResourceReceiveResponse) + printReceive(record); + else if (record.type() === WebInspector.TimelineModel.RecordType.ResourceFinish) + printFinish(record); + } + model.forAllRecords(format); + InspectorTest.completeTest(); + } + + function printRecord(record) + { + InspectorTest.addResult(""); + InspectorTest.printTimelineRecordProperties(record); + InspectorTest.addResult("Text details for " + record.type() + ": " + WebInspector.TimelineUIUtils.buildDetailsTextForTraceEvent(record.traceEvent())); + } + + function printSend(record) + { + printRecord(record); + var data = record.traceEvent().args["data"]; + requestId = data.requestId; + if (data.url === undefined) + InspectorTest.addResult("* No 'url' property in record"); + else if (data.url.indexOf(scriptUrl) === -1) + InspectorTest.addResult("* Didn't find URL: " + scriptUrl); + } + + function printReceive(record) + { + printRecord(record); + var data = record.traceEvent().args["data"]; + if (requestId !== data.requestId) + InspectorTest.addResult("Didn't find matching requestId: " + requestId); + if (data.statusCode !== 0) + InspectorTest.addResult("Response received status: " + data.statusCode); + } + + function printFinish(record) + { + printRecord(record); + var data = record.traceEvent().args["data"]; + if (requestId !== data.requestId) + InspectorTest.addResult("Didn't find matching requestId: " + requestId); + if (data.didFail) + InspectorTest.addResult("Request failed."); + } +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline API instrumentation of a network resource load +</p> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource.js b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource.js similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-network-resource.js rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-network/timeline-network-resource.js
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-node-reference.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-node-reference.html deleted file mode 100644 index df48149..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-node-reference.html +++ /dev/null
@@ -1,78 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/elements-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<style> -.relayout-boundary { - overflow: hidden; - width: 100px; - height: 100px; -} -</style> -<script> - -function performActions() -{ - var element = document.getElementById("invalidate1"); - element.style.marginTop = "10px"; - var unused = element.offsetHeight; -} - -function test() -{ - InspectorTest.evaluateInPage("var unused = document.body.offsetWidth;", function() { - InspectorTest.evaluateWithTimeline("performActions()", onTimelineRecorded); - }); - - function clickValueLink(record, row) - { - var panel = WebInspector.panels.timeline; - WebInspector.TimelineUIUtils.buildTraceEventDetails(record.traceEvent(), panel._model, new WebInspector.Linkifier(), true, onDetailsContentReady); - - function onDetailsContentReady(element) - { - var rows = element.querySelectorAll(".timeline-details-view-row"); - for (var i = 0; i < rows.length; ++i) { - if (rows[i].firstChild.textContent.indexOf(row) !== -1) { - rows[i].lastChild.firstChild.shadowRoot.lastChild.click(); - return; - } - } - } - } - - function onTimelineRecorded(records) - { - var layoutRecord = InspectorTest.findFirstTimelineRecord("Layout"); - WebInspector.notifications.addEventListener(WebInspector.NotificationService.Events.SelectedNodeChanged, onSelectedNodeChanged); - clickValueLink(layoutRecord, "Layout root"); - } - - function onSelectedNodeChanged() - { - var node = WebInspector.panels.elements.selectedDOMNode(); - // We may first get an old selected node while switching to the Elements panel. - if (node.nodeName() === "BODY") - return; - WebInspector.notifications.removeEventListener(WebInspector.NotificationService.Events.SelectedNodeChanged, onSelectedNodeChanged); - InspectorTest.addResult("Layout root node id: " + node.getAttribute("id")); - InspectorTest.completeTest(); - } -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline API instrumentation of a Layout event -</p> -<div id="boundary" class="relayout-boundary"> - <div> - <div id="invalidate1"><div>text</div></div> - </div> -</div> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-and-multiple-style-invalidations-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-and-multiple-style-invalidations-expected.txt deleted file mode 100644 index 0a1c47e..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-and-multiple-style-invalidations-expected.txt +++ /dev/null
@@ -1,84 +0,0 @@ -Tests the Timeline API instrumentation of multiple style recalc invalidations and ensures they are all collected on the paint event. - -PASS -PASS -PASS -first style recalc[ - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-paint-and-multiple-style-invalidations.html:10} - changedAttribute : undefined - changedClass : "red" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='red'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } -] -second style recalc[ - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-paint-and-multiple-style-invalidations.html:12} - changedAttribute : undefined - changedClass : "snow" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='snow'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-paint-and-multiple-style-invalidations.html:12} - changedAttribute : undefined - changedClass : "red" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='snow'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } -] -first paint[ - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-paint-and-multiple-style-invalidations.html:10} - changedAttribute : undefined - changedClass : "red" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='red'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-paint-and-multiple-style-invalidations.html:12} - changedAttribute : undefined - changedClass : "snow" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='snow'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-paint-and-multiple-style-invalidations.html:12} - changedAttribute : undefined - changedClass : "red" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='snow'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } -] -
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-and-multiple-style-invalidations.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-and-multiple-style-invalidations.html deleted file mode 100644 index dbc8e5c..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-and-multiple-style-invalidations.html +++ /dev/null
@@ -1,61 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function multipleStyleRecalcsAndDisplay(callback) -{ - requestAnimationFrame(function() { - document.getElementById("testElementOne").className = "red"; - var forceStyleRecalc1 = document.body.offsetTop; - document.getElementById("testElementOne").className = "snow"; - var forceStyleRecalc2 = document.body.offsetTop; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - - -function test() -{ - var currentPanel = WebInspector.inspectorView.currentPanel(); - InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); - Runtime.experiments.enableForTest("timelineInvalidationTracking"); - InspectorTest.invokeAsyncWithTimeline("multipleStyleRecalcsAndDisplay", testMultipleStyleRecalcs); - - function testMultipleStyleRecalcs() - { - var firstRecalc = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 0); - InspectorTest.addArray(firstRecalc._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first style recalc"); - var secondRecalc = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 1); - InspectorTest.addArray(secondRecalc._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second style recalc"); - var firstPaint = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.Paint, 0); - InspectorTest.addArray(firstPaint._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first paint"); - - var thirdRecalc = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 2); - InspectorTest.assertTrue(thirdRecalc === undefined, "There should be no additional style recalc records."); - var secondPaint = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.Paint, 1); - InspectorTest.assertTrue(secondPaint === undefined, "There should be no additional paint records."); - InspectorTest.completeTest(); - } -} -</script> -<style> - .testHolder > .red { background-color: red; } - .testHolder > .green { background-color: green; } - .testHolder > .blue { background-color: blue; } - .testHolder > .snow { background-color: snow; } - .testHolder > .red .dummy { } - .testHolder > .green .dummy { } - .testHolder > .blue .dummy { } - .testHolder > .snow .dummy { } -</style> -</head> -<body onload="runTest()"> -<p>Tests the Timeline API instrumentation of multiple style recalc invalidations and ensures they are all collected on the paint event.</p> -<div class="testHolder"> -<div id="testElementOne">PASS</div><div id="testElementTwo">PASS</div><div id="testElementThree">PASS</div> -</div> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-layout-invalidations-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-layout-invalidations-expected.txt deleted file mode 100644 index 6d5493db..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-layout-invalidations-expected.txt +++ /dev/null
@@ -1,79 +0,0 @@ -Tests the Timeline API instrumentation of paint events with layout invalidations. - -PASS - - -Running: testLocalFrame -paint invalidations[ - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint-with-layout-invalidations.html:10} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "BODY" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint-with-layout-invalidations.html:11} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV id='testElement'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Style changed, stackTrace: .../inspector/tracing/timeline-paint-with-layout-invalidations.html:12} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElement'" - selectorPart : undefined - type : "LayoutInvalidationTracking" - } -] - -Running: testSubframe -second paint invalidations[ - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint-with-layout-invalidations.html:21} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Style changed, stackTrace: .../inspector/tracing/timeline-paint-with-layout-invalidations.html:22} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV" - selectorPart : undefined - type : "LayoutInvalidationTracking" - } - { - cause : {reason: Unknown, stackTrace: .../inspector/tracing/timeline-paint-with-layout-invalidations.html:22} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "#document" - selectorPart : undefined - type : "LayoutInvalidationTracking" - } -] -
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-layout-invalidations-on-deleted-node-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-layout-invalidations-on-deleted-node-expected.txt deleted file mode 100644 index bbbdd8a8..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-layout-invalidations-on-deleted-node-expected.txt +++ /dev/null
@@ -1,100 +0,0 @@ -Tests the Timeline API instrumentation of layout invalidations on a deleted node. - - - -Running: testLocalFrame -paint invalidations[ - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint-with-layout-invalidations-on-deleted-node.html:10} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "BODY" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint-with-layout-invalidations-on-deleted-node.html:12} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV id='testElement'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Style changed, stackTrace: .../inspector/tracing/timeline-paint-with-layout-invalidations-on-deleted-node.html:13} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElement'" - selectorPart : undefined - type : "LayoutInvalidationTracking" - } - { - cause : {reason: Removed from layout, stackTrace: .../inspector/tracing/timeline-paint-with-layout-invalidations-on-deleted-node.html:14} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "#text" - selectorPart : undefined - type : "LayoutInvalidationTracking" - } - { - cause : {reason: Removed from layout, stackTrace: .../inspector/tracing/timeline-paint-with-layout-invalidations-on-deleted-node.html:14} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElement'" - selectorPart : undefined - type : "LayoutInvalidationTracking" - } -] - -Running: testSubframe -second paint invalidations[ - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint-with-layout-invalidations-on-deleted-node.html:24} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Style changed, stackTrace: .../inspector/tracing/timeline-paint-with-layout-invalidations-on-deleted-node.html:25} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV" - selectorPart : undefined - type : "LayoutInvalidationTracking" - } - { - cause : {reason: Removed from layout, stackTrace: .../inspector/tracing/timeline-paint-with-layout-invalidations-on-deleted-node.html:26} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV" - selectorPart : undefined - type : "LayoutInvalidationTracking" - } -] -
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-layout-invalidations-on-deleted-node.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-layout-invalidations-on-deleted-node.html deleted file mode 100644 index 5ae71fa..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-layout-invalidations-on-deleted-node.html +++ /dev/null
@@ -1,73 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function display(callback) -{ - requestAnimationFrame(function() { - document.body.style.backgroundColor = "blue"; - var element = document.getElementById("testElement"); - element.style.width = "100px"; - var forceLayout = document.body.offsetTop; - element.parentElement.removeChild(element); - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function updateSubframeAndDisplay(callback) -{ - requestAnimationFrame(function() { - var element = frames[0].document.body.children[0]; - element.style.width = "200px"; - var forceLayout = frames[0].document.body.offsetTop; - element.parentElement.removeChild(element); - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function test() -{ - var currentPanel = WebInspector.inspectorView.currentPanel(); - InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); - Runtime.experiments.enableForTest("timelineInvalidationTracking"); - - InspectorTest.runTestSuite([ - function testLocalFrame(next) - { - InspectorTest.invokeAsyncWithTimeline("display", function() { - var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); - InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "paint invalidations"); - - next(); - }); - }, - - function testSubframe(next) - { - InspectorTest.invokeAsyncWithTimeline("updateSubframeAndDisplay", function() { - // The first paint corresponds to the local frame and should have no invalidations. - var firstPaintRecord = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); - var firstInvalidations = firstPaintRecord._event.invalidationTrackingEvents; - InspectorTest.assertEquals(firstInvalidations, undefined); - - // The second paint corresponds to the subframe and should have our layout/style invalidations. - var secondPaintRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.Paint, 1); - InspectorTest.addArray(secondPaintRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second paint invalidations"); - - next(); - }); - } - ]); -} -</script> -</head> -<body onload="runTest()"> -<p>Tests the Timeline API instrumentation of layout invalidations on a deleted node.</p> -<div id="testElement">FAIL - this should not be present when the test finishes.</div> -<iframe src="resources/timeline-iframe-paint.html" style="position: absolute; left: 40px; top: 40px; width: 100px; height: 100px; border: none"></iframe> -</body> -</html> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-layout-invalidations.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-layout-invalidations.html deleted file mode 100644 index 3cfe674..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-layout-invalidations.html +++ /dev/null
@@ -1,69 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function display(callback) -{ - requestAnimationFrame(function() { - document.body.style.backgroundColor = "blue"; - document.getElementById("testElement").style.width = "100px"; - var forceLayout = document.body.offsetTop; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function updateSubframeAndDisplay(callback) -{ - requestAnimationFrame(function() { - frames[0].document.body.children[0].style.width = "200px"; - var forceLayout = frames[0].document.body.offsetTop; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function test() -{ - var currentPanel = WebInspector.inspectorView.currentPanel(); - InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); - Runtime.experiments.enableForTest("timelineInvalidationTracking"); - - InspectorTest.runTestSuite([ - function testLocalFrame(next) - { - InspectorTest.invokeAsyncWithTimeline("display", function() { - var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); - InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "paint invalidations"); - - next(); - }); - }, - - function testSubframe(next) - { - InspectorTest.invokeAsyncWithTimeline("updateSubframeAndDisplay", function() { - // The first paint corresponds to the local frame and should have no invalidations. - var firstPaintRecord = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); - var firstInvalidations = firstPaintRecord._event.invalidationTrackingEvents; - InspectorTest.assertEquals(firstInvalidations, undefined); - - // The second paint corresponds to the subframe and should have our layout/style invalidations. - var secondPaintRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.Paint, 1); - InspectorTest.addArray(secondPaintRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second paint invalidations"); - - next(); - }); - } - ]); -} -</script> -</head> -<body onload="runTest()"> -<p>Tests the Timeline API instrumentation of paint events with layout invalidations.</p> -<div id="testElement">PASS</div> -<iframe src="resources/timeline-iframe-paint.html" style="position: absolute; left: 40px; top: 40px; width: 100px; height: 100px; border: none"></iframe> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-style-recalc-invalidations-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-style-recalc-invalidations-expected.txt deleted file mode 100644 index 956b5d3..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-style-recalc-invalidations-expected.txt +++ /dev/null
@@ -1,46 +0,0 @@ -Tests the Timeline API instrumentation of paint events with style recalc invalidations. - -PASS - - -Running: testLocalFrame -first paint invalidations[ - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint-with-style-recalc-invalidations.html:10} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "BODY" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint-with-style-recalc-invalidations.html:11} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV id='testElement'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } -] - -Running: testSubframe -second paint invalidations[ - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint-with-style-recalc-invalidations.html:20} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } -] -
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-style-recalc-invalidations.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-style-recalc-invalidations.html deleted file mode 100644 index 608a212..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-with-style-recalc-invalidations.html +++ /dev/null
@@ -1,67 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function display(callback) -{ - requestAnimationFrame(function() { - document.body.style.backgroundColor = "blue"; - document.getElementById("testElement").style.backgroundColor = "salmon"; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function updateSubframeAndDisplay(callback) -{ - requestAnimationFrame(function() { - frames[0].document.body.children[0].style.backgroundColor = "green"; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function test() -{ - var currentPanel = WebInspector.inspectorView.currentPanel(); - InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); - Runtime.experiments.enableForTest("timelineInvalidationTracking"); - - InspectorTest.runTestSuite([ - function testLocalFrame(next) - { - InspectorTest.invokeAsyncWithTimeline("display", function() { - var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); - InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first paint invalidations"); - - next(); - }); - }, - - function testSubframe(next) - { - InspectorTest.invokeAsyncWithTimeline("updateSubframeAndDisplay", function() { - // The first paint corresponds to the local frame and should have no invalidations. - var firstPaintRecord = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); - var firstInvalidations = firstPaintRecord._event.invalidationTrackingEvents; - InspectorTest.assertEquals(firstInvalidations, undefined); - - // The second paint corresponds to the subframe and should have our style invalidations. - var secondPaintRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.Paint, 1); - InspectorTest.addArray(secondPaintRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second paint invalidations"); - - next(); - }); - } - ]); -} -</script> -</head> -<body onload="runTest()"> -<p>Tests the Timeline API instrumentation of paint events with style recalc invalidations.</p> -<div id="testElement">PASS</div> -<iframe src="resources/timeline-iframe-paint.html" style="position: absolute; left: 40px; top: 40px; width: 100px; height: 100px; border: none"></iframe> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint.html deleted file mode 100644 index 0557b71..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint.html +++ /dev/null
@@ -1,70 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function display(callback) -{ - requestAnimationFrame(function() { - document.body.style.backgroundColor = "blue"; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function updateSubframeAndDisplay(callback) -{ - requestAnimationFrame(function() { - frames[0].document.body.children[0].style.backgroundColor = "green"; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function test() -{ - InspectorTest.invokeAsyncWithTimeline("display", step1); - - function step1(records) - { - var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); - if (record) - InspectorTest.printTimelineRecordProperties(record); - else - InspectorTest.addResult("FAIL: no paint record found"); - InspectorTest.invokeAsyncWithTimeline("updateSubframeAndDisplay", step3); - } - - function step3(records) - { - var paintRecord = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); - InspectorTest.assertTrue(paintRecord, "Paint record with subframe paint not found"); - var topQuad = paintRecord.traceEvent().args["data"].clip; - var subframePaint = paintRecord.children()[0]; - var subframeQuad = subframePaint.traceEvent().args["data"].clip; - InspectorTest.assertEquals(8, topQuad.length); - InspectorTest.assertEquals(8, subframeQuad.length); - InspectorTest.assertGreaterOrEqual(subframeQuad[0], topQuad[0]); - InspectorTest.assertGreaterOrEqual(subframeQuad[1], topQuad[1]); - InspectorTest.assertGreaterOrEqual(topQuad[2], subframeQuad[2]); - InspectorTest.assertGreaterOrEqual(subframeQuad[3], topQuad[3]); - InspectorTest.assertGreaterOrEqual(topQuad[4], subframeQuad[4]); - InspectorTest.assertGreaterOrEqual(topQuad[5], subframeQuad[5]); - InspectorTest.assertGreaterOrEqual(subframeQuad[6], topQuad[6]); - InspectorTest.assertGreaterOrEqual(topQuad[7], subframeQuad[7]); - - InspectorTest.completeTest(); - } -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline API instrumentation of a paint event -</p> -<iframe src="resources/timeline-iframe-paint.html" style="position: absolute; left: 40px; top: 40px; width: 100px; height: 100px; border: none"></iframe> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/layer-tree-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/layer-tree-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/layer-tree-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/layer-tree-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/layer-tree.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/layer-tree.html new file mode 100644 index 0000000..5a3715c3e --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/layer-tree.html
@@ -0,0 +1,55 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script src="../../../http/tests/inspector/layers-test.js"></script> +<script src="../../tracing-test.js"></script> + +<script> +function doActions(callback) +{ + var div = document.createElement("div"); + div.id = "b4"; + document.getElementById("a").appendChild(div); + + // Make sure to force commit, otherwise some owner nodes will be missing. + var style = document.createElement("style"); + style.textContent = ".layer { transform: translateZ(10px); opacity: 0.8; }"; + document.head.appendChild(style); + generateFrames(3, callback); +} + +function test() +{ + WebInspector.panels.timeline._captureLayersAndPicturesSetting.set(true); + + InspectorTest.invokeAsyncWithTimeline("doActions", step1); + function step1() + { + var frames = InspectorTest.timelineFrameModel().frames(); + var lastFrame = InspectorTest.timelineFrameModel().frames().peekLast(); + var deferredLayerTree = lastFrame.layerTree; + deferredLayerTree.resolve(InspectorTest.safeWrap(layerTreeResolved)); + } + + function layerTreeResolved(layerTree) + { + InspectorTest.layerTreeModel().setLayerTree(layerTree); + InspectorTest.dumpLayerTree(); + InspectorTest.completeTest(); + } +} +</script> + +<body onload="runTestAfterDisplay()"> +Tests that LayerTreeModel successfully imports layers from a trace. +</p> +<div id="a" style="width: 200px; height: 200px" class="layer"> + <div class="layer" id="b1" style="width: 150px; height: 100px"></div> + <div id="b2" class="layer" style="width: 140px; height: 110px"> + <div id="c" class="layer" style="width: 100px; height: 90px"></div> + </div> + <div id="b3" class="layer" style="width: 140px; height: 110px"></div> +</div> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/paint-profiler-update-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/paint-profiler-update-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/paint-profiler-update-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/paint-profiler-update-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/paint-profiler-update.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/paint-profiler-update.html new file mode 100644 index 0000000..b8b5d787 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/paint-profiler-update.html
@@ -0,0 +1,84 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function performActions(callback) +{ + var square = document.getElementById("square"); + step1(); + + function step1() + { + square.style.backgroundColor = "red"; + testRunner.layoutAndPaintAsyncThen(step2); + } + + function step2() + { + square.style.backgroundColor = "black"; + testRunner.layoutAndPaintAsyncThen(callback); + } +} + +function test() +{ + var panel = WebInspector.panels.timeline; + + panel._captureLayersAndPicturesSetting.set(true); + panel._onModeChanged(); + + InspectorTest.invokeAsyncWithTimeline("performActions", onRecordingDone); + var paintEvents = []; + function onRecordingDone() + { + var events = InspectorTest.timelineModel()._mainThreadEvents; + for (var event of events) { + if (event.name === WebInspector.TimelineModel.RecordType.Paint) { + paintEvents.push(event); + if (!event.picture) + InspectorTest.addResult("Event without picture at " + paintEvents.length); + } + } + + if (paintEvents.length < 2) + throw new Error("FAIL: Expect at least two paint events"); + + InspectorTest.addSniffer(panel, "_appendDetailsTabsForTraceEventAndShowDetails", onRecordDetailsReady, false); + panel.select(WebInspector.TimelineSelection.fromTraceEvent(paintEvents[0]), WebInspector.TimelinePanel.DetailsTab.PaintProfiler); + } + + function onRecordDetailsReady() + { + var updateCount = 0; + var paintProfilerView = panel._lazyPaintProfilerView._paintProfilerView; + InspectorTest.addSniffer(paintProfilerView, "_update", onPaintProfilerUpdate, true); + + function onPaintProfilerUpdate() + { + // No snapshot, not a real update yet -- wait for another update! + if (!paintProfilerView._snapshot) + return; + var logSize = paintProfilerView._log && paintProfilerView._log.length ? ">0" : "0"; + InspectorTest.addResult("Paint " + updateCount + " log size: " + logSize); + if (updateCount++) + InspectorTest.completeTest(); + else + panel.select(WebInspector.TimelineSelection.fromTraceEvent(paintEvents[1]), WebInspector.TimelinePanel.DetailsTab.PaintProfiler); + } + } + +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests that paint profiler is properly update when an event is selected in Flame Chart +</p> + +<div id="square" style="width: 40px; height: 40px"></div> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations-expected.txt new file mode 100644 index 0000000..dcc6f15 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations-expected.txt
@@ -0,0 +1,84 @@ +Tests the Timeline API instrumentation of multiple style recalc invalidations and ensures they are all collected on the paint event. + +PASS +PASS +PASS +first style recalc[ + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations.html:10} + changedAttribute : undefined + changedClass : "red" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='red'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } +] +second style recalc[ + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations.html:12} + changedAttribute : undefined + changedClass : "snow" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='snow'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations.html:12} + changedAttribute : undefined + changedClass : "red" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='snow'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } +] +first paint[ + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations.html:10} + changedAttribute : undefined + changedClass : "red" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='red'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations.html:12} + changedAttribute : undefined + changedClass : "snow" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='snow'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations.html:12} + changedAttribute : undefined + changedClass : "red" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='snow'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } +] +
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations.html new file mode 100644 index 0000000..0d9381c --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations.html
@@ -0,0 +1,61 @@ +<!DOCTYPE HTML> +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function multipleStyleRecalcsAndDisplay(callback) +{ + requestAnimationFrame(function() { + document.getElementById("testElementOne").className = "red"; + var forceStyleRecalc1 = document.body.offsetTop; + document.getElementById("testElementOne").className = "snow"; + var forceStyleRecalc2 = document.body.offsetTop; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + + +function test() +{ + var currentPanel = WebInspector.inspectorView.currentPanel(); + InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); + Runtime.experiments.enableForTest("timelineInvalidationTracking"); + InspectorTest.invokeAsyncWithTimeline("multipleStyleRecalcsAndDisplay", testMultipleStyleRecalcs); + + function testMultipleStyleRecalcs() + { + var firstRecalc = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 0); + InspectorTest.addArray(firstRecalc._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first style recalc"); + var secondRecalc = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 1); + InspectorTest.addArray(secondRecalc._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second style recalc"); + var firstPaint = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.Paint, 0); + InspectorTest.addArray(firstPaint._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first paint"); + + var thirdRecalc = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 2); + InspectorTest.assertTrue(thirdRecalc === undefined, "There should be no additional style recalc records."); + var secondPaint = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.Paint, 1); + InspectorTest.assertTrue(secondPaint === undefined, "There should be no additional paint records."); + InspectorTest.completeTest(); + } +} +</script> +<style> + .testHolder > .red { background-color: red; } + .testHolder > .green { background-color: green; } + .testHolder > .blue { background-color: blue; } + .testHolder > .snow { background-color: snow; } + .testHolder > .red .dummy { } + .testHolder > .green .dummy { } + .testHolder > .blue .dummy { } + .testHolder > .snow .dummy { } +</style> +</head> +<body onload="runTest()"> +<p>Tests the Timeline API instrumentation of multiple style recalc invalidations and ensures they are all collected on the paint event.</p> +<div class="testHolder"> +<div id="testElementOne">PASS</div><div id="testElementTwo">PASS</div><div id="testElementThree">PASS</div> +</div> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations-expected.txt new file mode 100644 index 0000000..aeab905 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations-expected.txt
@@ -0,0 +1,79 @@ +Tests the Timeline API instrumentation of paint events with layout invalidations. + +PASS + + +Running: testLocalFrame +paint invalidations[ + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations.html:10} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "BODY" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations.html:11} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV id='testElement'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Style changed, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations.html:12} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElement'" + selectorPart : undefined + type : "LayoutInvalidationTracking" + } +] + +Running: testSubframe +second paint invalidations[ + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations.html:21} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Style changed, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations.html:22} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV" + selectorPart : undefined + type : "LayoutInvalidationTracking" + } + { + cause : {reason: Unknown, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations.html:22} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "#document" + selectorPart : undefined + type : "LayoutInvalidationTracking" + } +] +
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node-expected.txt new file mode 100644 index 0000000..040d739 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node-expected.txt
@@ -0,0 +1,100 @@ +Tests the Timeline API instrumentation of layout invalidations on a deleted node. + + + +Running: testLocalFrame +paint invalidations[ + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.html:10} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "BODY" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.html:12} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV id='testElement'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Style changed, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.html:13} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElement'" + selectorPart : undefined + type : "LayoutInvalidationTracking" + } + { + cause : {reason: Removed from layout, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.html:14} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "#text" + selectorPart : undefined + type : "LayoutInvalidationTracking" + } + { + cause : {reason: Removed from layout, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.html:14} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElement'" + selectorPart : undefined + type : "LayoutInvalidationTracking" + } +] + +Running: testSubframe +second paint invalidations[ + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.html:24} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Style changed, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.html:25} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV" + selectorPart : undefined + type : "LayoutInvalidationTracking" + } + { + cause : {reason: Removed from layout, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.html:26} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV" + selectorPart : undefined + type : "LayoutInvalidationTracking" + } +] +
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.html new file mode 100644 index 0000000..33eadbf3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.html
@@ -0,0 +1,73 @@ +<!DOCTYPE HTML> +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function display(callback) +{ + requestAnimationFrame(function() { + document.body.style.backgroundColor = "blue"; + var element = document.getElementById("testElement"); + element.style.width = "100px"; + var forceLayout = document.body.offsetTop; + element.parentElement.removeChild(element); + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function updateSubframeAndDisplay(callback) +{ + requestAnimationFrame(function() { + var element = frames[0].document.body.children[0]; + element.style.width = "200px"; + var forceLayout = frames[0].document.body.offsetTop; + element.parentElement.removeChild(element); + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function test() +{ + var currentPanel = WebInspector.inspectorView.currentPanel(); + InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); + Runtime.experiments.enableForTest("timelineInvalidationTracking"); + + InspectorTest.runTestSuite([ + function testLocalFrame(next) + { + InspectorTest.invokeAsyncWithTimeline("display", function() { + var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); + InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "paint invalidations"); + + next(); + }); + }, + + function testSubframe(next) + { + InspectorTest.invokeAsyncWithTimeline("updateSubframeAndDisplay", function() { + // The first paint corresponds to the local frame and should have no invalidations. + var firstPaintRecord = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); + var firstInvalidations = firstPaintRecord._event.invalidationTrackingEvents; + InspectorTest.assertEquals(firstInvalidations, undefined); + + // The second paint corresponds to the subframe and should have our layout/style invalidations. + var secondPaintRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.Paint, 1); + InspectorTest.addArray(secondPaintRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second paint invalidations"); + + next(); + }); + } + ]); +} +</script> +</head> +<body onload="runTest()"> +<p>Tests the Timeline API instrumentation of layout invalidations on a deleted node.</p> +<div id="testElement">FAIL - this should not be present when the test finishes.</div> +<iframe src="../resources/timeline-iframe-paint.html" style="position: absolute; left: 40px; top: 40px; width: 100px; height: 100px; border: none"></iframe> +</body> +</html> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations.html new file mode 100644 index 0000000..32c5fb2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-layout-invalidations.html
@@ -0,0 +1,69 @@ +<!DOCTYPE HTML> +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function display(callback) +{ + requestAnimationFrame(function() { + document.body.style.backgroundColor = "blue"; + document.getElementById("testElement").style.width = "100px"; + var forceLayout = document.body.offsetTop; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function updateSubframeAndDisplay(callback) +{ + requestAnimationFrame(function() { + frames[0].document.body.children[0].style.width = "200px"; + var forceLayout = frames[0].document.body.offsetTop; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function test() +{ + var currentPanel = WebInspector.inspectorView.currentPanel(); + InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); + Runtime.experiments.enableForTest("timelineInvalidationTracking"); + + InspectorTest.runTestSuite([ + function testLocalFrame(next) + { + InspectorTest.invokeAsyncWithTimeline("display", function() { + var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); + InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "paint invalidations"); + + next(); + }); + }, + + function testSubframe(next) + { + InspectorTest.invokeAsyncWithTimeline("updateSubframeAndDisplay", function() { + // The first paint corresponds to the local frame and should have no invalidations. + var firstPaintRecord = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); + var firstInvalidations = firstPaintRecord._event.invalidationTrackingEvents; + InspectorTest.assertEquals(firstInvalidations, undefined); + + // The second paint corresponds to the subframe and should have our layout/style invalidations. + var secondPaintRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.Paint, 1); + InspectorTest.addArray(secondPaintRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second paint invalidations"); + + next(); + }); + } + ]); +} +</script> +</head> +<body onload="runTest()"> +<p>Tests the Timeline API instrumentation of paint events with layout invalidations.</p> +<div id="testElement">PASS</div> +<iframe src="../resources/timeline-iframe-paint.html" style="position: absolute; left: 40px; top: 40px; width: 100px; height: 100px; border: none"></iframe> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations-expected.txt new file mode 100644 index 0000000..ae8173b --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations-expected.txt
@@ -0,0 +1,46 @@ +Tests the Timeline API instrumentation of paint events with style recalc invalidations. + +PASS + + +Running: testLocalFrame +first paint invalidations[ + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations.html:10} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "BODY" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations.html:11} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV id='testElement'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } +] + +Running: testSubframe +second paint invalidations[ + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations.html:20} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } +] +
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations.html new file mode 100644 index 0000000..9cb6312 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations.html
@@ -0,0 +1,67 @@ +<!DOCTYPE HTML> +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function display(callback) +{ + requestAnimationFrame(function() { + document.body.style.backgroundColor = "blue"; + document.getElementById("testElement").style.backgroundColor = "salmon"; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function updateSubframeAndDisplay(callback) +{ + requestAnimationFrame(function() { + frames[0].document.body.children[0].style.backgroundColor = "green"; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function test() +{ + var currentPanel = WebInspector.inspectorView.currentPanel(); + InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); + Runtime.experiments.enableForTest("timelineInvalidationTracking"); + + InspectorTest.runTestSuite([ + function testLocalFrame(next) + { + InspectorTest.invokeAsyncWithTimeline("display", function() { + var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); + InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first paint invalidations"); + + next(); + }); + }, + + function testSubframe(next) + { + InspectorTest.invokeAsyncWithTimeline("updateSubframeAndDisplay", function() { + // The first paint corresponds to the local frame and should have no invalidations. + var firstPaintRecord = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); + var firstInvalidations = firstPaintRecord._event.invalidationTrackingEvents; + InspectorTest.assertEquals(firstInvalidations, undefined); + + // The second paint corresponds to the subframe and should have our style invalidations. + var secondPaintRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.Paint, 1); + InspectorTest.addArray(secondPaintRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second paint invalidations"); + + next(); + }); + } + ]); +} +</script> +</head> +<body onload="runTest()"> +<p>Tests the Timeline API instrumentation of paint events with style recalc invalidations.</p> +<div id="testElement">PASS</div> +<iframe src="../resources/timeline-iframe-paint.html" style="position: absolute; left: 40px; top: 40px; width: 100px; height: 100px; border: none"></iframe> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint.html new file mode 100644 index 0000000..a49206c --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/timeline-paint.html
@@ -0,0 +1,70 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function display(callback) +{ + requestAnimationFrame(function() { + document.body.style.backgroundColor = "blue"; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function updateSubframeAndDisplay(callback) +{ + requestAnimationFrame(function() { + frames[0].document.body.children[0].style.backgroundColor = "green"; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function test() +{ + InspectorTest.invokeAsyncWithTimeline("display", step1); + + function step1(records) + { + var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); + if (record) + InspectorTest.printTimelineRecordProperties(record); + else + InspectorTest.addResult("FAIL: no paint record found"); + InspectorTest.invokeAsyncWithTimeline("updateSubframeAndDisplay", step3); + } + + function step3(records) + { + var paintRecord = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.Paint); + InspectorTest.assertTrue(paintRecord, "Paint record with subframe paint not found"); + var topQuad = paintRecord.traceEvent().args["data"].clip; + var subframePaint = paintRecord.children()[0]; + var subframeQuad = subframePaint.traceEvent().args["data"].clip; + InspectorTest.assertEquals(8, topQuad.length); + InspectorTest.assertEquals(8, subframeQuad.length); + InspectorTest.assertGreaterOrEqual(subframeQuad[0], topQuad[0]); + InspectorTest.assertGreaterOrEqual(subframeQuad[1], topQuad[1]); + InspectorTest.assertGreaterOrEqual(topQuad[2], subframeQuad[2]); + InspectorTest.assertGreaterOrEqual(subframeQuad[3], topQuad[3]); + InspectorTest.assertGreaterOrEqual(topQuad[4], subframeQuad[4]); + InspectorTest.assertGreaterOrEqual(topQuad[5], subframeQuad[5]); + InspectorTest.assertGreaterOrEqual(subframeQuad[6], topQuad[6]); + InspectorTest.assertGreaterOrEqual(topQuad[7], subframeQuad[7]); + + InspectorTest.completeTest(); + } +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline API instrumentation of a paint event +</p> +<iframe src="../resources/timeline-iframe-paint.html" style="position: absolute; left: 40px; top: 40px; width: 100px; height: 100px; border: none"></iframe> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/update-layer-tree-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/update-layer-tree-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/update-layer-tree-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/update-layer-tree-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/update-layer-tree.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/update-layer-tree.html new file mode 100644 index 0000000..a62404e --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-paint/update-layer-tree.html
@@ -0,0 +1,52 @@ +<html> +<head> +<style> +.layer { + position: absolute; + width: 20px; + height: 20px; + transform: translateZ(10px); +} +</style> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function doActions(callback) +{ + var layer = document.createElement("div"); + layer.classList.add("layer"); + document.getElementById("parent-layer").appendChild(layer); + + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); +} + +function test() +{ + InspectorTest.invokeWithTracing("doActions", onTracingComplete); + function onTracingComplete() + { + var events = InspectorTest.timelineModel().inspectedTargetEvents(); + for (var i = 0; i < events.length; ++i) { + var event = events[i]; + if (events[i].name === WebInspector.TimelineModel.RecordType.UpdateLayerTree) { + InspectorTest.addResult("Got UpdateLayerTree event, phase: " + events[i].phase); + break; + } + } + InspectorTest.addResult("Done"); + InspectorTest.completeTest(); + } +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the instrumentation of UpdateLayerTree event +</p> +<div id="parent-layer"></div> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-parse-html-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-parse-html-expected.txt deleted file mode 100644 index 2198380..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-parse-html-expected.txt +++ /dev/null
@@ -1,44 +0,0 @@ -Tests the Timeline API instrumentation of ParseHTML - -Test data -ParseHTML Properties: -{ - data : { - beginData : { - frame : <string> - stackTrace : <object> - startLine : 0 - url : .../inspector/tracing/timeline-parse-html.html - } - endData : { - endLine : -1 - } - } - endTime : <number> - frameId : <string> - stackTrace : <object> - startTime : <number> - type : "ParseHTML" -} -Text details for ParseHTML: timeline-parse-html.html [1…] -ParseHTML Properties: -{ - data : { - beginData : { - frame : <string> - stackTrace : <object> - startLine : 0 - url : .../inspector/tracing/timeline-parse-html.html - } - endData : { - endLine : -1 - } - } - endTime : <number> - frameId : <string> - stackTrace : <object> - startTime : <number> - type : "ParseHTML" -} -Text details for ParseHTML: timeline-parse-html.html [1…] -
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-parse-html.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-parse-html.html deleted file mode 100644 index 1697c36e..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-parse-html.html +++ /dev/null
@@ -1,31 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function performActions() -{ - var element = document.createElement("div"); - element.innerHTML = "Test data"; - document.body.appendChild(element); -} - -function test() -{ - InspectorTest.performActionsAndPrint("performActions()", "ParseHTML"); -} - -if (!window.testRunner) - setTimeout(performActions, 2000); - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline API instrumentation of ParseHTML -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-recalculate-styles.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-recalculate-styles.html deleted file mode 100644 index 1458e255..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-recalculate-styles.html +++ /dev/null
@@ -1,44 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> - -<style> -.test-style { - color: red; -} -</style> - -<script> - -function forceStyle() -{ - var element = document.createElement("div"); - element.className = "test-style"; - element.innerHTML = "<span>Test data</span>"; - document.querySelector('section > div').appendChild(element); - var unused = element.offsetWidth; -} - -function performActions() -{ - wrapCallFunctionForTimeline(forceStyle); -} - -function test() -{ - InspectorTest.performActionsAndPrint("performActions()", "UpdateLayoutTree"); -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline API instrumentation of a style recalculation event -</p> -<section> - <div></div> -</section> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-receive-response-event.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-receive-response-event.html deleted file mode 100644 index c4512b49b..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-receive-response-event.html +++ /dev/null
@@ -1,61 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function performActions(callback) -{ - var image = new Image(); - image.onload = bar; - image.src = "resources/anImage.png"; - - function bar() - { - var image = new Image(); - image.onload = function(event) { callback(); } // do not pass event argument to the callback. - image.src = "resources/anotherImage.png"; - } -} - -function test() -{ - WebInspector.TimelinePanel.show(); - WebInspector.panels.timeline._model._currentTarget = WebInspector.targetManager.mainTarget(); - WebInspector.panels.timeline._captureJSProfileSetting.set(false); - InspectorTest.invokeAsyncWithTimeline("performActions", finish); - - function finish() - { - var recordTypes = WebInspector.TimelineModel.RecordType; - var typesToDump = new Set([recordTypes.ResourceSendRequest, recordTypes.ResourceReceiveResponse, recordTypes.ResourceReceivedData, recordTypes.ResourceFinish, - recordTypes.EventDispatch, recordTypes.FunctionCall]); - function dumpEvent(traceEvent, level) - { - // Ignore stray paint & rendering events for better stability. - var categoryName = WebInspector.TimelineUIUtils.eventStyle(traceEvent).category.name; - if (categoryName !== "loading" && categoryName !== "scripting") - return; - // Here and below: pretend coalesced record are just not there, as coalescation is time dependent and, hence, not stable. - // Filter out InjectedScript function call because they happen out of sync. - if (typesToDump.has(traceEvent.name) && (traceEvent.name !== "FunctionCall" || traceEvent.args["data"].scriptName)) - InspectorTest.addResult(" ".repeat(level - 1) + traceEvent.name); - } - InspectorTest.walkTimelineEventTree(dumpEvent); - InspectorTest.completeTest(); - } -} - -if (!window.testRunner) - setTimeout(performActions, 3000); - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline API instrumentation of a SendRequest, ReceiveResponse etc. -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-sampling-codemap.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-sampling-codemap.html deleted file mode 100644 index 7a7f22f..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-sampling-codemap.html +++ /dev/null
@@ -1,64 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../tracing-test.js"></script> -<script> -function test() -{ - var codemap = new WebInspector.TimelineJSProfileProcessor.CodeMap(); - for (var i = 0; i < 10; i++) { - var address = i * 0x100 + 0x77000; - codemap.addEntry("0x" + address.toString(16), 0x80, "frame" + i); - } - - codemap.addEntry( "0x77010", 0x10, "frame1killer"); - codemap.addEntry( "0x77090", 0x200, "frames234killer"); - codemap.moveEntry("0x77090", "0x55000", 0x300); - codemap.moveEntry("0x77500", "0xfffffffffffff000", 0x80); - codemap.moveEntry("0x77600", "0x77700", 0x80); - - // fedcba9876543210 - // bank -> BBBAAAAAAAAAAAAA <- address - codemap.addEntry("0xffffffffffffff00", 2, "frameA"); - codemap.addEntry("0xffffffffffffff02", 2, "frameB"); - codemap.addEntry("0xffffffffffffff04", 2, "frameC"); - codemap.addEntry("0xffffffffffffff06", 2, "frameD"); - codemap.addEntry("0xffffffffffffff01", 5, "frameE"); - - InspectorTest.addResult("Lookup test:"); - var addresses = [ - "0x0", - "0x7700f", - "0x77010", - "0x77011", - "0x7701f", - "0x77020", - "0x77800", - "0x55007", - "0x88000", - "0xffffffffffffff00", - "0xffffffffffffff01", - "0xffffffffffffff02", - "0xffffffffffffff07", - "0xffffffffffffff08", - ]; - for (var i = 0; i < addresses.length; ++i) - InspectorTest.addResult(" " + addresses[i] + " -> " + codemap.lookupEntry(addresses[i])); - - InspectorTest.addResult(""); - for (var bankName of codemap._banks.keysArray()) { - InspectorTest.addResult("Bank \"" + bankName + "\":"); - var bank = codemap._banks.get(bankName); - for (var i = 0; i < bank._entries.length; ++i) { - var entry = bank._entries[i]; - InspectorTest.addResult(" 0x" + entry.address.toString(16) + " / " + entry.size + " : " + entry.callFrame); - } - } - InspectorTest.completeTest(); -} - -</script> -</head> -<body onload="runTest()"> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-id.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-id.html deleted file mode 100644 index ac751cc..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-id.html +++ /dev/null
@@ -1,70 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function test() -{ - function performActions(callback) - { - var timerOne = setTimeout("1 + 1", 10); - var timerTwo = setInterval(intervalTimerWork, 20); - var iteration = 0; - - function intervalTimerWork() - { - if (++iteration < 2) - return; - clearInterval(timerTwo); - callback(); - } - } - - var source = performActions.toString(); - source += "\n//# sourceURL=performActions.js"; - InspectorTest.evaluateInPage(source, startTimeline); - - function startTimeline() - { - InspectorTest.invokeAsyncWithTimeline("performActions", finish); - } - - var linkifier = new WebInspector.Linkifier(); - - var recordTypes = new Set(["TimerInstall", "TimerRemove", "FunctionCall"]); - function formatter(event) - { - if (!recordTypes.has(event.name)) - return; - - var detailsText = WebInspector.TimelineUIUtils.buildDetailsTextForTraceEvent(event, InspectorTest.timelineModel().target()); - InspectorTest.addResult("detailsTextContent for " + event.name + " event: '" + detailsText + "'"); - - var details = WebInspector.TimelineUIUtils.buildDetailsNodeForTraceEvent(event, InspectorTest.timelineModel().target(), linkifier); - if (!details) - return; - InspectorTest.addResult("details.textContent for " + event.name + " event: '" + details.textContent.replace(/VM[\d]+/, "VM") + "'"); - } - - function finish() - { - InspectorTest.walkTimelineEventTree(formatter); - InspectorTest.completeTest(); - } -} - -if (!window.testRunner) - setTimeout(performActions, 2000); - -</script> -</head> - -<body onload="runTest()"> -<p> -Test that checks location resolving mechanics for TimerInstall TimerRemove and FunctionCall events with scriptId. -</p><p> -It expects two FunctionCall for InjectedScript, two TimerInstall events, two FunctionCall events and one TimerRemove event to be logged with performActions.js script name and some line number. -</p> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-1.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-1.html deleted file mode 100644 index ee42786..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-1.html +++ /dev/null
@@ -1,55 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function performActions() -{ - var iframe = document.createElement("iframe"); - iframe.src = "resources/timeline-iframe-data.html"; - document.body.appendChild(iframe); -} - -function test() -{ - WebInspector.panels.timeline._captureJSProfileSetting.set(false); - InspectorTest.startTimeline(step1); - function step1() - { - InspectorTest.addConsoleSniffer(step2); - InspectorTest.evaluateInPage("performActions()"); - } - - function step2() - { - InspectorTest.stopTimeline(step3); - } - - function step3() - { - function format(record) - { - if (record.type() === WebInspector.TimelineModel.RecordType.EvaluateScript) { - InspectorTest.dumpTimelineRecord(record, undefined, undefined, [ - "TimeStamp", - ]); - InspectorTest.printTimelineRecordProperties(record); - } - } - - InspectorTest.printTimelineRecords(null, InspectorTest.safeWrap(format)); - InspectorTest.completeTest(); - } -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline API instrumentation of an HTML script tag. -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-2-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-2-expected.txt deleted file mode 100644 index 8ae1d29..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-2-expected.txt +++ /dev/null
@@ -1,17 +0,0 @@ -CONSOLE MESSAGE: line 1: SCRIPT TAG -Tests the Timeline API instrumentation of a script tag with an external script. - -EvaluateScript Properties: -{ - data : { - columnNumber : <number> - frame : <string> - lineNumber : <number> - url : .../inspector/tracing/timeline-script-tag-2.js - } - endTime : <number> - frameId : <string> - startTime : <number> - type : "EvaluateScript" -} -
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-2.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-2.html deleted file mode 100644 index 8f6beab..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-script-tag-2.html +++ /dev/null
@@ -1,44 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function performActions() -{ - var script = document.createElement("script"); - script.src = "timeline-script-tag-2.js"; - document.body.appendChild(script); -} - -function test() -{ - InspectorTest.startTimeline(step1); - function step1() - { - InspectorTest.addConsoleSniffer(step2); - InspectorTest.evaluateInPage("performActions()"); - } - - function step2() - { - InspectorTest.stopTimeline(step3); - } - - function step3() - { - InspectorTest.printTimelineRecords("EvaluateScript"); - InspectorTest.completeTest(); - } -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline API instrumentation of a script tag with an external script. -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-all-invalidator-types-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-all-invalidator-types-expected.txt deleted file mode 100644 index 477299a..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-all-invalidator-types-expected.txt +++ /dev/null
@@ -1,155 +0,0 @@ -Tests the Timeline API instrumentation of style recalc invalidator invalidations. - -PASS -PASS -PASS - -Running: testClassName -[ - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-all-invalidator-types.html:10} - changedAttribute : undefined - changedClass : "red" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='red'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-all-invalidator-types.html:11} - changedAttribute : undefined - changedClass : "red" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementTwo' class='red'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } -] - -Running: testIdWithoutStyleChange - -Running: testId -[ - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-all-invalidator-types.html:32} - changedAttribute : undefined - changedClass : undefined - changedId : "testElementFour" - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementFour' class='red'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-all-invalidator-types.html:33} - changedAttribute : undefined - changedClass : undefined - changedId : "testElementFive" - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementFive' class='red'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } -] - -Running: testStyleAttributeChange -[ - { - cause : {reason: StyleSheetChange, stackTrace: .../inspector/tracing/timeline-style-recalc-all-invalidator-types.html:43} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV id='testElementFour' class='red'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: StyleSheetChange, stackTrace: .../inspector/tracing/timeline-style-recalc-all-invalidator-types.html:44} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV id='testElementFive' class='red'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } -] - -Running: testAttributeChange -[ - { - cause : {reason: Attribute, stackTrace: .../inspector/tracing/timeline-style-recalc-all-invalidator-types.html:54} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "dir" - nodeName : "DIV id='testElementFour' class='red'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Attribute, stackTrace: .../inspector/tracing/timeline-style-recalc-all-invalidator-types.html:55} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "dir" - nodeName : "DIV id='testElementFive' class='red'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-all-invalidator-types.html:54} - changedAttribute : "dir" - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementFour' class='red'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-all-invalidator-types.html:55} - changedAttribute : "dir" - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementFive' class='red'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } -] - -Running: testPseudoChange -[ - { - cause : {reason: PseudoClass, stackTrace: .../inspector/tracing/timeline-style-recalc-all-invalidator-types.html:67} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : ":hover" - nodeName : "DIV id='testElementFive' class='red'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } -] -
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-all-invalidator-types.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-all-invalidator-types.html deleted file mode 100644 index ddf7ccb..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-all-invalidator-types.html +++ /dev/null
@@ -1,164 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function changeClassNameAndDisplay(callback) -{ - requestAnimationFrame(function() { - document.getElementById("testElementOne").className = "red"; - document.getElementById("testElementTwo").className = "red"; - var forceStyleRecalc = document.body.offsetTop; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function changeIdWithoutStyleChangeAndDisplay(callback) -{ - requestAnimationFrame(function() { - document.getElementById("testElementOne").id = "testElementNoMatchingStyles1"; - document.getElementById("testElementTwo").id = "testElementNoMatchingStyles2"; - var forceStyleRecalc = document.body.offsetTop; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function changeIdAndDisplay(callback) -{ - requestAnimationFrame(function() { - document.getElementById("testElementNoMatchingStyles1").id = "testElementFour"; - document.getElementById("testElementNoMatchingStyles2").id = "testElementFive"; - var forceStyleRecalc = document.body.offsetTop; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function changeStyleAttributeAndDisplay(callback) -{ - requestAnimationFrame(function() { - document.getElementById("testElementFour").setAttribute("style", "color: purple"); - document.getElementById("testElementFive").setAttribute("style", "color: pink"); - var forceStyleRecalc = document.body.offsetTop; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function changeAttributeAndDisplay(callback) -{ - requestAnimationFrame(function() { - document.getElementById("testElementFour").setAttribute("dir", "rtl"); - document.getElementById("testElementFive").setAttribute("dir", "rtl"); - var forceStyleRecalc = document.body.offsetTop; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function changePseudoAndDisplay(callback) -{ - requestAnimationFrame(function() { - var element1 = document.getElementById("testElementFour"); - var element2 = document.getElementById("testElementFive"); - eventSender.mouseMoveTo(element2.offsetLeft + 2, element2.offsetTop + 2); - requestAnimationFrame(function() { - var forceStyleRecalc = document.body.offsetTop; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); - }); -} - -function test() -{ - var currentPanel = WebInspector.inspectorView.currentPanel(); - InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); - Runtime.experiments.enableForTest("timelineInvalidationTracking"); - - InspectorTest.runTestSuite([ - function testClassName(next) - { - InspectorTest.invokeAsyncWithTimeline("changeClassNameAndDisplay", function() { - var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); - InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters); - next(); - }); - }, - - function testIdWithoutStyleChange(next) - { - InspectorTest.invokeAsyncWithTimeline("changeIdWithoutStyleChangeAndDisplay", function() { - var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); - InspectorTest.assertTrue(record === undefined, "There should be no style recalculation for an id change without style changes."); - next(); - }); - }, - - function testId(next) - { - InspectorTest.invokeAsyncWithTimeline("changeIdAndDisplay", function() { - var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); - InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters); - next(); - }); - }, - - function testStyleAttributeChange(next) - { - InspectorTest.invokeAsyncWithTimeline("changeStyleAttributeAndDisplay", function() { - var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); - InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters); - next(); - }); - }, - - function testAttributeChange(next) - { - InspectorTest.invokeAsyncWithTimeline("changeAttributeAndDisplay", function() { - var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); - InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters); - next(); - }); - }, - - function testPseudoChange(next) - { - InspectorTest.invokeAsyncWithTimeline("changePseudoAndDisplay", function() { - var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); - InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters); - next(); - }); - } - ]); -} -</script> -<style> - #testElementFour { color: yellow; } - #testElementFive { color: teal; } - #testElementFour:hover { color: azure; } - #testElementFive:hover { color: cornsilk; } - #testElementFour .dummy { } - #testElementFive .dummy { } - #testElementFour[dir] .dummy {} - - .testHolder > .red { background-color: red; } - .testHolder > .green { background-color: green; } - .testHolder > .blue { background-color: blue; } - .testHolder > .snow { background-color: snow; } - .testHolder > .red .dummy { } - .testHolder > .green .dummy { } - .testHolder > .blue .dummy { } - .testHolder > .snow .dummy { } -</style> -</head> -<body onload="runTest()"> -<p>Tests the Timeline API instrumentation of style recalc invalidator invalidations.</p> -<div class="testHolder"> -<div id="testElementOne">PASS</div><div id="testElementTwo">PASS</div><div id="testElementThree">PASS</div> -</div> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-with-invalidations-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-with-invalidations-expected.txt deleted file mode 100644 index 9f9772c..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-with-invalidations-expected.txt +++ /dev/null
@@ -1,133 +0,0 @@ -Tests the Timeline API instrumentation of style recalc events with invalidations. - -PASS -PASS -PASS - - -Running: testLocalFrame -first recalc style invalidations[ - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidations.html:10} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV id='testElementOne'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidations.html:11} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV id='testElementTwo'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } -] - -Running: multipleStyleRecalcs -first recalc style invalidations[ - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidations.html:25} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV id='testElementOne'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } -] -second recalc style invalidations[ - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidations.html:27} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV id='testElementOne'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidations.html:28} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV id='testElementTwo'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } -] -third recalc style invalidations[ - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidations.html:30} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV id='testElementOne'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidations.html:31} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV id='testElementTwo'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidations.html:32} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV id='testElementThree'" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } -] - -Running: testSubframe -first recalc style invalidations[ - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidations.html:43} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "BODY" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidations.html:44} - changedAttribute : undefined - changedClass : undefined - changedId : undefined - changedPseudo : undefined - extraData : "" - nodeName : "DIV" - selectorPart : undefined - type : "StyleRecalcInvalidationTracking" - } -] -
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-with-invalidations.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-with-invalidations.html deleted file mode 100644 index ae4aed2..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-with-invalidations.html +++ /dev/null
@@ -1,102 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function changeStylesAndDisplay(callback) -{ - requestAnimationFrame(function() { - document.getElementById("testElementOne").style.color = "red"; - document.getElementById("testElementTwo").style.color = "blue"; - var forceLayout = document.body.offsetTop; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function changeMultipleStylesAndDisplay(callback) -{ - requestAnimationFrame(function() { - var elementOne = document.getElementById("testElementOne"); - var elementTwo = document.getElementById("testElementTwo"); - var elementThree = document.getElementById("testElementThree"); - - elementOne.style.backgroundColor = "orangered"; - var forceStyleRecalc1 = document.body.offsetTop; - elementOne.style.color = "mediumvioletred"; - elementTwo.style.color = "deepskyblue"; - var forceStyleRecalc2 = document.body.offsetTop; - elementOne.style.color = "tomato"; - elementTwo.style.color = "mediumslateblue"; - elementThree.style.color = "mediumspringgreen"; - var forceStyleRecalc3 = document.body.offsetTop; - - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function changeSubframeStylesAndDisplay(callback) -{ - requestAnimationFrame(function() { - frames[0].document.body.style.backgroundColor = "papayawhip"; - frames[0].document.body.children[0].style.width = "200px"; - var forceLayout = frames[0].document.body.offsetTop; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function test() -{ - var currentPanel = WebInspector.inspectorView.currentPanel(); - InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); - Runtime.experiments.enableForTest("timelineInvalidationTracking"); - - InspectorTest.runTestSuite([ - function testLocalFrame(next) - { - InspectorTest.invokeAsyncWithTimeline("changeStylesAndDisplay", function() { - var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); - InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first recalc style invalidations"); - - next(); - }); - }, - - function multipleStyleRecalcs(next) - { - InspectorTest.invokeAsyncWithTimeline("changeMultipleStylesAndDisplay", function() { - var firstRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 0); - InspectorTest.addArray(firstRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first recalc style invalidations"); - - var secondRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 1); - InspectorTest.addArray(secondRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second recalc style invalidations"); - - var thirdRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 2); - InspectorTest.addArray(thirdRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "third recalc style invalidations"); - - next(); - }); - }, - - function testSubframe(next) - { - InspectorTest.invokeAsyncWithTimeline("changeSubframeStylesAndDisplay", function() { - var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); - InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first recalc style invalidations"); - - next(); - }); - } - ]); -} -</script> -</head> -<body onload="runTest()"> -<p>Tests the Timeline API instrumentation of style recalc events with invalidations.</p> -<div id="testElementOne">PASS</div><div id="testElementTwo">PASS</div><div id="testElementThree">PASS</div> -<iframe src="resources/timeline-iframe-paint.html" style="position: absolute; left: 40px; top: 40px; width: 100px; height: 100px; border: none"></iframe> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-with-invalidator-invalidations-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-with-invalidator-invalidations-expected.txt deleted file mode 100644 index 17a9958..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-with-invalidator-invalidations-expected.txt +++ /dev/null
@@ -1,291 +0,0 @@ -Tests the Timeline API instrumentation of style recalc events with invalidations. - -PASS -PASS -PASS - - -Running: testLocalFrame -first recalculate styles[ - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:10} - changedAttribute : undefined - changedClass : "red" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='red'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:11} - changedAttribute : undefined - changedClass : "red" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementTwo' class='red'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } -] - -Running: multipleStyleRecalcs -first recalculate styles[ - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:24} - changedAttribute : undefined - changedClass : "green" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='green'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:24} - changedAttribute : undefined - changedClass : "red" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='green'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } -] -second recalculate styles[ - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:26} - changedAttribute : undefined - changedClass : "blue" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='blue'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:26} - changedAttribute : undefined - changedClass : "green" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='blue'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:27} - changedAttribute : undefined - changedClass : "blue" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementTwo' class='blue'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:27} - changedAttribute : undefined - changedClass : "red" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementTwo' class='blue'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } -] -third recalculate styles[ - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:29} - changedAttribute : undefined - changedClass : "snow" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='snow'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:29} - changedAttribute : undefined - changedClass : "blue" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='snow'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:30} - changedAttribute : undefined - changedClass : "snow" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementTwo' class='snow'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:30} - changedAttribute : undefined - changedClass : "blue" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementTwo' class='snow'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:31} - changedAttribute : undefined - changedClass : "snow" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementThree' class='snow'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } -] - -Running: testSubframe -first recalculate styles[ - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:45} - changedAttribute : undefined - changedClass : "green" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='green'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } -] -second recalculate styles[ - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:47} - changedAttribute : undefined - changedClass : "blue" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='blue'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:47} - changedAttribute : undefined - changedClass : "green" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='blue'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:48} - changedAttribute : undefined - changedClass : "blue" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementTwo' class='blue'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } -] -third recalculate styles[ - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:50} - changedAttribute : undefined - changedClass : "snow" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='snow'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:50} - changedAttribute : undefined - changedClass : "blue" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementOne' class='snow'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:51} - changedAttribute : undefined - changedClass : "snow" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementTwo' class='snow'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:51} - changedAttribute : undefined - changedClass : "blue" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementTwo' class='snow'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } - { - cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html:52} - changedAttribute : undefined - changedClass : "snow" - changedId : undefined - changedPseudo : undefined - extraData : undefined - nodeName : "DIV id='testElementThree' class='snow'" - selectorPart : undefined - synthetic : true - type : "StyleRecalcInvalidationTracking" - } -] -
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html deleted file mode 100644 index 08d7a94..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style-recalc-with-invalidator-invalidations.html +++ /dev/null
@@ -1,125 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> -function changeStylesAndDisplay(callback) -{ - requestAnimationFrame(function() { - document.getElementById("testElementOne").className = "red"; - document.getElementById("testElementTwo").className = "red"; - var forceStyleRecalc = document.body.offsetTop; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function changeMultipleStylesAndDisplay(callback) -{ - requestAnimationFrame(function() { - var elementOne = document.getElementById("testElementOne"); - var elementTwo = document.getElementById("testElementTwo"); - var elementThree = document.getElementById("testElementThree"); - elementOne.className = "green"; - var forceStyleRecalc1 = document.body.offsetTop; - elementOne.className = "blue"; - elementTwo.className = "blue"; - var forceStyleRecalc2 = document.body.offsetTop; - elementOne.className = "snow"; - elementTwo.className = "snow"; - elementThree.className = "snow"; - var forceStyleRecalc3 = document.body.offsetTop; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function changeMultipleSubframeStylesAndDisplay(callback) -{ - requestAnimationFrame(function() { - var innerDocument = frames[0].document; - var elementOne = innerDocument.getElementById("testElementOne"); - var elementTwo = innerDocument.getElementById("testElementTwo"); - var elementThree = innerDocument.getElementById("testElementThree"); - elementOne.className = "green"; - var forceStyleRecalc1 = innerDocument.body.offsetTop; - elementOne.className = "blue"; - elementTwo.className = "blue"; - var forceStyleRecalc2 = innerDocument.body.offsetTop; - elementOne.className = "snow"; - elementTwo.className = "snow"; - elementThree.className = "snow"; - var forceStyleRecalc3 = innerDocument.body.offsetTop; - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); - }); -} - -function test() -{ - var currentPanel = WebInspector.inspectorView.currentPanel(); - InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); - Runtime.experiments.enableForTest("timelineInvalidationTracking"); - - InspectorTest.runTestSuite([ - function testLocalFrame(next) - { - InspectorTest.invokeAsyncWithTimeline("changeStylesAndDisplay", function() { - var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); - InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first recalculate styles"); - next(); - }); - }, - - function multipleStyleRecalcs(next) - { - InspectorTest.invokeAsyncWithTimeline("changeMultipleStylesAndDisplay", function() { - var firstRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 0); - InspectorTest.addArray(firstRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first recalculate styles"); - - var secondRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 1); - InspectorTest.addArray(secondRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second recalculate styles"); - - var thirdRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 2); - InspectorTest.addArray(thirdRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "third recalculate styles"); - next(); - }); - }, - - function testSubframe(next) - { - InspectorTest.invokeAsyncWithTimeline("changeMultipleSubframeStylesAndDisplay", function() { - var firstRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 0); - InspectorTest.addArray(firstRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first recalculate styles"); - - var secondRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 1); - InspectorTest.addArray(secondRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second recalculate styles"); - - var thirdRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 2); - InspectorTest.addArray(thirdRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "third recalculate styles"); - next(); - }); - } - ]); -} -</script> -<style> - .testHolder > .red { background-color: red; } - .testHolder > .green { background-color: green; } - .testHolder > .blue { background-color: blue; } - .testHolder > .snow { background-color: snow; } - .testHolder > .red .dummy { } - .testHolder > .green .dummy { } - .testHolder > .blue .dummy { } - .testHolder > .snow .dummy { } -</style> -</head> -<body onload="runTest()"> -<p>Tests the Timeline API instrumentation of style recalc events with invalidations.</p> -<div class="testHolder"> -<div id="testElementOne">PASS</div><div id="testElementTwo">PASS</div><div id="testElementThree">PASS</div> -</div> -<iframe src="resources/timeline-iframe-with-style.html" style="position: absolute; left: 40px; top: 40px; width: 100px; height: 100px; border: none"></iframe> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/parse-author-style-sheet-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/parse-author-style-sheet-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/parse-author-style-sheet-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/parse-author-style-sheet-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/parse-author-style-sheet.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/parse-author-style-sheet.html new file mode 100644 index 0000000..91c39511 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/parse-author-style-sheet.html
@@ -0,0 +1,41 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script src="../../tracing-test.js"></script> +<script> + +function importStyle(onComplete) +{ + var link = document.createElement('link'); + link.setAttribute('rel', 'stylesheet'); + link.type = 'text/css'; + link.href = '../resources/style.css'; + document.head.appendChild(link); + link.onload = onComplete.bind(this, null); +} + +function test() +{ + InspectorTest.invokeWithTracing("importStyle", processTracingEvents); + + function processTracingEvents() + { + var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.ParseAuthorStyleSheet); + if (record) + InspectorTest.addResult("SUCCESS: found ParseAuthorStyleSheet record"); + else + InspectorTest.addResult("FAIL: ParseAuthorStyleSheet record not found"); + InspectorTest.completeTest(); + } +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests that ParseAuthorStyleSheet trace event is recorded. +</p> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-recalculate-styles-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-recalculate-styles-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-recalculate-styles-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-recalculate-styles-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-recalculate-styles.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-recalculate-styles.html new file mode 100644 index 0000000..bef75e1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-recalculate-styles.html
@@ -0,0 +1,44 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> + +<style> +.test-style { + color: red; +} +</style> + +<script> + +function forceStyle() +{ + var element = document.createElement("div"); + element.className = "test-style"; + element.innerHTML = "<span>Test data</span>"; + document.querySelector('section > div').appendChild(element); + var unused = element.offsetWidth; +} + +function performActions() +{ + wrapCallFunctionForTimeline(forceStyle); +} + +function test() +{ + InspectorTest.performActionsAndPrint("performActions()", "UpdateLayoutTree"); +} + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline API instrumentation of a style recalculation event +</p> +<section> + <div></div> +</section> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-all-invalidator-types-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-all-invalidator-types-expected.txt new file mode 100644 index 0000000..3234b879 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-all-invalidator-types-expected.txt
@@ -0,0 +1,155 @@ +Tests the Timeline API instrumentation of style recalc invalidator invalidations. + +PASS +PASS +PASS + +Running: testClassName +[ + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.html:10} + changedAttribute : undefined + changedClass : "red" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='red'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.html:11} + changedAttribute : undefined + changedClass : "red" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementTwo' class='red'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } +] + +Running: testIdWithoutStyleChange + +Running: testId +[ + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.html:32} + changedAttribute : undefined + changedClass : undefined + changedId : "testElementFour" + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementFour' class='red'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.html:33} + changedAttribute : undefined + changedClass : undefined + changedId : "testElementFive" + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementFive' class='red'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } +] + +Running: testStyleAttributeChange +[ + { + cause : {reason: StyleSheetChange, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.html:43} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV id='testElementFour' class='red'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: StyleSheetChange, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.html:44} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV id='testElementFive' class='red'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } +] + +Running: testAttributeChange +[ + { + cause : {reason: Attribute, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.html:54} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "dir" + nodeName : "DIV id='testElementFour' class='red'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Attribute, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.html:55} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "dir" + nodeName : "DIV id='testElementFive' class='red'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.html:54} + changedAttribute : "dir" + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementFour' class='red'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.html:55} + changedAttribute : "dir" + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementFive' class='red'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } +] + +Running: testPseudoChange +[ + { + cause : {reason: PseudoClass, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.html:67} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : ":hover" + nodeName : "DIV id='testElementFive' class='red'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } +] +
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.html new file mode 100644 index 0000000..d805373 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.html
@@ -0,0 +1,164 @@ +<!DOCTYPE HTML> +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function changeClassNameAndDisplay(callback) +{ + requestAnimationFrame(function() { + document.getElementById("testElementOne").className = "red"; + document.getElementById("testElementTwo").className = "red"; + var forceStyleRecalc = document.body.offsetTop; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function changeIdWithoutStyleChangeAndDisplay(callback) +{ + requestAnimationFrame(function() { + document.getElementById("testElementOne").id = "testElementNoMatchingStyles1"; + document.getElementById("testElementTwo").id = "testElementNoMatchingStyles2"; + var forceStyleRecalc = document.body.offsetTop; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function changeIdAndDisplay(callback) +{ + requestAnimationFrame(function() { + document.getElementById("testElementNoMatchingStyles1").id = "testElementFour"; + document.getElementById("testElementNoMatchingStyles2").id = "testElementFive"; + var forceStyleRecalc = document.body.offsetTop; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function changeStyleAttributeAndDisplay(callback) +{ + requestAnimationFrame(function() { + document.getElementById("testElementFour").setAttribute("style", "color: purple"); + document.getElementById("testElementFive").setAttribute("style", "color: pink"); + var forceStyleRecalc = document.body.offsetTop; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function changeAttributeAndDisplay(callback) +{ + requestAnimationFrame(function() { + document.getElementById("testElementFour").setAttribute("dir", "rtl"); + document.getElementById("testElementFive").setAttribute("dir", "rtl"); + var forceStyleRecalc = document.body.offsetTop; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function changePseudoAndDisplay(callback) +{ + requestAnimationFrame(function() { + var element1 = document.getElementById("testElementFour"); + var element2 = document.getElementById("testElementFive"); + eventSender.mouseMoveTo(element2.offsetLeft + 2, element2.offsetTop + 2); + requestAnimationFrame(function() { + var forceStyleRecalc = document.body.offsetTop; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); + }); +} + +function test() +{ + var currentPanel = WebInspector.inspectorView.currentPanel(); + InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); + Runtime.experiments.enableForTest("timelineInvalidationTracking"); + + InspectorTest.runTestSuite([ + function testClassName(next) + { + InspectorTest.invokeAsyncWithTimeline("changeClassNameAndDisplay", function() { + var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); + InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters); + next(); + }); + }, + + function testIdWithoutStyleChange(next) + { + InspectorTest.invokeAsyncWithTimeline("changeIdWithoutStyleChangeAndDisplay", function() { + var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); + InspectorTest.assertTrue(record === undefined, "There should be no style recalculation for an id change without style changes."); + next(); + }); + }, + + function testId(next) + { + InspectorTest.invokeAsyncWithTimeline("changeIdAndDisplay", function() { + var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); + InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters); + next(); + }); + }, + + function testStyleAttributeChange(next) + { + InspectorTest.invokeAsyncWithTimeline("changeStyleAttributeAndDisplay", function() { + var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); + InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters); + next(); + }); + }, + + function testAttributeChange(next) + { + InspectorTest.invokeAsyncWithTimeline("changeAttributeAndDisplay", function() { + var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); + InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters); + next(); + }); + }, + + function testPseudoChange(next) + { + InspectorTest.invokeAsyncWithTimeline("changePseudoAndDisplay", function() { + var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); + InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters); + next(); + }); + } + ]); +} +</script> +<style> + #testElementFour { color: yellow; } + #testElementFive { color: teal; } + #testElementFour:hover { color: azure; } + #testElementFive:hover { color: cornsilk; } + #testElementFour .dummy { } + #testElementFive .dummy { } + #testElementFour[dir] .dummy {} + + .testHolder > .red { background-color: red; } + .testHolder > .green { background-color: green; } + .testHolder > .blue { background-color: blue; } + .testHolder > .snow { background-color: snow; } + .testHolder > .red .dummy { } + .testHolder > .green .dummy { } + .testHolder > .blue .dummy { } + .testHolder > .snow .dummy { } +</style> +</head> +<body onload="runTest()"> +<p>Tests the Timeline API instrumentation of style recalc invalidator invalidations.</p> +<div class="testHolder"> +<div id="testElementOne">PASS</div><div id="testElementTwo">PASS</div><div id="testElementThree">PASS</div> +</div> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-with-invalidations-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-with-invalidations-expected.txt new file mode 100644 index 0000000..ae643db --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-with-invalidations-expected.txt
@@ -0,0 +1,133 @@ +Tests the Timeline API instrumentation of style recalc events with invalidations. + +PASS +PASS +PASS + + +Running: testLocalFrame +first recalc style invalidations[ + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidations.html:10} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV id='testElementOne'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidations.html:11} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV id='testElementTwo'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } +] + +Running: multipleStyleRecalcs +first recalc style invalidations[ + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidations.html:25} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV id='testElementOne'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } +] +second recalc style invalidations[ + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidations.html:27} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV id='testElementOne'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidations.html:28} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV id='testElementTwo'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } +] +third recalc style invalidations[ + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidations.html:30} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV id='testElementOne'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidations.html:31} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV id='testElementTwo'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidations.html:32} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV id='testElementThree'" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } +] + +Running: testSubframe +first recalc style invalidations[ + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidations.html:43} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "BODY" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Inline CSS style declaration was mutated, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidations.html:44} + changedAttribute : undefined + changedClass : undefined + changedId : undefined + changedPseudo : undefined + extraData : "" + nodeName : "DIV" + selectorPart : undefined + type : "StyleRecalcInvalidationTracking" + } +] +
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-with-invalidations.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-with-invalidations.html new file mode 100644 index 0000000..3cac78a4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-with-invalidations.html
@@ -0,0 +1,102 @@ +<!DOCTYPE HTML> +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function changeStylesAndDisplay(callback) +{ + requestAnimationFrame(function() { + document.getElementById("testElementOne").style.color = "red"; + document.getElementById("testElementTwo").style.color = "blue"; + var forceLayout = document.body.offsetTop; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function changeMultipleStylesAndDisplay(callback) +{ + requestAnimationFrame(function() { + var elementOne = document.getElementById("testElementOne"); + var elementTwo = document.getElementById("testElementTwo"); + var elementThree = document.getElementById("testElementThree"); + + elementOne.style.backgroundColor = "orangered"; + var forceStyleRecalc1 = document.body.offsetTop; + elementOne.style.color = "mediumvioletred"; + elementTwo.style.color = "deepskyblue"; + var forceStyleRecalc2 = document.body.offsetTop; + elementOne.style.color = "tomato"; + elementTwo.style.color = "mediumslateblue"; + elementThree.style.color = "mediumspringgreen"; + var forceStyleRecalc3 = document.body.offsetTop; + + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function changeSubframeStylesAndDisplay(callback) +{ + requestAnimationFrame(function() { + frames[0].document.body.style.backgroundColor = "papayawhip"; + frames[0].document.body.children[0].style.width = "200px"; + var forceLayout = frames[0].document.body.offsetTop; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function test() +{ + var currentPanel = WebInspector.inspectorView.currentPanel(); + InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); + Runtime.experiments.enableForTest("timelineInvalidationTracking"); + + InspectorTest.runTestSuite([ + function testLocalFrame(next) + { + InspectorTest.invokeAsyncWithTimeline("changeStylesAndDisplay", function() { + var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); + InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first recalc style invalidations"); + + next(); + }); + }, + + function multipleStyleRecalcs(next) + { + InspectorTest.invokeAsyncWithTimeline("changeMultipleStylesAndDisplay", function() { + var firstRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 0); + InspectorTest.addArray(firstRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first recalc style invalidations"); + + var secondRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 1); + InspectorTest.addArray(secondRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second recalc style invalidations"); + + var thirdRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 2); + InspectorTest.addArray(thirdRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "third recalc style invalidations"); + + next(); + }); + }, + + function testSubframe(next) + { + InspectorTest.invokeAsyncWithTimeline("changeSubframeStylesAndDisplay", function() { + var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); + InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first recalc style invalidations"); + + next(); + }); + } + ]); +} +</script> +</head> +<body onload="runTest()"> +<p>Tests the Timeline API instrumentation of style recalc events with invalidations.</p> +<div id="testElementOne">PASS</div><div id="testElementTwo">PASS</div><div id="testElementThree">PASS</div> +<iframe src="../resources/timeline-iframe-paint.html" style="position: absolute; left: 40px; top: 40px; width: 100px; height: 100px; border: none"></iframe> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations-expected.txt new file mode 100644 index 0000000..2d1031b --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations-expected.txt
@@ -0,0 +1,291 @@ +Tests the Timeline API instrumentation of style recalc events with invalidations. + +PASS +PASS +PASS + + +Running: testLocalFrame +first recalculate styles[ + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:10} + changedAttribute : undefined + changedClass : "red" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='red'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:11} + changedAttribute : undefined + changedClass : "red" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementTwo' class='red'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } +] + +Running: multipleStyleRecalcs +first recalculate styles[ + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:24} + changedAttribute : undefined + changedClass : "green" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='green'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:24} + changedAttribute : undefined + changedClass : "red" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='green'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } +] +second recalculate styles[ + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:26} + changedAttribute : undefined + changedClass : "blue" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='blue'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:26} + changedAttribute : undefined + changedClass : "green" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='blue'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:27} + changedAttribute : undefined + changedClass : "blue" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementTwo' class='blue'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:27} + changedAttribute : undefined + changedClass : "red" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementTwo' class='blue'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } +] +third recalculate styles[ + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:29} + changedAttribute : undefined + changedClass : "snow" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='snow'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:29} + changedAttribute : undefined + changedClass : "blue" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='snow'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:30} + changedAttribute : undefined + changedClass : "snow" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementTwo' class='snow'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:30} + changedAttribute : undefined + changedClass : "blue" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementTwo' class='snow'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:31} + changedAttribute : undefined + changedClass : "snow" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementThree' class='snow'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } +] + +Running: testSubframe +first recalculate styles[ + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:45} + changedAttribute : undefined + changedClass : "green" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='green'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } +] +second recalculate styles[ + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:47} + changedAttribute : undefined + changedClass : "blue" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='blue'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:47} + changedAttribute : undefined + changedClass : "green" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='blue'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:48} + changedAttribute : undefined + changedClass : "blue" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementTwo' class='blue'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } +] +third recalculate styles[ + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:50} + changedAttribute : undefined + changedClass : "snow" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='snow'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:50} + changedAttribute : undefined + changedClass : "blue" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementOne' class='snow'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:51} + changedAttribute : undefined + changedClass : "snow" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementTwo' class='snow'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:51} + changedAttribute : undefined + changedClass : "blue" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementTwo' class='snow'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } + { + cause : {reason: Element has pending invalidation list, stackTrace: .../inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html:52} + changedAttribute : undefined + changedClass : "snow" + changedId : undefined + changedPseudo : undefined + extraData : undefined + nodeName : "DIV id='testElementThree' class='snow'" + selectorPart : undefined + synthetic : true + type : "StyleRecalcInvalidationTracking" + } +] +
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html new file mode 100644 index 0000000..5ab8b8e --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.html
@@ -0,0 +1,125 @@ +<!DOCTYPE HTML> +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> +function changeStylesAndDisplay(callback) +{ + requestAnimationFrame(function() { + document.getElementById("testElementOne").className = "red"; + document.getElementById("testElementTwo").className = "red"; + var forceStyleRecalc = document.body.offsetTop; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function changeMultipleStylesAndDisplay(callback) +{ + requestAnimationFrame(function() { + var elementOne = document.getElementById("testElementOne"); + var elementTwo = document.getElementById("testElementTwo"); + var elementThree = document.getElementById("testElementThree"); + elementOne.className = "green"; + var forceStyleRecalc1 = document.body.offsetTop; + elementOne.className = "blue"; + elementTwo.className = "blue"; + var forceStyleRecalc2 = document.body.offsetTop; + elementOne.className = "snow"; + elementTwo.className = "snow"; + elementThree.className = "snow"; + var forceStyleRecalc3 = document.body.offsetTop; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function changeMultipleSubframeStylesAndDisplay(callback) +{ + requestAnimationFrame(function() { + var innerDocument = frames[0].document; + var elementOne = innerDocument.getElementById("testElementOne"); + var elementTwo = innerDocument.getElementById("testElementTwo"); + var elementThree = innerDocument.getElementById("testElementThree"); + elementOne.className = "green"; + var forceStyleRecalc1 = innerDocument.body.offsetTop; + elementOne.className = "blue"; + elementTwo.className = "blue"; + var forceStyleRecalc2 = innerDocument.body.offsetTop; + elementOne.className = "snow"; + elementTwo.className = "snow"; + elementThree.className = "snow"; + var forceStyleRecalc3 = innerDocument.body.offsetTop; + if (window.testRunner) + testRunner.layoutAndPaintAsyncThen(callback); + }); +} + +function test() +{ + var currentPanel = WebInspector.inspectorView.currentPanel(); + InspectorTest.assertEquals(currentPanel._panelName, "timeline", "Current panel should be the timeline."); + Runtime.experiments.enableForTest("timelineInvalidationTracking"); + + InspectorTest.runTestSuite([ + function testLocalFrame(next) + { + InspectorTest.invokeAsyncWithTimeline("changeStylesAndDisplay", function() { + var record = InspectorTest.findFirstTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree); + InspectorTest.addArray(record._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first recalculate styles"); + next(); + }); + }, + + function multipleStyleRecalcs(next) + { + InspectorTest.invokeAsyncWithTimeline("changeMultipleStylesAndDisplay", function() { + var firstRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 0); + InspectorTest.addArray(firstRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first recalculate styles"); + + var secondRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 1); + InspectorTest.addArray(secondRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second recalculate styles"); + + var thirdRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 2); + InspectorTest.addArray(thirdRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "third recalculate styles"); + next(); + }); + }, + + function testSubframe(next) + { + InspectorTest.invokeAsyncWithTimeline("changeMultipleSubframeStylesAndDisplay", function() { + var firstRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 0); + InspectorTest.addArray(firstRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "first recalculate styles"); + + var secondRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 1); + InspectorTest.addArray(secondRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "second recalculate styles"); + + var thirdRecord = InspectorTest.findTimelineRecord(WebInspector.TimelineModel.RecordType.UpdateLayoutTree, 2); + InspectorTest.addArray(thirdRecord._event.invalidationTrackingEvents, InspectorTest.InvalidationFormatters, "", "third recalculate styles"); + next(); + }); + } + ]); +} +</script> +<style> + .testHolder > .red { background-color: red; } + .testHolder > .green { background-color: green; } + .testHolder > .blue { background-color: blue; } + .testHolder > .snow { background-color: snow; } + .testHolder > .red .dummy { } + .testHolder > .green .dummy { } + .testHolder > .blue .dummy { } + .testHolder > .snow .dummy { } +</style> +</head> +<body onload="runTest()"> +<p>Tests the Timeline API instrumentation of style recalc events with invalidations.</p> +<div class="testHolder"> +<div id="testElementOne">PASS</div><div id="testElementTwo">PASS</div><div id="testElementThree">PASS</div> +</div> +<iframe src="../resources/timeline-iframe-with-style.html" style="position: absolute; left: 40px; top: 40px; width: 100px; height: 100px; border: none"></iframe> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time-stamp.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time-stamp.html deleted file mode 100644 index 25007be3..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time-stamp.html +++ /dev/null
@@ -1,29 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function performActions() -{ - console.timeStamp("TIME STAMP"); -} - -function test() -{ - InspectorTest.performActionsAndPrint("performActions()", "TimeStamp", true); -} - -if (!window.testRunner) - setTimeout(performActions, 2000); - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline API timeStamp feature -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time.html deleted file mode 100644 index 4747c5f..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time.html +++ /dev/null
@@ -1,103 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -testRunner.setDumpConsoleMessages(false); - -function simpleConsoleTime() -{ - console.time("a"); - console.timeEnd("a"); -} - -function nestedConsoleTime() -{ - console.time("a"); - { - console.time("b"); - console.timeEnd("b"); - { - console.time("c"); - { - console.time("d"); - console.timeEnd("d"); - } - console.timeEnd("c"); - } - } - console.timeEnd("a"); -} - - -function unbalancedConsoleTime() -{ - console.time("a"); - console.time("b"); - console.timeEnd("a"); - console.timeEnd("b"); -} - -function consoleTimeWithoutConsoleTimeEnd() -{ - console.timeStamp("Foo"); - console.time("a"); - console.timeStamp("Bar"); - console.time("b"); - console.time("c"); - console.time("d"); - console.timeStamp("Baz"); - console.timeEnd("d"); -} - -function test() -{ - InspectorTest.runTestSuite([ - function testSimpleConsoleTime(next) - { - performActions("simpleConsoleTime()", next); - }, - - function testNestedConsoleTime(next) - { - performActions("nestedConsoleTime()", next); - }, - - function testUnbalancedConsoleTime(next) - { - performActions("unbalancedConsoleTime()", next); - }, - - function testConsoleTimeWithoutConsoleTimeEnd(next) - { - performActions("consoleTimeWithoutConsoleTimeEnd()", next); - } - ]); - - function performActions(actions, next) - { - var namesToDump = new Set(["FunctionCall", "ConsoleTime", "TimeStamp"]); - function dumpName(event, level) - { - if (namesToDump.has(event.name)) - InspectorTest.addResult("----".repeat(level) + "> " + WebInspector.TimelineUIUtils.eventTitle(event)); - } - function callback() - { - InspectorTest.walkTimelineEventTree(dumpName); - next(); - } - WebInspector.panels.timeline._captureJSProfileSetting.set(false); - InspectorTest.evaluateWithTimeline(actions, InspectorTest.safeWrap(callback), true); - } -} - -</script> -</head> - -<body onload="runTest()"> -<p>Test nesting of time/timeEnd records on Timeline</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-time-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-time-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-time-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time-stamp-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-time-stamp-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-time-stamp-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-time-stamp-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-time-stamp.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-time-stamp.html new file mode 100644 index 0000000..0e9c292 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-time-stamp.html
@@ -0,0 +1,29 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function performActions() +{ + console.timeStamp("TIME STAMP"); +} + +function test() +{ + InspectorTest.performActionsAndPrint("performActions()", "TimeStamp", true); +} + +if (!window.testRunner) + setTimeout(performActions, 2000); + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline API timeStamp feature +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-time.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-time.html new file mode 100644 index 0000000..0f7a473 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-time.html
@@ -0,0 +1,103 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +testRunner.setDumpConsoleMessages(false); + +function simpleConsoleTime() +{ + console.time("a"); + console.timeEnd("a"); +} + +function nestedConsoleTime() +{ + console.time("a"); + { + console.time("b"); + console.timeEnd("b"); + { + console.time("c"); + { + console.time("d"); + console.timeEnd("d"); + } + console.timeEnd("c"); + } + } + console.timeEnd("a"); +} + + +function unbalancedConsoleTime() +{ + console.time("a"); + console.time("b"); + console.timeEnd("a"); + console.timeEnd("b"); +} + +function consoleTimeWithoutConsoleTimeEnd() +{ + console.timeStamp("Foo"); + console.time("a"); + console.timeStamp("Bar"); + console.time("b"); + console.time("c"); + console.time("d"); + console.timeStamp("Baz"); + console.timeEnd("d"); +} + +function test() +{ + InspectorTest.runTestSuite([ + function testSimpleConsoleTime(next) + { + performActions("simpleConsoleTime()", next); + }, + + function testNestedConsoleTime(next) + { + performActions("nestedConsoleTime()", next); + }, + + function testUnbalancedConsoleTime(next) + { + performActions("unbalancedConsoleTime()", next); + }, + + function testConsoleTimeWithoutConsoleTimeEnd(next) + { + performActions("consoleTimeWithoutConsoleTimeEnd()", next); + } + ]); + + function performActions(actions, next) + { + var namesToDump = new Set(["FunctionCall", "ConsoleTime", "TimeStamp"]); + function dumpName(event, level) + { + if (namesToDump.has(event.name)) + InspectorTest.addResult("----".repeat(level) + "> " + WebInspector.TimelineUIUtils.eventTitle(event)); + } + function callback() + { + InspectorTest.walkTimelineEventTree(dumpName); + next(); + } + WebInspector.panels.timeline._captureJSProfileSetting.set(false); + InspectorTest.evaluateWithTimeline(actions, InspectorTest.safeWrap(callback), true); + } +} + +</script> +</head> + +<body onload="runTest()"> +<p>Test nesting of time/timeEnd records on Timeline</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-timer-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-timer-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-timer-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-timer-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-timer-fired-from-eval-call-site-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-timer-fired-from-eval-call-site-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-timer-fired-from-eval-call-site-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-timer-fired-from-eval-call-site-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-timer-fired-from-eval-call-site.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-timer-fired-from-eval-call-site.html new file mode 100644 index 0000000..c56b612c --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-timer-fired-from-eval-call-site.html
@@ -0,0 +1,58 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function performActions(callback) +{ + window.callWhenDone = callback; + var content = "" + + "var fn2 = function() {" + + " console.markTimeline(\"Script evaluated\");" + + " window.callWhenDone();" + + "};\\n" + + "var fn1 = function() {" + + " window.setTimeout(fn2, 1);" + + "};\\n" + + "window.setTimeout(fn1, 1);\\n" + + "//# sourceURL=fromEval.js"; + content = "eval('" + content + "');"; + var scriptElement = document.createElement('script'); + var contentNode = document.createTextNode(content); + scriptElement.appendChild(contentNode); + document.body.appendChild(scriptElement); + document.body.removeChild(scriptElement); +} + +function test() +{ + InspectorTest.invokeAsyncWithTimeline("performActions", finish); + + function finish() + { + function formatter(record) + { + if (record.type() === "TimerFire") { + var fnCallSite = record.children()[0].traceEvent().args["data"]; + InspectorTest.addResult(record.type() + " " + fnCallSite.scriptName + ":" + fnCallSite.scriptLine); + } + } + InspectorTest.printTimelineRecords(null, formatter); + InspectorTest.completeTest(); + } +} + +if (!window.testRunner) + setTimeout(performActions, 3000); + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline API instrumentation of a TimerFired events inside evaluated scripts. +</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-timer.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-timer.html new file mode 100644 index 0000000..beaed25 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-timer.html
@@ -0,0 +1,49 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script> + +function performActions(callback) +{ + var timerOne = setTimeout("1 + 1", 10); + var timerTwo = setInterval(intervalTimerWork, 20); + var iteration = 0; + + function intervalTimerWork() + { + if (++iteration < 2) + return; + clearInterval(timerTwo); + callback(); + } +} + +function test() +{ + WebInspector.panels.timeline._captureJSProfileSetting.set(false); + InspectorTest.invokeAsyncWithTimeline("performActions", finish); + + function finish() + { + InspectorTest.printTimelineRecordsWithDetails("TimerInstall"); + InspectorTest.printTimelineRecordsWithDetails("TimerFire"); + InspectorTest.printTimelineRecordsWithDetails("TimerRemove"); + InspectorTest.printTimelineRecords("FunctionCall"); + InspectorTest.printTimelineRecordsWithDetails("EvaluateScript"); + InspectorTest.completeTest(); + } +} + +if (!window.testRunner) + setTimeout(performActions, 2000); + +</script> +</head> + +<body onload="runTest()"> +<p> +Tests the Timeline events for Timers +</p> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-usertiming-expected.txt b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-usertiming-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/tracing/timeline-usertiming-expected.txt rename to third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-usertiming-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-usertiming.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-usertiming.html new file mode 100644 index 0000000..8339ecc3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-time/timeline-usertiming.html
@@ -0,0 +1,114 @@ +<html> +<head> +<script src="../../../http/tests/inspector/inspector-test.js"></script> +<script src="../../../http/tests/inspector/timeline-test.js"></script> +<script src="../../tracing-test.js"></script> +<script> + +function simplePerformanceMeasure() +{ + performance.mark("a-start"); + performance.mark("a-end"); + performance.measure("a", "a-start", "a-end"); +} + +function nestedPerformanceMeasure() +{ + performance.mark("a-start"); + { + performance.mark("b-start"); + performance.mark("b-end"); + { + performance.mark("c-start"); + { + performance.mark("d-start"); + performance.mark("d-end"); + } + performance.mark("c-end"); + } + } + performance.mark("a-end"); + performance.measure("a", "a-start", "a-end"); + performance.measure("b", "b-start", "b-end"); + performance.measure("c", "c-start", "c-end"); + performance.measure("d", "d-start", "d-end"); +} + + +function unbalancedPerformanceMeasure() +{ + performance.mark("a-start"); + performance.mark("b-start"); + performance.mark("a-end"); + performance.mark("b-end"); + performance.measure("a", "a-start", "a-end"); + performance.measure("b", "b-start", "b-end"); +} + + +function parentMeasureIsOnTop() +{ + performance.mark("startTime1"); + performance.mark("endTime1"); + + performance.mark("startTime2"); + performance.mark("endTime2"); + + performance.measure("durationTime1", "startTime1", "endTime1"); + performance.measure("durationTime2", "startTime2", "endTime2"); + performance.measure("durationTimeTotal", "startTime1", "endTime2"); +} + + +function test() +{ + InspectorTest.runTestSuite([ + function testSimplePerformanceMeasure(next) + { + performActions("simplePerformanceMeasure()", next); + }, + + function testNestedPerformanceMeasure(next) + { + performActions("nestedPerformanceMeasure()", next); + }, + + function testUnbalancedPerformanceMeasure(next) + { + performActions("unbalancedPerformanceMeasure()", next); + }, + + function testParentMeasureIsOnTop(next) + { + performActions("parentMeasureIsOnTop()", next); + } + ]); + + function dumpUserTimings() + { + var model = InspectorTest.timelineModel(); + var asyncEvents = model.mainThreadAsyncEvents() + + asyncEvents.forEach(function(eventGroup) { + eventGroup.forEach(function(event) { + if (event.hasCategory(WebInspector.TimelineModel.Category.UserTiming)) + InspectorTest.addResult(event.name); + }); + }) + } + + function performActions(actions, next) + { + InspectorTest.evaluateWithTimeline(actions, _ => { dumpUserTimings(); next(); }); + + } +} + +</script> +</head> + +<body onload="runTest()"> +<p>Test performance.mark/measure records on Timeline</p> + +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-timer-fired-from-eval-call-site.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-timer-fired-from-eval-call-site.html deleted file mode 100644 index 22569e8..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-timer-fired-from-eval-call-site.html +++ /dev/null
@@ -1,58 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function performActions(callback) -{ - window.callWhenDone = callback; - var content = "" + - "var fn2 = function() {" + - " console.markTimeline(\"Script evaluated\");" + - " window.callWhenDone();" + - "};\\n" + - "var fn1 = function() {" + - " window.setTimeout(fn2, 1);" + - "};\\n" + - "window.setTimeout(fn1, 1);\\n" + - "//# sourceURL=fromEval.js"; - content = "eval('" + content + "');"; - var scriptElement = document.createElement('script'); - var contentNode = document.createTextNode(content); - scriptElement.appendChild(contentNode); - document.body.appendChild(scriptElement); - document.body.removeChild(scriptElement); -} - -function test() -{ - InspectorTest.invokeAsyncWithTimeline("performActions", finish); - - function finish() - { - function formatter(record) - { - if (record.type() === "TimerFire") { - var fnCallSite = record.children()[0].traceEvent().args["data"]; - InspectorTest.addResult(record.type() + " " + fnCallSite.scriptName + ":" + fnCallSite.scriptLine); - } - } - InspectorTest.printTimelineRecords(null, formatter); - InspectorTest.completeTest(); - } -} - -if (!window.testRunner) - setTimeout(performActions, 3000); - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline API instrumentation of a TimerFired events inside evaluated scripts. -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-timer.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-timer.html deleted file mode 100644 index 04a846b..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-timer.html +++ /dev/null
@@ -1,49 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function performActions(callback) -{ - var timerOne = setTimeout("1 + 1", 10); - var timerTwo = setInterval(intervalTimerWork, 20); - var iteration = 0; - - function intervalTimerWork() - { - if (++iteration < 2) - return; - clearInterval(timerTwo); - callback(); - } -} - -function test() -{ - WebInspector.panels.timeline._captureJSProfileSetting.set(false); - InspectorTest.invokeAsyncWithTimeline("performActions", finish); - - function finish() - { - InspectorTest.printTimelineRecordsWithDetails("TimerInstall"); - InspectorTest.printTimelineRecordsWithDetails("TimerFire"); - InspectorTest.printTimelineRecordsWithDetails("TimerRemove"); - InspectorTest.printTimelineRecords("FunctionCall"); - InspectorTest.printTimelineRecordsWithDetails("EvaluateScript"); - InspectorTest.completeTest(); - } -} - -if (!window.testRunner) - setTimeout(performActions, 2000); - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline events for Timers -</p> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-trivial.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-trivial.html deleted file mode 100644 index e0fd6c6..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-trivial.html +++ /dev/null
@@ -1,27 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function test() { - /* This test seems silly, but originally it tickled bug 31080 */ - function callback() - { - InspectorTest.addResult("Timeline started"); - InspectorTest.completeTest(); - } - InspectorTest.startTimeline(callback); -} - - -</script> -</head> - -<body onload="runTest()"> -<p> -Trivial use of inspector frontend tests -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-usertiming.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-usertiming.html deleted file mode 100644 index 24672e0..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-usertiming.html +++ /dev/null
@@ -1,114 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script src="../tracing-test.js"></script> -<script> - -function simplePerformanceMeasure() -{ - performance.mark("a-start"); - performance.mark("a-end"); - performance.measure("a", "a-start", "a-end"); -} - -function nestedPerformanceMeasure() -{ - performance.mark("a-start"); - { - performance.mark("b-start"); - performance.mark("b-end"); - { - performance.mark("c-start"); - { - performance.mark("d-start"); - performance.mark("d-end"); - } - performance.mark("c-end"); - } - } - performance.mark("a-end"); - performance.measure("a", "a-start", "a-end"); - performance.measure("b", "b-start", "b-end"); - performance.measure("c", "c-start", "c-end"); - performance.measure("d", "d-start", "d-end"); -} - - -function unbalancedPerformanceMeasure() -{ - performance.mark("a-start"); - performance.mark("b-start"); - performance.mark("a-end"); - performance.mark("b-end"); - performance.measure("a", "a-start", "a-end"); - performance.measure("b", "b-start", "b-end"); -} - - -function parentMeasureIsOnTop() -{ - performance.mark("startTime1"); - performance.mark("endTime1"); - - performance.mark("startTime2"); - performance.mark("endTime2"); - - performance.measure("durationTime1", "startTime1", "endTime1"); - performance.measure("durationTime2", "startTime2", "endTime2"); - performance.measure("durationTimeTotal", "startTime1", "endTime2"); -} - - -function test() -{ - InspectorTest.runTestSuite([ - function testSimplePerformanceMeasure(next) - { - performActions("simplePerformanceMeasure()", next); - }, - - function testNestedPerformanceMeasure(next) - { - performActions("nestedPerformanceMeasure()", next); - }, - - function testUnbalancedPerformanceMeasure(next) - { - performActions("unbalancedPerformanceMeasure()", next); - }, - - function testParentMeasureIsOnTop(next) - { - performActions("parentMeasureIsOnTop()", next); - } - ]); - - function dumpUserTimings() - { - var model = InspectorTest.timelineModel(); - var asyncEvents = model.mainThreadAsyncEvents() - - asyncEvents.forEach(function(eventGroup) { - eventGroup.forEach(function(event) { - if (event.hasCategory(WebInspector.TimelineModel.Category.UserTiming)) - InspectorTest.addResult(event.name); - }); - }) - } - - function performActions(actions, next) - { - InspectorTest.evaluateWithTimeline(actions, _ => { dumpUserTimings(); next(); }); - - } -} - -</script> -</head> - -<body onload="runTest()"> -<p>Test performance.mark/measure records on Timeline</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-window-filter.html b/third_party/WebKit/LayoutTests/inspector/tracing/timeline-window-filter.html deleted file mode 100644 index 3bfdbde8..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/timeline-window-filter.html +++ /dev/null
@@ -1,66 +0,0 @@ -<html> -<head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script src="resources/timeline-data.js"></script> -<script> - -function test() -{ - var timeline = WebInspector.panels.timeline; - var overviewPane = timeline._overviewPane; - - InspectorTest.loadTimeline(InspectorTest.timelineData()); - - timeline._currentViews[0].refreshRecords(); - - overviewPane._update(); - InspectorTest.addResult("OverviewPane:"); - overviewPane._overviewCalculator.setDisplayWindow(450); - dumpDividers(overviewPane._overviewCalculator); - InspectorTest.addResult(""); - - function dumpFlameChartRecordsCountForRange(windowLeft, windowRight) - { - var mainView = timeline._currentViews[0]._mainView; - mainView._muteAnimation = true; - overviewPane._overviewGrid.setWindow(windowLeft, windowRight); - mainView.update(); - InspectorTest.addResult("range = " + windowLeft + " - " + windowRight); - InspectorTest.addResult("time range = " + mainView._timeWindowLeft + " - " + mainView._timeWindowRight); - InspectorTest.addResult(""); - } - - function dumpDividers(calculator) - { - var dividers = WebInspector.TimelineGrid.calculateDividerOffsets(calculator).offsets; - for (var i = 0; i < dividers.length; ++i) - dividers[i] -= calculator.zeroTime(); - InspectorTest.addResult("divider offsets: [" + dividers.join(", ") + "]. We are expecting round numbers."); - } - - dumpFlameChartRecordsCountForRange(0, 1); - dumpFlameChartRecordsCountForRange(0.25, 0.75); - dumpFlameChartRecordsCountForRange(0.33, 0.66); - - overviewPane._overviewGrid.setWindow(0.1, 0.9); - - InspectorTest.addResult("--------------------------------------------------------"); - InspectorTest.addResult("time range = " + timeline._windowStartTime + " - " + timeline._windowEndTime); - InspectorTest.completeTest(); -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the Timeline window filter. -</p> - -<p> -It applies different ranges to the OverviewGrid and expects that current view reflects the change. -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/inspector/tracing/update-layer-tree.html b/third_party/WebKit/LayoutTests/inspector/tracing/update-layer-tree.html deleted file mode 100644 index 30e0d0399..0000000 --- a/third_party/WebKit/LayoutTests/inspector/tracing/update-layer-tree.html +++ /dev/null
@@ -1,52 +0,0 @@ -<html> -<head> -<style> -.layer { - position: absolute; - width: 20px; - height: 20px; - transform: translateZ(10px); -} -</style> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> -<script> - -function doActions(callback) -{ - var layer = document.createElement("div"); - layer.classList.add("layer"); - document.getElementById("parent-layer").appendChild(layer); - - if (window.testRunner) - testRunner.layoutAndPaintAsyncThen(callback); -} - -function test() -{ - InspectorTest.invokeWithTracing("doActions", onTracingComplete); - function onTracingComplete() - { - var events = InspectorTest.timelineModel().inspectedTargetEvents(); - for (var i = 0; i < events.length; ++i) { - var event = events[i]; - if (events[i].name === WebInspector.TimelineModel.RecordType.UpdateLayerTree) { - InspectorTest.addResult("Got UpdateLayerTree event, phase: " + events[i].phase); - break; - } - } - InspectorTest.addResult("Done"); - InspectorTest.completeTest(); - } -} - -</script> -</head> - -<body onload="runTest()"> -<p> -Tests the instrumentation of UpdateLayerTree event -</p> -<div id="parent-layer"></div> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/media/audio-autoplay-experiment-modes-expected.txt b/third_party/WebKit/LayoutTests/media/audio-autoplay-experiment-modes-expected.txt index 32380902..b933889 100644 --- a/third_party/WebKit/LayoutTests/media/audio-autoplay-experiment-modes-expected.txt +++ b/third_party/WebKit/LayoutTests/media/audio-autoplay-experiment-modes-expected.txt
@@ -1,7 +1,6 @@ CONSOLE WARNING: line 71: Failed to execute 'play' on 'HTMLMediaElement': API can only be initiated by a user gesture. CONSOLE ERROR: line 71: Uncaught (in promise) NotAllowedError: play() can only be initiated by a user gesture. -END OF TEST - Check if the autoplay gesture override experiment works. There are a lot + Check if the autoplay gesture override experiment works. There are a lot of config options, so this test just runs all of them. The "results" table contains one row per config tested.
diff --git a/third_party/WebKit/LayoutTests/media/audio-autoplay-experiment-modes.html b/third_party/WebKit/LayoutTests/media/audio-autoplay-experiment-modes.html index f94a4b4..e68c605 100644 --- a/third_party/WebKit/LayoutTests/media/audio-autoplay-experiment-modes.html +++ b/third_party/WebKit/LayoutTests/media/audio-autoplay-experiment-modes.html
@@ -1,10 +1,8 @@ +<!DOCTYPE html> <html> <video autoplay controls></video> -<script src=media-file.js></script> -<!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956 - (Please avoid writing new tests using video-test.js) --> -<script src=video-test.js></script> -<script src=autoplay-experiment-helper.js></script> +<script src="media-file.js"></script> +<script src="autoplay-experiment-helper.js"></script> <body> <pre> Check if the autoplay gesture override experiment works. There are a lot
diff --git a/third_party/WebKit/LayoutTests/media/auto-play-in-sandbox-with-allow-scripts-expected.txt b/third_party/WebKit/LayoutTests/media/auto-play-in-sandbox-with-allow-scripts-expected.txt deleted file mode 100644 index c8bd32e..0000000 --- a/third_party/WebKit/LayoutTests/media/auto-play-in-sandbox-with-allow-scripts-expected.txt +++ /dev/null
@@ -1,12 +0,0 @@ - - --------- -Frame: '<!--framePath //<!--frame0-->-->' --------- -Test that play event fires when "src" set with an autoplay attribute in a sandbox with allows-scripts. - -EXPECTED (video.paused == 'true') OK -EVENT(play) -PLAY fired OK -END OF TEST -
diff --git a/third_party/WebKit/LayoutTests/media/auto-play-in-sandbox-with-allow-scripts.html b/third_party/WebKit/LayoutTests/media/auto-play-in-sandbox-with-allow-scripts.html index 29279545..49f263ef8 100644 --- a/third_party/WebKit/LayoutTests/media/auto-play-in-sandbox-with-allow-scripts.html +++ b/third_party/WebKit/LayoutTests/media/auto-play-in-sandbox-with-allow-scripts.html
@@ -1,10 +1,21 @@ -<script> -if (window.testRunner) { - testRunner.dumpAsText(); - testRunner.dumpChildFramesAsText(); -} -</script> +<!DOCTYPE html> +<title>Test that play event fires when "src" set with an autoplay attribute in a sandbox with allows-scripts.</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="media-file.js"></script> <iframe - style="width: 400px; height: 600px" sandbox="allow-scripts allow-same-origin" - src="resources/auto-play-in-sandbox-with-allow-scripts-iframe.html"></iframe> + src="resources/auto-play-in-sandbox-with-allow-scripts-iframe.html"> +</iframe> +<script> +async_test(function(t) { + var iframe = document.querySelector("iframe"); + + iframe.onload = t.step_func(function() { + var video = iframe.contentDocument.querySelector("video"); + assert_true(video.paused); + video.onplay = t.step_func_done(); + video.src = findMediaFile("video", "content/test"); + }); +}); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/media/autoplay-experiment-helper.js b/third_party/WebKit/LayoutTests/media/autoplay-experiment-helper.js index 183e2f1..f3feb89 100644 --- a/third_party/WebKit/LayoutTests/media/autoplay-experiment-helper.js +++ b/third_party/WebKit/LayoutTests/media/autoplay-experiment-helper.js
@@ -26,7 +26,7 @@ if (!enable) { // We can't transition out of optimized for mobile. - endTest(); + testRunner.notifyDone(); } else { // This only works once. mobileMetaTag = document.createElement('meta'); @@ -130,7 +130,7 @@ // Record the spec in the element, so that we can display the // results later. element.spec = spec; - window.internals.triggerAutoplayViewportCheck(element); + internals.triggerAutoplayViewportCheck(element); // Wait for canplaythrough before continuing, so that the media // might actually be playing. @@ -148,7 +148,7 @@ // We are supposed to scroll the player into view. element.scrollIntoView(true); // TODO(liberato): remove once autoplay gesture override experiment concludes. - window.internals.triggerAutoplayViewportCheck(element); + internals.triggerAutoplayViewportCheck(element); // Once these two methods return, changes to the element state due // to the autoplay experiment should be observable synchronously. checkElementStatus(element, spec); @@ -200,7 +200,7 @@ // Return null if configNumber was larger than the highest experiment. if (exp > 0) - endTest(); + testRunner.notifyDone(); configNumber++; @@ -263,9 +263,11 @@ } function start(mediaType, experiments) { - elementTypes = [ mediaType ]; - experimentTypes = experiments; + testRunner.waitUntilDone(); + testRunner.dumpAsText(); + elementTypes = [ mediaType ]; + experimentTypes = experiments; - window.internals.settings.setMediaPlaybackRequiresUserGesture(true); - runNextConfig(); + internals.settings.setMediaPlaybackRequiresUserGesture(true); + runNextConfig(); }
diff --git a/third_party/WebKit/LayoutTests/media/resources/auto-play-in-sandbox-with-allow-scripts-iframe.html b/third_party/WebKit/LayoutTests/media/resources/auto-play-in-sandbox-with-allow-scripts-iframe.html index e5457109..2494b0a1 100644 --- a/third_party/WebKit/LayoutTests/media/resources/auto-play-in-sandbox-with-allow-scripts-iframe.html +++ b/third_party/WebKit/LayoutTests/media/resources/auto-play-in-sandbox-with-allow-scripts-iframe.html
@@ -1,17 +1,3 @@ +<!DOCTYPE html> <base href=".."> -<video autoplay controls></video> -<p>Test that play event fires when "src" set with an autoplay attribute in a sandbox with allows-scripts.</p> -<script src=media-file.js></script> -<!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956 - (Please avoid writing new tests using video-test.js) --> -<script src=video-test.js></script> -<script> - testExpected("video.paused", true); - - waitForEvent('play', function () { - logResult(true, "PLAY fired"); - endTest(); - } ); - - video.src = findMediaFile("video", "content/test"); -</script> +<video autoplay></video> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-just-once-expected.txt b/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-just-once-expected.txt index eab5a67..78271f5 100644 --- a/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-just-once-expected.txt +++ b/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-just-once-expected.txt
@@ -1,5 +1,4 @@ Test that the autoplay experiment doesn't play media once the media is no longer eligible for autoplay. -First video should play OK -Second video should not play OK - +PASS First video is playing +PASS Second video isn't playing
diff --git a/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-just-once.html b/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-just-once.html index 5012642..77064e7a 100644 --- a/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-just-once.html +++ b/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-just-once.html
@@ -1,19 +1,15 @@ +<!DOCTYPE html> <script src=media-file.js></script> -<!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956 - (Please avoid writing new tests using video-test.js) --> -<script src=video-test.js></script> <script> - -function runTest() -{ +function runTest() { var canPlayThroughCount = 0; var videoShouldPlay; var videoShouldNotPlay; testRunner.waitUntilDone(); + testRunner.dumpAsText(); - function canPlayThrough() - { + function canPlayThrough() { canPlayThroughCount++; if (canPlayThroughCount == 2) { // Pause() will clear the autoplaying flag, which should also prevent the @@ -23,16 +19,27 @@ // Scroll them into view, and see if they start playing. parent.scrollIntoView(true); // TODO(liberato): remove once autoplay gesture override experiment concludes. - window.internals.triggerAutoplayViewportCheck(videoShouldPlay); - window.internals.triggerAutoplayViewportCheck(videoShouldNotPlay); - logResult(didPlaybackStart(videoShouldPlay), "First video should play"); - logResult(!didPlaybackStart(videoShouldNotPlay), "Second video should not play"); + internals.triggerAutoplayViewportCheck(videoShouldPlay); + internals.triggerAutoplayViewportCheck(videoShouldNotPlay); + var result; + if (didPlaybackStart(videoShouldPlay)) + result = document.createTextNode("PASS First video is playing"); + else + result = document.createTextNode("FAIL First video isn't playing"); + document.body.appendChild(result); + + document.body.appendChild(document.createElement("br")); + + if (!didPlaybackStart(videoShouldNotPlay)) + result = document.createTextNode("PASS Second video isn't playing"); + else + result = document.createTextNode("FAIL Second video is playing"); + document.body.appendChild(result); testRunner.notifyDone(); } } - function prepareVideo(parent) - { + function prepareVideo(parent) { var video = document.createElement("video"); video.oncanplaythrough = canPlayThrough; video.src = findMediaFile("video", "content/test"); @@ -42,8 +49,7 @@ return video; } - function didPlaybackStart(element) - { + function didPlaybackStart(element) { return !element.paused || element.ended; } @@ -65,7 +71,6 @@ videoShouldPlay = prepareVideo(parent); videoShouldNotPlay = prepareVideo(parent); } - </script> <p>Test that the autoplay experiment doesn't play media once the media is no longer eligible for autoplay.</p>
diff --git a/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes-expected.txt b/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes-expected.txt index d56aeaa..1b8a007 100644 --- a/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes-expected.txt +++ b/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes-expected.txt
@@ -14,8 +14,7 @@ CONSOLE ERROR: line 71: Uncaught (in promise) NotAllowedError: play() can only be initiated by a user gesture. CONSOLE WARNING: line 71: Failed to execute 'play' on 'HTMLMediaElement': API can only be initiated by a user gesture. CONSOLE ERROR: line 71: Uncaught (in promise) NotAllowedError: play() can only be initiated by a user gesture. -END OF TEST - Check if the autoplay gesture override experiment works. There are a lot + Check if the autoplay gesture override experiment works. There are a lot of config options, so this test just runs all of them. The "results" table contains one row per config tested.
diff --git a/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes.html b/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes.html index 0d64292..3f65d26 100644 --- a/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes.html +++ b/third_party/WebKit/LayoutTests/media/video-autoplay-experiment-modes.html
@@ -1,10 +1,8 @@ +<!DOCTYPE html> <html> <video autoplay controls></video> -<script src=media-file.js></script> -<!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956 - (Please avoid writing new tests using video-test.js) --> -<script src=video-test.js></script> -<script src=autoplay-experiment-helper.js></script> +<script src="media-file.js"></script> +<script src="autoplay-experiment-helper.js"></script> <body> <pre> Check if the autoplay gesture override experiment works. There are a lot
diff --git a/third_party/WebKit/LayoutTests/media/video-poster-delayed-expected.txt b/third_party/WebKit/LayoutTests/media/video-poster-delayed-expected.txt deleted file mode 100644 index 212b733..0000000 --- a/third_party/WebKit/LayoutTests/media/video-poster-delayed-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ - -Video loaded - -EXPECTED (video.clientWidth == '320') OK -EXPECTED (video.clientHeight == '240') OK -EXPECTED (video.videoWidth == '320') OK -EXPECTED (video.videoHeight == '240') OK - -Poster loaded - -EXPECTED (video.clientWidth == '320') OK -EXPECTED (video.clientHeight == '240') OK -EXPECTED (video.videoWidth == '320') OK -EXPECTED (video.videoHeight == '240') OK -END OF TEST -
diff --git a/third_party/WebKit/LayoutTests/media/video-poster-delayed.html b/third_party/WebKit/LayoutTests/media/video-poster-delayed.html index c3b622c9..9f378b3 100644 --- a/third_party/WebKit/LayoutTests/media/video-poster-delayed.html +++ b/third_party/WebKit/LayoutTests/media/video-poster-delayed.html
@@ -1,55 +1,28 @@ <!DOCTYPE HTML5> +<title>Delayed load of poster should not overwrite intrinsic size of video.</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="media-file.js"></script> +<video></video> +<script> +async_test(function(t) { + var video = document.querySelector("video"); -<html> - <head> - <title>Delayed load of poster should not overwrite intrinsic size of video</title> - <!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956 - (Please avoid writing new tests using video-test.js) --> - <script src=video-test.js></script> - <script src=media-file.js></script> - <style> - video { - border: 3px solid red; - background-color: magenta; - } - </style> - <script> - function start() - { - video = document.getElementById('video'); + video.onloadeddata = t.step_func(function() { + testVideoSize(); + video.poster = "content/abe.png"; + var image = document.createElement("img"); + image.src = "content/abe.png"; + image.onload = t.step_func_done(testVideoSize); + }); - video.addEventListener("loadeddata", function(ev) { + function testVideoSize() { + assert_equals(video.clientWidth, 320); + assert_equals(video.clientHeight, 240); + assert_equals(video.videoWidth, 320); + assert_equals(video.videoHeight, 240); + } - consoleWrite("<br><b>Video loaded</b><br>"); - - testExpected("video.clientWidth", 320); - testExpected("video.clientHeight", 240); - testExpected("video.videoWidth", 320); - testExpected("video.videoHeight", 240); - - video.poster = "content/abe.png"; - setTimeout(testAfterLoadingPoster, 100); - }); - - video.src = findMediaFile("video", "content/test"); - } - - function testAfterLoadingPoster() - { - consoleWrite("<br><b>Poster loaded</b><br>"); - - testExpected("video.clientWidth", 320); - testExpected("video.clientHeight", 240); - testExpected("video.videoWidth", 320); - testExpected("video.videoHeight", 240); - - endTest(); - } - </script> - </head> - - - <body onload="start()"> - <video id=video></video> - </body> -</html> + video.src = findMediaFile("video", "content/test"); +}); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/media/video-poster-expected.txt b/third_party/WebKit/LayoutTests/media/video-poster-expected.txt deleted file mode 100644 index d0bc367..0000000 --- a/third_party/WebKit/LayoutTests/media/video-poster-expected.txt +++ /dev/null
@@ -1,59 +0,0 @@ -Test <video> element with and without a poster. - -Testing poster null, with 'width' and 'height' attributes. -EXPECTED (video.getAttribute('poster') == 'null') OK -EXPECTED (relativeURL(video.poster) == '') OK -EXPECTED (video.clientWidth == '320') OK -EXPECTED (video.clientHeight == '240') OK - -Setting poster to "content/greenbox.png" -Testing 25x25 poster 'content/greenbox.png', size should equal image size. -EXPECTED (video.getAttribute('poster') == 'content/greenbox.png') OK -EXPECTED (relativeURL(video.poster) == 'content/greenbox.png') OK -EXPECTED (video.clientWidth == '25') OK -EXPECTED (video.clientHeight == '25') OK - -Setting poster to "" -Testing poster '', with NO 'width' or 'height' attributes so size should be <video> default. -EXPECTED (video.getAttribute('poster') == '') OK -EXPECTED (relativeURL(video.poster) == 'video-poster.html') OK -EXPECTED (video.clientWidth == '300') OK -EXPECTED (video.clientHeight == '150') OK - -Setting poster to "content/abe.png" -Testing 76x103 poster 'content/abe.png', size should equal image size. -EXPECTED (video.getAttribute('poster') == 'content/abe.png') OK -EXPECTED (relativeURL(video.poster) == 'content/abe.png') OK -EXPECTED (video.clientWidth == '76') OK -EXPECTED (video.clientHeight == '103') OK - -Setting poster to "content/bogus.png" -Testing 300x150 poster 'content/bogus.png', invalid url so size should revert to <video> default. -EXPECTED (video.getAttribute('poster') == 'content/bogus.png') OK -EXPECTED (relativeURL(video.poster) == 'content/bogus.png') OK -EXPECTED (video.clientWidth == '300') OK -EXPECTED (video.clientHeight == '150') OK - -Setting poster to "" -Testing poster '', with only a 'width' attribute so size should have the same aspect ratio as <video> default. -EXPECTED (video.getAttribute('poster') == '') OK -EXPECTED (relativeURL(video.poster) == 'video-poster.html') OK -EXPECTED (video.clientWidth == '600') OK -EXPECTED (video.clientHeight == '300') OK - -Setting poster to "content/abe.png" -Testing 152x206 poster 'content/abe.png', with only a 'width' attribute so size should equal a scaled up image size with the same aspect ratio as the original image. -EXPECTED (video.getAttribute('poster') == 'content/abe.png') OK -EXPECTED (relativeURL(video.poster) == 'content/abe.png') OK -EXPECTED (video.clientWidth == '152') OK -EXPECTED (video.clientHeight == '206') OK - -Setting poster to "content/bogus.png" -Testing 600x300 poster 'content/bogus.png', invalid url w/ width attribute so size should have the same aspect ratio as <video> default. -EXPECTED (video.getAttribute('poster') == 'content/bogus.png') OK -EXPECTED (relativeURL(video.poster) == 'content/bogus.png') OK -EXPECTED (video.clientWidth == '600') OK -EXPECTED (video.clientHeight == '300') OK - -END OF TEST -
diff --git a/third_party/WebKit/LayoutTests/media/video-poster.html b/third_party/WebKit/LayoutTests/media/video-poster.html index 8e12e19f..f7b9150 100644 --- a/third_party/WebKit/LayoutTests/media/video-poster.html +++ b/third_party/WebKit/LayoutTests/media/video-poster.html
@@ -1,142 +1,75 @@ -<html> - <head> - <title><video> element with poster size test</title> - <!-- TODO(foolip): Convert test to testharness.js. crbug.com/588956 - (Please avoid writing new tests using video-test.js) --> - <script src=video-test.js></script> - <script> - var posterInfo = - { - current:0, - posters: - [ - { - description:", with 'width' and 'height' attributes", - url:null, - reflectedUrl:"", - width:320, - height:240 - }, - { - description:", size should equal image size", - url:"content/greenbox.png", - width:25, - height:25 - }, - { - description:", with NO 'width' or 'height' attributes so size should be <video> default", - url:"", - reflectedUrl:"video-poster.html", - width:300, - height:150 - }, - { - description:", size should equal image size", - url:"content/abe.png", - width:76, - height:103 - }, - { - description:", invalid url so size should revert to <video> default", - url:"content/bogus.png", - width:300, - height:150 - }, - { - description:", with only a 'width' attribute so size should have the same aspect ratio as <video> default", - url:"", - reflectedUrl:"video-poster.html", - width:600, - height:300, - widthAttr: 600 - }, - { - description:", with only a 'width' attribute so size should equal a scaled up image size with the same aspect ratio as the original image", - url:"content/abe.png", - width:152, - height:206, - widthAttr: 152 - }, - { - description:", invalid url w/ width attribute so size should have the same aspect ratio as <video> default", - url:"content/bogus.png", - width:600, - height:300, - widthAttr: 600 - }, - ] - }; +<!DOCTYPE html> +<title>Test video poster with different dimensions.</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<body> +<script> +var posterInfo = [ + { + description: "Testing poster null, with 'width' and 'height' attributes.", + url: null, reflectedUrl: "", expectedWidth: 320, expectedHeight: 240, setSize: true + }, + { + description: "Testing 25x25 poster 'content/greenbox.png', size should equal image size.", + url: "content/greenbox.png", expectedWidth: 25, expectedHeight: 25 + }, + { + description: "Testing poster '', with NO 'width' or 'height' attributes so size should be <video> default.", + url: "", reflectedUrl: "video-poster.html", expectedWidth: 300, expectedHeight: 150 + }, + { + description: "Testing 76x103 poster 'content/abe.png', size should equal image size.", + url: "content/abe.png", expectedWidth: 76, expectedHeight: 103 + }, + { + description: "Testing 300x150 poster 'content/bogus.png', invalid url so size should revert to <video> default.", + url: "content/bogus.png", expectedWidth: 300, expectedHeight: 150 + }, + { + description: "Testing poster '', with only a 'width' attribute so size should have the same aspect ratio as <video> default.", + url: "", reflectedUrl: "video-poster.html", expectedWidth: 600, expectedHeight: 300, widthAttr: 600 + }, + { + description: "Testing 152x206 poster 'content/abe.png', with only a 'width' attribute so size should equal a scaled up image size with the same aspect ratio as the original image.", + url: "content/abe.png", expectedWidth: 152, expectedHeight: 206, widthAttr: 152 + }, + { + description: "Testing 600x300 poster 'content/bogus.png', invalid url w/ width attribute so size should have the same aspect ratio as <video> default.", + url: "content/bogus.png", expectedWidth: 600, expectedHeight: 300, widthAttr: 600 + } +]; - // Wait for |video| to have the |expectedWidth| and |expectedHeight| - // and invoke |callback()|. - function listenForWidthAndHeight(expectedWidth, expectedHeight, callback) { - if (video.clientWidth == expectedWidth && video.clientHeight == expectedHeight) { - callback(); - } else { - // This uses a 20ms sleep loop to accomplish the wait, since the - // standard specifies no events that fire on poster load or error. - window.setTimeout(listenForWidthAndHeight, 20, expectedWidth, expectedHeight, callback); - } - } +posterInfo.forEach(function(poster) { + async_test(function(t) { + var video = document.createElement("video"); + document.body.appendChild(video); + if (poster.setSize) { + video.setAttribute("width", "320"); + video.setAttribute("height", "240"); + } else { + video.poster = poster.url; + } + if (poster.widthAttr) + video.width = poster.widthAttr; + if (poster.url) { + var image = document.createElement("img"); + image.src = poster.url; + document.body.appendChild(image); + if (image.src.indexOf("bogus") > 0) + image.onerror = t.step_func_done(testPoster); + else + image.onload = t.step_func_done(testPoster); + } else { + setTimeout(t.step_func_done(testPoster), 0); + } - function testPoster() - { - var temp = document.body.offsetWidth; - var poster = posterInfo.posters[posterInfo.current]; - - var size = poster.url ? (" " + poster.width + "x" + poster.height) : ""; - var urlStr = typeof(poster.url) == "string" ? ("'" + poster.url + "'") : 'null'; - var desc = "<b>Testing" + size + " poster <em>"+ urlStr + "</em>" + poster.description + ".</b>"; - consoleWrite(desc); - - testExpected("video.getAttribute('poster')", poster.url); - testExpected("relativeURL(video.poster)", poster.hasOwnProperty("reflectedUrl") ? poster.reflectedUrl : poster.url); - testExpected("video.clientWidth", poster.width); - testExpected("video.clientHeight", poster.height); - - // Remove width/height attributes if present - if (video.width) - video.removeAttribute('width'); - if (video.height) - video.removeAttribute('height'); - - posterInfo.current++; - consoleWrite(""); - if (posterInfo.current >= posterInfo.posters.length) { - endTest(); - return; - } - var currentPoster = posterInfo.posters[posterInfo.current]; - - if (currentPoster.widthAttr) - video.width = currentPoster.widthAttr; - - var url = currentPoster.url; - var desc = "<b>Setting poster to <em>\""+ url + "\"</em></b>"; - consoleWrite(desc); - video.poster = url; - listenForWidthAndHeight(currentPoster.width, currentPoster.height, testPoster); - } - - function unexpectedEvent(evt) - { - consoleWrite(""); - failTest("Unexpected '" + evt.type + "' event fired!"); - } - - function setup() - { - document.addEventListener("error", unexpectedEvent); - document.addEventListener("load", unexpectedEvent); - findMediaElement(); - testPoster(); - } - </script> - </head> - - <body> - <video controls width=320 height=240></video> - <p>Test <video> element with and without a poster.</p> - <script>setup();</script> - </body> -</html> + function testPoster() { + assert_equals(video.getAttribute("poster"), poster.url); + var url = video.poster.substr(video.poster.lastIndexOf("/media/") + 7); + assert_equals(url, (poster.hasOwnProperty("reflectedUrl") ? poster.reflectedUrl : poster.url)); + assert_equals(video.clientWidth, poster.expectedWidth); + assert_equals(video.clientHeight, poster.expectedHeight); + } + }, poster.description); +}); +</script> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/iframe-scrollbar-hover-expected.txt b/third_party/WebKit/LayoutTests/paint/invalidation/iframe-scrollbar-hover-expected.txt new file mode 100644 index 0000000..b27b6bd8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/paint/invalidation/iframe-scrollbar-hover-expected.txt
@@ -0,0 +1,26 @@ +{ + "name": "Content Root Layer", + "bounds": [800, 600], + "children": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "drawsContent": true, + "paintInvalidations": [ + { + "object": "LayoutView #document", + "rect": [187, 102, 15, 200], + "reason": "scroll" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "VerticalScrollbar", + "reason": "scroll" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/iframe-scrollbar-hover.html b/third_party/WebKit/LayoutTests/paint/invalidation/iframe-scrollbar-hover.html new file mode 100644 index 0000000..561030d --- /dev/null +++ b/third_party/WebKit/LayoutTests/paint/invalidation/iframe-scrollbar-hover.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<script src="../../fast/repaint/resources/text-based-repaint.js"></script> +<script> +function repaintTest() { + eventSender.mouseMoveTo(195, 120); +} +if (window.eventSender) + onload = runRepaintTest; +</script> +Tests paint invalidation when mouse hovers on the scrollbar in an iframe. +<iframe id="iframe" + style="position: absolute; top: 100px; left: 0; width: 200px; height: 200px" + srcdoc="<div style='height: 300px'></div>"></iframe>
diff --git a/third_party/WebKit/LayoutTests/payments/payment-request-interface.html b/third_party/WebKit/LayoutTests/payments/payment-request-interface.html index c0854654..670f291 100644 --- a/third_party/WebKit/LayoutTests/payments/payment-request-interface.html +++ b/third_party/WebKit/LayoutTests/payments/payment-request-interface.html
@@ -204,6 +204,10 @@ ['Duplicate supported payment method identifiers should throw TypeError.', null, function() { new PaymentRequest([{'supportedMethods': ['foo']}, {'supportedMethods': ['foo']}], buildDetails(), {}) }], + ['Duplicate shipping option identifiers should throw TypeError.', null, function() { + var shippingOptions = [buildItem({'id': 'express', 'selected': false}), buildItem({'id': 'express', 'selected': true})]; + new PaymentRequest([{'supportedMethods': ['foo']}], {'total': buildItem(), 'displayItems': [buildItem()], 'shippingOptions': shippingOptions}, {'requestShipping': true}) + }], ['Absence of total should throw TypeError.', null, function() { new PaymentRequest([{'supportedMethods': ['foo']}], {'displayItems': [buildItem()]}) }],
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/css/object-fit-grow-landscape-expected.png b/third_party/WebKit/LayoutTests/platform/android/fast/css/object-fit-grow-landscape-expected.png new file mode 100644 index 0000000..3c2500b --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/fast/css/object-fit-grow-landscape-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/css/object-fit-grow-portrait-expected.png b/third_party/WebKit/LayoutTests/platform/android/fast/css/object-fit-grow-portrait-expected.png new file mode 100644 index 0000000..5d41825 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/fast/css/object-fit-grow-portrait-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/android/fast/text/hyphens/can-hyphenate-locale-expected.txt b/third_party/WebKit/LayoutTests/platform/android/fast/text/hyphens/can-hyphenate-locale-expected.txt new file mode 100644 index 0000000..a33f2111 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/fast/text/hyphens/can-hyphenate-locale-expected.txt
@@ -0,0 +1,6 @@ +This is a testharness.js-based test. +PASS This test requires "internals.canHyphenate" +PASS "en-us" can hyphenate +PASS "ja-jp" cannot hyphenate +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/platform/android/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange-expected.txt b/third_party/WebKit/LayoutTests/platform/android/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange-expected.txt new file mode 100644 index 0000000..6aa9277 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/android/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange-expected.txt
@@ -0,0 +1,45 @@ +This is a testharness.js-based test. +PASS test of input.setSelectionRange +PASS input typeof(input.setSelectionRange)' +PASS input setSelectionRange return void +PASS input setSelectionRange(0,1) +PASS input setSelectionRange(0,input.value.length+1) +PASS input setSelectionRange(2,2) +PASS input setSelectionRange(2,1) +PASS input direction of setSelectionRange(0,1,"backward") +PASS input direction of setSelectionRange(0,1,"forward") +FAIL input direction of setSelectionRange(0,1,"none") assert_equals: The direction of the selection must be set to forward if direction is a case-sensitive match for the string "none" expected "none" but got "forward" +FAIL input direction of setSelectionRange(0,1,"hoge") assert_equals: otherwise expected "none" but got "forward" +FAIL input direction of setSelectionRange(0,1,"BACKWARD") assert_equals: selectionDirection should be 'none' expected "none" but got "forward" +PASS input direction of setSelectionRange(0,1) +PASS input setSelectionRange("string",1) +PASS input setSelectionRange(true,1) +PASS input setSelectionRange([],1) +PASS input setSelectionRange({},1) +PASS input setSelectionRange(NaN,1) +PASS input setSelectionRange(null,1) +PASS input setSelectionRange(undefined,1) +PASS input setSelectionRange fires a select event +PASS test of textarea.setSelectionRange +PASS textarea typeof(input.setSelectionRange)' +PASS textarea setSelectionRange return void +PASS textarea setSelectionRange(0,1) +PASS textarea setSelectionRange(0,textarea.value.length+1) +PASS textarea setSelectionRange(2,2) +PASS textarea setSelectionRange(2,1) +PASS textarea direction of setSelectionRange(0,1,"backward") +PASS textarea direction of setSelectionRange(0,1,"forward") +FAIL textarea direction of setSelectionRange(0,1,"none") assert_equals: The direction of the selection must be set to forward if direction is a case-sensitive match for the string "none" expected "none" but got "forward" +FAIL textarea direction of setSelectionRange(0,1,"hoge") assert_equals: otherwise expected "none" but got "forward" +FAIL textarea direction of setSelectionRange(0,1,"BACKWARD") assert_equals: selectionDirection should be 'none' expected "none" but got "forward" +FAIL textarea direction of setSelectionRange(0,1) assert_equals: if the argument is omitted expected "none" but got "forward" +PASS textarea setSelectionRange("string",1) +PASS textarea setSelectionRange(true,1) +PASS textarea setSelectionRange([],1) +PASS textarea setSelectionRange({},1) +PASS textarea setSelectionRange(NaN,1) +PASS textarea setSelectionRange(null,1) +PASS textarea setSelectionRange(undefined,1) +PASS textarea setSelectionRange fires a select event +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png deleted file mode 100644 index 3800115..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png deleted file mode 100644 index 48bb2ea7..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png deleted file mode 100644 index 5719692b..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png deleted file mode 100644 index 9d5233a2..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png deleted file mode 100644 index 2ae568db..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png deleted file mode 100644 index 5dc078d..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux-precise/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/img-layer-object-fit-expected.png b/third_party/WebKit/LayoutTests/platform/linux/compositing/img-layer-object-fit-expected.png new file mode 100644 index 0000000..0f664d90 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/img-layer-object-fit-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/img-layer-object-fit-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/compositing/img-layer-object-fit-expected.txt new file mode 100644 index 0000000..65d36b2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/img-layer-object-fit-expected.txt
@@ -0,0 +1,17 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x156 + LayoutBlockFlow {HTML} at (0,0) size 800x156 + LayoutBlockFlow {BODY} at (8,8) size 784x140 + LayoutBR {BR} at (100,15) size 0x19 + LayoutBR {BR} at (100,50) size 0x19 + LayoutBR {BR} at (100,85) size 0x19 + LayoutBR {BR} at (100,120) size 0x19 +layer at (8,8) size 100x30 + LayoutImage {IMG} at (0,0) size 100x30 +layer at (8,43) size 100x30 + LayoutImage {IMG} at (0,35) size 100x30 +layer at (8,78) size 100x30 + LayoutImage {IMG} at (0,70) size 100x30 +layer at (8,113) size 100x30 + LayoutImage {IMG} at (0,105) size 100x30
diff --git a/third_party/WebKit/LayoutTests/platform/linux/compositing/tiled-layers-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/compositing/tiled-layers-hidpi-expected.txt new file mode 100644 index 0000000..702643f --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/compositing/tiled-layers-hidpi-expected.txt
@@ -0,0 +1,23 @@ +{ + "name": "Content Root Layer", + "bounds": [1808, 585], + "children": [ + { + "name": "LayoutView #document", + "bounds": [1808, 585], + "contentsOpaque": true, + "drawsContent": true, + "children": [ + { + "name": "LayoutBlockFlow DIV id='composited'", + "position": [8, 8], + "bounds": [1800, 10], + "contentsOpaque": true, + "drawsContent": true, + "backgroundColor": "#0000FF" + } + ] + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hidpi-expected.txt new file mode 100644 index 0000000..3a37906 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hidpi-expected.txt
@@ -0,0 +1,27 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x600 + LayoutBlockFlow {HTML} at (0,0) size 800x600 + LayoutBlockFlow {BODY} at (8,8) size 784x584 + LayoutSVGRoot {svg} at (8,8) size 0x0 + LayoutSVGHiddenContainer {defs} at (0,0) size 0x0 + LayoutSVGResourceFilter {filter} [id="displacement"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse] + [feDisplacementMap scale="10.00" xChannelSelector="RED" yChannelSelector="GREEN"] + [SourceGraphic] + [SourceGraphic] + LayoutSVGResourceFilter {filter} [id="turbulence"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse] + [feTurbulence type="TURBULENCE" baseFrequency="0.05, 0.05" seed="0.00" numOctaves="2" stitchTiles="0"] + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 +layer at (20,20) size 160x90 + LayoutImage (positioned) {IMG} at (20,20) size 160x90 +layer at (220,20) size 160x90 + LayoutImage (positioned) {IMG} at (220,20) size 160x90 +layer at (20,150) size 160x90 + LayoutImage (positioned) {IMG} at (20,150) size 160x90 +layer at (220,150) size 160x90 + LayoutImage (positioned) {IMG} at (220,150) size 160x90
diff --git a/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hidpi-hw-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hidpi-hw-expected.txt new file mode 100644 index 0000000..3a37906 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/css3/filters/effect-reference-hidpi-hw-expected.txt
@@ -0,0 +1,27 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x600 + LayoutBlockFlow {HTML} at (0,0) size 800x600 + LayoutBlockFlow {BODY} at (8,8) size 784x584 + LayoutSVGRoot {svg} at (8,8) size 0x0 + LayoutSVGHiddenContainer {defs} at (0,0) size 0x0 + LayoutSVGResourceFilter {filter} [id="displacement"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse] + [feDisplacementMap scale="10.00" xChannelSelector="RED" yChannelSelector="GREEN"] + [SourceGraphic] + [SourceGraphic] + LayoutSVGResourceFilter {filter} [id="turbulence"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse] + [feTurbulence type="TURBULENCE" baseFrequency="0.05, 0.05" seed="0.00" numOctaves="2" stitchTiles="0"] + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 +layer at (20,20) size 160x90 + LayoutImage (positioned) {IMG} at (20,20) size 160x90 +layer at (220,20) size 160x90 + LayoutImage (positioned) {IMG} at (220,20) size 160x90 +layer at (20,150) size 160x90 + LayoutImage (positioned) {IMG} at (20,150) size 160x90 +layer at (220,150) size 160x90 + LayoutImage (positioned) {IMG} at (220,150) size 160x90
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/backgrounds/gradient-background-leakage-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/backgrounds/gradient-background-leakage-hidpi-expected.txt new file mode 100644 index 0000000..2c151137 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/backgrounds/gradient-background-leakage-hidpi-expected.txt
@@ -0,0 +1,7 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x68 + LayoutBlockFlow {HTML} at (0,0) size 800x68 + LayoutBlockFlow {BODY} at (8,8) size 784x52 + LayoutBlockFlow {DIV} at (0,0) size 220x52 [bgcolor=#FF0000] + LayoutBlockFlow {DIV} at (10,10) size 202x32 [border: (1px solid #008000)]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-landscape-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-landscape-expected.png new file mode 100644 index 0000000..51e608b --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-landscape-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-landscape-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-landscape-expected.txt new file mode 100644 index 0000000..f807a257 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-landscape-expected.txt
@@ -0,0 +1,18 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x358 + LayoutBlockFlow {HTML} at (0,0) size 800x358 + LayoutBlockFlow {BODY} at (8,8) size 784x342 + LayoutImage {IMG} at (10,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (166,151) size 4x19 + text run at (166,151) width 4: " " + LayoutImage {IMG} at (180,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (336,151) size 4x19 + text run at (336,151) width 4: " " + LayoutImage {IMG} at (350,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (506,151) size 4x19 + text run at (506,151) width 4: " " + LayoutImage {IMG} at (520,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (0,0) size 0x0 + LayoutImage {IMG} at (10,181) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-portrait-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-portrait-expected.png new file mode 100644 index 0000000..2d36ac6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-portrait-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-portrait-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-portrait-expected.txt new file mode 100644 index 0000000..f807a257 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/css/object-fit-grow-portrait-expected.txt
@@ -0,0 +1,18 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x358 + LayoutBlockFlow {HTML} at (0,0) size 800x358 + LayoutBlockFlow {BODY} at (8,8) size 784x342 + LayoutImage {IMG} at (10,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (166,151) size 4x19 + text run at (166,151) width 4: " " + LayoutImage {IMG} at (180,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (336,151) size 4x19 + text run at (336,151) width 4: " " + LayoutImage {IMG} at (350,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (506,151) size 4x19 + text run at (506,151) width 4: " " + LayoutImage {IMG} at (520,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (0,0) size 0x0 + LayoutImage {IMG} at (10,181) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/dom/comment-not-documentElement-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/dom/comment-not-documentElement-expected.png index 48234fa..a82e03e6 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/dom/comment-not-documentElement-expected.png +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/dom/comment-not-documentElement-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/dom/comment-not-documentElement-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/dom/comment-not-documentElement-expected.txt index d0394209..41795fa 100644 --- a/third_party/WebKit/LayoutTests/platform/linux/fast/dom/comment-not-documentElement-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/dom/comment-not-documentElement-expected.txt
@@ -3,5 +3,5 @@ layer at (0,0) size 800x600 LayoutBlockFlow {HTML} at (0,0) size 800x600 LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutText {#text} at (0,0) size 58x19 - text run at (0,0) width 58: "SUCESS" + LayoutText {#text} at (0,0) size 69x19 + text run at (0,0) width 69: "SUCCESS"
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-none-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-none-expected.png new file mode 100644 index 0000000..90524e8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-none-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-none-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-none-expected.txt new file mode 100644 index 0000000..0ca2ae51 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/forms/select/menulist-appearance-none-expected.txt
@@ -0,0 +1,24 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x600 + LayoutBlockFlow {HTML} at (0,0) size 800x600 + LayoutBlockFlow {BODY} at (8,8) size 784x584 + LayoutBlockFlow {P} at (0,0) size 784x40 + LayoutText {#text} at (0,0) size 111x19 + text run at (0,0) width 111: "Rendering test for " + LayoutInline {I} at (0,0) size 779x39 + LayoutInline {A} at (0,0) size 410x19 [color=#0000EE] + LayoutText {#text} at (111,0) size 410x19 + text run at (111,0) width 410: "https://bugs.chromium.org/p/chromium/issues/detail?id=626278" + LayoutText {#text} at (520,0) size 779x39 + text run at (520,0) width 5: " " + text run at (524,0) width 255: "Regression: HTML Select's text appears" + text run at (0,20) width 234: "chopped if appearance is set to none" + LayoutText {#text} at (234,20) size 4x19 + text run at (234,20) width 4: "." + LayoutBlockFlow (anonymous) at (0,56) size 784x42 + LayoutMenuList {SELECT} at (0,0) size 26x42 [bgcolor=#C0C0C0] [border: (1px solid #A9A9A9)] + LayoutBlockFlow (anonymous) at (1,1) size 24x40 + LayoutText (anonymous) at (0,12) size 24x16 + text run at (0,12) width 24: "Test" + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/device-scale-factor-paint-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/device-scale-factor-paint-expected.txt new file mode 100644 index 0000000..9dc946c --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/device-scale-factor-paint-expected.txt
@@ -0,0 +1,7 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x8 + LayoutBlockFlow {HTML} at (0,0) size 800x8 + LayoutBlockFlow {BODY} at (8,8) size 784x0 +layer at (5,10) size 50x50 + LayoutBlockFlow (positioned) {DIV} at (5,10) size 50x50 [bgcolor=#008000]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/focus-rings-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/focus-rings-expected.png new file mode 100644 index 0000000..837ac39 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/focus-rings-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/focus-rings-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/focus-rings-expected.txt new file mode 100644 index 0000000..ff6671b4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/focus-rings-expected.txt
@@ -0,0 +1,6 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x168 + LayoutBlockFlow {HTML} at (0,0) size 800x168 + LayoutBlockFlow {BODY} at (8,8) size 784x152 + LayoutBlockFlow {DIV} at (0,0) size 302x152 [border: (1px solid #000000)]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/gradient-with-scaled-ancestor-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/gradient-with-scaled-ancestor-expected.txt new file mode 100644 index 0000000..d24aa5a --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/gradient-with-scaled-ancestor-expected.txt
@@ -0,0 +1,8 @@ +layer at (0,0) size 800x600 scrollWidth 1184 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x318 + LayoutBlockFlow {HTML} at (0,0) size 800x318 + LayoutBlockFlow {BODY} at (8,8) size 784x302 +layer at (8,8) size 784x302 + LayoutBlockFlow {DIV} at (0,0) size 784x302 + LayoutBlockFlow {DIV} at (0,0) size 302x302 [border: (1px solid #000000)]
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/image-srcset-intrinsic-size-zero-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/image-srcset-intrinsic-size-zero-expected.txt new file mode 100644 index 0000000..27bb9c4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/image-srcset-intrinsic-size-zero-expected.txt
@@ -0,0 +1,6 @@ +PASS successfullyParsed is true + +TEST COMPLETE +PASS imgWidth is 33554431 +This test passes if the image is displayed with infinite dimensions. +
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/shadows-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/shadows-hidpi-expected.txt new file mode 100644 index 0000000..8d1c2ecc --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/fast/sub-pixel/shadows-hidpi-expected.txt
@@ -0,0 +1,20 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x58 + LayoutBlockFlow {HTML} at (0,0) size 800x58 + LayoutBlockFlow {BODY} at (8,8) size 784x42 + LayoutBlockFlow {DIV} at (0,0) size 784x10 + LayoutText {#text} at (0,0) size 30x10 + text run at (0,0) width 30: "XXX" + LayoutBlockFlow (anonymous) at (0,10) size 784x32 + LayoutBR {BR} at (0,0) size 0x10 + LayoutBR {BR} at (0,10) size 0x10 + LayoutBlockFlow {DIV} at (0,20) size 32x12 [border: (1px solid #000000)] + LayoutText {#text} at (1,1) size 30x10 + text run at (1,1) width 30: "XXX" + LayoutText {#text} at (32,21) size 10x10 + text run at (32,21) width 10: " " + LayoutBlockFlow {DIV} at (42,20) size 32x12 [border: (1px solid #000000)] + LayoutText {#text} at (1,1) size 30x10 + text run at (1,1) width 30: "XXX" + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt new file mode 100644 index 0000000..28ceb64 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt
@@ -0,0 +1,47 @@ +{ + "name": "Content Root Layer", + "bounds": [800, 600], + "children": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "drawsContent": true, + "paintInvalidations": [ + { + "object": "LayoutInline SPAN id='target'", + "rect": [6, 6, 204, 58], + "reason": "style change" + }, + { + "object": "LayoutImage IMG", + "rect": [8, 8, 200, 50], + "reason": "forced by layout" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutBlockFlow BODY", + "reason": "forced by layout" + }, + { + "object": "RootInlineBox", + "reason": "forced by layout" + }, + { + "object": "LayoutInline SPAN id='target'", + "reason": "style change" + }, + { + "object": "InlineFlowBox", + "reason": "style change" + }, + { + "object": "LayoutImage IMG", + "reason": "forced by layout" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/platform/linux/svg/filters/filter-source-position-expected.png b/third_party/WebKit/LayoutTests/platform/linux/svg/filters/filter-source-position-expected.png deleted file mode 100644 index 45ad640..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/svg/filters/filter-source-position-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-none-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-none-expected.png new file mode 100644 index 0000000..d813324e --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-none-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-none-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-none-expected.txt new file mode 100644 index 0000000..c9a371a --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.10/fast/forms/select/menulist-appearance-none-expected.txt
@@ -0,0 +1,24 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x600 + LayoutBlockFlow {HTML} at (0,0) size 800x600 + LayoutBlockFlow {BODY} at (8,8) size 784x584 + LayoutBlockFlow {P} at (0,0) size 784x36 + LayoutText {#text} at (0,0) size 120x18 + text run at (0,0) width 120: "Rendering test for " + LayoutInline {I} at (0,0) size 739x36 + LayoutInline {A} at (0,0) size 414x18 [color=#0000EE] + LayoutText {#text} at (119,0) size 414x18 + text run at (119,0) width 414: "https://bugs.chromium.org/p/chromium/issues/detail?id=626278" + LayoutText {#text} at (533,0) size 739x36 + text run at (533,0) width 4: " " + text run at (537,0) width 202: "Regression: HTML Select's text" + text run at (0,18) width 291: "appears chopped if appearance is set to none" + LayoutText {#text} at (290,18) size 5x18 + text run at (290,18) width 5: "." + LayoutBlockFlow (anonymous) at (0,52) size 784x42 + LayoutMenuList {SELECT} at (0,0) size 23x42 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)] + LayoutBlockFlow (anonymous) at (1,1) size 21x40 + LayoutText (anonymous) at (0,13) size 21x13 + text run at (0,13) width 21: "Test" + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-none-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-none-expected.png new file mode 100644 index 0000000..9db9d55 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-none-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-none-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-none-expected.txt new file mode 100644 index 0000000..741aebe --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac-mac10.9/fast/forms/select/menulist-appearance-none-expected.txt
@@ -0,0 +1,24 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x600 + LayoutBlockFlow {HTML} at (0,0) size 800x600 + LayoutBlockFlow {BODY} at (8,8) size 784x584 + LayoutBlockFlow {P} at (0,0) size 784x36 + LayoutText {#text} at (0,0) size 120x18 + text run at (0,0) width 120: "Rendering test for " + LayoutInline {I} at (0,0) size 739x36 + LayoutInline {A} at (0,0) size 414x18 [color=#0000EE] + LayoutText {#text} at (119,0) size 414x18 + text run at (119,0) width 414: "https://bugs.chromium.org/p/chromium/issues/detail?id=626278" + LayoutText {#text} at (533,0) size 739x36 + text run at (533,0) width 4: " " + text run at (537,0) width 202: "Regression: HTML Select's text" + text run at (0,18) width 291: "appears chopped if appearance is set to none" + LayoutText {#text} at (290,18) size 5x18 + text run at (290,18) width 5: "." + LayoutBlockFlow (anonymous) at (0,52) size 784x42 + LayoutMenuList {SELECT} at (0,0) size 25x42 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)] + LayoutBlockFlow (anonymous) at (1,1) size 23x40 + LayoutText (anonymous) at (0,13) size 23x13 + text run at (0,13) width 23: "Test" + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png deleted file mode 100644 index a68f08e4..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png deleted file mode 100644 index cf65cf9..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png deleted file mode 100644 index aa6a2fb..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png deleted file mode 100644 index aa84c0a..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png deleted file mode 100644 index 9462fd8..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png deleted file mode 100644 index 22f8cc8..0000000 --- a/third_party/WebKit/LayoutTests/platform/mac-retina/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/compositing/img-layer-object-fit-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/compositing/img-layer-object-fit-expected.txt new file mode 100644 index 0000000..08ab093 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/compositing/img-layer-object-fit-expected.txt
@@ -0,0 +1,17 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x152 + LayoutBlockFlow {HTML} at (0,0) size 800x152 + LayoutBlockFlow {BODY} at (8,8) size 784x136 + LayoutBR {BR} at (100,16) size 0x18 + LayoutBR {BR} at (100,50) size 0x18 + LayoutBR {BR} at (100,84) size 0x18 + LayoutBR {BR} at (100,118) size 0x18 +layer at (8,8) size 100x30 + LayoutImage {IMG} at (0,0) size 100x30 +layer at (8,42) size 100x30 + LayoutImage {IMG} at (0,34) size 100x30 +layer at (8,76) size 100x30 + LayoutImage {IMG} at (0,68) size 100x30 +layer at (8,110) size 100x30 + LayoutImage {IMG} at (0,102) size 100x30
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-landscape-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-landscape-expected.png new file mode 100644 index 0000000..7352cb57 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-landscape-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-landscape-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-landscape-expected.txt new file mode 100644 index 0000000..c977439 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-landscape-expected.txt
@@ -0,0 +1,18 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x356 + LayoutBlockFlow {HTML} at (0,0) size 800x356 + LayoutBlockFlow {BODY} at (8,8) size 784x340 + LayoutImage {IMG} at (10,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (166,152) size 4x18 + text run at (166,152) width 4: " " + LayoutImage {IMG} at (180,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (336,152) size 4x18 + text run at (336,152) width 4: " " + LayoutImage {IMG} at (350,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (506,152) size 4x18 + text run at (506,152) width 4: " " + LayoutImage {IMG} at (520,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (0,0) size 0x0 + LayoutImage {IMG} at (10,180) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-portrait-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-portrait-expected.png new file mode 100644 index 0000000..159d3cb --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-portrait-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-portrait-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-portrait-expected.txt new file mode 100644 index 0000000..c977439 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/css/object-fit-grow-portrait-expected.txt
@@ -0,0 +1,18 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x356 + LayoutBlockFlow {HTML} at (0,0) size 800x356 + LayoutBlockFlow {BODY} at (8,8) size 784x340 + LayoutImage {IMG} at (10,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (166,152) size 4x18 + text run at (166,152) width 4: " " + LayoutImage {IMG} at (180,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (336,152) size 4x18 + text run at (336,152) width 4: " " + LayoutImage {IMG} at (350,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (506,152) size 4x18 + text run at (506,152) width 4: " " + LayoutImage {IMG} at (520,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (0,0) size 0x0 + LayoutImage {IMG} at (10,180) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/dom/comment-not-documentElement-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/dom/comment-not-documentElement-expected.png index d44dacb12..ce74fb7 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/dom/comment-not-documentElement-expected.png +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/dom/comment-not-documentElement-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/dom/comment-not-documentElement-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/dom/comment-not-documentElement-expected.txt index 1ef4997..783028b 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/fast/dom/comment-not-documentElement-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/dom/comment-not-documentElement-expected.txt
@@ -3,5 +3,5 @@ layer at (0,0) size 800x600 LayoutBlockFlow {HTML} at (0,0) size 800x600 LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutText {#text} at (0,0) size 59x18 - text run at (0,0) width 59: "SUCESS" + LayoutText {#text} at (0,0) size 70x18 + text run at (0,0) width 70: "SUCCESS"
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-none-expected.png b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-none-expected.png new file mode 100644 index 0000000..0b66b1f --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-none-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-none-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-none-expected.txt new file mode 100644 index 0000000..741aebe --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/forms/select/menulist-appearance-none-expected.txt
@@ -0,0 +1,24 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x600 + LayoutBlockFlow {HTML} at (0,0) size 800x600 + LayoutBlockFlow {BODY} at (8,8) size 784x584 + LayoutBlockFlow {P} at (0,0) size 784x36 + LayoutText {#text} at (0,0) size 120x18 + text run at (0,0) width 120: "Rendering test for " + LayoutInline {I} at (0,0) size 739x36 + LayoutInline {A} at (0,0) size 414x18 [color=#0000EE] + LayoutText {#text} at (119,0) size 414x18 + text run at (119,0) width 414: "https://bugs.chromium.org/p/chromium/issues/detail?id=626278" + LayoutText {#text} at (533,0) size 739x36 + text run at (533,0) width 4: " " + text run at (537,0) width 202: "Regression: HTML Select's text" + text run at (0,18) width 291: "appears chopped if appearance is set to none" + LayoutText {#text} at (290,18) size 5x18 + text run at (290,18) width 5: "." + LayoutBlockFlow (anonymous) at (0,52) size 784x42 + LayoutMenuList {SELECT} at (0,0) size 25x42 [bgcolor=#F8F8F8] [border: (1px solid #A6A6A6)] + LayoutBlockFlow (anonymous) at (1,1) size 23x40 + LayoutText (anonymous) at (0,13) size 23x13 + text run at (0,13) width 23: "Test" + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac/fast/text/hyphens/can-hyphenate-locale-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/fast/text/hyphens/can-hyphenate-locale-expected.txt new file mode 100644 index 0000000..a33f2111 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/mac/fast/text/hyphens/can-hyphenate-locale-expected.txt
@@ -0,0 +1,6 @@ +This is a testharness.js-based test. +PASS This test requires "internals.canHyphenate" +PASS "en-us" can hyphenate +PASS "ja-jp" cannot hyphenate +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/platform/mac/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange-expected.txt index 440795b33f..cca148f5e 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange-expected.txt
@@ -4,6 +4,8 @@ PASS input setSelectionRange return void PASS input setSelectionRange(0,1) PASS input setSelectionRange(0,input.value.length+1) +PASS input setSelectionRange(input.value.length+1,input.value.length+1) +PASS input setSelectionRange(input.value.length+1,input.value.length+1) PASS input setSelectionRange(2,2) PASS input setSelectionRange(2,1) PASS input direction of setSelectionRange(0,1,"backward") @@ -12,6 +14,8 @@ PASS input direction of setSelectionRange(0,1,"hoge") PASS input direction of setSelectionRange(0,1,"BACKWARD") PASS input direction of setSelectionRange(0,1) +FAIL input setSelectionRange(1,-1) assert_equals: element.selectionStart should be 1 expected 1 but got 0 +FAIL input setSelectionRange(-1,1) assert_equals: ECMAScript conversion to unsigned long + if end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end expected 1 but got 0 PASS input setSelectionRange("string",1) PASS input setSelectionRange(true,1) PASS input setSelectionRange([],1)
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/img-layer-object-fit-expected.txt b/third_party/WebKit/LayoutTests/platform/win/compositing/img-layer-object-fit-expected.txt new file mode 100644 index 0000000..2470a2a4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/img-layer-object-fit-expected.txt
@@ -0,0 +1,17 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x152 + LayoutBlockFlow {HTML} at (0,0) size 800x152 + LayoutBlockFlow {BODY} at (8,8) size 784x136 + LayoutBR {BR} at (100,16) size 0x17 + LayoutBR {BR} at (100,50) size 0x17 + LayoutBR {BR} at (100,84) size 0x17 + LayoutBR {BR} at (100,118) size 0x17 +layer at (8,8) size 100x30 + LayoutImage {IMG} at (0,0) size 100x30 +layer at (8,42) size 100x30 + LayoutImage {IMG} at (0,34) size 100x30 +layer at (8,76) size 100x30 + LayoutImage {IMG} at (0,68) size 100x30 +layer at (8,110) size 100x30 + LayoutImage {IMG} at (0,102) size 100x30
diff --git a/third_party/WebKit/LayoutTests/platform/win/compositing/tiled-layers-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/compositing/tiled-layers-hidpi-expected.txt new file mode 100644 index 0000000..a6cbb89 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/compositing/tiled-layers-hidpi-expected.txt
@@ -0,0 +1,23 @@ +{ + "name": "Content Root Layer", + "bounds": [3616, 1170], + "children": [ + { + "name": "LayoutView #document", + "bounds": [3616, 1170], + "contentsOpaque": true, + "drawsContent": true, + "children": [ + { + "name": "LayoutBlockFlow DIV id='composited'", + "position": [16, 16], + "bounds": [3600, 20], + "contentsOpaque": true, + "drawsContent": true, + "backgroundColor": "#0000FF" + } + ] + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hidpi-expected.txt new file mode 100644 index 0000000..7e0b8609 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hidpi-expected.txt
@@ -0,0 +1,27 @@ +layer at (0,0) size 1600x1200 + LayoutView at (0,0) size 1600x1200 +layer at (0,0) size 1600x1200 + LayoutBlockFlow {HTML} at (0,0) size 1600x1200 + LayoutBlockFlow {BODY} at (16,16) size 1568x1168 + LayoutSVGRoot {svg} at (16,16) size 0x0 + LayoutSVGHiddenContainer {defs} at (0,0) size 0x0 + LayoutSVGResourceFilter {filter} [id="displacement"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse] + [feDisplacementMap scale="10.00" xChannelSelector="RED" yChannelSelector="GREEN"] + [SourceGraphic] + [SourceGraphic] + LayoutSVGResourceFilter {filter} [id="turbulence"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse] + [feTurbulence type="TURBULENCE" baseFrequency="0.05, 0.05" seed="0.00" numOctaves="2" stitchTiles="0"] + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 +layer at (40,40) size 320x180 + LayoutImage (positioned) {IMG} at (40,40) size 320x180 +layer at (440,40) size 320x180 + LayoutImage (positioned) {IMG} at (440,40) size 320x180 +layer at (40,300) size 320x180 + LayoutImage (positioned) {IMG} at (40,300) size 320x180 +layer at (440,300) size 320x180 + LayoutImage (positioned) {IMG} at (440,300) size 320x180
diff --git a/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hidpi-hw-expected.txt b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hidpi-hw-expected.txt new file mode 100644 index 0000000..7e0b8609 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/css3/filters/effect-reference-hidpi-hw-expected.txt
@@ -0,0 +1,27 @@ +layer at (0,0) size 1600x1200 + LayoutView at (0,0) size 1600x1200 +layer at (0,0) size 1600x1200 + LayoutBlockFlow {HTML} at (0,0) size 1600x1200 + LayoutBlockFlow {BODY} at (16,16) size 1568x1168 + LayoutSVGRoot {svg} at (16,16) size 0x0 + LayoutSVGHiddenContainer {defs} at (0,0) size 0x0 + LayoutSVGResourceFilter {filter} [id="displacement"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse] + [feDisplacementMap scale="10.00" xChannelSelector="RED" yChannelSelector="GREEN"] + [SourceGraphic] + [SourceGraphic] + LayoutSVGResourceFilter {filter} [id="turbulence"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse] + [feTurbulence type="TURBULENCE" baseFrequency="0.05, 0.05" seed="0.00" numOctaves="2" stitchTiles="0"] + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 + LayoutText {#text} at (0,0) size 0x0 +layer at (40,40) size 320x180 + LayoutImage (positioned) {IMG} at (40,40) size 320x180 +layer at (440,40) size 320x180 + LayoutImage (positioned) {IMG} at (440,40) size 320x180 +layer at (40,300) size 320x180 + LayoutImage (positioned) {IMG} at (40,300) size 320x180 +layer at (440,300) size 320x180 + LayoutImage (positioned) {IMG} at (440,300) size 320x180
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/grammar-markers-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/grammar-markers-hidpi-expected.png index cbd9217..7add1851 100644 --- a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/grammar-markers-hidpi-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/grammar-markers-hidpi-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png index 9b0a45b..02ffae2 100644 --- a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-expected.png index 65f5988b..4c89f6c 100644 --- a/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/editing/spelling/inline-spelling-markers-hidpi-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/gradient-background-leakage-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/gradient-background-leakage-hidpi-expected.txt new file mode 100644 index 0000000..c7e9a68 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/fast/backgrounds/gradient-background-leakage-hidpi-expected.txt
@@ -0,0 +1,7 @@ +layer at (0,0) size 1600x1200 + LayoutView at (0,0) size 1600x1200 +layer at (0,0) size 1600x136 + LayoutBlockFlow {HTML} at (0,0) size 1600x136 + LayoutBlockFlow {BODY} at (16,16) size 1568x104 + LayoutBlockFlow {DIV} at (0,0) size 440x104 [bgcolor=#FF0000] + LayoutBlockFlow {DIV} at (20,20) size 404x64 [border: (2px solid #008000)]
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-hidpi-blurry-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-hidpi-blurry-expected.png new file mode 100644 index 0000000..6a9b251 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/fast/canvas/canvas-hidpi-blurry-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-landscape-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-landscape-expected.png new file mode 100644 index 0000000..bd72523 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-landscape-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-landscape-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-landscape-expected.txt new file mode 100644 index 0000000..650f620 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-landscape-expected.txt
@@ -0,0 +1,18 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x356 + LayoutBlockFlow {HTML} at (0,0) size 800x356 + LayoutBlockFlow {BODY} at (8,8) size 784x340 + LayoutImage {IMG} at (10,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (166,152) size 4x17 + text run at (166,152) width 4: " " + LayoutImage {IMG} at (180,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (336,152) size 4x17 + text run at (336,152) width 4: " " + LayoutImage {IMG} at (350,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (506,152) size 4x17 + text run at (506,152) width 4: " " + LayoutImage {IMG} at (520,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (0,0) size 0x0 + LayoutImage {IMG} at (10,180) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-portrait-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-portrait-expected.png new file mode 100644 index 0000000..ce5c0bfd --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-portrait-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-portrait-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-portrait-expected.txt new file mode 100644 index 0000000..650f620 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/fast/css/object-fit-grow-portrait-expected.txt
@@ -0,0 +1,18 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x356 + LayoutBlockFlow {HTML} at (0,0) size 800x356 + LayoutBlockFlow {BODY} at (8,8) size 784x340 + LayoutImage {IMG} at (10,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (166,152) size 4x17 + text run at (166,152) width 4: " " + LayoutImage {IMG} at (180,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (336,152) size 4x17 + text run at (336,152) width 4: " " + LayoutImage {IMG} at (350,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (506,152) size 4x17 + text run at (506,152) width 4: " " + LayoutImage {IMG} at (520,10) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (0,0) size 0x0 + LayoutImage {IMG} at (10,180) size 146x146 [bgcolor=#808080] [border: (1px solid #000000)] + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/dom/comment-not-documentElement-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/dom/comment-not-documentElement-expected.png index a6c2f23b..56d1662 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/dom/comment-not-documentElement-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/dom/comment-not-documentElement-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/dom/comment-not-documentElement-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/dom/comment-not-documentElement-expected.txt index 7f5523f4..1bd152a3 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/dom/comment-not-documentElement-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/fast/dom/comment-not-documentElement-expected.txt
@@ -3,5 +3,5 @@ layer at (0,0) size 800x600 LayoutBlockFlow {HTML} at (0,0) size 800x600 LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutText {#text} at (0,0) size 59x17 - text run at (0,0) width 59: "SUCESS" + LayoutText {#text} at (0,0) size 70x17 + text run at (0,0) width 70: "SUCCESS"
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-none-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-none-expected.png new file mode 100644 index 0000000..7ed686f7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-none-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-none-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-none-expected.txt new file mode 100644 index 0000000..d9edd6a --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/select/menulist-appearance-none-expected.txt
@@ -0,0 +1,24 @@ +layer at (0,0) size 800x600 + LayoutView at (0,0) size 800x600 +layer at (0,0) size 800x600 + LayoutBlockFlow {HTML} at (0,0) size 800x600 + LayoutBlockFlow {BODY} at (8,8) size 784x584 + LayoutBlockFlow {P} at (0,0) size 784x36 + LayoutText {#text} at (0,0) size 120x17 + text run at (0,0) width 120: "Rendering test for " + LayoutInline {I} at (0,0) size 739x35 + LayoutInline {A} at (0,0) size 414x17 [color=#0000EE] + LayoutText {#text} at (119,0) size 414x17 + text run at (119,0) width 414: "https://bugs.chromium.org/p/chromium/issues/detail?id=626278" + LayoutText {#text} at (532,0) size 739x35 + text run at (532,0) width 5: " " + text run at (536,0) width 203: "Regression: HTML Select's text" + text run at (0,18) width 291: "appears chopped if appearance is set to none" + LayoutText {#text} at (290,18) size 5x17 + text run at (290,18) width 5: "." + LayoutBlockFlow (anonymous) at (0,52) size 784x42 + LayoutMenuList {SELECT} at (0,0) size 26x42 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)] + LayoutBlockFlow (anonymous) at (1,1) size 24x40 + LayoutText (anonymous) at (0,12) size 24x16 + text run at (0,12) width 24: "Test" + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-icon-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-icon-hidpi-expected.png index 057c02d..cbe0ac6 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-icon-hidpi-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-icon-hidpi-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-icon-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-icon-hidpi-expected.txt index ce6b59d..efa9043 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-icon-hidpi-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-icon-hidpi-expected.txt
@@ -1,17 +1,17 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x58 - LayoutBlockFlow {HTML} at (0,0) size 800x58 - LayoutBlockFlow {BODY} at (8,8) size 784x42 - LayoutBlockFlow {DIV} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 755x17 - text run at (0,0) width 755: "This test passes if the broken image icon appears high-resolution in HiDPI and if the outline is of the appropriate size." - LayoutBlockFlow (anonymous) at (0,18) size 784x24 - LayoutBlockFlow {IMG} at (0,0) size 20x24 +layer at (0,0) size 1600x1200 + LayoutView at (0,0) size 1600x1200 +layer at (0,0) size 1600x117 + LayoutBlockFlow {HTML} at (0,0) size 1600x117 + LayoutBlockFlow {BODY} at (16,16) size 1568x85 + LayoutBlockFlow {DIV} at (0,0) size 1568x37 + LayoutText {#text} at (0,0) size 1510x36 + text run at (0,0) width 1510: "This test passes if the broken image icon appears high-resolution in HiDPI and if the outline is of the appropriate size." + LayoutBlockFlow (anonymous) at (0,37) size 1568x48 + LayoutBlockFlow {IMG} at (0,0) size 40x48 LayoutText {#text} at (0,0) size 0x0 LayoutText {#text} at (0,0) size 0x0 -layer at (8,26) size 20x20 clip at (9,27) size 18x18 - LayoutBlockFlow {DIV} at (0,0) size 20x20 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 -layer at (26,28) size 0x0 - LayoutBlockFlow {DIV} at (18,2) size 0x0 +layer at (16,53) size 40x40 clip at (18,55) size 36x36 + LayoutBlockFlow {DIV} at (0,0) size 40x40 [border: (2px solid #C0C0C0)] + LayoutImage (floating) {IMG} at (4,4) size 32x32 +layer at (52,57) size 0x0 + LayoutBlockFlow {DIV} at (36,4) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.png index ede3843c..a4009dd 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.txt index c536f23e..e222846b 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.txt
@@ -1,17 +1,17 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x188 - LayoutBlockFlow {HTML} at (0,0) size 800x188 - LayoutBlockFlow {BODY} at (8,8) size 784x172 - LayoutBlockFlow {DIV} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 652x17 - text run at (0,0) width 652: "This test passes if the broken image icon appears high-resolution in HiDPI and is the appropriate size." - LayoutBlockFlow (anonymous) at (0,18) size 784x154 - LayoutBlockFlow {IMG} at (0,0) size 300x150 +layer at (0,0) size 1600x1200 + LayoutView at (0,0) size 1600x1200 +layer at (0,0) size 1600x377 + LayoutBlockFlow {HTML} at (0,0) size 1600x377 + LayoutBlockFlow {BODY} at (16,16) size 1568x345 + LayoutBlockFlow {DIV} at (0,0) size 1568x37 + LayoutText {#text} at (0,0) size 1304x36 + text run at (0,0) width 1304: "This test passes if the broken image icon appears high-resolution in HiDPI and is the appropriate size." + LayoutBlockFlow (anonymous) at (0,37) size 1568x308 + LayoutBlockFlow {IMG} at (0,0) size 600x300 LayoutText {#text} at (0,0) size 0x0 LayoutText {#text} at (0,0) size 0x0 -layer at (8,26) size 300x150 clip at (9,27) size 298x148 - LayoutBlockFlow {DIV} at (0,0) size 300x150 [border: (1px solid #C0C0C0)] - LayoutImage (floating) {IMG} at (2,2) size 16x16 -layer at (26,28) size 280x0 - LayoutBlockFlow {DIV} at (18,2) size 280x0 +layer at (16,53) size 600x300 clip at (18,55) size 596x296 + LayoutBlockFlow {DIV} at (0,0) size 600x300 [border: (2px solid #C0C0C0)] + LayoutImage (floating) {IMG} at (4,4) size 32x32 +layer at (52,57) size 560x0 + LayoutBlockFlow {DIV} at (36,4) size 560x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/clip-text-in-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/clip-text-in-hidpi-expected.png index fe1f4ec..981ddf2d 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/clip-text-in-hidpi-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/clip-text-in-hidpi-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/clip-text-in-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/clip-text-in-hidpi-expected.txt index f689fe0..ba3e16e 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/clip-text-in-hidpi-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/clip-text-in-hidpi-expected.txt
@@ -1,14 +1,14 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x34 - LayoutBlockFlow {HTML} at (0,0) size 800x34 - LayoutBlockFlow {BODY} at (8,8) size 784x18 - LayoutInline {SPAN} at (0,0) size 360x17 [bgcolor=#FF0000] - LayoutText {#text} at (0,0) size 360x17 - text run at (0,0) width 360: "This text should be nice and sharp. devicePixelRatio is: " +layer at (0,0) size 1600x1200 + LayoutView at (0,0) size 1600x1200 +layer at (0,0) size 1600x69 + LayoutBlockFlow {HTML} at (0,0) size 1600x69 + LayoutBlockFlow {BODY} at (16,16) size 1568x37 + LayoutInline {SPAN} at (0,0) size 719x36 [bgcolor=#FF0000] + LayoutText {#text} at (0,0) size 719x36 + text run at (0,0) width 719: "This text should be nice and sharp. devicePixelRatio is: " LayoutText {#text} at (0,0) size 0x0 - LayoutInline {SPAN} at (0,0) size 9x17 - LayoutText {#text} at (359,0) size 9x17 - text run at (359,0) width 9: "2" + LayoutInline {SPAN} at (0,0) size 17x36 + LayoutText {#text} at (718,0) size 17x36 + text run at (718,0) width 17: "2" LayoutText {#text} at (0,0) size 0x0 LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/device-scale-factor-paint-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/device-scale-factor-paint-expected.txt new file mode 100644 index 0000000..8e122b1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/device-scale-factor-paint-expected.txt
@@ -0,0 +1,7 @@ +layer at (0,0) size 1600x1200 + LayoutView at (0,0) size 1600x1200 +layer at (0,0) size 1600x16 + LayoutBlockFlow {HTML} at (0,0) size 1600x16 + LayoutBlockFlow {BODY} at (16,16) size 1568x0 +layer at (10,20) size 100x100 + LayoutBlockFlow (positioned) {DIV} at (10,20) size 100x100 [bgcolor=#008000]
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/focus-rings-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/focus-rings-expected.png index 837ac39..5fd8184 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/focus-rings-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/focus-rings-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/focus-rings-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/focus-rings-expected.txt new file mode 100644 index 0000000..b64aafba --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/focus-rings-expected.txt
@@ -0,0 +1,6 @@ +layer at (0,0) size 1600x1200 + LayoutView at (0,0) size 1600x1200 +layer at (0,0) size 1600x336 + LayoutBlockFlow {HTML} at (0,0) size 1600x336 + LayoutBlockFlow {BODY} at (16,16) size 1568x304 + LayoutBlockFlow {DIV} at (0,0) size 604x304 [border: (2px solid #000000)]
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/gradient-with-scaled-ancestor-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/gradient-with-scaled-ancestor-expected.txt new file mode 100644 index 0000000..9dc9f5a --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/gradient-with-scaled-ancestor-expected.txt
@@ -0,0 +1,8 @@ +layer at (0,0) size 1600x1200 scrollWidth 2368 + LayoutView at (0,0) size 1600x1200 +layer at (0,0) size 1600x636 + LayoutBlockFlow {HTML} at (0,0) size 1600x636 + LayoutBlockFlow {BODY} at (16,16) size 1568x604 +layer at (16,16) size 1568x604 + LayoutBlockFlow {DIV} at (0,0) size 1568x604 + LayoutBlockFlow {DIV} at (0,0) size 604x604 [border: (2px solid #000000)]
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/image-srcset-intrinsic-size-zero-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/image-srcset-intrinsic-size-zero-expected.txt new file mode 100644 index 0000000..af1c507d4 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/image-srcset-intrinsic-size-zero-expected.txt
@@ -0,0 +1,6 @@ +PASS successfullyParsed is true + +TEST COMPLETE +PASS imgWidth is 16777216 +This test passes if the image is displayed with infinite dimensions. +
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/resize-corner-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/resize-corner-hidpi-expected.png index e9a4abe..dd8545e 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/resize-corner-hidpi-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/resize-corner-hidpi-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/resize-corner-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/resize-corner-hidpi-expected.txt index 4470182..7f27e05 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/resize-corner-hidpi-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/resize-corner-hidpi-expected.txt
@@ -1,14 +1,14 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x76 - LayoutBlockFlow {HTML} at (0,0) size 800x76 - LayoutBlockFlow {BODY} at (8,8) size 784x60 - LayoutBlockFlow {DIV} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 476x17 - text run at (0,0) width 476: "This test passes if the resize corner icon appears high-resolution in HiDPI." - LayoutBlockFlow (anonymous) at (0,18) size 784x42 +layer at (0,0) size 1600x1200 + LayoutView at (0,0) size 1600x1200 +layer at (0,0) size 1600x149 + LayoutBlockFlow {HTML} at (0,0) size 1600x149 + LayoutBlockFlow {BODY} at (16,16) size 1568x117 + LayoutBlockFlow {DIV} at (0,0) size 1568x37 + LayoutText {#text} at (0,0) size 951x36 + text run at (0,0) width 951: "This test passes if the resize corner icon appears high-resolution in HiDPI." + LayoutBlockFlow (anonymous) at (0,37) size 1568x80 LayoutText {#text} at (0,0) size 0x0 LayoutText {#text} at (0,0) size 0x0 -layer at (8,26) size 181x38 clip at (9,27) size 179x36 - LayoutTextControl {TEXTAREA} at (0,0) size 181x38 [bgcolor=#FFFFFF] [border: (1px solid #A9A9A9)] - LayoutBlockFlow {DIV} at (3,3) size 175x16 +layer at (16,53) size 347x72 clip at (18,55) size 343x68 + LayoutTextControl {TEXTAREA} at (0,0) size 347x72 [bgcolor=#FFFFFF] [border: (2px solid #A9A9A9)] + LayoutBlockFlow {DIV} at (6,6) size 335x30
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/sub-pixel/shadows-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/sub-pixel/shadows-hidpi-expected.txt new file mode 100644 index 0000000..d7695196 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/fast/sub-pixel/shadows-hidpi-expected.txt
@@ -0,0 +1,20 @@ +layer at (0,0) size 1600x1200 + LayoutView at (0,0) size 1600x1200 +layer at (0,0) size 1600x116 + LayoutBlockFlow {HTML} at (0,0) size 1600x116 + LayoutBlockFlow {BODY} at (16,16) size 1568x84 + LayoutBlockFlow {DIV} at (0,0) size 1568x20 + LayoutText {#text} at (0,0) size 60x20 + text run at (0,0) width 60: "XXX" + LayoutBlockFlow (anonymous) at (0,20) size 1568x64 + LayoutBR {BR} at (0,0) size 0x20 + LayoutBR {BR} at (0,20) size 0x20 + LayoutBlockFlow {DIV} at (0,40) size 64x24 [border: (2px solid #000000)] + LayoutText {#text} at (2,2) size 60x20 + text run at (2,2) width 60: "XXX" + LayoutText {#text} at (64,42) size 20x20 + text run at (64,42) width 20: " " + LayoutBlockFlow {DIV} at (84,40) size 64x24 [border: (2px solid #000000)] + LayoutText {#text} at (2,2) size 60x20 + text run at (2,2) width 60: "XXX" + LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange-expected.txt b/third_party/WebKit/LayoutTests/platform/win/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange-expected.txt index 6aa9277..4ea2add 100644 --- a/third_party/WebKit/LayoutTests/platform/win/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/imported/wpt/html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange-expected.txt
@@ -4,6 +4,8 @@ PASS input setSelectionRange return void PASS input setSelectionRange(0,1) PASS input setSelectionRange(0,input.value.length+1) +PASS input setSelectionRange(input.value.length+1,input.value.length+1) +PASS input setSelectionRange(input.value.length+1,input.value.length+1) PASS input setSelectionRange(2,2) PASS input setSelectionRange(2,1) PASS input direction of setSelectionRange(0,1,"backward") @@ -12,6 +14,8 @@ FAIL input direction of setSelectionRange(0,1,"hoge") assert_equals: otherwise expected "none" but got "forward" FAIL input direction of setSelectionRange(0,1,"BACKWARD") assert_equals: selectionDirection should be 'none' expected "none" but got "forward" PASS input direction of setSelectionRange(0,1) +FAIL input setSelectionRange(1,-1) assert_equals: element.selectionStart should be 1 expected 1 but got 0 +FAIL input setSelectionRange(-1,1) assert_equals: ECMAScript conversion to unsigned long + if end is less than or equal to start then the start of the selection and the end of the selection must both be placed immediately before the character with offset end expected 1 but got 0 PASS input setSelectionRange("string",1) PASS input setSelectionRange(true,1) PASS input setSelectionRange([],1)
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt new file mode 100644 index 0000000..fd99d4f --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/outline-containing-image-in-non-standard-mode-expected.txt
@@ -0,0 +1,47 @@ +{ + "name": "Content Root Layer", + "bounds": [800, 600], + "children": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "drawsContent": true, + "paintInvalidations": [ + { + "object": "LayoutInline SPAN id='target'", + "rect": [6, 6, 204, 57], + "reason": "style change" + }, + { + "object": "LayoutImage IMG", + "rect": [8, 8, 200, 50], + "reason": "forced by layout" + } + ] + } + ], + "objectPaintInvalidations": [ + { + "object": "LayoutBlockFlow BODY", + "reason": "forced by layout" + }, + { + "object": "RootInlineBox", + "reason": "forced by layout" + }, + { + "object": "LayoutInline SPAN id='target'", + "reason": "style change" + }, + { + "object": "InlineFlowBox", + "reason": "style change" + }, + { + "object": "LayoutImage IMG", + "reason": "forced by layout" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/as-image/image-respects-deviceScaleFactor-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/as-image/image-respects-deviceScaleFactor-expected.png index 1de1f4d..195c9e8 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/as-image/image-respects-deviceScaleFactor-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/as-image/image-respects-deviceScaleFactor-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/as-image/image-respects-deviceScaleFactor-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/as-image/image-respects-deviceScaleFactor-expected.txt index e3afdb4..9374d44e 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/as-image/image-respects-deviceScaleFactor-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/svg/as-image/image-respects-deviceScaleFactor-expected.txt
@@ -1,14 +1,14 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x584 - LayoutBlockFlow {P} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 527x17 - text run at (0,0) width 527: "This test passes if both of the circles have sharp edges when deviceScaleFactor=2." - LayoutBlockFlow (anonymous) at (0,34) size 784x132 - LayoutImage {IMG} at (0,0) size 128x128 - LayoutText {#text} at (128,114) size 4x17 - text run at (128,114) width 4: " " - LayoutImage {IMG} at (132,0) size 128x128 +layer at (0,0) size 1600x1200 + LayoutView at (0,0) size 1600x1200 +layer at (0,0) size 1600x1200 + LayoutBlockFlow {HTML} at (0,0) size 1600x1200 + LayoutBlockFlow {BODY} at (16,16) size 1568x1168 + LayoutBlockFlow {P} at (0,0) size 1568x37 + LayoutText {#text} at (0,0) size 1054x36 + text run at (0,0) width 1054: "This test passes if both of the circles have sharp edges when deviceScaleFactor=2." + LayoutBlockFlow (anonymous) at (0,69) size 1568x264 + LayoutImage {IMG} at (0,0) size 256x256 + LayoutText {#text} at (256,227) size 8x36 + text run at (256,227) width 8: " " + LayoutImage {IMG} at (264,0) size 256x256 LayoutText {#text} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/custom/masking-clipping-hidpi-expected.txt b/third_party/WebKit/LayoutTests/platform/win/svg/custom/masking-clipping-hidpi-expected.txt index f870203..bcc57d4 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/custom/masking-clipping-hidpi-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/svg/custom/masking-clipping-hidpi-expected.txt
@@ -1,15 +1,15 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutSVGRoot {svg} at (0,0) size 292x362 +layer at (0,0) size 1600x1200 + LayoutView at (0,0) size 1600x1200 +layer at (0,0) size 1600x1200 + LayoutSVGRoot {svg} at (0,0) size 583x724 LayoutSVGHiddenContainer {defs} at (0,0) size 0x0 LayoutSVGResourceMasker {mask} [id="textMask"] [maskUnits=objectBoundingBox] [maskContentUnits=userSpaceOnUse] - LayoutSVGRect {rect} at (0,0) size 800x600 [fill={[type=SOLID] [color=#FFFFFF]}] [x=0.00] [y=0.00] [width=800.00] [height=600.00] + LayoutSVGRect {rect} at (0,0) size 1600x1200 [fill={[type=SOLID] [color=#FFFFFF]}] [x=0.00] [y=0.00] [width=800.00] [height=600.00] LayoutSVGText {text} at (0,-3) size 165x19 contains 1 chunk(s) LayoutSVGInlineText {#text} at (0,0) size 165x18 chunk 1 text run 1 at (0.00,12.00) startOffset 0 endOffset 26 width 164.87: "This text should be sharp." - LayoutSVGRect {rect} at (0,0) size 200x100 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=200.00] [height=100.00] - LayoutSVGRect {rect} at (0,0) size 200x100 [fill={[type=SOLID] [color=#FFFFFF]}] [x=0.00] [y=0.00] [width=200.00] [height=100.00] + LayoutSVGRect {rect} at (0,0) size 400x200 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=0.00] [width=200.00] [height=100.00] + LayoutSVGRect {rect} at (0,0) size 400x200 [fill={[type=SOLID] [color=#FFFFFF]}] [x=0.00] [y=0.00] [width=200.00] [height=100.00] [masker="textMask"] LayoutSVGResourceMasker {mask} at (0,-2.50) size 220x112.50 LayoutSVGHiddenContainer {defs} at (0,0) size 0x0 LayoutSVGResourceLinearGradient {linearGradient} [id="blackGradient"] [gradientUnits=objectBoundingBox] [start=(0,0)] [end=(1,0)] @@ -21,10 +21,10 @@ LayoutSVGHiddenContainer {defs} at (0,0) size 0x0 LayoutSVGResourceClipper {clipPath} [id="circleClipPath"] [clipPathUnits=objectBoundingBox] LayoutSVGEllipse {circle} at (0,0) size 1x1 [fill={[type=SOLID] [color=#000000]}] [cx=0.25] [cy=0.25] [r=0.20] - LayoutSVGEllipse {circle} at (0,0) size 1x1 [fill={[type=SOLID] [color=#000000]}] [cx=0.25] [cy=0.75] [r=0.20] - LayoutSVGRect {rect} at (4,65) size 41x90 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=60.00] [width=100.00] [height=100.00] + LayoutSVGEllipse {circle} at (0,1) size 1x1 [fill={[type=SOLID] [color=#000000]}] [cx=0.25] [cy=0.75] [r=0.20] + LayoutSVGRect {rect} at (9,130) size 81x180 [fill={[type=SOLID] [color=#000000]}] [x=0.00] [y=60.00] [width=100.00] [height=100.00] [clipPath="circleClipPath"] LayoutSVGResourceClipper {clipPath} at (5,65) size 40x90 LayoutSVGHiddenContainer {defs} at (0,0) size 0x0 LayoutSVGResourcePattern {pattern} [id="Pattern"] [patternUnits=objectBoundingBox] [patternContentUnits=userSpaceOnUse] - LayoutSVGEllipse {circle} at (5,5) size 40x40 [fill={[type=LINEAR-GRADIENT] [id="blackGradient"]}] [cx=25.00] [cy=25.00] [r=20.00] - LayoutSVGRect {rect} at (0,162) size 200x200 [fill={[type=PATTERN] [id="Pattern"]}] [x=0.00] [y=162.00] [width=200.00] [height=200.00] + LayoutSVGEllipse {circle} at (10,10) size 80x80 [fill={[type=LINEAR-GRADIENT] [id="blackGradient"]}] [cx=25.00] [cy=25.00] [r=20.00] + LayoutSVGRect {rect} at (0,324) size 400x400 [fill={[type=PATTERN] [id="Pattern"]}] [x=0.00] [y=162.00] [width=200.00] [height=200.00]
diff --git a/third_party/WebKit/LayoutTests/platform/win/svg/filters/filter-source-position-expected.png b/third_party/WebKit/LayoutTests/platform/win/svg/filters/filter-source-position-expected.png index af54d677..45ad640 100644 --- a/third_party/WebKit/LayoutTests/platform/win/svg/filters/filter-source-position-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/svg/filters/filter-source-position-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-hidpi-blurry-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-hidpi-blurry-expected.png new file mode 100644 index 0000000..6a9b251 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-hidpi-blurry-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-hidpi-blurry-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-hidpi-blurry-expected.png new file mode 100644 index 0000000..92e03005 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu/fast/canvas/canvas-hidpi-blurry-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png index f7a547d..45aed31 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png index c2cbe03c..86a8e04a 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png index e4f124f7..38e0c9f 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png index 3c0a74c..5143b15 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png index 2281f56e..b730167d 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png index f592d2a..890a68e2 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png b/third_party/WebKit/LayoutTests/platform/win7/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png new file mode 100644 index 0000000..efd7dc2 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win7/editing/spelling/inline-spelling-markers-hidpi-composited-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/svg/filters/filter-source-position-expected.png b/third_party/WebKit/LayoutTests/platform/win7/svg/filters/filter-source-position-expected.png new file mode 100644 index 0000000..af54d677 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win7/svg/filters/filter-source-position-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png index 8168623..4f7790e 100644 --- a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/calendar-picker-appearance-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png deleted file mode 100644 index c2cbe03c..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/data-suggestion-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png deleted file mode 100644 index e4f124f7..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor150/fast/hidpi/static/popup-menu-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png index 7e20663..9d787d8 100644 --- a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/calendar-picker-appearance-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png deleted file mode 100644 index 2281f56e..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/data-suggestion-picker-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png b/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png deleted file mode 100644 index f592d2a..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/resources/idlharness.js b/third_party/WebKit/LayoutTests/resources/idlharness.js index b6a16af..5002ec5 100644 --- a/third_party/WebKit/LayoutTests/resources/idlharness.js +++ b/third_party/WebKit/LayoutTests/resources/idlharness.js
@@ -307,6 +307,28 @@ return ret; }; +function exposed_in(globals) { + if ('document' in self) { + return globals.indexOf("Window") >= 0; + } + if ('DedicatedWorkerGlobalScope' in self && + self instanceof DedicatedWorkerGlobalScope) { + return globals.indexOf("Worker") >= 0 || + globals.indexOf("DedicatedWorker") >= 0; + } + if ('SharedWorkerGlobalScope' in self && + self instanceof SharedWorkerGlobalScope) { + return globals.indexOf("Worker") >= 0 || + globals.indexOf("SharedWorker") >= 0; + } + if ('ServiceWorkerGlobalScope' in self && + self instanceof ServiceWorkerGlobalScope) { + return globals.indexOf("Worker") >= 0 || + globals.indexOf("ServiceWorker") >= 0; + } + throw "Unexpected global object"; +} + //@} IdlArray.prototype.test = function() //@{ @@ -353,6 +375,23 @@ } this["implements"] = {}; + Object.getOwnPropertyNames(this.members).forEach(function(memberName) { + var member = this.members[memberName]; + if (!(member instanceof IdlInterface)) { + return; + } + + var exposed = member.extAttrs.filter(function(a) { return a.name == "Exposed" }); + if (exposed.length > 1) { + throw "Unexpected Exposed extended attributes on " + memberName + ": " + exposed; + } + + var globals = exposed.length === 1 + ? exposed[0].rhs.value + : ["Window"]; + member.exposed = exposed_in(globals); + }.bind(this)); + // Now run test() on every member, and test_object() for every object. for (var name in this.members) { @@ -678,6 +717,13 @@ return; } + if (!this.exposed) { + test(function() { + assert_false(this.name in self); + }.bind(this), this.name + " interface: existence and properties of interface object"); + return; + } + if (!this.untested) { // First test things to do with the exception/interface object and @@ -701,7 +747,6 @@ test(function() { // This function tests WebIDL as of 2015-01-13. - // TODO: Consider [Exposed]. // "For every interface that is exposed in a given ECMAScript global // environment and:
diff --git a/third_party/WebKit/LayoutTests/resources/testharness.js b/third_party/WebKit/LayoutTests/resources/testharness.js index ceb3a4b..91dfab5 100644 --- a/third_party/WebKit/LayoutTests/resources/testharness.js +++ b/third_party/WebKit/LayoutTests/resources/testharness.js
@@ -471,6 +471,11 @@ self instanceof ServiceWorkerGlobalScope) { return new ServiceWorkerTestEnvironment(); } + if ('WorkerGlobalScope' in self && + self instanceof WorkerGlobalScope) { + return new DedicatedWorkerTestEnvironment(); + } + throw new Error("Unsupported test environment"); }
diff --git a/third_party/WebKit/LayoutTests/resources/testharnessreport.js b/third_party/WebKit/LayoutTests/resources/testharnessreport.js index 0dba6f20..15a0710 100644 --- a/third_party/WebKit/LayoutTests/resources/testharnessreport.js +++ b/third_party/WebKit/LayoutTests/resources/testharnessreport.js
@@ -79,7 +79,7 @@ document.head.appendChild(common_script); } - path = path.replace(/imported\/wpt\/(.*)\.html$/, "imported/wpt_automation/$1-input.js"); + path = path.replace(/imported\/wpt\/(.*)\.html$/, "imported/wpt_automation/$1-automation.js"); var input_script = document.createElement('script'); input_script.setAttribute('src', path); document.head.appendChild(input_script);
diff --git a/third_party/WebKit/LayoutTests/svg/custom/global-constructors-expected.txt b/third_party/WebKit/LayoutTests/svg/custom/global-constructors-expected.txt index 94caad7e..863ab20 100644 --- a/third_party/WebKit/LayoutTests/svg/custom/global-constructors-expected.txt +++ b/third_party/WebKit/LayoutTests/svg/custom/global-constructors-expected.txt
@@ -102,7 +102,6 @@ PASS SVGViewElement.toString() is 'function SVGViewElement() { [native code] }' PASS SVGScriptElement.toString() is 'function SVGScriptElement() { [native code] }' FAIL SVGEvent.toString() should be function SVGEvent() { [native code] }. Threw exception ReferenceError: SVGEvent is not defined -PASS SVGZoomEvent.toString() is 'function SVGZoomEvent() { [native code] }' PASS SVGAnimationElement.toString() is 'function SVGAnimationElement() { [native code] }' PASS SVGAnimateElement.toString() is 'function SVGAnimateElement() { [native code] }' PASS SVGSetElement.toString() is 'function SVGSetElement() { [native code] }'
diff --git a/third_party/WebKit/LayoutTests/svg/custom/immutable-properties-expected.txt b/third_party/WebKit/LayoutTests/svg/custom/immutable-properties-expected.txt index a02ef36..1f8e471 100644 --- a/third_party/WebKit/LayoutTests/svg/custom/immutable-properties-expected.txt +++ b/third_party/WebKit/LayoutTests/svg/custom/immutable-properties-expected.txt
@@ -1,4 +1,3 @@ -CONSOLE WARNING: line 15: 'SVGZoomEvent' is deprecated and will be removed in M52, around July 2016. See https://www.chromestatus.com/features/5760883808534528 for more details. Tests whether immutable properties can not be modified. On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". @@ -7,19 +6,6 @@ PASS viewport.x is 0 PASS viewport.x is 100 PASS svgDoc.documentElement.viewport.x is 0 -PASS zoomRectScreen.x is 0 -PASS zoomRectScreen.x = 100; threw exception NoModificationAllowedError: Failed to set the 'x' property on 'SVGRect': The attribute is read-only.. -PASS zoomEvent.previousScale is 0 -PASS zoomEvent.previousScale is 0 -PASS previousTranslate.x is 0 -PASS previousTranslate.x = 300; threw exception NoModificationAllowedError: Failed to set the 'x' property on 'SVGPoint': The attribute is read-only.. -PASS zoomEvent.previousTranslate.x is 0 -PASS zoomEvent.newScale is 0 -FAIL zoomEvent.newScale = 200; should throw an exception. Was 200. -PASS zoomEvent.newScale is 0 -PASS newTranslate.x is 0 -PASS newTranslate.x = 300; threw exception NoModificationAllowedError: Failed to set the 'x' property on 'SVGPoint': The attribute is read-only.. -PASS newTranslate.x is 0 PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/svg/custom/script-tests/global-constructors.js b/third_party/WebKit/LayoutTests/svg/custom/script-tests/global-constructors.js index 1096664..6b73d03b 100644 --- a/third_party/WebKit/LayoutTests/svg/custom/script-tests/global-constructors.js +++ b/third_party/WebKit/LayoutTests/svg/custom/script-tests/global-constructors.js
@@ -105,7 +105,6 @@ shouldBeDefined("SVGViewElement"); shouldBeDefined("SVGScriptElement"); shouldBeDefined("SVGEvent"); -shouldBeDefined("SVGZoomEvent"); shouldBeDefined("SVGAnimationElement"); shouldBeDefined("SVGAnimateElement"); shouldBeDefined("SVGSetElement");
diff --git a/third_party/WebKit/LayoutTests/svg/custom/script-tests/immutable-properties.js b/third_party/WebKit/LayoutTests/svg/custom/script-tests/immutable-properties.js index d0c14ac..8d6db64 100644 --- a/third_party/WebKit/LayoutTests/svg/custom/script-tests/immutable-properties.js +++ b/third_party/WebKit/LayoutTests/svg/custom/script-tests/immutable-properties.js
@@ -11,38 +11,4 @@ shouldBe("viewport.x", "100"); shouldBe("svgDoc.documentElement.viewport.x", "0"); -// Every attribute of SVGZoomEvent is immutable (Spec: The object itself and its contents are both readonly.) -var zoomEvent = svgDoc.createEvent("SVGZoomEvents"); - -// 'zoomRectScreen' property -var zoomRectScreen = zoomEvent.zoomRectScreen; - -shouldBe("zoomRectScreen.x", "0"); -shouldThrow("zoomRectScreen.x = 100;"); - -// 'previousScale' property -shouldBe("zoomEvent.previousScale", "0") -zoomEvent.previousScale = 200; -shouldBe("zoomEvent.previousScale", "0") - -// 'previousTranslate' property -var previousTranslate = zoomEvent.previousTranslate; - -shouldBe("previousTranslate.x", "0"); -shouldThrow("previousTranslate.x = 300;"); - -shouldBe("zoomEvent.previousTranslate.x", "0"); - -// 'newScale' property -shouldBe("zoomEvent.newScale", "0"); -shouldThrow("zoomEvent.newScale = 200;"); -shouldBe("zoomEvent.newScale", "0"); - -// 'newTranslate' property -var newTranslate = zoomEvent.newTranslate; - -shouldBe("newTranslate.x", "0"); -shouldThrow("newTranslate.x = 300;"); -shouldBe("newTranslate.x", "0"); - var successfullyParsed = true;
diff --git a/third_party/WebKit/LayoutTests/svg/dom/SVGLength-value-setter.html b/third_party/WebKit/LayoutTests/svg/dom/SVGLength-value-setter.html deleted file mode 100644 index 1e6f470..0000000 --- a/third_party/WebKit/LayoutTests/svg/dom/SVGLength-value-setter.html +++ /dev/null
@@ -1,16 +0,0 @@ -<!DOCTYPE html> -<title>Tests SVGLength.value setter</title> -<script src="../../resources/testharness.js"></script> -<script src="../../resources/testharnessreport.js"></script> -<svg width="1" height="1" visibility="hidden"> -</svg> -<script> -test(function() { - var svgElement = document.querySelector("svg"); - svgElement.setAttribute("width", "10em"); - assert_equals(svgElement.width.baseVal.unitType, SVGLength.SVG_LENGTHTYPE_EMS); - svgElement.width.baseVal.value = 100; - assert_equals(svgElement.width.baseVal.value, 100); - assert_equals(svgElement.width.baseVal.unitType, SVGLength.SVG_LENGTHTYPE_NUMBER); -}, "Tests SVGLength.value setter"); -</script>
diff --git a/third_party/WebKit/LayoutTests/svg/dom/svg2-inheritance-expected.txt b/third_party/WebKit/LayoutTests/svg/dom/svg2-inheritance-expected.txt index 1d4b0534..ddb9fe6 100644 --- a/third_party/WebKit/LayoutTests/svg/dom/svg2-inheritance-expected.txt +++ b/third_party/WebKit/LayoutTests/svg/dom/svg2-inheritance-expected.txt
@@ -84,7 +84,6 @@ PASS SVGUseElement inherits SVGGraphicsElement PASS SVGViewElement inherits SVGElement PASS SVGViewSpec inherits Object -PASS SVGZoomEvent inherits UIEvent FAIL TimeEvent is not defined PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/svg/dom/svg2-inheritance.html b/third_party/WebKit/LayoutTests/svg/dom/svg2-inheritance.html index 4a5e3cc..fff1ab9 100644 --- a/third_party/WebKit/LayoutTests/svg/dom/svg2-inheritance.html +++ b/third_party/WebKit/LayoutTests/svg/dom/svg2-inheritance.html
@@ -105,7 +105,6 @@ checkParent("SVGUseElement", "SVGGraphicsElement"); checkParent("SVGViewElement", "SVGElement"); checkParent("SVGViewSpec", "Object"); -checkParent("SVGZoomEvent", "UIEvent"); checkParent("TimeEvent", "Event"); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/typedcssom/cssVariableReferenceValue.html b/third_party/WebKit/LayoutTests/typedcssom/cssVariableReferenceValue.html new file mode 100644 index 0000000..028cfee --- /dev/null +++ b/third_party/WebKit/LayoutTests/typedcssom/cssVariableReferenceValue.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> + +<script> + +test(function() { + var expected = 'anything'; + var variableReferenceValue = new CSSVariableReferenceValue(expected); + assert_true(variableReferenceValue instanceof CSSVariableReferenceValue); + assert_equals(variableReferenceValue.variable, expected); +}, "The 'variable' attribute is correct"); + +</script>
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt index c217e975..23d6476 100644 --- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -4985,14 +4985,6 @@ getter zoomAndPan method constructor setter zoomAndPan -interface SVGZoomEvent : UIEvent - attribute @@toStringTag - getter newScale - getter newTranslate - getter previousScale - getter previousTranslate - getter zoomRectScreen - method constructor interface Screen attribute @@toStringTag getter availHeight
diff --git a/third_party/WebKit/LayoutTests/virtual/threaded/animations/composited-pseudo-element-animation-expected.html b/third_party/WebKit/LayoutTests/virtual/threaded/animations/composited-pseudo-element-animation-expected.html new file mode 100644 index 0000000..06b3765 --- /dev/null +++ b/third_party/WebKit/LayoutTests/virtual/threaded/animations/composited-pseudo-element-animation-expected.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<style> +div { + width: 100px; + height: 100px; + background: orange; +} +div::before { + content: ":)"; + transform: translateX(20px); + transition-property: transform; + transition-duration: 1ms; + display: block; +} +</style> +<div></div>
diff --git a/third_party/WebKit/LayoutTests/virtual/threaded/animations/composited-pseudo-element-animation.html b/third_party/WebKit/LayoutTests/virtual/threaded/animations/composited-pseudo-element-animation.html new file mode 100644 index 0000000..f7bd3422 --- /dev/null +++ b/third_party/WebKit/LayoutTests/virtual/threaded/animations/composited-pseudo-element-animation.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<style> +div { + width: 100px; + height: 100px; + background: orange; +} +div::before { + content: ":)"; + transition-property: transform; + transition-duration: 1ms; + + /* Make the pseudo element "transformable" as per + * https://www.w3.org/TR/css-transforms-1/#transformable-element. + */ + display: block; +} +</style> +<div></div> +<script> +if (window.testRunner) + window.testRunner.waitUntilDone(); + +requestAnimationFrame(function(ts) { + document.styleSheets[0].addRule('div::before', 'transform: translateX(20px)'); + requestAnimationFrame(function(ts) { + requestAnimationFrame(function(ts) { + if (window.testRunner) + window.testRunner.notifyDone(); + }); + }); +}); +</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-cancel-event.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-cancel-event.html new file mode 100644 index 0000000..57260498 --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-cancel-event.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Canceling an animation: cancel event</title> +<link rel="help" href="https://w3c.github.io/web-animations/#canceling-an-animation-section"> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<body> +<script> +var anim1 = document.body.animate([], 100000); +var anim2 = document.body.animate([], 100000); + +var cancelTest = async_test('Cancelling animation should fire a cancel event.'); +var fired = false; + +anim1.oncancel = function(event) { + cancelTest.step(function() { + assert_equals(event.target, anim1, 'Target of cancel event should be anim1.'); + assert_equals(event.currentTime, null, 'currentTime of cancel event should be null.'); + assert_equals(event.timelineTime, document.timeline.currentTime, 'Event timelineTime should be same as document.timeline.currentTime.'); + }); + fired = true; +}; + +anim2.onfinish = function() { + cancelTest.step(function() { + assert_true(fired, 'anim1.oncancel should be called.'); + }); + cancelTest.done(); +}; + +anim1.cancel(); +anim2.finish(); +</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-cancel-ready-finished-ordering.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-cancel-ready-finished-ordering.html new file mode 100644 index 0000000..db0be86a --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-cancel-ready-finished-ordering.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Cancel an animation: ready/finished ordering</title +<link rel="help" href="https://w3c.github.io/web-animations/#canceling-an-animation-section"> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script> +async_test(function(t) { + var animation = document.documentElement.animate([], 100000); + var ready = false; + animation.ready.catch(function() { + t.step(function() { + ready = true; + }); + }); + animation.finished.catch(function() { + t.step(function() { + assert_true(ready); + }); + t.done(); + }); + animation.cancel(); +}, 'The ready promise should be rejected before the finished promise'); +</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-constructor.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-constructor.html deleted file mode 100644 index 6c131ee..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/animation-constructor.html +++ /dev/null
@@ -1,36 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> - -<div id='e'></div> - -<script> -var element = document.getElementById('e'); - -var keyframes = [{opacity: '1'}, {opacity: '0'}]; -var timingObject = {duration: 2, iterations: 5}; - -test(function() { - var keyframeEffect = new KeyframeEffect(element, keyframes, timingObject); - assert_not_equals(keyframeEffect, undefined); - assert_equals(keyframeEffect.constructor, KeyframeEffect); -}, 'Calling new KeyframeEffect() with a timing object input should create an keyframeEffect.'); - -test(function() { - var keyframeEffect = new KeyframeEffect(element, keyframes, 2); - assert_not_equals(keyframeEffect, undefined); - assert_equals(keyframeEffect.constructor, KeyframeEffect); -}, 'Calling new KeyframeEffect() with a duration input should create an keyframeEffect.'); - -test(function() { - var keyframeEffect = new KeyframeEffect(element, keyframes); - assert_not_equals(keyframeEffect, undefined); - assert_equals(keyframeEffect.constructor, KeyframeEffect); -}, 'Calling new KeyframeEffect() with no timing input should create an keyframeEffect.'); - -test(function() { - var keyframeEffect = new KeyframeEffect(null, keyframes); - assert_not_equals(keyframeEffect, undefined); - assert_equals(keyframeEffect.constructor, KeyframeEffect); -}, 'Calling new KeyframeEffect() with no target should create an keyframeEffect.'); -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-effect-read-only-expected.txt b/third_party/WebKit/LayoutTests/web-animations-api/animation-effect-read-only-expected.txt new file mode 100644 index 0000000..23ba0b3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-effect-read-only-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL animation.effect should be read-only assert_approx_equals: expected 1000 +/- 0.0005 but got 1500 +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-effect-read-only.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-effect-read-only.html new file mode 100644 index 0000000..c7275b79 --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-effect-read-only.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Test that extending effect should not cause a change in start time</title> +<link rel="https://w3c.github.io/web-animations/#the-animation-interface"> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="../imported/wpt/web-animations/testcommon.js"></script> +<script> +test(function() { + var animation = document.documentElement.animate([], 1000); + animation.effect.timing.duration = 1500; + assert_times_equal(animation.effect.timing.duration, 1000); +}, 'animation.effect should be read-only'); +</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-effect-timing-easing-expected.txt b/third_party/WebKit/LayoutTests/web-animations-api/animation-effect-timing-easing-expected.txt new file mode 100644 index 0000000..5c33c31b --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-effect-timing-easing-expected.txt
@@ -0,0 +1,8 @@ +CONSOLE WARNING: line 9: Specifying animation easing as a function is deprecated and all support will be removed in M54, around October 2016, at which point this will throw a TypeError. This warning may have been triggered by the Web Animations or Polymer polyfills. See http://crbug.com/601672 for details. +This is a testharness.js-based test. +PASS Valid easing functions should come out the same as they went in +PASS steps easing second parameter defaults to end +PASS Should accept arbitrary casing and escape chararcters +FAIL Invalid easing values should throw a TypeError assert_throws: with inputEasing='function (a){return a}' function "function () { animate_with_easing(inputEasing); }" did not throw +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-effect-timing-easing.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-effect-timing-easing.html index 71b6b486..c45d554 100644 --- a/third_party/WebKit/LayoutTests/web-animations-api/animation-effect-timing-easing.html +++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-effect-timing-easing.html
@@ -1,4 +1,7 @@ <!DOCTYPE html> +<meta charset=utf-8> +<title>AnimationEffectTiming easing tests</title> +<link rel="help" href="https://w3c.github.io/web-animations/#the-animationeffecttiming-interface"> <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> <script> @@ -53,11 +56,9 @@ assert_animate_with_easing_throws('steps(3, nowhere)'); assert_animate_with_easing_throws('steps(-3, end)'); assert_animate_with_easing_throws('cubic-bezier(0.1, 0, 4, 0.4)'); -}, 'Invalid easing values should throw a TypeError'); - -test(function() { - assert_animate_with_easing_succeeds('function (a){return a}', 'linear'); + assert_animate_with_easing_throws('function (a){return a}'); assert_animate_with_easing_throws('function (x){return x}'); assert_animate_with_easing_throws('function(x, y){return 0.3}'); -}, 'Function values for easing should throw a TypeError, except for one special linear case, which is deprecated for now and returns the default'); + assert_animate_with_easing_throws('7'); +}, 'Invalid easing values should throw a TypeError'); </script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-finish-event-cancelled.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-finish-event-cancelled.html new file mode 100644 index 0000000..afd891f --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-finish-event-cancelled.html
@@ -0,0 +1,26 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Canceling an animation: finish event</title> +<link rel="help" href="https://w3c.github.io/web-animations/#canceling-an-animation-section"> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<body> +<script> +async_test(t => { + var anim1 = document.body.animate([], 100000); + var anim2 = document.body.animate([], 100000); + + var success = false; + anim2.finished.catch(function() { + success = true; + }); + + anim1.finished.then(function() { + assert_true(success, 'anim2 finished promise should be rejected on cancelation'); + t.done(); + }); + + anim2.cancel(); + anim1.finish(); +}, 'Animation finished promise should be rejected when animation canceled'); +</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-finish-ready-finished-ordering.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-finish-ready-finished-ordering.html new file mode 100644 index 0000000..ea77ea1b --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-finish-ready-finished-ordering.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Finishing an animation: ready/finished ordering</title +<link rel="help" href="https://w3c.github.io/web-animations/#finishing-an-animation-section"> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> + +<script> +async_test(function(t) { + var animation = document.documentElement.animate([], 100000); + var ready = false; + animation.ready.then(function() { + t.step(function() { + ready = true; + }); + }); + animation.finished.then(function() { + t.step(function() { + assert_true(ready); + }); + t.done(); + }); + animation.finish(); +}, 'The ready promise should be resolved before the finished promise'); +</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-onfinish.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-onfinish.html new file mode 100644 index 0000000..c9b9460 --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-onfinish.html
@@ -0,0 +1,81 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Tests for the finish event</title> +<link rel="help" href="https://w3c.github.io/web-animations/#the-current-finished-promise"> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="../imported/wpt/web-animations/testcommon.js"></script> +<body> +<script> +'use strict'; +function validateFinishEvent(t, event, animation) { + t.step(function() { + assert_equals(event, animation, 'Animation should be target'); + assert_times_equal(event.currentTime, animation.currentTime, 'Event currentTime should be animation currentTime'); + }); +} + +async_test(function(t) { + var div = createDiv(t); + var animation = div.animate(null, 70.0); + animation.finished.then(function(event) { + t.unreached_func("Seeking to finish should not queue finished event"); + }) + animation.finish(); + animation.currentTime = 0; + animation.pause(); + t.done(); +}, "animation.finished doesn't run when the animation seeks to finish"); + +async_test(function(t) { + var div = createDiv(t); + var animation = div.animate(null, 70.0); + animation.finished.then(function (event) { + t.unreached_func("Seeking past finish should not queue finished event"); + }) + animation.currentTime = 80.0; + animation.currentTime = 0; + animation.pause(); + t.done(); +}, "animation.finished doesn't run when the animation seeks past finish"); + +async_test(function(t) { + var div = createDiv(t); + var animation = div.animate(null, 90.0); + animation.finished.then(function(event) { + validateFinishEvent(t, event, animation); + t.done(); + }) + animation.finish(); +}, "animation.finished runs when the animation completes with .finish()"); + +async_test(function(t) { + var div = createDiv(t); + var animation = div.animate(null, 100); + animation.finished.then(function(event) { + validateFinishEvent(t, event, animation); + t.done(); + }) +}, "animation.finished runs when the animation completes"); + +// TODO(alancutter): Change this to a promise_test. +async_test(function(t) { + var animation1 = createDiv(t).animate(null, 0.05); + animation1.finished.then(function(event) { + validateFinishEvent(t, event, animation1); + animation1.currentTime = 0; + return animation1.finished; + }).then(function(event) { + var animation2 = createDiv(t).animate(null, 0.05); + // TODO(alancutter): Move this .then to the outer promise chain. + animation2.finished.then(function(event) { + validateFinishEvent(t, event, animation2); + animation2.play(); + return animation2.finished; + }) + return animation2.finished; + }).then(function(event) { + t.done(); + }) +}, "animation.finished calls can be chained"); +</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-play-after-finish-restarts.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-play-after-finish-restarts.html new file mode 100644 index 0000000..18e511b --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-play-after-finish-restarts.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Animation resets when play() called after finish()</title> +<link rel="help" href="http://w3c.github.io/web-animations/#play-an-animation"> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> + +<div id='element'></div> + +<script> +var element = document.getElementById('element'); + +test(function() { + var animation = element.animate([{left: '0px'}, {left: '100px'}], 10); + animation.finish(); + assert_equals(getComputedStyle(element).left, 'auto'); + + animation.play(); + assert_equals(getComputedStyle(element).left, '0px'); +}, 'Calling play() after finish() causes the animation to reset'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-reverse-end-exclusive.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-reverse-end-exclusive.html new file mode 100644 index 0000000..2a9d1e6e --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-reverse-end-exclusive.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Animation Reverse End Exclusive</title> +<link rel="help" href="https://w3c.github.io/web-animations/#speed-control"> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script> + +test(function() { + document.documentElement.style.opacity = 1; + var animation = document.documentElement.animate([{opacity: 0.5}, {opacity: 0.5}], 100000); + animation.playbackRate = -1; + animation.currentTime = 0; + assert_equals(getComputedStyle(document.documentElement).opacity, "1"); +}, "An animation which is not filling backwards should not be in effect at time 0 when playing backwards"); +</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-set-timeline-expected.txt b/third_party/WebKit/LayoutTests/web-animations-api/animation-set-timeline-expected.txt new file mode 100644 index 0000000..ffb4933 --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-set-timeline-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Animations are retriggered if timeline time changes promise_test: Unhandled rejection with value: object "ReferenceError: DocumentTimeline is not defined" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-set-timeline.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-set-timeline.html new file mode 100644 index 0000000..728f5c5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-set-timeline.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Animations are retriggered if timeline time changes</title> +<link rel="help" href="http://w3c.github.io/web-animations/#set-the-timeline-of-an-animation"> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="../imported/wpt/web-animations/testcommon.js"></script> + +<div id="div"></div> + +<script> + +promise_test(function(t) { + var animation = div.animate([], 10); + + return animation.ready.then(function() { + animation.timeline = new DocumentTimeline(-5); + animation.startTime = document.timeline.currentTime; + assert_times_equal(animation.currentTime, 5); + assert_equals(animation.playState, "running"); + + animation.timeline = new DocumentTimeline(-15); + animation.startTime = document.timeline.currentTime; + assert_times_equal(animation.currentTime, 10); + assert_equals(animation.playState, "finished"); + + animation.timeline = new DocumentTimeline(0); + animation.startTime = document.timeline.currentTime; + assert_times_equal(animation.currentTime, 0); + assert_equals(animation.playState, "running"); + + animation.timeline = new DocumentTimeline(-5); + animation.startTime = document.timeline.currentTime; + assert_times_equal(animation.currentTime, 5); + assert_equals(animation.playState, "running"); + }); +}, 'Animations are retriggered if timeline time changes'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-state-changes-negative-playback-rate.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-state-changes-negative-playback-rate.html index e6903c7..0c254b55 100644 --- a/third_party/WebKit/LayoutTests/web-animations-api/animation-state-changes-negative-playback-rate.html +++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-state-changes-negative-playback-rate.html
@@ -1,4 +1,8 @@ <!DOCTYPE html> +<meta charset=utf-8> +<title>Test play state changes for animations with a negative playback rate</title> +<link rel="help" href="http://w3c.github.io/web-animations/#play-state"> +<script src="../imported/wpt/web-animations/testcommon.js"></script> <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> @@ -23,7 +27,7 @@ return animation; } -function pendingStartTimeAnimation() { +function pendingAnimation() { var animation = idleAnimation(); animation.play(); return animation; @@ -48,35 +52,35 @@ assert_unresolved(animation.startTime); assert_unresolved(animation.currentTime); assert_equals(animation.playState, 'idle'); -}, "idle"); +}, "Play state is idle after cancelling a reversed animation"); test(function() { - var animation = pendingStartTimeAnimation(); + var animation = pendingAnimation(); assert_unresolved(animation.startTime); assert_equals(animation.currentTime, duration); assert_equals(animation.playState, 'pending'); -}, "pending startTime"); +}, "Play state is pending after playing a cancelled reversed animation"); test(function() { var animation = runningAnimation(); - assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime)); - assert_approx_equals(animation.currentTime, duration / 2, 0.000001); + assert_times_equal(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime)); + assert_times_equal(animation.currentTime, duration / 2); assert_equals(animation.playState, 'running'); -}, "running"); +}, "Play state is running after playing and setting start time of a cancelled reversed animation"); test(function() { var animation = pausedAnimation(); assert_unresolved(animation.startTime); assert_equals(animation.currentTime, duration); assert_equals(animation.playState, 'paused'); -}, "paused"); +}, "Play state is paused after pausing and setting current time of a cancelled reversed animation"); test(function() { var animation = finishedAnimation(); assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime)); assert_equals(animation.currentTime, 0); assert_equals(animation.playState, 'finished'); -}, "finished"); +}, "Play state is finished after playing and finishing a cancelled reversed animation"); test(function() { var animation = idleAnimation(); @@ -84,7 +88,7 @@ assert_unresolved(animation.startTime); assert_equals(animation.currentTime, duration); assert_equals(animation.playState, 'pending'); -}, "idle -> play()"); +}, "Calling play() on an idle animation"); test(function() { var animation = idleAnimation(); @@ -92,7 +96,7 @@ assert_unresolved(animation.startTime); assert_equals(animation.currentTime, duration); assert_equals(animation.playState, 'pending'); -}, "idle -> pause()"); +}, "Calling pause() on an idle animation"); test(function() { var animation = idleAnimation(); @@ -100,7 +104,7 @@ assert_unresolved(animation.startTime); assert_unresolved(animation.currentTime); assert_equals(animation.playState, 'idle'); -}, "idle -> cancel()"); +}, "Calling cancel() on an idle animation"); test(function() { var animation = idleAnimation(); @@ -108,7 +112,7 @@ assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime)); assert_equals(animation.currentTime, 0); assert_equals(animation.playState, 'finished'); -}, "idle -> finish()"); +}, "Calling finish() on an idle animation"); test(function() { var animation = idleAnimation(); @@ -116,7 +120,7 @@ assert_unresolved(animation.startTime); assert_equals(animation.currentTime, 0); assert_equals(animation.playState, 'pending'); -}, "idle -> reverse()"); +}, "Calling reverse() on an idle animation"); test(function() { var animation = idleAnimation(); @@ -124,71 +128,71 @@ assert_unresolved(animation.startTime); assert_equals(animation.currentTime, 1000); assert_equals(animation.playState, 'paused'); -}, "idle -> set currentTime"); +}, "Setting currentTime on an idle animation"); test(function() { var animation = idleAnimation(); animation.startTime = document.timeline.currentTime + 1000; - assert_equals(animation.startTime, document.timeline.currentTime + 1000); - assert_equals(animation.currentTime, 1000); + assert_times_equal(animation.startTime, document.timeline.currentTime + 1000); + assert_times_equal(animation.currentTime, 1000); assert_equals(animation.playState, 'running'); -}, "idle -> set startTime"); +}, "Setting startTime on an idle animation"); test(function() { - var animation = pendingStartTimeAnimation(); + var animation = pendingAnimation(); animation.play(); assert_unresolved(animation.startTime); assert_equals(animation.currentTime, duration); assert_equals(animation.playState, 'pending'); -}, "pending startTime -> play()"); +}, "Calling play() on a pending animation"); test(function() { - var animation = pendingStartTimeAnimation(); + var animation = pendingAnimation(); animation.pause(); assert_unresolved(animation.startTime); assert_equals(animation.currentTime, duration); assert_equals(animation.playState, 'pending'); -}, "pending startTime -> pause()"); +}, "Calling pause() on a pending animation"); test(function() { - var animation = pendingStartTimeAnimation(); + var animation = pendingAnimation(); animation.cancel(); assert_unresolved(animation.startTime); assert_unresolved(animation.currentTime); assert_equals(animation.playState, 'idle'); -}, "pending startTime -> cancel()"); +}, "Calling cancel() on a pending animation"); test(function() { - var animation = pendingStartTimeAnimation(); + var animation = pendingAnimation(); animation.finish(); - assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime)); + assert_times_equal(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime)); assert_equals(animation.currentTime, 0); assert_equals(animation.playState, 'finished'); -}, "pending startTime -> finish()"); +}, "Calling finish() on a pending animation"); test(function() { - var animation = pendingStartTimeAnimation(); + var animation = pendingAnimation(); animation.reverse(); assert_unresolved(animation.startTime); assert_equals(animation.currentTime, 0); assert_equals(animation.playState, 'pending'); -}, "pending startTime -> reverse()"); +}, "Calling reverse() on a pending animation"); test(function() { - var animation = pendingStartTimeAnimation(); + var animation = pendingAnimation(); animation.currentTime = 1000; assert_unresolved(animation.startTime); assert_equals(animation.currentTime, 1000); assert_equals(animation.playState, 'pending'); -}, "pending startTime -> set currentTime"); +}, "Setting currentTime on a pending animation"); test(function() { - var animation = pendingStartTimeAnimation(); + var animation = pendingAnimation(); animation.startTime = document.timeline.currentTime + 1000; - assert_equals(animation.startTime, document.timeline.currentTime + 1000); - assert_equals(animation.currentTime, 1000); + assert_times_equal(animation.startTime, document.timeline.currentTime + 1000); + assert_times_equal(animation.currentTime, 1000); assert_equals(animation.playState, 'running'); -}, "pending startTime -> set startTime"); +}, "Setting startTime on a pending animation"); test(function() { var animation = runningAnimation(); @@ -198,15 +202,15 @@ assert_equals(animation.startTime, startTime); assert_equals(animation.currentTime, currentTime); assert_equals(animation.playState, 'running'); -}, "running -> play()"); +}, "Calling play() on a running animation"); test(function() { var animation = runningAnimation(); animation.pause(); assert_unresolved(animation.startTime); - assert_approx_equals(animation.currentTime, duration / 2, 0.000001); + assert_times_equal(animation.currentTime, duration / 2); assert_equals(animation.playState, 'pending'); -}, "running -> pause()"); +}, "Calling pause() on a running animation"); test(function() { var animation = runningAnimation(); @@ -214,39 +218,39 @@ assert_unresolved(animation.startTime); assert_unresolved(animation.currentTime); assert_equals(animation.playState, 'idle'); -}, "running -> cancel()"); +}, "Calling cancel() on a running animation"); test(function() { var animation = runningAnimation(); animation.finish(); - assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime)); + assert_times_equal(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime)); assert_equals(animation.currentTime, 0); assert_equals(animation.playState, 'finished'); -}, "running -> finish()"); +}, "Calling finish() on a running animation"); test(function() { var animation = runningAnimation(); animation.reverse(); assert_unresolved(animation.startTime); - assert_approx_equals(animation.currentTime, duration / 2, 0.000001); + assert_times_equal(animation.currentTime, duration / 2); assert_equals(animation.playState, 'pending'); -}, "running -> reverse()"); +}, "Calling reverse() on a running animation"); test(function() { var animation = runningAnimation(); animation.currentTime = 1000; - assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime)); + assert_times_equal(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime)); assert_equals(animation.currentTime, 1000); assert_equals(animation.playState, 'running'); -}, "running -> set currentTime"); +}, "Setting currentTime on a running animation"); test(function() { var animation = runningAnimation(); animation.startTime = document.timeline.currentTime + 1000; - assert_equals(animation.startTime, document.timeline.currentTime + 1000); - assert_equals(animation.currentTime, 1000); + assert_times_equal(animation.startTime, document.timeline.currentTime + 1000); + assert_times_equal(animation.currentTime, 1000); assert_equals(animation.playState, 'running'); -}, "running -> set startTime"); +}, "Setting startTime on a running animation"); test(function() { var animation = pausedAnimation(); @@ -254,7 +258,7 @@ assert_unresolved(animation.startTime); assert_equals(animation.currentTime, duration); assert_equals(animation.playState, 'pending'); -}, "paused -> play()"); +}, "Calling play() on a paused animation"); test(function() { var animation = pausedAnimation(); @@ -262,7 +266,7 @@ assert_unresolved(animation.startTime); assert_equals(animation.currentTime, duration); assert_equals(animation.playState, 'paused'); -}, "paused -> pause()"); +}, "Calling pause() on a paused animation"); test(function() { var animation = pausedAnimation(); @@ -270,15 +274,15 @@ assert_unresolved(animation.startTime); assert_unresolved(animation.currentTime); assert_equals(animation.playState, 'idle'); -}, "paused -> cancel()"); +}, "Calling cancel() on a paused animation"); test(function() { var animation = pausedAnimation(); animation.finish(); - assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime)); + assert_times_equal(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime)); assert_equals(animation.currentTime, 0); assert_equals(animation.playState, 'finished'); -}, "paused -> finish()"); +}, "Calling finish() on a paused animation"); test(function() { var animation = pausedAnimation(); @@ -286,7 +290,7 @@ assert_unresolved(animation.startTime); assert_equals(animation.currentTime, 0); assert_equals(animation.playState, 'pending'); -}, "paused -> reverse()"); +}, "Calling reverse() on a paused animation"); test(function() { var animation = pausedAnimation(); @@ -294,15 +298,15 @@ assert_unresolved(animation.startTime); assert_equals(animation.currentTime, 1000); assert_equals(animation.playState, 'paused'); -}, "paused -> set currentTime"); +}, "Setting currentTime on a paused animation"); test(function() { var animation = pausedAnimation(); animation.startTime = document.timeline.currentTime + 1000; - assert_equals(animation.startTime, document.timeline.currentTime + 1000); - assert_equals(animation.currentTime, 1000); + assert_times_equal(animation.startTime, document.timeline.currentTime + 1000); + assert_times_equal(animation.currentTime, 1000); assert_equals(animation.playState, 'running'); -}, "paused -> set startTime"); +}, "Setting startTime on a paused animation"); test(function() { var animation = finishedAnimation(); @@ -310,7 +314,7 @@ assert_unresolved(animation.startTime); assert_equals(animation.currentTime, duration); assert_equals(animation.playState, 'pending'); -}, "finished -> play()"); +}, "Calling play() on a finished animation"); test(function() { var animation = finishedAnimation(); @@ -318,7 +322,7 @@ assert_unresolved(animation.startTime); assert_equals(animation.currentTime, 0); assert_equals(animation.playState, 'pending'); -}, "finished -> pause()"); +}, "Calling pause() on a finished animation"); test(function() { var animation = finishedAnimation(); @@ -326,15 +330,15 @@ assert_unresolved(animation.startTime); assert_unresolved(animation.currentTime); assert_equals(animation.playState, 'idle'); -}, "finished -> cancel()"); +}, "Calling cancel() on a finished animation"); test(function() { var animation = finishedAnimation(); animation.finish(); - assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime)); + assert_times_equal(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime)); assert_equals(animation.currentTime, 0); assert_equals(animation.playState, 'finished'); -}, "finished -> finish()"); +}, "Calling finish() on a finished animation"); test(function() { var animation = finishedAnimation(); @@ -342,13 +346,13 @@ assert_unresolved(animation.startTime); assert_equals(animation.currentTime, 0); assert_equals(animation.playState, 'pending'); -}, "finished -> reverse()"); +}, "Calling reverse() on a finished animation"); test(function() { var animation = finishedAnimation(); animation.currentTime = 1000; - assert_equals(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime)); + assert_times_equal(animation.startTime, document.timeline.currentTime - (animation.playbackRate * animation.currentTime)); assert_equals(animation.currentTime, 1000); assert_equals(animation.playState, 'running'); -}, "finished -> set currentTime"); +}, "Setting currentTime on a finished animation"); </script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-state-changes.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-state-changes.html deleted file mode 100644 index ba22634..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/animation-state-changes.html +++ /dev/null
@@ -1,392 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> - -<script> -var duration = 100000; - -function assert_unresolved(value) { - assert_equals(value, null); -} - -function idleAnimation() { - var animation = document.documentElement.animate([], duration); - animation.cancel(); - return animation; -} - -function runningAnimation() { - var animation = idleAnimation(); - animation.play(); - animation.startTime = document.timeline.currentTime; - return animation; -} - -function pendingStartTimeAnimation() { - var animation = idleAnimation(); - animation.play(); - return animation; -} - -function pendingStartTimeAndCurrentTimeAnimation() { - var animation = idleAnimation(); - animation.play(); - animation.pause(); - animation.play(); - return animation; -} - -function pausedAnimation() { - var animation = idleAnimation(); - animation.pause(); - animation.currentTime = 0; - return animation; -} - -function finishedAnimation() { - var animation = idleAnimation(); - animation.play(); - animation.finish(); - return animation; -} - -test(function() { - var animation = idleAnimation(); - assert_unresolved(animation.startTime); - assert_unresolved(animation.currentTime); - assert_equals(animation.playState, 'idle'); -}, "idle"); - -test(function() { - var animation = pendingStartTimeAnimation(); - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, 0); - assert_equals(animation.playState, 'pending'); -}, "pending startTime"); - -test(function() { - var animation = runningAnimation(); - assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); - assert_equals(animation.currentTime, 0); - assert_equals(animation.playState, 'running'); -}, "running"); - -test(function() { - var animation = pausedAnimation(); - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, 0); - assert_equals(animation.playState, 'paused'); -}, "paused"); - -test(function() { - var animation = finishedAnimation(); - assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); - assert_equals(animation.currentTime, duration); - assert_equals(animation.playState, 'finished'); -}, "finished"); - -test(function() { - var animation = idleAnimation(); - animation.play(); - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, 0); - assert_equals(animation.playState, 'pending'); -}, "idle -> play()"); - -test(function() { - var animation = idleAnimation(); - animation.pause(); - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, 0); - assert_equals(animation.playState, 'pending'); -}, "idle -> pause()"); - -test(function() { - var animation = idleAnimation(); - animation.cancel(); - assert_unresolved(animation.startTime); - assert_unresolved(animation.currentTime); - assert_equals(animation.playState, 'idle'); -}, "idle -> cancel()"); - -test(function() { - var animation = idleAnimation(); - animation.finish(); - assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); - assert_equals(animation.currentTime, duration); - assert_equals(animation.playState, 'finished'); -}, "idle -> finish()"); - -test(function() { - var animation = idleAnimation(); - animation.reverse(); - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, duration); - assert_equals(animation.playState, 'pending'); -}, "idle -> reverse()"); - -test(function() { - var animation = idleAnimation(); - animation.currentTime = 1000; - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, 1000); - assert_equals(animation.playState, 'paused'); -}, "idle -> set currentTime"); - -test(function() { - var animation = idleAnimation(); - animation.startTime = document.timeline.currentTime - 1000; - assert_equals(animation.startTime, document.timeline.currentTime - 1000); - assert_equals(animation.currentTime, 1000); - assert_equals(animation.playState, 'running'); -}, "idle -> set startTime"); - -test(function() { - var animation = pendingStartTimeAnimation(); - animation.play(); - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, 0); - assert_equals(animation.playState, 'pending'); -}, "pending startTime -> play()"); - -test(function() { - var animation = pendingStartTimeAnimation(); - animation.pause(); - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, 0); - assert_equals(animation.playState, 'pending'); -}, "pending startTime -> pause()"); - -test(function() { - var animation = pendingStartTimeAnimation(); - animation.cancel(); - assert_unresolved(animation.startTime); - assert_unresolved(animation.currentTime); - assert_equals(animation.playState, 'idle'); -}, "pending startTime -> cancel()"); - -test(function() { - var animation = pendingStartTimeAnimation(); - animation.finish(); - assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); - assert_equals(animation.currentTime, duration); - assert_equals(animation.playState, 'finished'); -}, "pending startTime -> finish()"); - -test(function() { - var animation = pendingStartTimeAnimation(); - animation.reverse(); - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, duration); - assert_equals(animation.playState, 'pending'); -}, "pending startTime -> reverse()"); - -test(function() { - var animation = pendingStartTimeAnimation(); - animation.currentTime = 1000; - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, 1000); - assert_equals(animation.playState, 'pending'); -}, "pending startTime -> set currentTime"); - -test(function() { - var animation = pendingStartTimeAnimation(); - animation.startTime = document.timeline.currentTime - 1000; - assert_equals(animation.startTime, document.timeline.currentTime - 1000); - assert_equals(animation.currentTime, 1000); - assert_equals(animation.playState, 'running'); -}, "pending startTime -> set startTime"); - -test(function() { - var animation = runningAnimation(); - var startTime = animation.startTime; - var currentTime = animation.currentTime; - animation.play(); - assert_equals(animation.startTime, startTime); - assert_equals(animation.currentTime, currentTime); - assert_equals(animation.playState, 'running'); -}, "running -> play()"); - -test(function() { - var animation = runningAnimation(); - animation.pause(); - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, 0); - assert_equals(animation.playState, 'pending'); -}, "running -> pause()"); - -test(function() { - var animation = runningAnimation(); - animation.cancel(); - assert_unresolved(animation.startTime); - assert_unresolved(animation.currentTime); - assert_equals(animation.playState, 'idle'); -}, "running -> cancel()"); - -test(function() { - var animation = runningAnimation(); - animation.finish(); - assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); - assert_equals(animation.currentTime, duration); - assert_equals(animation.playState, 'finished'); -}, "running -> finish()"); - -test(function() { - var animation = runningAnimation(); - animation.reverse(); - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, duration); - assert_equals(animation.playState, 'pending'); -}, "running -> reverse()"); - -test(function() { - var animation = runningAnimation(); - animation.currentTime = 1000; - assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); - assert_equals(animation.currentTime, 1000); - assert_equals(animation.playState, 'running'); -}, "running -> set currentTime"); - -test(function() { - var animation = runningAnimation(); - animation.startTime = document.timeline.currentTime - 1000; - assert_equals(animation.startTime, document.timeline.currentTime - 1000); - assert_equals(animation.currentTime, 1000); - assert_equals(animation.playState, 'running'); -}, "running -> set startTime"); - -test(function() { - var animation = pausedAnimation(); - animation.play(); - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, 0); - assert_equals(animation.playState, 'pending'); -}, "paused -> play()"); - -test(function() { - var animation = pausedAnimation(); - animation.pause(); - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, 0); - assert_equals(animation.playState, 'paused'); -}, "paused -> pause()"); - -test(function() { - var animation = pausedAnimation(); - animation.cancel(); - assert_unresolved(animation.startTime); - assert_unresolved(animation.currentTime); - assert_equals(animation.playState, 'idle'); -}, "paused -> cancel()"); - -test(function() { - var animation = pausedAnimation(); - animation.finish(); - assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); - assert_equals(animation.currentTime, duration); - assert_equals(animation.playState, 'finished'); -}, "paused -> finish()"); - -test(function() { - var animation = pausedAnimation(); - animation.reverse(); - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, duration); - assert_equals(animation.playState, 'pending'); -}, "paused -> reverse()"); - -test(function() { - var animation = pausedAnimation(); - animation.currentTime = 1000; - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, 1000); - assert_equals(animation.playState, 'paused'); -}, "paused -> set currentTime"); - -test(function() { - var animation = pausedAnimation(); - animation.startTime = document.timeline.currentTime - 1000; - assert_equals(animation.startTime, document.timeline.currentTime - 1000); - assert_equals(animation.currentTime, 1000); - assert_equals(animation.playState, 'running'); -}, "paused -> set startTime"); - -test(function() { - var animation = finishedAnimation(); - animation.play(); - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, 0); - assert_equals(animation.playState, 'pending'); -}, "finished -> play()"); - -test(function() { - var animation = finishedAnimation(); - animation.pause(); - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, duration); - assert_equals(animation.playState, 'pending'); -}, "finished -> pause()"); - -test(function() { - var animation = finishedAnimation(); - animation.cancel(); - assert_unresolved(animation.startTime); - assert_unresolved(animation.currentTime); - assert_equals(animation.playState, 'idle'); -}, "finished -> cancel()"); - -test(function() { - var animation = finishedAnimation(); - animation.finish(); - assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); - assert_equals(animation.currentTime, duration); - assert_equals(animation.playState, 'finished'); -}, "finished -> finish()"); - -test(function() { - var animation = finishedAnimation(); - animation.reverse(); - assert_unresolved(animation.startTime); - assert_equals(animation.currentTime, duration); - assert_equals(animation.playState, 'pending'); -}, "finished -> reverse()"); - -test(function() { - var animation = finishedAnimation(); - animation.currentTime = 1000; - assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); - assert_equals(animation.currentTime, 1000); - assert_equals(animation.playState, 'running'); -}, "finished -> set currentTime"); - -{ - let test = async_test("pending (play) -> ready.then()"); - let animation = idleAnimation(); - animation.play(); - let animationCurrentTime = animation.currentTime; - let timelineCurrentTime = document.timeline.currentTime; - animation.ready.then(() => { - test.step(() => { - assert_equals(animation.playState, 'running'); - assert_greater_than_equal(animation.startTime, timelineCurrentTime); - assert_greater_than_equal(animation.currentTime, animationCurrentTime); - }); - test.done(); - }); -} - -{ - let test = async_test("pending (pause) -> ready.then()"); - let animation = runningAnimation(); - animation.pause(); - let animationCurrentTime = animation.currentTime; - animation.ready.then(() => { - test.step(() => { - assert_equals(animation.playState, 'paused'); - assert_unresolved(animation.startTime); - assert_greater_than_equal(animation.currentTime, animationCurrentTime); - }); - test.done(); - }); -} -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/animation-update-effect.html b/third_party/WebKit/LayoutTests/web-animations-api/animation-update-effect.html new file mode 100644 index 0000000..56acf2d --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/animation-update-effect.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Element style is updated when the Animation's effect is update</title> +<link rel="help" href="http://w3c.github.io/web-animations/#set-the-target-effect-of-an-animation"> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> + +<div id='element'></div> + +<script> +var element = document.getElementById('element'); + +test(function() { + var animation = element.animate([{left: '0px'}, {left: '100px'}], 10); + assert_equals(getComputedStyle(element).left, '0px'); + + var effect = animation.effect + animation.effect = null; + assert_equals(getComputedStyle(element).left, 'auto'); + + animation.effect = effect; + assert_equals(getComputedStyle(element).left, '0px'); +}, 'Element style updated after clear and set effect'); + +</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/eased-keyframes-non-animatable.html b/third_party/WebKit/LayoutTests/web-animations-api/eased-keyframes-non-animatable.html deleted file mode 100644 index e5dcd8f..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/eased-keyframes-non-animatable.html +++ /dev/null
@@ -1,27 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="w3c/resources/keyframes-test.js"></script> -<script> -test(function() { - assertAnimationStyles([ - {opacity: '0', position: 'absolute', easing: 'steps(4, start)'}, - {opacity: '0.5', position: 'relative'} - ], { - 0: {opacity: '0.125', position: 'absolute'}, - 0.25: {opacity: '0.25', position: 'relative'}, - 0.5: {opacity: '0.375', position: 'relative'}, - 0.75: {opacity: '0.5', position: 'relative'}, - 1: {opacity: '0.5', position: 'relative'} - }); -}, -'element.animate() with eased keyframe on non-animatable property', -{ - assert: [ - 'element.animate() should start an animation when keyframes are specified with timing functions', - 'for their easing property. Non-animatable properties should take on the first value when the', - 'functions value is less than 0.5, and the second value otherwise.', - ], - author: 'George Caley', -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/eased-keyframes.html b/third_party/WebKit/LayoutTests/web-animations-api/eased-keyframes.html deleted file mode 100644 index 902dbc7..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/eased-keyframes.html +++ /dev/null
@@ -1,108 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="w3c/resources/keyframes-test.js"></script> -<script> -// FIXME: Remove the need for and use of this function. -// Currently our animation timeline is not stable during page load script execution. -// By deferring the tests to requestAnimationFrame() we can get a stable timeline and -// avoid flaky test results. -function testInRAF(testFunction, description, properties) { - async_test(function(testHandle) { - requestAnimationFrame(function() { - testHandle.step(testFunction); - testHandle.done(); - }) - }, description, properties); -} - -testInRAF(function() { - assertAnimationStyles([ - {opacity: '0', left: '0px', easing: 'steps(2, start)'}, - {opacity: '0.25', left: '25px'}, - {opacity: '0.75', left: '75px'}, - ], { - 0: {opacity: '0.125', left: '12.5px'}, - 0.125: {opacity: '0.125', left: '12.5px'}, - 0.25: {opacity: '0.25', left: '25px'}, - 0.375: {opacity: '0.25', left: '25px'}, - 0.5: {opacity: '0.25', left: '25px'}, - 0.625: {opacity: '0.375', left: '37.5px'}, - 0.75: {opacity: '0.5', left: '50px'}, - 0.875: {opacity: '0.625', left: '62.5px'}, - 1: {opacity: '0.75', left: '75px'}, - }, 'with easing on first keyframe'); - - assertAnimationStyles([ - {opacity: '0', left: '0px'}, - {opacity: '0.5', left: '50px', easing: 'steps(2, start)'}, - {opacity: '0.75', left: '75px'}, - ], { - 0: {opacity: '0', left: '0px'}, - 0.125: {opacity: '0.125', left: '12.5px'}, - 0.25: {opacity: '0.25', left: '25px'}, - 0.375: {opacity: '0.375', left: '37.5px'}, - 0.5: {opacity: '0.625', left: '62.5px'}, - 0.625: {opacity: '0.625', left: '62.5px'}, - 0.75: {opacity: '0.75', left: '75px'}, - 0.875: {opacity: '0.75', left: '75px'}, - 1: {opacity: '0.75', left: '75px'}, - }, 'with easing on second keyframe'); -}, -'element.animate() with eased keyframe', -{ - help: 'http://dev.w3.org/fxtf/web-animations/#the-keyframe-dictionary', - assert: [ - 'element.animate() should start an animation when keyframes are specified with timing functions', - 'for their easing property. The animation should use the given timing function between consecutive', - 'keyframe offsets.', - ], - author: 'Alan Cutter', -}); - -testInRAF(function() { - assertAnimationStyles([ - {opacity: '0', offset: 0, easing: 'steps(2, start)'}, - {left: '0px', offset: 0}, - {opacity: '0.5', left: '50px'}, - ], { - 0: {opacity: '0.25', left: '0px'}, - 0.25: {opacity: '0.25', left: '12.5px'}, - 0.5: {opacity: '0.5', left: '25px'}, - 0.75: {opacity: '0.5', left: '37.5px'}, - 1: {opacity: '0.5', left: '50px'}, - }); -}, -'element.animate() with eased keyframe on single property', -{ - help: 'http://dev.w3.org/fxtf/web-animations/#the-keyframe-dictionary', - assert: [ - 'element.animate() should start an animation when keyframes are specified with timing functions', - 'for their easing property. The animation should use the given timing function only on the properties', - 'specified in the same keyframe.', - ], - author: 'Alan Cutter', -}); - -testInRAF(function() { - assertAnimationStyles([ - {opacity: '0', left: '0px'}, - {opacity: '0.5', left: '50px', easing: 'steps(2, start)'}, - ], { - 0: {opacity: '0', left: '0px'}, - 0.25: {opacity: '0.125', left: '12.5px'}, - 0.5: {opacity: '0.25', left: '25px'}, - 0.75: {opacity: '0.375', left: '37.5px'}, - 1: {opacity: '0.5', left: '50px'}, - }); -}, -'element.animate() with easing on last keyframe', -{ - help: 'http://dev.w3.org/fxtf/web-animations/#the-keyframe-dictionary', - assert: [ - 'element.animate() should start an animation when keyframes are specified with timing functions', - 'for their easing property. Easing on the last keyframes should have no effect on the animation.', - ], - author: 'Alan Cutter', -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/infinite-end-time.html b/third_party/WebKit/LayoutTests/web-animations-api/infinite-end-time.html deleted file mode 100644 index 5c5e2ce..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/infinite-end-time.html +++ /dev/null
@@ -1,54 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<body> -<script> -function infiniteAnimation() { - var anim = document.body.animate([], - {duration: 1000, iterations: Infinity}); - anim.cancel(); - return anim; -} - -test(function() { - var anim = infiniteAnimation(); - try { - anim.finish(); - assert_unreached(); - } catch (e) { - assert_equals(e.code, DOMException.INVALID_STATE_ERR); - } -}, "finishing an infinite animation"); - -test(function() { - var anim = infiniteAnimation(); - anim.playbackRate = -1; - try { - anim.pause(); - assert_unreached(); - } catch (e) { - assert_equals(e.code, DOMException.INVALID_STATE_ERR); - } -}, "pausing a reversed infinite animation"); - -test(function() { - var anim = infiniteAnimation(); - anim.playbackRate = -1; - try { - anim.play(); - assert_unreached(); - } catch (e) { - assert_equals(e.code, DOMException.INVALID_STATE_ERR); - } -}, "playing a reversed infinite animation"); - -test(function() { - var anim = infiniteAnimation(); - try { - anim.reverse(); - assert_unreached(); - } catch (e) { - assert_equals(e.code, DOMException.INVALID_STATE_ERR); - } -}, "reversing an infinite animation"); -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/playState-changes.html b/third_party/WebKit/LayoutTests/web-animations-api/playState-changes.html new file mode 100644 index 0000000..6398c09 --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/playState-changes.html
@@ -0,0 +1,384 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Tests for discrete animation</title> +<link rel="help" href="https://w3c.github.io/web-animations/#play-state"> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="../imported/wpt/web-animations/testcommon.js"></script> +<body> +<script> +'use strict'; +function createIdleAnimation(t) { + var animation = createDiv(t).animate([], 100000); + animation.cancel(); + return animation; +} + +function createRunningAnimation(t) { + var animation = createIdleAnimation(t); + animation.play(); + animation.startTime = document.timeline.currentTime; + return animation; +} + +function createPendingStartTimeAnimation(t) { + var animation = createIdleAnimation(t); + animation.play(); + return animation; +} + +function createPausedAnimation(t) { + var animation = createIdleAnimation(t); + animation.pause(); + animation.currentTime = 0; + return animation; +} + +function createFinishedAnimation(t) { + var animation = createIdleAnimation(t); + animation.play(); + animation.finish(); + return animation; +} + +// Initial animation states +test(function(t) { + var animation = createIdleAnimation(t); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, null); + assert_equals(animation.playState, 'idle'); +}, "Play state is idle after cancelling an animation"); + +test(function(t) { + var animation = createPendingStartTimeAnimation(t); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 0); + assert_equals(animation.playState, 'pending'); +}, "Play state is pending after playing a cancelled animation"); + +test(function(t) { + var animation = createRunningAnimation(t); + assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); + assert_equals(animation.currentTime, 0); + assert_equals(animation.playState, 'running'); +}, "Play state is running after playing and setting start time of a cancelled animation"); + +test(function(t) { + var animation = createPausedAnimation(t); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 0); + assert_equals(animation.playState, 'paused'); +}, "Play state is paused after pausing and setting current time of a cancelled animation"); + +test(function(t) { + var animation = createFinishedAnimation(t); + assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); + assert_equals(animation.currentTime, 100000); + assert_equals(animation.playState, 'finished'); +}, "Play state is finished after playing and finishing a cancelled animation"); + +// Changed animation states +test(function(t) { + var animation = createIdleAnimation(t); + animation.play(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 0); + assert_equals(animation.playState, 'pending'); +}, "Calling play() on an idle animation"); + +test(function(t) { + var animation = createIdleAnimation(t); + animation.pause(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 0); + assert_equals(animation.playState, 'pending'); +}, "Calling pause() on an idle animation"); + +test(function(t) { + var animation = createIdleAnimation(t); + animation.cancel(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, null); + assert_equals(animation.playState, 'idle'); +}, "Calling cancel() on an idle animation"); + +test(function(t) { + var animation = createIdleAnimation(t); + animation.finish(); + assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); + assert_equals(animation.currentTime, 100000); + assert_equals(animation.playState, 'finished'); +}, "Calling finish() on an idle animation"); + +test(function(t) { + var animation = createIdleAnimation(t); + animation.reverse(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 100000); + assert_equals(animation.playState, 'pending'); +}, "Calling reverse() on an idle animation"); + +test(function(t) { + var animation = createIdleAnimation(t); + animation.currentTime = 1000; + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 1000); + assert_equals(animation.playState, 'paused'); +}, "Setting currentTime on an idle animation"); + +test(function(t) { + var animation = createIdleAnimation(t); + animation.startTime = document.timeline.currentTime - 1000; + assert_equals(animation.startTime, document.timeline.currentTime - 1000); + assert_equals(animation.currentTime, 1000); + assert_equals(animation.playState, 'running'); +}, "Setting startTime on an idle animation"); + +test(function(t) { + var animation = createPendingStartTimeAnimation(t); + animation.play(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 0); + assert_equals(animation.playState, 'pending'); +}, "Calling play() on a pending starttime animation"); + +test(function(t) { + var animation = createPendingStartTimeAnimation(t); + animation.pause(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 0); + assert_equals(animation.playState, 'pending'); +}, "Calling pause() on a pending starttime animation"); + +test(function(t) { + var animation = createPendingStartTimeAnimation(t); + animation.cancel(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, null); + assert_equals(animation.playState, 'idle'); +}, "Calling cancel() on a pending starttime animation"); + +test(function(t) { + var animation = createPendingStartTimeAnimation(t); + animation.finish(); + assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); + assert_equals(animation.currentTime, 100000); + assert_equals(animation.playState, 'finished'); +}, "Calling finish() on a pending starttime animation"); + +test(function(t) { + var animation = createPendingStartTimeAnimation(t); + animation.reverse(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 100000); + assert_equals(animation.playState, 'pending'); +}, "Calling reverse() on a pending starttime animation"); + +test(function(t) { + var animation = createPendingStartTimeAnimation(t); + animation.currentTime = 1000; + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 1000); + assert_equals(animation.playState, 'pending'); +}, "Setting currentTime on a pending starttime animation"); + +test(function(t) { + var animation = createPendingStartTimeAnimation(t); + animation.startTime = document.timeline.currentTime - 1000; + assert_equals(animation.startTime, document.timeline.currentTime - 1000); + assert_equals(animation.currentTime, 1000); + assert_equals(animation.playState, 'running'); +}, "Setting startTime on a pending starttime animation"); + +test(function(t) { + var animation = createRunningAnimation(t); + var startTime = animation.startTime; + var currentTime = animation.currentTime; + animation.play(); + assert_equals(animation.startTime, startTime); + assert_equals(animation.currentTime, currentTime); + assert_equals(animation.playState, 'running'); +}, "Setting play() on a running animation"); + +test(function(t) { + var animation = createRunningAnimation(t); + animation.pause(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 0); + assert_equals(animation.playState, 'pending'); +}, "Setting pause() on a running animation"); + +test(function(t) { + var animation = createRunningAnimation(t); + animation.cancel(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, null); + assert_equals(animation.playState, 'idle'); +}, "Setting cancel() on a running animation"); + +test(function(t) { + var animation = createRunningAnimation(t); + animation.finish(); + assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); + assert_equals(animation.currentTime, 100000); + assert_equals(animation.playState, 'finished'); +}, "Setting finish() on a running animation"); + +test(function(t) { + var animation = createRunningAnimation(t); + animation.reverse(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 100000); + assert_equals(animation.playState, 'pending'); +}, "Setting reverse() on a running animation"); + + +test(function(t) { + var animation = createRunningAnimation(t); + animation.currentTime = 1000; + assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); + assert_equals(animation.currentTime, 1000); + assert_equals(animation.playState, 'running'); +}, "Setting currentTime on a running animation"); + +test(function(t) { + var animation = createRunningAnimation(t); + animation.startTime = document.timeline.currentTime - 1000; + assert_equals(animation.startTime, document.timeline.currentTime - 1000); + assert_equals(animation.currentTime, 1000); + assert_equals(animation.playState, 'running'); +}, "Setting startTime on a running animation"); + +test(function(t) { + var animation = createPausedAnimation(t); + animation.play(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 0); + assert_equals(animation.playState, 'pending'); +}, "Calling play() on a paused animation"); + +test(function(t) { + var animation = createPausedAnimation(t); + animation.pause(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 0); + assert_equals(animation.playState, 'paused'); +}, "Calling pause() on a paused animation"); + +test(function(t) { + var animation = createPausedAnimation(t); + animation.cancel(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, null); + assert_equals(animation.playState, 'idle'); +}, "Calling cancel() on a paused animation"); + +test(function(t) { + var animation = createPausedAnimation(t); + animation.finish(); + assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); + assert_equals(animation.currentTime, 100000); + assert_equals(animation.playState, 'finished'); +}, "Calling finish() on a paused animation"); + +test(function(t) { + var animation = createPausedAnimation(t); + animation.reverse(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 100000); + assert_equals(animation.playState, 'pending'); +}, "Calling reverse() on a paused animation"); + +test(function(t) { + var animation = createPausedAnimation(t); + animation.currentTime = 1000; + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 1000); + assert_equals(animation.playState, 'paused'); +}, "Setting currentTime on a paused animation"); + +test(function(t) { + var animation = createPausedAnimation(t); + animation.startTime = document.timeline.currentTime - 1000; + assert_equals(animation.startTime, document.timeline.currentTime - 1000); + assert_equals(animation.currentTime, 1000); + assert_equals(animation.playState, 'running'); +}, "Setting startTime on a paused animation"); + +test(function(t) { + var animation = createFinishedAnimation(t); + animation.play(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 0); + assert_equals(animation.playState, 'pending'); +}, "Calling play() on a finished animation"); + +test(function(t) { + var animation = createFinishedAnimation(t); + animation.pause(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 100000); + assert_equals(animation.playState, 'pending'); +}, "Calling pause() on a finished animation"); + +test(function(t) { + var animation = createFinishedAnimation(t); + animation.cancel(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, null); + assert_equals(animation.playState, 'idle'); +}, "Calling cancel() on a finished animation"); + +test(function(t) { + var animation = createFinishedAnimation(t); + animation.finish(); + assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); + assert_equals(animation.currentTime, 100000); + assert_equals(animation.playState, 'finished'); +}, "Calling finish() on a finished animation"); + +test(function(t) { + var animation = createFinishedAnimation(t); + animation.reverse(); + assert_equals(animation.startTime, null); + assert_equals(animation.currentTime, 100000); + assert_equals(animation.playState, 'pending'); +}, "Calling reverse() on a finished animation"); + +test(function(t) { + var animation = createFinishedAnimation(t); + animation.currentTime = 1000; + assert_equals(animation.startTime, document.timeline.currentTime - animation.currentTime); + assert_equals(animation.currentTime, 1000); + assert_equals(animation.playState, 'running'); +}, "Setting currentTime on a finished animation"); + +async_test(function(t) { + var animation = createIdleAnimation(t); + animation.play(); + var animationCurrentTime = animation.currentTime; + var timelineCurrentTime = document.timeline.currentTime; + animation.ready.then(() => { + t.step(() => { + assert_equals(animation.playState, 'running'); + assert_greater_than_equal(animation.startTime, timelineCurrentTime); + assert_greater_than_equal(animation.currentTime, animationCurrentTime); + }); + t.done(); + }); +}, "PlayState is 'running' while playing a cancelled animation"); + +async_test(function(t) { + let animation = createRunningAnimation(t); + animation.pause(); + let animationCurrentTime = animation.currentTime; + animation.ready.then(() => { + t.step(() => { + assert_equals(animation.playState, 'paused'); + assert_equals(animation.startTime, null); + assert_greater_than_equal(animation.currentTime, animationCurrentTime); + }); + t.done(); + }); +}, "PlayState is 'running' while pausing a running animation"); +</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/player-cancel-event.html b/third_party/WebKit/LayoutTests/web-animations-api/player-cancel-event.html deleted file mode 100644 index 5aa7298..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/player-cancel-event.html +++ /dev/null
@@ -1,31 +0,0 @@ -<!DOCTYPE html> -<body> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script> -var anim1 = document.body.animate([], 100000); -var anim2 = document.body.animate([], 100000); - -var cancelTest = async_test('Cancelling animation should create cancel event.'); -var fired = false; - -anim1.oncancel = function(event) { - cancelTest.step(function() { - assert_equals(event.target, anim1, 'Target of cancel event should be anim1.'); - assert_equals(event.currentTime, null, 'currentTime of cancel event should be null.'); - assert_equals(event.timelineTime, document.timeline.currentTime, 'Event timelineTime should be same as document.timeline.currentTime.'); - }); - fired = true; -}; - -anim2.onfinish = function() { - cancelTest.step(function() { - assert_true(fired, 'anim1.oncancel should be called.'); - }); - cancelTest.done(); -}; - -anim1.cancel(); -anim2.finish(); -</script> -</body>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/player-cancel-events-nofinish.html b/third_party/WebKit/LayoutTests/web-animations-api/player-cancel-events-nofinish.html deleted file mode 100644 index 09413239..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/player-cancel-events-nofinish.html +++ /dev/null
@@ -1,30 +0,0 @@ -<!DOCTYPE html> -<body> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script> -var anim1 = document.body.animate([], 100000); -var anim2 = document.body.animate([], 100000); -var anim3 = document.body.animate([], 100000); - -var noFinish = async_test('Animation finish event should not fire when cancelled'); - -anim1.onfinish = function() { - noFinish.step(function() { - anim3.finish(); - }); -}; - -anim2.onfinish = function() { - noFinish.step(function() { - assert_true(false); - }); -}; - -anim3.onfinish = function() { - noFinish.done(); -}; - -anim1.finish(); -anim2.cancel(); -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/player-finish-event-expected.txt b/third_party/WebKit/LayoutTests/web-animations-api/player-finish-event-expected.txt deleted file mode 100644 index 830cae8..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/player-finish-event-expected.txt +++ /dev/null
@@ -1,10 +0,0 @@ -PASS: playerMiddle is target -PASS: event currentTime equals player currentTime -PASS: event timelineTime equals timeline currentTime -PASS: playerBottom is target -PASS: event currentTime equals player currentTime -PASS: event timelineTime equals timeline currentTime -PASS: playerTop is target -PASS: event currentTime equals player currentTime -PASS: event timelineTime equals timeline currentTime -
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/player-finish-event.html b/third_party/WebKit/LayoutTests/web-animations-api/player-finish-event.html deleted file mode 100644 index acb2071..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/player-finish-event.html +++ /dev/null
@@ -1,92 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <style type="text/css"> - .anim { - position: absolute; - left: 10px; - height: 90px; - width: 100px; - background-color: black; - } - </style> - <script type="text/javascript"> - -function log(message) { - var results = document.getElementById('results'); - results.innerHTML += message + '<br>'; -} - -function validateFinishEvent(player, event) { - if (event.target === player) { - log('PASS: ' + player.name + ' is target'); - } else { - log('FAIL: expected target named ' + player.name + ', actual target is ' + event.target); - } - if (event.currentTime === player.currentTime) { - log('PASS: event currentTime equals player currentTime'); - } else { - log('FAIL: event currentTime ' + event.currentTime + ' does not equal player currentTime ' + player.currentTime); - } - if (event.timelineTime === document.timeline.currentTime) { - log('PASS: event timelineTime equals timeline currentTime'); - } else { - log('FAIL: event timelineTime ' + event.timelineTime + - ' does not equal timeline currentTime ' + document.timeline.currentTime); - } -} - -var playerTop, playerMiddle, playerBottom; - -function onFinishTop(event) { - validateFinishEvent(playerTop, event); - if (window.testRunner) { - testRunner.notifyDone(); - } -} - -function onFinishMiddle(event) { - validateFinishEvent(playerMiddle, event); -} - -function onFinishBottom(event) { - validateFinishEvent(playerBottom, event); -} - -function animate() { - - var keyframes = [ - {left: '10px', opacity: '1', offset: 0}, - {left: '100px', opacity: '0', offset: 1} - ]; - - playerTop = document.getElementById('top').animate(keyframes, 600); - playerTop.name = 'playerTop'; - playerTop.onfinish = onFinishTop; - - playerMiddle = document.getElementById('middle').animate(keyframes, 100); - playerMiddle.name = 'playerMiddle'; - playerMiddle.onfinish = onFinishMiddle; - - playerBottom = document.getElementById('bottom').animate(keyframes, 100); - playerBottom.name = 'playerBottom'; - playerBottom.onfinish = onFinishBottom; - - if (window.testRunner) { - testRunner.dumpAsText(); - testRunner.waitUntilDone(); - } -} - -window.onload = animate; - - </script> - </head> - <body> - <div class="anim" id="top"></div> - <div class="anim" id="middle"></div> - <div class="anim" id="bottom"></div> - <div id="results"></div> - </body> -</html> -
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/player-finish-repeats-expected.txt b/third_party/WebKit/LayoutTests/web-animations-api/player-finish-repeats-expected.txt deleted file mode 100644 index d01ad61e..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/player-finish-repeats-expected.txt +++ /dev/null
@@ -1,19 +0,0 @@ -PASS: playerTop is target -PASS: event currentTime equals player currentTime -PASS: event timelineTime equals timeline currentTime -PASS: playerTop is target -PASS: event currentTime equals player currentTime -PASS: event timelineTime equals timeline currentTime -PASS: playerMiddle is target -PASS: event currentTime equals player currentTime -PASS: event timelineTime equals timeline currentTime -PASS: playerMiddle is target -PASS: event currentTime equals player currentTime -PASS: event timelineTime equals timeline currentTime -PASS: playerBottom is target -PASS: event currentTime equals player currentTime -PASS: event timelineTime equals timeline currentTime -PASS: playerBottom is target -PASS: event currentTime equals player currentTime -PASS: event timelineTime equals timeline currentTime -
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/player-finish-repeats.html b/third_party/WebKit/LayoutTests/web-animations-api/player-finish-repeats.html deleted file mode 100644 index 85842a5..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/player-finish-repeats.html +++ /dev/null
@@ -1,123 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <style type="text/css"> - .anim { - position: absolute; - left: 10px; - height: 90px; - width: 100px; - background-color: blue; - opacity: 0.1; - } - - #top { - top: 0px; - } - #middle { - top: 100px; - } - #bottom { - top: 200px; - } - #results { - top: 300px; - } - </style> - <script type="text/javascript"> - -function log(message) { - var results = document.getElementById('results'); - results.innerHTML += message + '<br>'; -} - -function validateFinishEvent(player, event) { - if (event.target === player) { - log('PASS: ' + player.name + ' is target'); - } else { - log('FAIL: expected target named ' + player.name + ', actual target is ' + event.target); - } - if (event.currentTime === player.currentTime) { - log('PASS: event currentTime equals player currentTime'); - } else { - log('FAIL: event currentTime ' + event.currentTime + ' does not equal player currentTime ' + player.currentTime); - } - if (event.timelineTime === document.timeline.currentTime) { - log('PASS: event timelineTime equals timeline currentTime'); - } else { - log('FAIL: event timelineTime ' + event.timelineTime + - ' does not equal timeline currentTime ' + document.timeline.currentTime); - } -} - -var keyframes = [ - {left: '10px', offset: 0}, - {left: '100px', offset: 1} -]; - -var playerTop, playerMiddle, playerBottom; -var firstTop = true, firstMiddle = true, firstBottom = true; - -function onFinishTop(event) { - validateFinishEvent(playerTop, event); - - if (firstTop) { - firstTop = false; - playerTop.currentTime = 0; - } else { - playerMiddle = document.getElementById('middle').animate(keyframes, 0.05); - playerMiddle.name = 'playerMiddle'; - playerMiddle.onfinish = onFinishMiddle; - } -} - -function onFinishMiddle(event) { - validateFinishEvent(playerMiddle, event); - - if (firstMiddle) { - firstMiddle = false; - playerMiddle.play(); - } else { - playerBottom = document.getElementById('bottom').animate(keyframes, 0.05); - playerBottom.name = 'playerBottom'; - playerBottom.onfinish = onFinishBottom; - } -} - -function onFinishBottom(event) { - validateFinishEvent(playerBottom, event); - - if (firstBottom) { - firstBottom = false; - playerBottom.reverse(); - } else { - if (window.testRunner) { - testRunner.notifyDone(); - } - } -} - -function animate() { - - playerTop = document.getElementById('top').animate(keyframes, 0.05); - playerTop.name = 'playerTop'; - playerTop.onfinish = onFinishTop; - - if (window.testRunner) { - testRunner.dumpAsText(); - testRunner.waitUntilDone(); - } -} - -window.onload = animate; - - </script> - </head> - <body> - <div class="anim" id="top"></div> - <div class="anim" id="middle"></div> - <div class="anim" id="bottom"></div> - <div id="results"></div> - </body> -</html> -
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/player-finish-sample-only-expected.txt b/third_party/WebKit/LayoutTests/web-animations-api/player-finish-sample-only-expected.txt deleted file mode 100644 index 3fd5bae..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/player-finish-sample-only-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -PASS: playerTop is target -PASS: event currentTime equals player currentTime -PASS: event timelineTime equals timeline currentTime -
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/player-finish-sample-only.html b/third_party/WebKit/LayoutTests/web-animations-api/player-finish-sample-only.html deleted file mode 100644 index df82825..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/player-finish-sample-only.html +++ /dev/null
@@ -1,99 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <style type="text/css"> - .anim { - position: absolute; - left: 10px; - height: 90px; - width: 100px; - background-color: black; - } - </style> - <script type="text/javascript"> - -function log(message) { - var results = document.getElementById('results'); - results.innerHTML += message + '<br>'; -} - -function validateFinishEvent(player, event) { - if (event.target === player) { - log('PASS: ' + player.name + ' is target'); - } else { - log('FAIL: expected target named ' + player.name + ', actual target is ' + event.target); - } - if (event.currentTime === player.currentTime) { - log('PASS: event currentTime equals player currentTime'); - } else { - log('FAIL: event currentTime ' + event.currentTime + ' does not equal player currentTime ' + player.currentTime); - } - if (event.timelineTime === document.timeline.currentTime) { - log('PASS: event timelineTime equals timeline currentTime'); - } else { - log('FAIL: event timelineTime ' + event.timelineTime + - ' does not equal timeline currentTime ' + document.timeline.currentTime); - } -} - -var playerTop, playerMiddle, playerBottom; - -function onFinishTop(event) { - validateFinishEvent(playerTop, event); - if (window.testRunner) { - testRunner.notifyDone(); - } -} - -function onFinishMiddle(event) { - log('FAIL: seeking to finish should not queue event'); -} - -function onFinishBottom(event) { - log('FAIL: seeking past finish should not queue event'); -} - -function animate() { - - var keyframes = [ - {left: '10px', opacity: '1', offset: 0}, - {left: '100px', opacity: '0', offset: 1} - ]; - - playerMiddle = document.getElementById('middle').animate(keyframes, 70.0); - playerMiddle.name = 'playerMiddle'; - playerMiddle.onfinish = onFinishMiddle; - playerMiddle.finish(); - playerMiddle.currentTime = 0; - playerMiddle.pause(); - - playerBottom = document.getElementById('bottom').animate(keyframes, 70.0); - playerBottom.name = 'playerBottom'; - playerBottom.onfinish = onFinishBottom; - playerBottom.currentTime = 80.0; - playerBottom.currentTime = 0; - playerBottom.pause(); - - playerTop = document.getElementById('top').animate(keyframes, 90.0); - playerTop.name = 'playerTop'; - playerTop.onfinish = onFinishTop; - playerTop.finish(); - - if (window.testRunner) { - testRunner.dumpAsText(); - testRunner.waitUntilDone(); - } -} - -window.onload = animate; - - </script> - </head> - <body> - <div class="anim" id="top"></div> - <div class="anim" id="middle"></div> - <div class="anim" id="bottom"></div> - <div id="results"></div> - </body> -</html> -
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/player-ready-finished-ordering.html b/third_party/WebKit/LayoutTests/web-animations-api/player-ready-finished-ordering.html deleted file mode 100644 index f3f54126..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/player-ready-finished-ordering.html +++ /dev/null
@@ -1,39 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> - -<script> -async_test(function(t) { - var player = document.documentElement.animate([], 100000); - var ready = false; - player.ready.then(function() { - t.step(function() { - ready = true; - }); - }); - player.finished.then(function() { - t.step(function() { - assert_true(ready); - }); - t.done(); - }); - player.finish(); -}, 'The ready promise should be resolved before the finished promise'); - -async_test(function(t) { - var player = document.documentElement.animate([], 100000); - var ready = false; - player.ready.then(null, function() { - t.step(function() { - ready = true; - }); - }); - player.finished.then(null, function() { - t.step(function() { - assert_true(ready); - }); - t.done(); - }); - player.cancel(); -}, 'The ready promise should be rejected before the finished promise'); -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/player-reverse-end-exclusive.html b/third_party/WebKit/LayoutTests/web-animations-api/player-reverse-end-exclusive.html deleted file mode 100644 index be7d0e1..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/player-reverse-end-exclusive.html +++ /dev/null
@@ -1,18 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script> -function finishedPlayer() { - var player = document.documentElement.animate([], 100000); - player.finish(); - return player; -} - -test(function() { - var initial = getComputedStyle(document.documentElement).background; - var player = document.documentElement.animate([{background: 'red'}, {background: 'red'}], 100000); - player.playbackRate = -1; - player.currentTime = 0; - assert_equals(getComputedStyle(document.documentElement).background, initial); -}, "An animation which is not filling backwards should not be in effect at time 0 when playing backwards"); -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/player-source-becomes-longer.html b/third_party/WebKit/LayoutTests/web-animations-api/player-source-becomes-longer.html deleted file mode 100644 index ee86412..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/player-source-becomes-longer.html +++ /dev/null
@@ -1,20 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> - -<script> -test(function() { - document.timeline.playbackRate = 0; - document.timeline.currentTime = 0; - var player = document.documentElement.animate([], 1000); - player.startTime = -1000; - - assert_equals(player.currentTime, 1000); - - player.effect.timing.duration = 1500; - document.timeline.currentTime = 2000; - - assert_equals(player.startTime, -1000); - assert_equals(player.currentTime, 1500); -}, 'Extending effect should not cause a change in start time.'); -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/player-unresolved-times.html b/third_party/WebKit/LayoutTests/web-animations-api/player-unresolved-times.html deleted file mode 100644 index cbdacfe..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/player-unresolved-times.html +++ /dev/null
@@ -1,17 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> - -<script> -function assert_unresolved(value) { - assert_equals(value, null); -} - -test(function() { - var player = document.documentElement.animate([], 100000); - player.cancel(); - assert_unresolved(player.startTime); - assert_unresolved(player.currentTime); -}, "unresolved startTime and currentTime"); - -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/quirky-keyframes.html b/third_party/WebKit/LayoutTests/web-animations-api/quirky-keyframes.html deleted file mode 100644 index d0bcf22..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/quirky-keyframes.html +++ /dev/null
@@ -1,30 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> - -<style> -body { - color: blue; -} - -#target { - color: green; -} -</style> - -<body> - <div id="target"></div> -</body> - -<script> -test(function() { - var animation = target.animate([{ - color: '-webkit-text', - }, { - color: '-webkit-text', - }], 1); - animation.pause(); - animation.currentTime = 0; - assert_equals(getComputedStyle(target).color, 'rgb(0, 128, 0)'); -}, 'KeyframeEffects do not support quirky values.'); -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/startTime-expected.txt b/third_party/WebKit/LayoutTests/web-animations-api/startTime-expected.txt new file mode 100644 index 0000000..420d718 --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/startTime-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +FAIL startTime of a newly created (idle) animation is unresolved Animation is not defined +FAIL startTime of a play-pending animation is unresolved Animation is not defined +FAIL startTime of a pause-pending animation is unresolved Animation is not defined +PASS startTime of a play-pending animation created using Element.animate shortcut is unresolved +PASS startTime is resolved when running +PASS startTime and currentTime are unresolved when animation is cancelled +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/startTime.html b/third_party/WebKit/LayoutTests/web-animations-api/startTime.html new file mode 100644 index 0000000..cd840416 --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/startTime.html
@@ -0,0 +1,56 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Animation.startTime tests</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-animation-starttime"> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="../imported/wpt/web-animations/testcommon.js"></script> +<link rel="stylesheet" href="../resources/testharness.css"> +<body> +<div>This test is a copy of LayoutTests/imported/wpt/web-animations/interfaces/Animation/startTime.html. Make sure to upstream this to the w3c test suite as it contains an added test that would fit well there.</div> +<div id="log"></div> +<script> +'use strict'; + +test(function(t) { + var animation = new Animation(new KeyframeEffect(createDiv(t), null), + document.timeline); + assert_equals(animation.startTime, null, 'startTime is unresolved'); +}, 'startTime of a newly created (idle) animation is unresolved'); + +test(function(t) { + var animation = new Animation(new KeyframeEffect(createDiv(t), null), + document.timeline); + animation.play(); + assert_equals(animation.startTime, null, 'startTime is unresolved'); +}, 'startTime of a play-pending animation is unresolved'); + +test(function(t) { + var animation = new Animation(new KeyframeEffect(createDiv(t), null), + document.timeline); + animation.pause(); + assert_equals(animation.startTime, null, 'startTime is unresolved'); +}, 'startTime of a pause-pending animation is unresolved'); + +test(function(t) { + var animation = createDiv(t).animate(null); + assert_equals(animation.startTime, null, 'startTime is unresolved'); +}, 'startTime of a play-pending animation created using Element.animate' + + ' shortcut is unresolved'); + +promise_test(function(t) { + var animation = createDiv(t).animate(null, 100 * MS_PER_SEC); + return animation.ready.then(function() { + assert_greater_than(animation.startTime, 0, 'startTime when running'); + }); +}, 'startTime is resolved when running'); + +test(function() { + var player = document.documentElement.animate([], 100000); + player.cancel(); + assert_equals(player.startTime, null); + assert_equals(player.currentTime, null); +}, "startTime and currentTime are unresolved when animation is cancelled"); + +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/the-effect-value-of-a-keyframe-effect.html b/third_party/WebKit/LayoutTests/web-animations-api/the-effect-value-of-a-keyframe-effect.html new file mode 100644 index 0000000..6d655f6 --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/the-effect-value-of-a-keyframe-effect.html
@@ -0,0 +1,26 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Keyframe handling tests</title> +<link rel="help" href="https://w3c.github.io/web-animations/#the-effect-value-of-a-keyframe-animation-effect"> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="../imported/wpt/web-animations/testcommon.js"></script> +<body> +<div id="log"></div> +<div id="target"></div> +<script> +'use strict'; + +test(function(t) { + var div = createDiv(t); + div.style.color = 'rgb(0, 0, 0)'; + var anim = div.animate({ color: [ '-webkit-text', '-webkit-text'] }, 1000); + + anim.pause(); + anim.currentTime = 0; + + assert_equals(getComputedStyle(div).color, 'rgb(0, 0, 0)'); + +}, 'Tests keyframes with property values which are unsupported are removed'); +</script> +</body> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/time-consistent-across-frames.html b/third_party/WebKit/LayoutTests/web-animations-api/time-consistent-across-frames.html index f72f6656..eefc54b 100644 --- a/third_party/WebKit/LayoutTests/web-animations-api/time-consistent-across-frames.html +++ b/third_party/WebKit/LayoutTests/web-animations-api/time-consistent-across-frames.html
@@ -1,23 +1,30 @@ <!DOCTYPE html> +<meta charset=utf-8> +<title>Model liveness: currentTime will not change in a task (frames)</title> +<link rel="help" href="https://w3c.github.io/web-animations/#model-liveness"> <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script> +<script src="../imported/wpt/web-animations/testcommon.js"></script> <iframe id=frame></iframe> <script> -var handle = async_test('Animation time should tick consistently across frames'); +var handle = async_test('Document timeline should tick consistently across frames'); var baseTime = document.timeline.currentTime; var frameBaseTime = frame.contentDocument.timeline.currentTime; -setTimeout(function() { +setTimeout(() => { + // Ensure that time in this task has advanced sufficiently for implementations + // that might bind the currentTime lazily. var start = performance.now(); while (performance.now() - start < 30); var delta = document.timeline.currentTime - baseTime; + // Advance time further before querying the frame's time. var start = performance.now(); while (performance.now() - start < 30); var frameDelta = frame.contentDocument.timeline.currentTime - frameBaseTime; - handle.step(() => assert_equals(Math.round(delta), Math.round(frameDelta))); + handle.step(() => assert_times_equal(delta, frameDelta)); handle.done(); }); </script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/timed-item-specified-setters.html b/third_party/WebKit/LayoutTests/web-animations-api/timed-item-specified-setters.html deleted file mode 100644 index 105ed3c..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/timed-item-specified-setters.html +++ /dev/null
@@ -1,118 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script> -var typeError = {name: 'TypeError'}; -var timing = new KeyframeEffect(null, null).timing; - -test(function() { - timing.delay = 2; - assert_equals(timing.delay, 2); - timing.delay = -4; - assert_equals(timing.delay, -4); - - assert_throws(typeError, () => timing.delay = NaN); - assert_equals(timing.delay, -4); - - assert_throws(typeError, () => timing.delay = Infinity); - assert_equals(timing.delay, -4); -}, 'AnimationEffectTiming should have a setter for delay.'); - -test(function() { - timing.endDelay = 0.5; - assert_equals(timing.endDelay, 0.5); - - timing.endDelay = -5; - assert_equals(timing.endDelay, -5); - - assert_throws(typeError, () => timing.endDelay = NaN); - assert_equals(timing.endDelay, -5); - - assert_throws(typeError, () => timing.endDelay = Infinity); - assert_equals(timing.endDelay, -5); -}, 'AnimationEffectTiming should have a setter for endDelay.'); - -test(function() { - timing.fill = 'backwards'; - assert_equals(timing.fill, 'backwards'); - - timing.fill = 'both'; - assert_equals(timing.fill, 'both'); -}, 'AnimationEffectTiming should have a setter for fill.'); - -test(function() { - timing.iterationStart = 1.5; - assert_equals(timing.iterationStart, 1.5); - - assert_throws(typeError, () => timing.iterationStart = -0.5); - assert_equals(timing.iterationStart, 1.5); - - assert_throws(typeError, () => timing.iterationStart = NaN); - assert_equals(timing.iterationStart, 1.5); - - assert_throws(typeError, () => timing.iterationStart = Infinity); - assert_equals(timing.iterationStart, 1.5); -}, 'AnimationEffectTiming should have a setter for iterationStart.'); - -test(function() { - timing.iterations = 10; - assert_equals(timing.iterations, 10); - - timing.iterations = Infinity; - assert_equals(timing.iterations, Infinity); - - assert_throws(typeError, () => timing.iterations = -20); - assert_equals(timing.iterations, Infinity); - - assert_throws(typeError, () => timing.iterations = NaN); - assert_equals(timing.iterations, Infinity); -}, 'AnimationEffectTiming should have a setter for iterations.'); - -test(function() { - timing.duration = Infinity; - assert_equals(timing.duration, Infinity); - - timing.duration = 1234; - assert_equals(timing.duration, 1234); - - assert_throws(typeError, () => timing.duration = -10); - assert_equals(timing.duration, 1234); - - assert_throws(typeError, () => timing.duration = NaN); - assert_equals(timing.duration, 1234); - - assert_throws(typeError, () => timing.duration = 'very long'); - assert_equals(timing.duration, 1234); -}, 'AnimationEffectTiming should have a setter for duration.'); - -test(function() { - timing.playbackRate = 2; - assert_equals(timing.playbackRate, 2); - - timing.playbackRate = -2; - assert_equals(timing.playbackRate, -2); - - assert_throws(typeError, () => timing.playbackRate = NaN); - assert_equals(timing.playbackRate, -2); -}, 'AnimationEffectTiming should have a setter for playbackRate.'); - -test(function() { - timing.direction = 'reverse'; - assert_equals(timing.direction, 'reverse'); - - timing.direction = 'alternate'; - assert_equals(timing.direction, 'alternate'); -}, 'AnimationEffectTiming should have a setter for direction.'); - -test(function() { - timing.easing = "step-start"; - assert_equals(timing.easing, 'step-start'); - - timing.easing = "eAse\\2d iN-ouT"; - assert_equals(timing.easing, 'ease-in-out'); - - - assert_throws(typeError, () => timing.easing = 'ponies'); - assert_equals(timing.easing, 'ease-in-out'); -}, 'AnimationEffectTiming should have a setter for easing.'); -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/timeline-set-current-time.html b/third_party/WebKit/LayoutTests/web-animations-api/timeline-set-current-time.html deleted file mode 100644 index 5e78f2c1..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/timeline-set-current-time.html +++ /dev/null
@@ -1,35 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> - -<!-- This tests that animation timeline current time affects players correctly. --> - -<div id='element'></div> - -<script> -async_test(function(t) { - var player = element.animate([], 10); - var readyPromise = player.ready.then(function() { - t.step(function() { - assert_equals(player.currentTime, 0); - document.timeline.currentTime = player.startTime + 5; - assert_approx_equals(player.currentTime, 5, 0.1); - assert_equals(player.playState, "running"); - - document.timeline.currentTime = player.startTime + 15; - assert_approx_equals(player.currentTime, 10, 0.1); - assert_equals(player.playState, "finished"); - - document.timeline.currentTime = player.startTime; - assert_equals(player.currentTime, 0); - assert_equals(player.playState, "running"); - - document.timeline.currentTime = player.startTime + 5; - assert_approx_equals(player.currentTime, 5, 0.1); - assert_equals(player.playState, "running"); - }); - t.done(); - }); -}, 'Animation players are retriggered if timeline time changes'); - -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/timeline-time.html b/third_party/WebKit/LayoutTests/web-animations-api/timeline-time.html index a608400b..76c3aaa 100644 --- a/third_party/WebKit/LayoutTests/web-animations-api/timeline-time.html +++ b/third_party/WebKit/LayoutTests/web-animations-api/timeline-time.html
@@ -1,4 +1,7 @@ <!DOCTYPE html> +<meta charset=utf-8> +<title>Document timeline is increasing</title> +<link rel="help" href="http://w3c.github.io/web-animations/#the-documents-default-timeline"> <script src="../resources/testharness.js"></script> <script src="../resources/testharnessreport.js"></script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/timeline-updates-players.html b/third_party/WebKit/LayoutTests/web-animations-api/timeline-updates-players.html deleted file mode 100644 index 13f50d82..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/timeline-updates-players.html +++ /dev/null
@@ -1,35 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> - -<!-- This tests that players get updated even if they have previously had their effect removed or go out of effect. --> - -<div id='element'></div> - -<script> -var element = document.getElementById('element'); -var keyframeEffect = new KeyframeEffect(element, [{left: '0px'}, {left: '100px'}], 10); -test(function() { - var player = document.timeline.play(keyframeEffect); - player.finish(); - assert_equals(getComputedStyle(element).left, 'auto'); - - player.play(); - assert_equals(getComputedStyle(element).left, '0px'); - - player.finish(); -}, 'Player updated after finish and play'); - -test(function() { - var player = document.timeline.play(keyframeEffect); - assert_equals(getComputedStyle(element).left, '0px'); - var effect = player.effect - player.effect = null; - assert_equals(getComputedStyle(element).left, 'auto'); - - player.effect = effect; - assert_equals(getComputedStyle(element).left, '0px'); - - player.finish(); -}, 'Player updated after clear and set effect'); -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/w3c/eased-keyframes.html b/third_party/WebKit/LayoutTests/web-animations-api/w3c/eased-keyframes.html deleted file mode 100644 index d278b09f..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/w3c/eased-keyframes.html +++ /dev/null
@@ -1,95 +0,0 @@ -<!DOCTYPE html> -<script src="../../resources/testharness.js"></script> -<script src="../../resources/testharnessreport.js"></script> -<script src="resources/keyframes-test.js"></script> -<script> -test(function() { - assertAnimationStyles([ - {opacity: '0', left: '0px', easing: 'steps(2, start)'}, - {opacity: '0.25', left: '25px'}, - {opacity: '0.75', left: '75px'}, - ], { - 0: {opacity: '0.125', left: '12.5px'}, - 0.125: {opacity: '0.125', left: '12.5px'}, - 0.25: {opacity: '0.25', left: '25px'}, - 0.375: {opacity: '0.25', left: '25px'}, - 0.5: {opacity: '0.25', left: '25px'}, - 0.625: {opacity: '0.375', left: '37.5px'}, - 0.75: {opacity: '0.5', left: '50px'}, - 0.875: {opacity: '0.625', left: '62.5px'}, - 1: {opacity: '0.75', left: '75px'}, - }, 'with easing on first keyframe'); - - assertAnimationStyles([ - {opacity: '0', left: '0px'}, - {opacity: '0.5', left: '50px', easing: 'steps(2, start)'}, - {opacity: '0.75', left: '75px'}, - ], { - 0: {opacity: '0', left: '0px'}, - 0.125: {opacity: '0.125', left: '12.5px'}, - 0.25: {opacity: '0.25', left: '25px'}, - 0.375: {opacity: '0.375', left: '37.5px'}, - 0.5: {opacity: '0.625', left: '62.5px'}, - 0.625: {opacity: '0.625', left: '62.5px'}, - 0.75: {opacity: '0.75', left: '75px'}, - 0.875: {opacity: '0.75', left: '75px'}, - 1: {opacity: '0.75', left: '75px'}, - }, 'with easing on second keyframe'); -}, -'element.animate() with eased keyframe', -{ - help: 'http://dev.w3.org/fxtf/web-animations/#the-keyframe-dictionary', - assert: [ - 'element.animate() should start an animation when keyframes are specified with timing functions', - 'for their easing property. The animation should use the given timing function between consecutive', - 'keyframe offsets.', - ], - author: 'Alan Cutter', -}); - -test(function() { - assertAnimationStyles([ - {opacity: '0', offset: 0, easing: 'steps(2, start)'}, - {left: '0px', offset: 0}, - {opacity: '0.5', left: '50px'}, - ], { - 0: {opacity: '0.25', left: '0px'}, - 0.25: {opacity: '0.25', left: '12.5px'}, - 0.5: {opacity: '0.5', left: '25px'}, - 0.75: {opacity: '0.5', left: '37.5px'}, - 1: {opacity: '0.5', left: '50px'}, - }); -}, -'element.animate() with eased keyframe on single property', -{ - help: 'http://dev.w3.org/fxtf/web-animations/#the-keyframe-dictionary', - assert: [ - 'element.animate() should start an animation when keyframes are specified with timing functions', - 'for their easing property. The animation should use the given timing function only on the properties', - 'specified in the same keyframe.', - ], - author: 'Alan Cutter', -}); - -test(function() { - assertAnimationStyles([ - {opacity: '0', left: '0px'}, - {opacity: '0.5', left: '50px', easing: 'steps(2, start)'}, - ], { - 0: {opacity: '0', left: '0px'}, - 0.25: {opacity: '0.125', left: '12.5px'}, - 0.5: {opacity: '0.25', left: '25px'}, - 0.75: {opacity: '0.375', left: '37.5px'}, - 1: {opacity: '0.5', left: '50px'}, - }); -}, -'element.animate() with easing on last keyframe', -{ - help: 'http://dev.w3.org/fxtf/web-animations/#the-keyframe-dictionary', - assert: [ - 'element.animate() should start an animation when keyframes are specified with timing functions', - 'for their easing property. Easing on the last keyframes should have no effect on the animation.', - ], - author: 'Alan Cutter', -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/w3c/get-animation-players.html b/third_party/WebKit/LayoutTests/web-animations-api/w3c/get-animation-players.html deleted file mode 100644 index 8e340e80..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/w3c/get-animation-players.html +++ /dev/null
@@ -1,108 +0,0 @@ -<!DOCTYPE html> -<script src="../../resources/testharness.js"></script> -<script src="../../resources/testharnessreport.js"></script> -<div id='container'> - <div id='element'></div> -</div> - -<script> - -var container = document.getElementById('container'); -var element = document.getElementById('element'); - -test(function() { - assert_equals(document.timeline.getAnimations().length, 0); - assert_equals(container.getAnimations().length, 0); - assert_equals(element.getAnimations().length, 0); - - var animation = element.animate([], 1000); - assert_equals(document.timeline.getAnimations().length, 1); - assert_equals(document.timeline.getAnimations()[0], animation); - - var animation2 = container.animate([], 1000); - assert_equals(document.timeline.getAnimations().length, 2); - assert_equals(document.timeline.getAnimations()[0], animation); - assert_equals(document.timeline.getAnimations()[1], animation2); - - animation.finish(); - assert_equals(document.timeline.getAnimations().length, 1); - assert_equals(document.timeline.getAnimations()[0], animation2); - - animation2.finish(); - assert_equals(document.timeline.getAnimations().length, 0); -}, 'Timeline getAnimations()'); - -test(function() { - assert_equals(document.timeline.getAnimations().length, 0); - assert_equals(container.getAnimations().length, 0); - assert_equals(element.getAnimations().length, 0); - - var animation = element.animate([], 1000); - assert_equals(document.timeline.getAnimations().length, 1); - assert_equals(document.timeline.getAnimations()[0], animation); - assert_equals(container.getAnimations().length, 0); - assert_equals(element.getAnimations().length, 1); - assert_equals(element.getAnimations()[0], animation); - - var animation2 = container.animate([], 1000); - assert_equals(document.timeline.getAnimations().length, 2); - assert_equals(document.timeline.getAnimations()[0], animation); - assert_equals(document.timeline.getAnimations()[1], animation2); - assert_equals(container.getAnimations().length, 1); - assert_equals(container.getAnimations()[0], animation2); - assert_equals(element.getAnimations().length, 1); - assert_equals(element.getAnimations()[0], animation); - - animation.finish(); - assert_equals(document.timeline.getAnimations().length, 1); - assert_equals(document.timeline.getAnimations()[0], animation2); - assert_equals(container.getAnimations().length, 1); - assert_equals(container.getAnimations()[0], animation2); - assert_equals(element.getAnimations().length, 0); - - animation2.finish(); - assert_equals(document.timeline.getAnimations().length, 0); - assert_equals(container.getAnimations().length, 0); - assert_equals(element.getAnimations().length, 0); - -}, 'Animatable getAnimations()'); - -test(function() { - assert_equals(document.timeline.getAnimations().length, 0); - assert_equals(container.getAnimations().length, 0); - assert_equals(element.getAnimations().length, 0); - - var animation = element.animate([], {duration: 1000, delay: 500}); - assert_equals(document.timeline.getAnimations().length, 1); - assert_equals(document.timeline.getAnimations()[0], animation); - assert_equals(container.getAnimations().length, 0); - assert_equals(element.getAnimations().length, 1); - assert_equals(element.getAnimations()[0], animation); - - animation.finish(); - assert_equals(document.timeline.getAnimations().length, 0); - assert_equals(container.getAnimations().length, 0); - assert_equals(element.getAnimations().length, 0); - -}, 'getAnimations() with delays'); - -test(function() { - assert_equals(document.timeline.getAnimations().length, 0); - assert_equals(container.getAnimations().length, 0); - assert_equals(element.getAnimations().length, 0); - - var animation = element.animate([], {duration: 1000, delay: 500, fill: 'both'}); - assert_equals(document.timeline.getAnimations().length, 1); - assert_equals(document.timeline.getAnimations()[0], animation); - assert_equals(container.getAnimations().length, 0); - assert_equals(element.getAnimations().length, 1); - assert_equals(element.getAnimations()[0], animation); - - animation.finish(); - assert_equals(document.timeline.getAnimations().length, 1); - // assert_equals(container.getAnimations().length, 1); - // assert_equals(element.getAnimations().length, 1); - -}, 'getAnimations() - in effect animations'); - -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/w3c/get-animations-expected.txt b/third_party/WebKit/LayoutTests/web-animations-api/w3c/get-animations-expected.txt new file mode 100644 index 0000000..ec75744 --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/w3c/get-animations-expected.txt
@@ -0,0 +1,6 @@ +This is a testharness.js-based test. +FAIL getAnimations() normal behaviour (without delays) document.getAnimations is not a function +FAIL getAnimations() with animation delays document.getAnimations is not a function +FAIL getAnimations() with in effect animations document.getAnimations is not a function +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/w3c/get-animations.html b/third_party/WebKit/LayoutTests/web-animations-api/w3c/get-animations.html new file mode 100644 index 0000000..761e7a5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/web-animations-api/w3c/get-animations.html
@@ -0,0 +1,90 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>Get Animations</title> +<link rel="help" href="https://w3c.github.io/web-animations/#dom-document-getanimations"> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<div id='container'> + <div id='element'></div> +</div> + +<script> + +var container = document.getElementById('container'); +var element = document.getElementById('element'); + +test(function() { + assert_equals(document.getAnimations().length, 0); + assert_equals(container.getAnimations().length, 0); + assert_equals(element.getAnimations().length, 0); + + var animation = element.animate([], 1000); + assert_equals(document.getAnimations().length, 1); + assert_equals(document.getAnimations()[0], animation); + assert_equals(container.getAnimations().length, 0); + assert_equals(element.getAnimations().length, 1); + assert_equals(element.getAnimations()[0], animation); + + var animation2 = container.animate([], 1000); + assert_equals(document.getAnimations().length, 2); + assert_equals(document.getAnimations()[0], animation); + assert_equals(document.getAnimations()[1], animation2); + assert_equals(container.getAnimations().length, 1); + assert_equals(container.getAnimations()[0], animation2); + assert_equals(element.getAnimations().length, 1); + assert_equals(element.getAnimations()[0], animation); + + animation.finish(); + assert_equals(document.getAnimations().length, 1); + assert_equals(document.getAnimations()[0], animation2); + assert_equals(container.getAnimations().length, 1); + assert_equals(container.getAnimations()[0], animation2); + assert_equals(element.getAnimations().length, 0); + + animation2.finish(); + assert_equals(document.getAnimations().length, 0); + assert_equals(container.getAnimations().length, 0); + assert_equals(element.getAnimations().length, 0); + +}, 'getAnimations() normal behaviour (without delays)'); + +test(function() { + assert_equals(document.getAnimations().length, 0); + assert_equals(container.getAnimations().length, 0); + assert_equals(element.getAnimations().length, 0); + + var animation = element.animate([], {duration: 1000, delay: 500}); + assert_equals(document.getAnimations().length, 1); + assert_equals(document.getAnimations()[0], animation); + assert_equals(container.getAnimations().length, 0); + assert_equals(element.getAnimations().length, 1); + assert_equals(element.getAnimations()[0], animation); + + animation.finish(); + assert_equals(document.getAnimations().length, 0); + assert_equals(container.getAnimations().length, 0); + assert_equals(element.getAnimations().length, 0); + +}, 'getAnimations() with animation delays'); + +test(function() { + assert_equals(document.getAnimations().length, 0); + assert_equals(container.getAnimations().length, 0); + assert_equals(element.getAnimations().length, 0); + + var animation = element.animate([], {duration: 1000, delay: 500, fill: 'both'}); + assert_equals(document.getAnimations().length, 1); + assert_equals(document.getAnimations()[0], animation); + assert_equals(container.getAnimations().length, 0); + assert_equals(element.getAnimations().length, 1); + assert_equals(element.getAnimations()[0], animation); + + animation.finish(); + assert_equals(document.getAnimations().length, 1); + assert_equals(container.getAnimations().length, 0); + assert_equals(element.getAnimations().length, 1); + +}, 'getAnimations() with in effect animations'); + + +</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/w3c/keyframes-with-null-offsets.html b/third_party/WebKit/LayoutTests/web-animations-api/w3c/keyframes-with-null-offsets.html index 8b46edf..179b0b7 100644 --- a/third_party/WebKit/LayoutTests/web-animations-api/w3c/keyframes-with-null-offsets.html +++ b/third_party/WebKit/LayoutTests/web-animations-api/w3c/keyframes-with-null-offsets.html
@@ -1,4 +1,8 @@ <!DOCTYPE html> +<meta charset=utf-8> +<title>Test keyframes with null offsets</title> +<link rel="help" href="https://w3c.github.io/web-animations/#keyframes-section"> + <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="resources/keyframes-test.js"></script> @@ -14,7 +18,7 @@ 0.5: {opacity: '0', left: '0px'}, 0.75: {opacity: '0.375', left: '37.5px'}, 1: {opacity: '0.75', left: '75px'}, - }, 'case A'); + }, 'Null and missing offsets behave identically'); assertAnimationStyles([ {opacity: '0.5', left: '50px', offset: null}, {opacity: '0', left: '0px', offset: 0.25}, @@ -26,7 +30,7 @@ 0.5: {opacity: '0.25', left: '25px'}, 0.75: {opacity: '0.5', left: '50px'}, 1: {opacity: '0.75', left: '75px'}, - }, 'case B'); + }, 'Null and explicit offsets behave as with missing and explicit offsets.'); }, 'element.animate() with null offsets specified', {
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/w3c/out-of-order-keyframes.html b/third_party/WebKit/LayoutTests/web-animations-api/w3c/out-of-order-keyframes.html deleted file mode 100644 index 6c80fd4..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/w3c/out-of-order-keyframes.html +++ /dev/null
@@ -1,26 +0,0 @@ -<!doctype html> -<title>Web Animations API: Out of order Keyframe tests</title> -<script src='../../resources/testharness.js'></script> -<script src='../../resources/testharnessreport.js'></script> -<div id='log'></div> -<div id='div'></div> -<script> - -test(function() { - assert_throws({name: 'TypeError'}, function() { - div.animate([{height: '100px', offset: 0.5}, {height: '200px', offset: 0}, {height: '300px', offset: 1}], 1); - }, 'Out-of-order properties should not work'); - - assert_throws({name: 'TypeError'}, function() { - div.animate([{height: '100px', offset: 0.5}, {height: '150px'}, - {height: '200px', offset: 0}, {height: '300px', offset: 1}], 1); - }, 'Auto offsets combined with out-of-order properties should not work'); -}, -'Out-of-order Keyframe tests', -{ - help: 'http://dev.w3.org/fxtf/web-animations/#normalizing-a-sequence-of-keyframes', - assert: 'Keyframes with out-of-order offsets should work, unless there are also auto offsets', - author: 'Shane Stephens' -}); - -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/w3c/same-offset-keyframes.html b/third_party/WebKit/LayoutTests/web-animations-api/w3c/same-offset-keyframes.html deleted file mode 100644 index f3c5da9..0000000 --- a/third_party/WebKit/LayoutTests/web-animations-api/w3c/same-offset-keyframes.html +++ /dev/null
@@ -1,52 +0,0 @@ -<!DOCTYPE html> -<script src="../../resources/testharness.js"></script> -<script src="../../resources/testharnessreport.js"></script> -<script src="resources/keyframes-test.js"></script> -<script> -test(function() { - assertAnimationStyles([ - {opacity: '0', left: '0px'}, - {opacity: '0.5', left: '50px', offset: 0.5}, - {opacity: '0', left: '0px', offset: 0.5}, - {opacity: '0.75', left: '75px', offset: 0.5}, - {opacity: '0.25', left: '25px'}, - ], { - 0.25: {opacity: '0.25', left: '25px'}, - 0.5: {opacity: '0.75', left: '75px'}, - 0.75: {opacity: '0.5', left: '50px'}, - }) -}, -'element.animate() with keyframes at the same offset with overlapping properties', -{ - help: 'http://dev.w3.org/fxtf/web-animations/#the-unaccumulated-animation-value-of-a-keyframe-animation-effect', - assert: [ - 'element.animate() should start an animation when keyframes have equal offset values.', - 'The overlapping properties in the equal offset keyframes should see a disjoint', - 'interpolation pattern at the offset relative to the ordering of the keyframes.', - ], - author: 'Alan Cutter', -}); - -test(function() { - assertAnimationStyles([ - {opacity: '0', left: '0px'}, - {opacity: '0.75', offset: 0.5}, - {left: '75px', offset: 0.5}, - {opacity: '0.25', left: '25px'}, - ], { - 0.25: {opacity: '0.375', left: '37.5px'}, - 0.5: {opacity: '0.75', left: '75px'}, - 0.75: {opacity: '0.5', left: '50px'}, - }) -}, -'element.animate() with keyframes at the same offset with disjoint properties', -{ - help: 'http://dev.w3.org/fxtf/web-animations/#the-unaccumulated-animation-value-of-a-keyframe-animation-effect', - assert: [ - 'element.animate() should start an animation when keyframes have equal offset values.', - 'If the properties of the equal offset keyframes are disjoint then the animation should', - 'be equivalent to having a single keyframe at that offset (assuming the easings are equal too).', - ], - author: 'Alan Cutter', -}); -</script>
diff --git a/third_party/WebKit/LayoutTests/web-animations-api/w3c/simple-keyframes.html b/third_party/WebKit/LayoutTests/web-animations-api/w3c/simple-keyframes.html index fee77a18..8c403f4 100644 --- a/third_party/WebKit/LayoutTests/web-animations-api/w3c/simple-keyframes.html +++ b/third_party/WebKit/LayoutTests/web-animations-api/w3c/simple-keyframes.html
@@ -1,45 +1,58 @@ <!DOCTYPE html> +<meta charset=utf-8> +<title>Animate() with no offsets</title> +<link rel="help" href="https://w3c.github.io/web-animations/#keyframe-animation-effects"> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> -<script src="resources/keyframes-test.js"></script> +<script src="../../imported/wpt/web-animations/testcommon.js"></script> +<body> <script> -test(function() { - assertAnimationStyles([ +'use strict'; +test(function(t) { + var keyframes = [ {opacity: '0.25', left: '25px'}, {opacity: '0.75', left: '75px'}, - ], { + ]; + var expectations = { 0.5: {opacity: '0.5', left: '50px'}, - }); -}, -'element.animate() with 2 keyframes', -{ - help: 'http://dev.w3.org/fxtf/web-animations/#keyframe-animation-effects', - assert: [ - 'element.animate() should start an animation when two keyframes', - 'are provided with matching properties and no offsets specified.', - ], - author: 'Alan Cutter', -}); + }; + for (var progress in expectations) { + var element = createDiv(t); + element.animate(keyframes, { + duration: 1000, + fill: 'forwards', + delay: -progress * 1000, + }); + var computedStyle = getComputedStyle(element); + for (var property in expectations[progress]) { + assert_equals(computedStyle[property], expectations[progress][property], + property + ' at ' + (progress * 100) + '%'); + } + } +}, 'element.animate() with 2 keyframes'); -test(function() { - assertAnimationStyles([ +test(function(t) { + var keyframes =[ {opacity: '0', left: '0px'}, {opacity: '0.25', left: '25px'}, {opacity: '0.75', left: '75px'}, - ], { + ]; + var expectations = { 0.25: {opacity: '0.125', left: '12.5px'}, 0.75: {opacity: '0.5', left: '50px'}, - }); -}, -'element.animate() with 3 keyframes', -{ - help: 'http://dev.w3.org/fxtf/web-animations/#keyframe-animation-effects', - assert: [ - 'element.animate() should start an animation when three keyframes', - 'are provided with matching properties and no offsets specified.', - 'The keyframes must maintain their ordering and get distributed', - 'correctly.', - ], - author: 'Alan Cutter', -}); + }; + for (var progress in expectations) { + var element = createDiv(t); + element.animate(keyframes, { + duration: 1000, + fill: 'forwards', + delay: -progress * 1000, + }); + var computedStyle = getComputedStyle(element); + for (var property in expectations[progress]) { + assert_equals(computedStyle[property], expectations[progress][property], + property + ' at ' + (progress * 100) + '%'); + } + } +}, 'element.animate() with 3 keyframes'); </script>
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 3dea1c1..f3ca836 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -642,6 +642,10 @@ getter y getter z method constructor +interface CSSVariableReferenceValue + attribute @@toStringTag + getter variable + method constructor interface CSSViewportRule : CSSRule attribute @@toStringTag getter style @@ -4440,9 +4444,9 @@ method revoke interface PhotoCapabilities attribute @@toStringTag + getter focusMode getter zoom method constructor - setter zoom interface Plugin attribute @@toStringTag getter description @@ -5794,14 +5798,6 @@ getter zoomAndPan method constructor setter zoomAndPan -interface SVGZoomEvent : UIEvent - attribute @@toStringTag - getter newScale - getter newTranslate - getter previousScale - getter previousTranslate - getter zoomRectScreen - method constructor interface Screen attribute @@toStringTag getter availHeight
diff --git a/third_party/WebKit/PRESUBMIT.py b/third_party/WebKit/PRESUBMIT.py index 5f060cc..cee4638e 100644 --- a/third_party/WebKit/PRESUBMIT.py +++ b/third_party/WebKit/PRESUBMIT.py
@@ -320,30 +320,3 @@ results.extend(input_api.canned_checks.CheckChangeHasDescription( input_api, output_api)) return results - - -def GetPreferredTryMasters(project, change): - import json - import os.path - import platform - import subprocess - - cq_config_path = os.path.join( - change.RepositoryRoot(), 'infra', 'config', 'cq.cfg') - # commit_queue.py below is a script in depot_tools directory, which has a - # 'builders' command to retrieve a list of CQ builders from the CQ config. - is_win = platform.system() == 'Windows' - masters = json.loads(subprocess.check_output( - ['commit_queue', 'builders', cq_config_path], shell=is_win)) - - try_config = {} - for master in masters: - try_config.setdefault(master, {}) - for builder in masters[master]: - # Do not trigger presubmit builders, since they're likely to fail - # (e.g. OWNERS checks before finished code review), and we're - # running local presubmit anyway. - if 'presubmit' not in builder: - try_config[master][builder] = ['defaulttests'] - - return try_config
diff --git a/third_party/WebKit/Source/bindings/core/v8/Nullable.h b/third_party/WebKit/Source/bindings/core/v8/Nullable.h index 8598486b..31b0f612 100644 --- a/third_party/WebKit/Source/bindings/core/v8/Nullable.h +++ b/third_party/WebKit/Source/bindings/core/v8/Nullable.h
@@ -65,9 +65,7 @@ T& get() { ASSERT(!m_isNull); return m_value; } bool isNull() const { return m_isNull; } - // See comment in RefPtr.h about what UnspecifiedBoolType is. - typedef const T* UnspecifiedBoolType; - operator UnspecifiedBoolType() const { return m_isNull ? 0 : &m_value; } + explicit operator bool() const { return !m_isNull; } bool operator==(const Nullable& other) const {
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp index f5c668d..fb9ae287 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptController.cpp
@@ -111,7 +111,7 @@ m_windowProxyManager->windowProxy(isolatedContext.first->world())->updateSecurityOrigin(isolatedContext.second); } -v8::Local<v8::Value> ScriptController::executeScriptAndReturnValue(v8::Local<v8::Context> context, const ScriptSourceCode& source, AccessControlStatus accessControlStatus, double* compilationFinishTime) +v8::Local<v8::Value> ScriptController::executeScriptAndReturnValue(v8::Local<v8::Context> context, const ScriptSourceCode& source, AccessControlStatus accessControlStatus) { TRACE_EVENT1("devtools.timeline", "EvaluateScript", "data", InspectorEvaluateScriptEvent::data(frame(), source.url().getString(), source.startPosition())); InspectorInstrumentation::NativeBreakpoint nativeBreakpoint(frame()->document(), "scriptFirstStatement", false); @@ -147,9 +147,6 @@ if (!v8Call(V8ScriptRunner::compileScript(source, isolate(), accessControlStatus, v8CacheOptions), script, tryCatch)) return result; - if (compilationFinishTime) { - *compilationFinishTime = WTF::monotonicallyIncreasingTime(); - } if (!v8Call(V8ScriptRunner::runCompiledScript(isolate(), script, frame()->document()), result, tryCatch)) return result; } @@ -266,14 +263,8 @@ void ScriptController::updateDocument() { - bool forceMainWorldInitialization = false; - if (canExecuteScripts(NotAboutToExecuteScript) && !frame()->loader().stateMachine()->creatingInitialEmptyDocument()) { - Settings* settings = frame()->settings(); - forceMainWorldInitialization = settings && settings->forceMainWorldInitialization(); - } - // For an uninitialized main window windowProxy, do not incur the cost of context initialization. - if (!forceMainWorldInitialization && !m_windowProxyManager->mainWorldProxy()->isGlobalInitialized()) + if (!m_windowProxyManager->mainWorldProxy()->isGlobalInitialized()) return; if (!initializeMainWorld()) @@ -377,10 +368,10 @@ evaluateScriptInMainWorld(ScriptSourceCode(script), NotSharableCrossOrigin, policy); } -void ScriptController::executeScriptInMainWorld(const ScriptSourceCode& sourceCode, AccessControlStatus accessControlStatus, double* compilationFinishTime) +void ScriptController::executeScriptInMainWorld(const ScriptSourceCode& sourceCode, AccessControlStatus accessControlStatus) { v8::HandleScope handleScope(isolate()); - evaluateScriptInMainWorld(sourceCode, accessControlStatus, DoNotExecuteScriptWhenScriptsDisabled, compilationFinishTime); + evaluateScriptInMainWorld(sourceCode, accessControlStatus, DoNotExecuteScriptWhenScriptsDisabled); } v8::Local<v8::Value> ScriptController::executeScriptInMainWorldAndReturnValue(const ScriptSourceCode& sourceCode, ExecuteScriptPolicy policy) @@ -388,7 +379,7 @@ return evaluateScriptInMainWorld(sourceCode, NotSharableCrossOrigin, policy); } -v8::Local<v8::Value> ScriptController::evaluateScriptInMainWorld(const ScriptSourceCode& sourceCode, AccessControlStatus accessControlStatus, ExecuteScriptPolicy policy, double* compilationFinishTime) +v8::Local<v8::Value> ScriptController::evaluateScriptInMainWorld(const ScriptSourceCode& sourceCode, AccessControlStatus accessControlStatus, ExecuteScriptPolicy policy) { if (policy == DoNotExecuteScriptWhenScriptsDisabled && !canExecuteScripts(AboutToExecuteScript)) return v8::Local<v8::Value>(); @@ -402,7 +393,7 @@ if (frame()->loader().stateMachine()->isDisplayingInitialEmptyDocument()) frame()->loader().didAccessInitialDocument(); - v8::Local<v8::Value> object = executeScriptAndReturnValue(scriptState->context(), sourceCode, accessControlStatus, compilationFinishTime); + v8::Local<v8::Value> object = executeScriptAndReturnValue(scriptState->context(), sourceCode, accessControlStatus); if (object.IsEmpty()) return v8::Local<v8::Value>();
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptController.h b/third_party/WebKit/Source/bindings/core/v8/ScriptController.h index db961fd..2779e0f 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptController.h +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptController.h
@@ -85,9 +85,9 @@ // Evaluate JavaScript in the main world. void executeScriptInMainWorld(const String&, ExecuteScriptPolicy = DoNotExecuteScriptWhenScriptsDisabled); - void executeScriptInMainWorld(const ScriptSourceCode&, AccessControlStatus = NotSharableCrossOrigin, double* compilationFinishTime = 0); + void executeScriptInMainWorld(const ScriptSourceCode&, AccessControlStatus = NotSharableCrossOrigin); v8::Local<v8::Value> executeScriptInMainWorldAndReturnValue(const ScriptSourceCode&, ExecuteScriptPolicy = DoNotExecuteScriptWhenScriptsDisabled); - v8::Local<v8::Value> executeScriptAndReturnValue(v8::Local<v8::Context>, const ScriptSourceCode&, AccessControlStatus = NotSharableCrossOrigin, double* compilationFinishTime = 0); + v8::Local<v8::Value> executeScriptAndReturnValue(v8::Local<v8::Context>, const ScriptSourceCode&, AccessControlStatus = NotSharableCrossOrigin); // Executes JavaScript in an isolated world. The script gets its own global scope, // its own prototypes for intrinsic JavaScript objects (String, Array, and so-on), @@ -146,7 +146,7 @@ LocalFrame* frame() const { return toLocalFrame(m_windowProxyManager->frame()); } - v8::Local<v8::Value> evaluateScriptInMainWorld(const ScriptSourceCode&, AccessControlStatus, ExecuteScriptPolicy, double* compilationFinishTime = 0); + v8::Local<v8::Value> evaluateScriptInMainWorld(const ScriptSourceCode&, AccessControlStatus, ExecuteScriptPolicy); Member<WindowProxyManager> m_windowProxyManager; };
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp index 88d1096..895dab34 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptValueSerializer.cpp
@@ -1626,7 +1626,7 @@ return false; if (m_position + length > m_length) return false; - *value = v8AtomicString(isolate(), reinterpret_cast<const char*>(m_buffer + m_position), length); + *value = v8StringFromUtf8(isolate(), reinterpret_cast<const char*>(m_buffer + m_position), length); m_position += length; return true; }
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Binding.h b/third_party/WebKit/Source/bindings/core/v8/V8Binding.h index eabb4a2..906fe6f 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8Binding.h +++ b/third_party/WebKit/Source/bindings/core/v8/V8Binding.h
@@ -50,6 +50,7 @@ #include "platform/heap/Handle.h" #include "platform/text/CompressibleString.h" #include "wtf/text/AtomicString.h" +#include "wtf/text/StringView.h" #include <v8.h> namespace blink { @@ -421,16 +422,18 @@ return V8PerIsolateData::from(isolate)->getStringCache()->v8ExternalString(isolate, string); } -inline v8::Local<v8::String> v8AtomicString(v8::Isolate* isolate, const char* str, int length = -1) +inline v8::Local<v8::String> v8AtomicString(v8::Isolate* isolate, const StringView& string) { - ASSERT(isolate); - v8::Local<v8::String> value; - if (LIKELY(v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kInternalized, length).ToLocal(&value))) - return value; - // Immediately crashes when NewFromUtf8() fails because it only fails the - // given str is too long. - RELEASE_NOTREACHED(); - return v8::String::Empty(isolate); + DCHECK(isolate); + if (string.is8Bit()) + return v8CallOrCrash(v8::String::NewFromOneByte(isolate, reinterpret_cast<const uint8_t*>(string.characters8()), v8::NewStringType::kInternalized, static_cast<int>(string.length()))); + return v8CallOrCrash(v8::String::NewFromTwoByte(isolate, reinterpret_cast<const uint16_t*>(string.characters16()), v8::NewStringType::kInternalized, static_cast<int>(string.length()))); +} + +inline v8::Local<v8::String> v8StringFromUtf8(v8::Isolate* isolate, const char* bytes, int length) +{ + DCHECK(isolate); + return v8CallOrCrash(v8::String::NewFromUtf8(isolate, bytes, v8::NewStringType::kNormal, length)); } inline v8::Local<v8::Value> v8Undefined()
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp b/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp index 00a1df1..cff1640 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8PerIsolateData.cpp
@@ -113,10 +113,6 @@ case v8::Isolate::kLegacyConst: blinkFeature = UseCounter::LegacyConst; break; - case v8::Isolate::kObjectObserve: - blinkFeature = UseCounter::ObjectObserve; - deprecated = true; - break; case v8::Isolate::kSloppyMode: blinkFeature = UseCounter::V8SloppyMode; break;
diff --git a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp index c6cb296..a8d4be01 100644 --- a/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp
@@ -466,10 +466,9 @@ token = frameSecurityToken + token; } - CString utf8Token = token.utf8(); // NOTE: V8 does identity comparison in fast path, must use a symbol // as the security token. - context->SetSecurityToken(v8AtomicString(m_isolate, utf8Token.data(), utf8Token.length())); + context->SetSecurityToken(v8AtomicString(m_isolate, token)); } void WindowProxy::updateDocument()
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp index 730dd279..4725c465 100644 --- a/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8WindowCustom.cpp
@@ -173,6 +173,10 @@ // None of these need to be RefPtr because info and context are guaranteed // to hold on to them. DOMWindow* window = V8Window::toImpl(info.Holder()); + // TODO(yukishiino): The HTML spec specifies that we should use the + // Incumbent Realm instead of the Current Realm, but currently we don't have + // a way to retrieve the Incumbent Realm. See also: + // https://html.spec.whatwg.org/multipage/comms.html#dom-window-postmessage LocalDOMWindow* source = currentDOMWindow(info.GetIsolate()); ASSERT(window);
diff --git a/third_party/WebKit/Source/bindings/scripts/idl_types.py b/third_party/WebKit/Source/bindings/scripts/idl_types.py index 67edb06..b593332 100644 --- a/third_party/WebKit/Source/bindings/scripts/idl_types.py +++ b/third_party/WebKit/Source/bindings/scripts/idl_types.py
@@ -363,6 +363,14 @@ return True @property + def is_array_type(self): + return False + + @property + def is_sequence_type(self): + return False + + @property def is_frozen_array(self): return False @@ -391,6 +399,10 @@ def name(self): return self.element_type.name + 'Array' + @property + def is_array_type(self): + return True + class IdlSequenceType(IdlArrayOrSequenceType): def __init__(self, element_type): @@ -403,6 +415,10 @@ def name(self): return self.element_type.name + 'Sequence' + @property + def is_sequence_type(self): + return True + class IdlFrozenArrayType(IdlArrayOrSequenceType): def __init__(self, element_type): @@ -420,7 +436,6 @@ return True - ################################################################################ # IdlNullableType ################################################################################
diff --git a/third_party/WebKit/Source/bindings/scripts/v8_interface.py b/third_party/WebKit/Source/bindings/scripts/v8_interface.py index f2b579d..848ef26 100644 --- a/third_party/WebKit/Source/bindings/scripts/v8_interface.py +++ b/third_party/WebKit/Source/bindings/scripts/v8_interface.py
@@ -116,7 +116,9 @@ method['origin_trial_feature_name'])] ) # Group members by origin_trial_feature_name - members_by_name = itertools.groupby(origin_trial_members, itemgetter('origin_trial_feature_name')) + members_by_name = itertools.groupby(sorted(origin_trial_members, + key=itemgetter('origin_trial_feature_name')), + itemgetter('origin_trial_feature_name')) # Construct the list of dictionaries. 'needs_instance' will be true if any # member for the feature has 'on_instance' defined as true. features = [{'name': name,
diff --git a/third_party/WebKit/Source/build/scripts/make_event_factory.py b/third_party/WebKit/Source/build/scripts/make_event_factory.py index 9ffcfb0..34d1479 100755 --- a/third_party/WebKit/Source/build/scripts/make_event_factory.py +++ b/third_party/WebKit/Source/build/scripts/make_event_factory.py
@@ -68,21 +68,10 @@ or name == 'TouchEvent') -def create_event_deprecate_list(name): - return (name == 'SVGZoomEvent' - or name == 'SVGZoomEvents') - - def measure_name(name): return 'DocumentCreateEvent' + name -def deprecate_name(name): - if (name.startswith('SVGZoomEvent')): - return 'SVGZoomEvent' - return None - - class EventFactoryWriter(in_generator.Writer): defaults = { 'ImplementedAs': None, @@ -98,9 +87,7 @@ 'lower_first': name_utilities.lower_first, 'script_name': name_utilities.script_name, 'create_event_whitelist': create_event_whitelist, - 'create_event_deprecate_list': create_event_deprecate_list, 'measure_name': measure_name, - 'deprecate_name': deprecate_name, } def __init__(self, in_file_path):
diff --git a/third_party/WebKit/Source/build/scripts/templates/EventFactory.cpp.tmpl b/third_party/WebKit/Source/build/scripts/templates/EventFactory.cpp.tmpl index cd9f0a9..fa0067d0 100644 --- a/third_party/WebKit/Source/build/scripts/templates/EventFactory.cpp.tmpl +++ b/third_party/WebKit/Source/build/scripts/templates/EventFactory.cpp.tmpl
@@ -22,12 +22,8 @@ if (type == "{{event|script_name}}"{% if event.RuntimeEnabled %} && RuntimeEnabledFeatures::{{event.RuntimeEnabled|lower_first}}(){% endif %}) { {% endif %} {% if not event|script_name|create_event_whitelist %} - {% if event|script_name|create_event_deprecate_list %} - Deprecation::countDeprecation(executionContext, UseCounter::{{event|script_name|deprecate_name}}); - {% else %} UseCounter::count(executionContext, UseCounter::{{event|script_name|measure_name}}); {% endif %} - {% endif %} return {{event|cpp_name}}::create(); } {% endfor %}
diff --git a/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.cpp b/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.cpp index 54e47b4..29b6bf2e 100644 --- a/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.cpp +++ b/third_party/WebKit/Source/core/animation/SVGLengthInterpolationType.cpp
@@ -23,6 +23,10 @@ LengthInterpolatedEXS, LengthInterpolatedREMS, LengthInterpolatedCHS, + LengthInterpolatedViewportWidth, + LengthInterpolatedViewportHeight, + LengthInterpolatedViewportMin, + LengthInterpolatedViewportMax, }; static const CSSPrimitiveValue::UnitType unitTypes[] = { @@ -31,7 +35,11 @@ CSSPrimitiveValue::UnitType::Ems, CSSPrimitiveValue::UnitType::Exs, CSSPrimitiveValue::UnitType::Rems, - CSSPrimitiveValue::UnitType::Chs + CSSPrimitiveValue::UnitType::Chs, + CSSPrimitiveValue::UnitType::ViewportWidth, + CSSPrimitiveValue::UnitType::ViewportHeight, + CSSPrimitiveValue::UnitType::ViewportMin, + CSSPrimitiveValue::UnitType::ViewportMax, }; const size_t numLengthInterpolatedUnits = WTF_ARRAY_LENGTH(unitTypes); @@ -71,6 +79,14 @@ return LengthInterpolatedREMS; case CSSPrimitiveValue::UnitType::Chs: return LengthInterpolatedCHS; + case CSSPrimitiveValue::UnitType::ViewportWidth: + return LengthInterpolatedViewportWidth; + case CSSPrimitiveValue::UnitType::ViewportHeight: + return LengthInterpolatedViewportHeight; + case CSSPrimitiveValue::UnitType::ViewportMin: + return LengthInterpolatedViewportMin; + case CSSPrimitiveValue::UnitType::ViewportMax: + return LengthInterpolatedViewportMax; } }
diff --git a/third_party/WebKit/Source/core/animation/StringKeyframe.cpp b/third_party/WebKit/Source/core/animation/StringKeyframe.cpp index 3829675..9cc5716 100644 --- a/third_party/WebKit/Source/core/animation/StringKeyframe.cpp +++ b/third_party/WebKit/Source/core/animation/StringKeyframe.cpp
@@ -29,7 +29,7 @@ m_cssPropertyMap->setProperty(property, value, false, styleSheetContents); } -void StringKeyframe::setCSSPropertyValue(CSSPropertyID property, CSSValue* value) +void StringKeyframe::setCSSPropertyValue(CSSPropertyID property, const CSSValue* value) { ASSERT(property != CSSPropertyInvalid); ASSERT(CSSAnimations::isAnimatableProperty(property));
diff --git a/third_party/WebKit/Source/core/animation/StringKeyframe.h b/third_party/WebKit/Source/core/animation/StringKeyframe.h index 51c343b0..6469a52a 100644 --- a/third_party/WebKit/Source/core/animation/StringKeyframe.h +++ b/third_party/WebKit/Source/core/animation/StringKeyframe.h
@@ -23,18 +23,18 @@ } void setCSSPropertyValue(CSSPropertyID, const String& value, Element*, StyleSheetContents*); - void setCSSPropertyValue(CSSPropertyID, CSSValue*); + void setCSSPropertyValue(CSSPropertyID, const CSSValue*); void setPresentationAttributeValue(CSSPropertyID, const String& value, Element*, StyleSheetContents*); void setSVGAttributeValue(const QualifiedName&, const String& value); - CSSValue* cssPropertyValue(CSSPropertyID property) const + const CSSValue* cssPropertyValue(CSSPropertyID property) const { int index = m_cssPropertyMap->findPropertyIndex(property); RELEASE_ASSERT(index >= 0); return m_cssPropertyMap->propertyAt(static_cast<unsigned>(index)).value(); } - CSSValue* presentationAttributeValue(CSSPropertyID property) const + const CSSValue* presentationAttributeValue(CSSPropertyID property) const { int index = m_presentationAttributeMap->findPropertyIndex(property); RELEASE_ASSERT(index >= 0);
diff --git a/third_party/WebKit/Source/core/core.gypi b/third_party/WebKit/Source/core/core.gypi index aec61cf8..64a5ed7bd 100644 --- a/third_party/WebKit/Source/core/core.gypi +++ b/third_party/WebKit/Source/core/core.gypi
@@ -55,6 +55,7 @@ 'css/cssom/CSSTransformComponent.idl', 'css/cssom/CSSTransformValue.idl', 'css/cssom/CSSTranslation.idl', + 'css/cssom/CSSVariableReferenceValue.idl', 'css/cssom/StylePropertyMap.idl', 'dom/ArrayBuffer.idl', 'dom/ArrayBufferView.idl', @@ -367,7 +368,6 @@ 'svg/SVGUseElement.idl', 'svg/SVGViewElement.idl', 'svg/SVGViewSpec.idl', - 'svg/SVGZoomEvent.idl', 'timing/MemoryInfo.idl', 'timing/Performance.idl', 'timing/PerformanceCompositeTiming.idl', @@ -493,7 +493,6 @@ 'events/UIEvent.idl', 'events/WheelEvent.idl', 'html/track/TrackEvent.idl', - 'svg/SVGZoomEvent.idl', ], # IDL files that only have typedefs/enums. 'core_typedefs_enums_only_idl_files': [ @@ -1361,6 +1360,7 @@ 'css/cssom/CSSSkew.h', 'css/cssom/CSSStyleValue.cpp', 'css/cssom/CSSStyleValue.h', + 'css/cssom/CSSStyleVariableReferenceValue.h', 'css/cssom/CSSTransformComponent.cpp', 'css/cssom/CSSTransformComponent.h', 'css/cssom/CSSTransformValue.cpp', @@ -1766,7 +1766,6 @@ 'frame/LocalDOMWindow.h', 'frame/LocalFrame.cpp', 'frame/LocalFrame.h', - 'frame/LocalFrameLifecycleNotifier.cpp', 'frame/LocalFrameLifecycleNotifier.h', 'frame/LocalFrameLifecycleObserver.h', 'frame/Location.cpp', @@ -2271,6 +2270,7 @@ 'workers/Worker.h', 'workers/WorkerBackingThread.cpp', 'workers/WorkerBackingThread.h', + 'workers/WorkerClients.cpp', 'workers/WorkerClients.h', 'workers/WorkerEventQueue.cpp', 'workers/WorkerEventQueue.h', @@ -2623,6 +2623,8 @@ 'dom/StyleSheetCollection.h', 'dom/TagCollection.cpp', 'dom/TagCollection.h', + 'dom/TaskRunnerHelper.cpp', + 'dom/TaskRunnerHelper.h', 'dom/Text.cpp', 'dom/TextLinkColors.cpp', 'dom/TextLinkColors.h', @@ -3692,8 +3694,6 @@ 'svg/SVGViewSpec.h', 'svg/SVGZoomAndPan.cpp', 'svg/SVGZoomAndPan.h', - 'svg/SVGZoomEvent.cpp', - 'svg/SVGZoomEvent.h', 'svg/animation/SMILTime.cpp', 'svg/animation/SMILTimeContainer.cpp', 'svg/animation/SMILTimeContainer.h',
diff --git a/third_party/WebKit/Source/core/css/CSSBasicShapeValues.cpp b/third_party/WebKit/Source/core/css/CSSBasicShapeValues.cpp index 9194706..96b71234 100644 --- a/third_party/WebKit/Source/core/css/CSSBasicShapeValues.cpp +++ b/third_party/WebKit/Source/core/css/CSSBasicShapeValues.cpp
@@ -325,7 +325,7 @@ } if (horizontalRadii != verticalRadii) { result.append(separator); - result.append("/"); + result.append('/'); for (size_t i = 0; i < verticalRadii.size(); ++i) { result.append(separator);
diff --git a/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp b/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp index bef1f771..f0f3d05e 100644 --- a/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp +++ b/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp
@@ -146,6 +146,7 @@ CSSPropertyOutlineOffset, CSSPropertyOutlineStyle, CSSPropertyOutlineWidth, + CSSPropertyOverflowAnchor, CSSPropertyOverflowWrap, CSSPropertyOverflowX, CSSPropertyOverflowY,
diff --git a/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.cpp b/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.cpp index fb46e0c..dc58bdd 100644 --- a/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.cpp +++ b/third_party/WebKit/Source/core/css/CSSFontFaceSrcValue.cpp
@@ -58,14 +58,14 @@ if (isLocal()) { result.append("local("); result.append(serializeString(m_absoluteResource)); - result.append(")"); + result.append(')'); } else { result.append(serializeURI(m_specifiedResource)); } if (!m_format.isEmpty()) { result.append(" format("); result.append(serializeString(m_format)); - result.append(")"); + result.append(')'); } return result.toString(); }
diff --git a/third_party/WebKit/Source/core/css/CSSGridAutoRepeatValue.cpp b/third_party/WebKit/Source/core/css/CSSGridAutoRepeatValue.cpp index 238c6ed..a27a586 100644 --- a/third_party/WebKit/Source/core/css/CSSGridAutoRepeatValue.cpp +++ b/third_party/WebKit/Source/core/css/CSSGridAutoRepeatValue.cpp
@@ -15,7 +15,7 @@ result.append(getValueName(autoRepeatID())); result.append(", "); result.append(CSSValueList::customCSSText()); - result.append(")"); + result.append(')'); return result.toString(); }
diff --git a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp index d48c615..600f0b5 100644 --- a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp +++ b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.cpp
@@ -118,7 +118,7 @@ m_images.add(size, image); } -PassRefPtr<Image> CSSImageGeneratorValue::image(const LayoutObject& layoutObject, const IntSize& size) +PassRefPtr<Image> CSSImageGeneratorValue::image(const LayoutObject& layoutObject, const IntSize& size, float zoom) { switch (getClassType()) { case CrossfadeClass: @@ -126,7 +126,7 @@ case LinearGradientClass: return toCSSLinearGradientValue(this)->image(layoutObject, size); case PaintClass: - return toCSSPaintValue(this)->image(layoutObject, size); + return toCSSPaintValue(this)->image(layoutObject, size, zoom); case RadialGradientClass: return toCSSRadialGradientValue(this)->image(layoutObject, size); default:
diff --git a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h index bb378f6d..759c7b1 100644 --- a/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h +++ b/third_party/WebKit/Source/core/css/CSSImageGeneratorValue.h
@@ -60,7 +60,7 @@ void addClient(const LayoutObject*, const IntSize&); void removeClient(const LayoutObject*); - PassRefPtr<Image> image(const LayoutObject&, const IntSize&); + PassRefPtr<Image> image(const LayoutObject&, const IntSize&, float zoom); bool isFixedSize() const; IntSize fixedSize(const LayoutObject&, const FloatSize& defaultObjectSize);
diff --git a/third_party/WebKit/Source/core/css/CSSNamespaceRule.cpp b/third_party/WebKit/Source/core/css/CSSNamespaceRule.cpp index 220d7eac..f1401d6 100644 --- a/third_party/WebKit/Source/core/css/CSSNamespaceRule.cpp +++ b/third_party/WebKit/Source/core/css/CSSNamespaceRule.cpp
@@ -26,7 +26,7 @@ result.append("@namespace "); serializeIdentifier(prefix(), result); if (!prefix().isEmpty()) - result.append(" "); + result.append(' '); result.append("url("); result.append(serializeString(namespaceURI())); result.append(");");
diff --git a/third_party/WebKit/Source/core/css/CSSPageRule.cpp b/third_party/WebKit/Source/core/css/CSSPageRule.cpp index fa99594..1fc0c5b1 100644 --- a/third_party/WebKit/Source/core/css/CSSPageRule.cpp +++ b/third_party/WebKit/Source/core/css/CSSPageRule.cpp
@@ -79,7 +79,7 @@ String pageSelectors = selectorText(); result.append(pageSelectors); if (!pageSelectors.isEmpty()) - result.append(" "); + result.append(' '); result.append("{ "); String decls = m_pageRule->properties().asText(); result.append(decls);
diff --git a/third_party/WebKit/Source/core/css/CSSPaintImageGenerator.h b/third_party/WebKit/Source/core/css/CSSPaintImageGenerator.h index 59b56ba..069ab3c 100644 --- a/third_party/WebKit/Source/core/css/CSSPaintImageGenerator.h +++ b/third_party/WebKit/Source/core/css/CSSPaintImageGenerator.h
@@ -39,7 +39,7 @@ // Invokes the CSS Paint API 'paint' callback. May return a nullptr // representing an invalid image if an error occurred. - virtual PassRefPtr<Image> paint(const LayoutObject&, const IntSize&) = 0; + virtual PassRefPtr<Image> paint(const LayoutObject&, const IntSize&, float zoom) = 0; virtual const Vector<CSSPropertyID>& nativeInvalidationProperties() const = 0; virtual const Vector<AtomicString>& customInvalidationProperties() const = 0;
diff --git a/third_party/WebKit/Source/core/css/CSSPaintValue.cpp b/third_party/WebKit/Source/core/css/CSSPaintValue.cpp index 82cc7572..7d6652a 100644 --- a/third_party/WebKit/Source/core/css/CSSPaintValue.cpp +++ b/third_party/WebKit/Source/core/css/CSSPaintValue.cpp
@@ -36,12 +36,12 @@ return m_name->value(); } -PassRefPtr<Image> CSSPaintValue::image(const LayoutObject& layoutObject, const IntSize& size) +PassRefPtr<Image> CSSPaintValue::image(const LayoutObject& layoutObject, const IntSize& size, float zoom) { if (!m_generator) m_generator = CSSPaintImageGenerator::create(name(), layoutObject.document(), m_paintImageGeneratorObserver); - return m_generator->paint(layoutObject, size); + return m_generator->paint(layoutObject, size, zoom); } void CSSPaintValue::Observer::paintImageGeneratorReady()
diff --git a/third_party/WebKit/Source/core/css/CSSPaintValue.h b/third_party/WebKit/Source/core/css/CSSPaintValue.h index bfc41aa..ed3fa7d 100644 --- a/third_party/WebKit/Source/core/css/CSSPaintValue.h +++ b/third_party/WebKit/Source/core/css/CSSPaintValue.h
@@ -24,7 +24,7 @@ String name() const; - PassRefPtr<Image> image(const LayoutObject&, const IntSize&); + PassRefPtr<Image> image(const LayoutObject&, const IntSize&, float zoom); bool isFixedSize() const { return false; } IntSize fixedSize(const LayoutObject&) { return IntSize(); }
diff --git a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h index 0b50bb5..574b331 100644 --- a/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h +++ b/third_party/WebKit/Source/core/css/CSSPrimitiveValueMappings.h
@@ -2629,6 +2629,41 @@ return NormalWordBreak; } +template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EOverflowAnchor e) + : CSSValue(PrimitiveClass) +{ + init(UnitType::ValueID); + switch (e) { + case AnchorVisible: + m_value.valueID = CSSValueVisible; + break; + case AnchorNone: + m_value.valueID = CSSValueNone; + break; + case AnchorAuto: + m_value.valueID = CSSValueAuto; + break; + } +} + +template<> inline EOverflowAnchor CSSPrimitiveValue::convertTo() const +{ + DCHECK(isValueID()); + switch (m_value.valueID) { + case CSSValueVisible: + return AnchorVisible; + case CSSValueNone: + return AnchorNone; + case CSSValueAuto: + return AnchorAuto; + default: + break; + } + + NOTREACHED(); + return AnchorNone; +} + template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EOverflowWrap e) : CSSValue(PrimitiveClass) {
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.in b/third_party/WebKit/Source/core/css/CSSProperties.in index 593a53b3..39071e06 100644 --- a/third_party/WebKit/Source/core/css/CSSProperties.in +++ b/third_party/WebKit/Source/core/css/CSSProperties.in
@@ -261,6 +261,7 @@ outline-offset interpolable, converter=convertComputedLength<int> outline-style custom_all outline-width interpolable, converter=convertLineWidth<unsigned short> +overflow-anchor runtime_flag=ScrollAnchoring, type_name=EOverflowAnchor overflow-wrap inherited overflow-x type_name=EOverflow overflow-y type_name=EOverflow
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp index 0fe51e79e..2676b775 100644 --- a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp +++ b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
@@ -2162,6 +2162,8 @@ return zoomAdjustedPixelValue(style.outlineWidth(), style); case CSSPropertyOverflow: return CSSPrimitiveValue::create(max(style.overflowX(), style.overflowY())); + case CSSPropertyOverflowAnchor: + return CSSPrimitiveValue::create(style.overflowAnchor()); case CSSPropertyOverflowWrap: return CSSPrimitiveValue::create(style.overflowWrap()); case CSSPropertyOverflowX:
diff --git a/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp b/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp index 06b2d69f..4175b43 100644 --- a/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp +++ b/third_party/WebKit/Source/core/css/RemoteFontFaceSource.cpp
@@ -325,10 +325,10 @@ const int boundary = 1 << 2; DEFINE_STATIC_LOCAL(EnumerationHistogram, interventionHistogram, ("WebFont.InterventionResult", boundary)); - DEFINE_STATIC_LOCAL(EnumerationHistogram, missCachedInterventionHistogram, ("WebFont.MissCachedInterventionResult", boundary)); + DEFINE_STATIC_LOCAL(EnumerationHistogram, missedCacheInterventionHistogram, ("WebFont.InterventionResult.MissedCache", boundary)); interventionHistogram.count(interventionResult); if (isLoadedFromNetwork) - missCachedInterventionHistogram.count(interventionResult); + missedCacheInterventionHistogram.count(interventionResult); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp index 02a5a13..dd15534e 100644 --- a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp +++ b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp
@@ -853,7 +853,7 @@ builder.append("repeat-x"); } else { builder.append(repeatX.cssText()); - builder.append(" "); + builder.append(' '); builder.append(repeatY.cssText()); } }
diff --git a/third_party/WebKit/Source/core/css/StylePropertySet.cpp b/third_party/WebKit/Source/core/css/StylePropertySet.cpp index da201110..c464170 100644 --- a/third_party/WebKit/Source/core/css/StylePropertySet.cpp +++ b/third_party/WebKit/Source/core/css/StylePropertySet.cpp
@@ -307,7 +307,7 @@ return CSSParser::parseValueForCustomProperty(this, customPropertyName, value, important, contextStyleSheet); } -void MutableStylePropertySet::setProperty(CSSPropertyID propertyID, CSSValue* value, bool important) +void MutableStylePropertySet::setProperty(CSSPropertyID propertyID, const CSSValue* value, bool important) { StylePropertyShorthand shorthand = shorthandForProperty(propertyID); if (!shorthand.length()) {
diff --git a/third_party/WebKit/Source/core/css/StylePropertySet.h b/third_party/WebKit/Source/core/css/StylePropertySet.h index 8732c54..91c92b7e 100644 --- a/third_party/WebKit/Source/core/css/StylePropertySet.h +++ b/third_party/WebKit/Source/core/css/StylePropertySet.h
@@ -203,7 +203,7 @@ // These expand shorthand properties into multiple properties. bool setProperty(CSSPropertyID unresolvedProperty, const String& value, bool important = false, StyleSheetContents* contextStyleSheet = 0); bool setProperty(const AtomicString& customPropertyName, const String& value, bool important = false, StyleSheetContents* contextStyleSheet = 0); - void setProperty(CSSPropertyID, CSSValue*, bool important = false); + void setProperty(CSSPropertyID, const CSSValue*, bool important = false); // These do not. FIXME: This is too messy, we can do better. bool setProperty(CSSPropertyID, CSSValueID identifier, bool important = false);
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSStyleVariableReferenceValue.h b/third_party/WebKit/Source/core/css/cssom/CSSStyleVariableReferenceValue.h new file mode 100644 index 0000000..068b52c --- /dev/null +++ b/third_party/WebKit/Source/core/css/cssom/CSSStyleVariableReferenceValue.h
@@ -0,0 +1,37 @@ +// 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 CSSStyleVariableReferenceValue_h +#define CSSStyleVariableReferenceValue_h + +#include "bindings/core/v8/ScriptWrappable.h" +#include "core/CoreExport.h" + +namespace blink { + +class CORE_EXPORT CSSStyleVariableReferenceValue final : public GarbageCollectedFinalized<CSSStyleVariableReferenceValue>, public ScriptWrappable { + WTF_MAKE_NONCOPYABLE(CSSStyleVariableReferenceValue); + DEFINE_WRAPPERTYPEINFO(); +public: + virtual ~CSSStyleVariableReferenceValue() { } + + // TODO(anthonyhkf): add fallback: create(variable, fallback) + static CSSStyleVariableReferenceValue* create(const String& variable) + { + return new CSSStyleVariableReferenceValue(variable); + } + + DEFINE_INLINE_TRACE() { } + + const String& variable() const { return m_variable; } + +protected: + CSSStyleVariableReferenceValue(String variable): m_variable(variable) { } + + String m_variable; +}; + +} // namespace blink + +#endif // CSSStyleVariableReference_h
diff --git a/third_party/WebKit/Source/core/css/cssom/CSSVariableReferenceValue.idl b/third_party/WebKit/Source/core/css/cssom/CSSVariableReferenceValue.idl new file mode 100644 index 0000000..4e76631 --- /dev/null +++ b/third_party/WebKit/Source/core/css/cssom/CSSVariableReferenceValue.idl
@@ -0,0 +1,15 @@ +// 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(anthonyhkf): add fallback: Constructor(DOMString variable, CSSTokenStreamValue fallback) + Constructor(DOMString variable), + Exposed=(Window,PaintWorklet), + RuntimeEnabled=CSSTypedOM, + // TODO(anthonyhkf): rename CSSStyleVariableReferenceValue + ImplementedAs=CSSStyleVariableReferenceValue +] interface CSSVariableReferenceValue { + readonly attribute DOMString variable; + // TODO(anthonyhkf): add fallback: readonly attribute CSSTokenStreamValue fallback; +};
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp index 7719e27b..354b483e 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParserFastPaths.cpp
@@ -550,6 +550,8 @@ return valueID == CSSValueFill || valueID == CSSValueContain || valueID == CSSValueCover || valueID == CSSValueNone || valueID == CSSValueScaleDown; case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto return valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble); + case CSSPropertyOverflowAnchor: + return valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAuto; case CSSPropertyOverflowWrap: // normal | break-word case CSSPropertyWordWrap: return valueID == CSSValueNormal || valueID == CSSValueBreakWord; @@ -750,6 +752,7 @@ case CSSPropertyMaskType: case CSSPropertyObjectFit: case CSSPropertyOutlineStyle: + case CSSPropertyOverflowAnchor: case CSSPropertyOverflowWrap: case CSSPropertyOverflowX: case CSSPropertyOverflowY:
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserToken.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserToken.cpp index fb46fac5..adfb8763 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserToken.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParserToken.cpp
@@ -219,7 +219,7 @@ case UrlToken: builder.append("url("); serializeIdentifier(value().toString(), builder); - return builder.append(")"); + return builder.append(')'); case DelimiterToken: if (delimiter() == '\\') return builder.append("\\\n");
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserToken.h b/third_party/WebKit/Source/core/css/parser/CSSParserToken.h index 6158842c..fa88236 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserToken.h +++ b/third_party/WebKit/Source/core/css/parser/CSSParserToken.h
@@ -94,7 +94,9 @@ CSSParserTokenType type() const { return static_cast<CSSParserTokenType>(m_type); } StringView value() const { - return StringView(m_valueDataCharRaw, m_valueLength, m_valueIs8Bit); + if (m_valueIs8Bit) + return StringView(reinterpret_cast<const LChar*>(m_valueDataCharRaw), m_valueLength); + return StringView(reinterpret_cast<const UChar*>(m_valueDataCharRaw), m_valueLength); } UChar delimiter() const;
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp index a0bb361..9199cbe 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -63,7 +63,7 @@ m_range.consumeWhitespace(); } -void CSSPropertyParser::addProperty(CSSPropertyID property, CSSPropertyID currentShorthand, CSSValue* value, bool important, bool implicit) +void CSSPropertyParser::addProperty(CSSPropertyID property, CSSPropertyID currentShorthand, const CSSValue& value, bool important, bool implicit) { ASSERT(!isPropertyAlias(property)); @@ -78,10 +78,10 @@ shorthandIndex = indexOfShorthandForLonghand(currentShorthand, shorthands); } - m_parsedProperties->append(CSSProperty(property, *value, important, setFromShorthand, shorthandIndex, implicit)); + m_parsedProperties->append(CSSProperty(property, value, important, setFromShorthand, shorthandIndex, implicit)); } -void CSSPropertyParser::addExpandedPropertyForValue(CSSPropertyID property, CSSValue* value, bool important) +void CSSPropertyParser::addExpandedPropertyForValue(CSSPropertyID property, const CSSValue& value, bool important) { const StylePropertyShorthand& shorthand = shorthandForProperty(property); unsigned shorthandLength = shorthand.length(); @@ -159,9 +159,9 @@ if (parseShorthand(unresolvedProperty, important)) return true; } else { - if (CSSValue* parsedValue = parseSingleValue(unresolvedProperty)) { + if (const CSSValue* parsedValue = parseSingleValue(unresolvedProperty)) { if (m_range.atEnd()) { - addProperty(propertyId, CSSPropertyInvalid, parsedValue, important); + addProperty(propertyId, CSSPropertyInvalid, *parsedValue, important); return true; } } @@ -171,10 +171,10 @@ CSSVariableReferenceValue* variable = CSSVariableReferenceValue::create(CSSVariableData::create(originalRange)); if (isShorthand) { - CSSPendingSubstitutionValue* pendingValue = CSSPendingSubstitutionValue::create(propertyId, variable); + const CSSPendingSubstitutionValue& pendingValue = *CSSPendingSubstitutionValue::create(propertyId, variable); addExpandedPropertyForValue(propertyId, pendingValue, important); } else { - addProperty(propertyId, CSSPropertyInvalid, variable, important); + addProperty(propertyId, CSSPropertyInvalid, *variable, important); } return true; } @@ -279,9 +279,9 @@ if (!shorthand.length()) { if (CSSPropertyMetadata::isDescriptorOnly(unresolvedProperty)) return false; - addProperty(property, CSSPropertyInvalid, value, important); + addProperty(property, CSSPropertyInvalid, *value, important); } else { - addExpandedPropertyForValue(property, value, important); + addExpandedPropertyForValue(property, *value, important); } m_range = rangeCopy; return true; @@ -1330,7 +1330,7 @@ } for (size_t i = 0; i < longhandCount; ++i) - addProperty(shorthand.properties()[i], shorthand.id(), longhands[i], important); + addProperty(shorthand.properties()[i], shorthand.id(), *longhands[i], important); return m_range.atEnd(); } @@ -4094,7 +4094,7 @@ if (!parsedValue || !m_range.atEnd()) return false; - addProperty(propId, CSSPropertyInvalid, parsedValue, false); + addProperty(propId, CSSPropertyInvalid, *parsedValue, false); return true; } @@ -4111,18 +4111,18 @@ AtomicString fontFamily; LayoutTheme::theme().systemFont(systemFontID, fontStyle, fontWeight, fontSize, fontFamily); - addProperty(CSSPropertyFontStyle, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(fontStyle == FontStyleItalic ? CSSValueItalic : CSSValueNormal), important); - addProperty(CSSPropertyFontWeight, CSSPropertyFont, CSSPrimitiveValue::create(fontWeight), important); - addProperty(CSSPropertyFontSize, CSSPropertyFont, CSSPrimitiveValue::create(fontSize, CSSPrimitiveValue::UnitType::Pixels), important); + addProperty(CSSPropertyFontStyle, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(fontStyle == FontStyleItalic ? CSSValueItalic : CSSValueNormal), important); + addProperty(CSSPropertyFontWeight, CSSPropertyFont, *CSSPrimitiveValue::create(fontWeight), important); + addProperty(CSSPropertyFontSize, CSSPropertyFont, *CSSPrimitiveValue::create(fontSize, CSSPrimitiveValue::UnitType::Pixels), important); CSSValueList* fontFamilyList = CSSValueList::createCommaSeparated(); fontFamilyList->append(*CSSFontFamilyValue::create(fontFamily)); - addProperty(CSSPropertyFontFamily, CSSPropertyFont, fontFamilyList, important); + addProperty(CSSPropertyFontFamily, CSSPropertyFont, *fontFamilyList, important); - addProperty(CSSPropertyFontStretch, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); - addProperty(CSSPropertyFontVariantCaps, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); - addProperty(CSSPropertyFontVariantLigatures, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); - addProperty(CSSPropertyFontVariantNumeric, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); - addProperty(CSSPropertyLineHeight, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); + addProperty(CSSPropertyFontStretch, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); + addProperty(CSSPropertyFontVariantCaps, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); + addProperty(CSSPropertyFontVariantLigatures, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); + addProperty(CSSPropertyFontVariantNumeric, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); + addProperty(CSSPropertyLineHeight, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); return true; } @@ -4167,28 +4167,28 @@ if (m_range.atEnd()) return false; - addProperty(CSSPropertyFontStyle, CSSPropertyFont, fontStyle ? fontStyle : CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); - addProperty(CSSPropertyFontVariantCaps, CSSPropertyFont, fontVariantCaps ? fontVariantCaps : CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); - addProperty(CSSPropertyFontVariantLigatures, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); - addProperty(CSSPropertyFontVariantNumeric, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); + addProperty(CSSPropertyFontStyle, CSSPropertyFont, fontStyle ? *fontStyle : *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); + addProperty(CSSPropertyFontVariantCaps, CSSPropertyFont, fontVariantCaps ? *fontVariantCaps : *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); + addProperty(CSSPropertyFontVariantLigatures, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); + addProperty(CSSPropertyFontVariantNumeric, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); - addProperty(CSSPropertyFontWeight, CSSPropertyFont, fontWeight ? fontWeight : CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); - addProperty(CSSPropertyFontStretch, CSSPropertyFont, fontStretch ? fontStretch : CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); + addProperty(CSSPropertyFontWeight, CSSPropertyFont, fontWeight ? *fontWeight : *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); + addProperty(CSSPropertyFontStretch, CSSPropertyFont, fontStretch ? *fontStretch : *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); // Now a font size _must_ come. CSSValue* fontSize = consumeFontSize(m_range, m_context.mode()); if (!fontSize || m_range.atEnd()) return false; - addProperty(CSSPropertyFontSize, CSSPropertyFont, fontSize, important); + addProperty(CSSPropertyFontSize, CSSPropertyFont, *fontSize, important); if (consumeSlashIncludingWhitespace(m_range)) { CSSPrimitiveValue* lineHeight = consumeLineHeight(m_range, m_context.mode()); if (!lineHeight) return false; - addProperty(CSSPropertyLineHeight, CSSPropertyFont, lineHeight, important); + addProperty(CSSPropertyLineHeight, CSSPropertyFont, *lineHeight, important); } else { - addProperty(CSSPropertyLineHeight, CSSPropertyFont, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); + addProperty(CSSPropertyLineHeight, CSSPropertyFont, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); } // Font family must come now. @@ -4196,7 +4196,7 @@ if (!parsedFamilyValue) return false; - addProperty(CSSPropertyFontFamily, CSSPropertyFont, parsedFamilyValue, important); + addProperty(CSSPropertyFontFamily, CSSPropertyFont, *parsedFamilyValue, important); // FIXME: http://www.w3.org/TR/2011/WD-css3-fonts-20110324/#font-prop requires that // "font-stretch", "font-size-adjust", and "font-kerning" be reset to their initial values @@ -4207,8 +4207,8 @@ bool CSSPropertyParser::consumeFontVariantShorthand(bool important) { if (identMatches<CSSValueNormal, CSSValueNone>(m_range.peek().id())) { - addProperty(CSSPropertyFontVariantLigatures, CSSPropertyFontVariant, consumeIdent(m_range), important); - addProperty(CSSPropertyFontVariantCaps, CSSPropertyFontVariant, CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); + addProperty(CSSPropertyFontVariantLigatures, CSSPropertyFontVariant, *consumeIdent(m_range), important); + addProperty(CSSPropertyFontVariantCaps, CSSPropertyFontVariant, *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); return m_range.atEnd(); } @@ -4244,9 +4244,9 @@ } } while (!m_range.atEnd()); - addProperty(CSSPropertyFontVariantLigatures, CSSPropertyFontVariant, ligaturesParser.finalizeValue(), important); - addProperty(CSSPropertyFontVariantNumeric, CSSPropertyFontVariant, numericParser.finalizeValue(), important); - addProperty(CSSPropertyFontVariantCaps, CSSPropertyFontVariant, capsValue ? capsValue : CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); + addProperty(CSSPropertyFontVariantLigatures, CSSPropertyFontVariant, *ligaturesParser.finalizeValue(), important); + addProperty(CSSPropertyFontVariantNumeric, CSSPropertyFontVariant, *numericParser.finalizeValue(), important); + addProperty(CSSPropertyFontVariantCaps, CSSPropertyFontVariant, capsValue ? *capsValue : *CSSPrimitiveValue::createIdentifier(CSSValueNormal), important); return true; } @@ -4260,8 +4260,8 @@ verticalSpacing = consumeLength(m_range, m_context.mode(), ValueRangeNonNegative, UnitlessQuirk::Allow); if (!verticalSpacing || !m_range.atEnd()) return false; - addProperty(CSSPropertyWebkitBorderHorizontalSpacing, CSSPropertyBorderSpacing, horizontalSpacing, important); - addProperty(CSSPropertyWebkitBorderVerticalSpacing, CSSPropertyBorderSpacing, verticalSpacing, important); + addProperty(CSSPropertyWebkitBorderHorizontalSpacing, CSSPropertyBorderSpacing, *horizontalSpacing, important); + addProperty(CSSPropertyWebkitBorderVerticalSpacing, CSSPropertyBorderSpacing, *verticalSpacing, important); return true; } @@ -4313,8 +4313,8 @@ maxWidth = consumeSingleViewportDescriptor(m_range, CSSPropertyMaxWidth, m_context.mode()); if (!maxWidth || !m_range.atEnd()) return false; - addProperty(CSSPropertyMinWidth, CSSPropertyInvalid, minWidth, important); - addProperty(CSSPropertyMaxWidth, CSSPropertyInvalid, maxWidth, important); + addProperty(CSSPropertyMinWidth, CSSPropertyInvalid, *minWidth, important); + addProperty(CSSPropertyMaxWidth, CSSPropertyInvalid, *maxWidth, important); return true; } case CSSPropertyHeight: { @@ -4326,8 +4326,8 @@ maxHeight = consumeSingleViewportDescriptor(m_range, CSSPropertyMaxHeight, m_context.mode()); if (!maxHeight || !m_range.atEnd()) return false; - addProperty(CSSPropertyMinHeight, CSSPropertyInvalid, minHeight, important); - addProperty(CSSPropertyMaxHeight, CSSPropertyInvalid, maxHeight, important); + addProperty(CSSPropertyMinHeight, CSSPropertyInvalid, *minHeight, important); + addProperty(CSSPropertyMaxHeight, CSSPropertyInvalid, *maxHeight, important); return true; } case CSSPropertyMinWidth: @@ -4342,7 +4342,7 @@ CSSValue* parsedValue = consumeSingleViewportDescriptor(m_range, propId, m_context.mode()); if (!parsedValue || !m_range.atEnd()) return false; - addProperty(propId, CSSPropertyInvalid, parsedValue, important); + addProperty(propId, CSSPropertyInvalid, *parsedValue, important); return true; } default: @@ -4379,8 +4379,8 @@ columnWidth = CSSPrimitiveValue::createIdentifier(CSSValueAuto); if (!columnCount) columnCount = CSSPrimitiveValue::createIdentifier(CSSValueAuto); - addProperty(CSSPropertyColumnWidth, CSSPropertyInvalid, columnWidth, important); - addProperty(CSSPropertyColumnCount, CSSPropertyInvalid, columnCount, important); + addProperty(CSSPropertyColumnWidth, CSSPropertyInvalid, *columnWidth, important); + addProperty(CSSPropertyColumnCount, CSSPropertyInvalid, *columnCount, important); return true; } @@ -4404,9 +4404,9 @@ for (size_t i = 0; i < shorthand.length(); ++i) { if (longhands[i]) - addProperty(shorthandProperties[i], shorthand.id(), longhands[i], important); + addProperty(shorthandProperties[i], shorthand.id(), *longhands[i], important); else - addProperty(shorthandProperties[i], shorthand.id(), CSSInitialValue::createLegacyImplicit(), important); + addProperty(shorthandProperties[i], shorthand.id(), *CSSInitialValue::createLegacyImplicit(), important); } return true; } @@ -4459,9 +4459,9 @@ if (!m_range.atEnd()) return false; - addProperty(CSSPropertyFlexGrow, CSSPropertyFlex, CSSPrimitiveValue::create(clampTo<float>(flexGrow), CSSPrimitiveValue::UnitType::Number), important); - addProperty(CSSPropertyFlexShrink, CSSPropertyFlex, CSSPrimitiveValue::create(clampTo<float>(flexShrink), CSSPrimitiveValue::UnitType::Number), important); - addProperty(CSSPropertyFlexBasis, CSSPropertyFlex, flexBasis, important); + addProperty(CSSPropertyFlexGrow, CSSPropertyFlex, *CSSPrimitiveValue::create(clampTo<float>(flexGrow), CSSPrimitiveValue::UnitType::Number), important); + addProperty(CSSPropertyFlexShrink, CSSPropertyFlex, *CSSPrimitiveValue::create(clampTo<float>(flexShrink), CSSPrimitiveValue::UnitType::Number), important); + addProperty(CSSPropertyFlexBasis, CSSPropertyFlex, *flexBasis, important); return true; } @@ -4500,10 +4500,10 @@ if (!color) color = CSSInitialValue::createLegacyImplicit(); - addExpandedPropertyForValue(CSSPropertyBorderWidth, width, important); - addExpandedPropertyForValue(CSSPropertyBorderStyle, style, important); - addExpandedPropertyForValue(CSSPropertyBorderColor, color, important); - addExpandedPropertyForValue(CSSPropertyBorderImage, CSSInitialValue::createLegacyImplicit(), important); + addExpandedPropertyForValue(CSSPropertyBorderWidth, *width, important); + addExpandedPropertyForValue(CSSPropertyBorderStyle, *style, important); + addExpandedPropertyForValue(CSSPropertyBorderColor, *color, important); + addExpandedPropertyForValue(CSSPropertyBorderImage, *CSSInitialValue::createLegacyImplicit(), important); return m_range.atEnd(); } @@ -4532,10 +4532,10 @@ if (!left) left = right; - addProperty(longhands[0], shorthand.id(), top, important); - addProperty(longhands[1], shorthand.id(), right, important); - addProperty(longhands[2], shorthand.id(), bottom, important); - addProperty(longhands[3], shorthand.id(), left, important); + addProperty(longhands[0], shorthand.id(), *top, important); + addProperty(longhands[1], shorthand.id(), *right, important); + addProperty(longhands[2], shorthand.id(), *bottom, important); + addProperty(longhands[3], shorthand.id(), *left, important); return m_range.atEnd(); } @@ -4550,18 +4550,18 @@ if (consumeBorderImageComponents(property, m_range, m_context, source, slice, width, outset, repeat)) { switch (property) { case CSSPropertyWebkitMaskBoxImage: - addProperty(CSSPropertyWebkitMaskBoxImageSource, CSSPropertyWebkitMaskBoxImage, source ? source : CSSInitialValue::createLegacyImplicit(), important); - addProperty(CSSPropertyWebkitMaskBoxImageSlice, CSSPropertyWebkitMaskBoxImage, slice ? slice : CSSInitialValue::createLegacyImplicit(), important); - addProperty(CSSPropertyWebkitMaskBoxImageWidth, CSSPropertyWebkitMaskBoxImage, width ? width : CSSInitialValue::createLegacyImplicit(), important); - addProperty(CSSPropertyWebkitMaskBoxImageOutset, CSSPropertyWebkitMaskBoxImage, outset ? outset : CSSInitialValue::createLegacyImplicit(), important); - addProperty(CSSPropertyWebkitMaskBoxImageRepeat, CSSPropertyWebkitMaskBoxImage, repeat ? repeat : CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyWebkitMaskBoxImageSource, CSSPropertyWebkitMaskBoxImage, source ? *source : *CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyWebkitMaskBoxImageSlice, CSSPropertyWebkitMaskBoxImage, slice ? *slice : *CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyWebkitMaskBoxImageWidth, CSSPropertyWebkitMaskBoxImage, width ? *width : *CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyWebkitMaskBoxImageOutset, CSSPropertyWebkitMaskBoxImage, outset ? *outset : *CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyWebkitMaskBoxImageRepeat, CSSPropertyWebkitMaskBoxImage, repeat ? *repeat : *CSSInitialValue::createLegacyImplicit(), important); return true; case CSSPropertyBorderImage: - addProperty(CSSPropertyBorderImageSource, CSSPropertyBorderImage, source ? source : CSSInitialValue::createLegacyImplicit(), important); - addProperty(CSSPropertyBorderImageSlice, CSSPropertyBorderImage, slice ? slice : CSSInitialValue::createLegacyImplicit(), important); - addProperty(CSSPropertyBorderImageWidth, CSSPropertyBorderImage, width ? width : CSSInitialValue::createLegacyImplicit(), important); - addProperty(CSSPropertyBorderImageOutset, CSSPropertyBorderImage, outset ? outset : CSSInitialValue::createLegacyImplicit(), important); - addProperty(CSSPropertyBorderImageRepeat, CSSPropertyBorderImage, repeat ? repeat : CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyBorderImageSource, CSSPropertyBorderImage, source ? *source : *CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyBorderImageSlice, CSSPropertyBorderImage, slice ? *slice : *CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyBorderImageWidth, CSSPropertyBorderImage, width ? *width : *CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyBorderImageOutset, CSSPropertyBorderImage, outset ? *outset : *CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyBorderImageRepeat, CSSPropertyBorderImage, repeat ? *repeat : *CSSInitialValue::createLegacyImplicit(), important); return true; default: ASSERT_NOT_REACHED(); @@ -4637,7 +4637,7 @@ return false; CSSPropertyID genericBreakProperty = mapFromLegacyBreakProperty(property); - addProperty(genericBreakProperty, property, CSSPrimitiveValue::createIdentifier(value), important); + addProperty(genericBreakProperty, property, *CSSPrimitiveValue::createIdentifier(value), important); return true; } @@ -4772,7 +4772,7 @@ CSSPropertyID property = shorthand.properties()[i]; if (property == CSSPropertyBackgroundSize && longhands[i] && m_context.useLegacyBackgroundSizeShorthandBehavior()) continue; - addProperty(property, shorthand.id(), longhands[i], important, implicit); + addProperty(property, shorthand.id(), *longhands[i], important, implicit); } return true; } @@ -4796,8 +4796,8 @@ } if (!m_range.atEnd()) return false; - addProperty(shorthand.properties()[0], shorthandId, startValue, important); - addProperty(shorthand.properties()[1], shorthandId, endValue, important); + addProperty(shorthand.properties()[0], shorthandId, *startValue, important); + addProperty(shorthand.properties()[1], shorthandId, *endValue, important); return true; } @@ -4835,10 +4835,10 @@ if (!columnEndValue) columnEndValue = columnStartValue->isCustomIdentValue() ? columnStartValue : CSSPrimitiveValue::createIdentifier(CSSValueAuto); - addProperty(CSSPropertyGridRowStart, CSSPropertyGridArea, rowStartValue, important); - addProperty(CSSPropertyGridColumnStart, CSSPropertyGridArea, columnStartValue, important); - addProperty(CSSPropertyGridRowEnd, CSSPropertyGridArea, rowEndValue, important); - addProperty(CSSPropertyGridColumnEnd, CSSPropertyGridArea, columnEndValue, important); + addProperty(CSSPropertyGridRowStart, CSSPropertyGridArea, *rowStartValue, important); + addProperty(CSSPropertyGridColumnStart, CSSPropertyGridArea, *columnStartValue, important); + addProperty(CSSPropertyGridRowEnd, CSSPropertyGridArea, *rowEndValue, important); + addProperty(CSSPropertyGridColumnEnd, CSSPropertyGridArea, *columnEndValue, important); return true; } @@ -4887,9 +4887,9 @@ } else { columnsValue = CSSPrimitiveValue::createIdentifier(CSSValueNone); } - addProperty(CSSPropertyGridTemplateRows, shorthandId, templateRows, important); - addProperty(CSSPropertyGridTemplateColumns, shorthandId, columnsValue, important); - addProperty(CSSPropertyGridTemplateAreas, shorthandId, CSSGridTemplateAreasValue::create(gridAreaMap, rowCount, columnCount), important); + addProperty(CSSPropertyGridTemplateRows, shorthandId, *templateRows, important); + addProperty(CSSPropertyGridTemplateColumns, shorthandId, *columnsValue, important); + addProperty(CSSPropertyGridTemplateAreas, shorthandId, *CSSGridTemplateAreasValue::create(gridAreaMap, rowCount, columnCount), important); return true; } @@ -4903,9 +4903,9 @@ // 1- 'none' case. if (rowsValue && m_range.atEnd()) { - addProperty(CSSPropertyGridTemplateRows, shorthandId, CSSPrimitiveValue::createIdentifier(CSSValueNone), important); - addProperty(CSSPropertyGridTemplateColumns, shorthandId, CSSPrimitiveValue::createIdentifier(CSSValueNone), important); - addProperty(CSSPropertyGridTemplateAreas, shorthandId, CSSPrimitiveValue::createIdentifier(CSSValueNone), important); + addProperty(CSSPropertyGridTemplateRows, shorthandId, *CSSPrimitiveValue::createIdentifier(CSSValueNone), important); + addProperty(CSSPropertyGridTemplateColumns, shorthandId, *CSSPrimitiveValue::createIdentifier(CSSValueNone), important); + addProperty(CSSPropertyGridTemplateAreas, shorthandId, *CSSPrimitiveValue::createIdentifier(CSSValueNone), important); return true; } @@ -4920,9 +4920,9 @@ if (!columnsValue || !m_range.atEnd()) return false; - addProperty(CSSPropertyGridTemplateRows, shorthandId, rowsValue, important); - addProperty(CSSPropertyGridTemplateColumns, shorthandId, columnsValue, important); - addProperty(CSSPropertyGridTemplateAreas, shorthandId, CSSPrimitiveValue::createIdentifier(CSSValueNone), important); + addProperty(CSSPropertyGridTemplateRows, shorthandId, *rowsValue, important); + addProperty(CSSPropertyGridTemplateColumns, shorthandId, *columnsValue, important); + addProperty(CSSPropertyGridTemplateAreas, shorthandId, *CSSPrimitiveValue::createIdentifier(CSSValueNone), important); return true; } @@ -4942,11 +4942,11 @@ if (consumeGridTemplateShorthand(CSSPropertyGrid, important)) { // It can only be specified the explicit or the implicit grid properties in a single grid declaration. // The sub-properties not specified are set to their initial value, as normal for shorthands. - addProperty(CSSPropertyGridAutoFlow, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important); - addProperty(CSSPropertyGridAutoColumns, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important); - addProperty(CSSPropertyGridAutoRows, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important); - addProperty(CSSPropertyGridColumnGap, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important); - addProperty(CSSPropertyGridRowGap, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyGridAutoFlow, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyGridAutoColumns, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyGridAutoRows, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyGridColumnGap, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyGridRowGap, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important); return true; } @@ -4983,14 +4983,14 @@ // It can only be specified the explicit or the implicit grid properties in a single grid declaration. // The sub-properties not specified are set to their initial value, as normal for shorthands. - addProperty(CSSPropertyGridTemplateColumns, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important); - addProperty(CSSPropertyGridTemplateRows, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important); - addProperty(CSSPropertyGridTemplateAreas, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important); - addProperty(CSSPropertyGridAutoFlow, CSSPropertyGrid, gridAutoFlow, important); - addProperty(CSSPropertyGridAutoColumns, CSSPropertyGrid, autoColumnsValue, important); - addProperty(CSSPropertyGridAutoRows, CSSPropertyGrid, autoRowsValue, important); - addProperty(CSSPropertyGridColumnGap, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important); - addProperty(CSSPropertyGridRowGap, CSSPropertyGrid, CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyGridTemplateColumns, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyGridTemplateRows, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyGridTemplateAreas, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyGridAutoFlow, CSSPropertyGrid, *gridAutoFlow, important); + addProperty(CSSPropertyGridAutoColumns, CSSPropertyGrid, *autoColumnsValue, important); + addProperty(CSSPropertyGridAutoRows, CSSPropertyGrid, *autoRowsValue, important); + addProperty(CSSPropertyGridColumnGap, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important); + addProperty(CSSPropertyGridRowGap, CSSPropertyGrid, *CSSInitialValue::createLegacyImplicit(), important); return true; } @@ -5004,15 +5004,15 @@ if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebkitMarginBeforeCollapse, id, m_context.mode())) return false; CSSValue* beforeCollapse = CSSPrimitiveValue::createIdentifier(id); - addProperty(CSSPropertyWebkitMarginBeforeCollapse, CSSPropertyWebkitMarginCollapse, beforeCollapse, important); + addProperty(CSSPropertyWebkitMarginBeforeCollapse, CSSPropertyWebkitMarginCollapse, *beforeCollapse, important); if (m_range.atEnd()) { - addProperty(CSSPropertyWebkitMarginAfterCollapse, CSSPropertyWebkitMarginCollapse, beforeCollapse, important); + addProperty(CSSPropertyWebkitMarginAfterCollapse, CSSPropertyWebkitMarginCollapse, *beforeCollapse, important); return true; } id = m_range.consumeIncludingWhitespace().id(); if (!CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyWebkitMarginAfterCollapse, id, m_context.mode())) return false; - addProperty(CSSPropertyWebkitMarginAfterCollapse, CSSPropertyWebkitMarginCollapse, CSSPrimitiveValue::createIdentifier(id), important); + addProperty(CSSPropertyWebkitMarginAfterCollapse, CSSPropertyWebkitMarginCollapse, *CSSPrimitiveValue::createIdentifier(id), important); return true; } case CSSPropertyOverflow: { @@ -5033,8 +5033,8 @@ overflowXValue = CSSPrimitiveValue::createIdentifier(CSSValueAuto); else overflowXValue = overflowYValue; - addProperty(CSSPropertyOverflowX, CSSPropertyOverflow, overflowXValue, important); - addProperty(CSSPropertyOverflowY, CSSPropertyOverflow, overflowYValue, important); + addProperty(CSSPropertyOverflowX, CSSPropertyOverflow, *overflowXValue, important); + addProperty(CSSPropertyOverflowY, CSSPropertyOverflow, *overflowYValue, important); return true; } case CSSPropertyFont: { @@ -5080,9 +5080,9 @@ CSSValue* marker = parseSingleValue(CSSPropertyMarkerStart); if (!marker || !m_range.atEnd()) return false; - addProperty(CSSPropertyMarkerStart, CSSPropertyMarker, marker, important); - addProperty(CSSPropertyMarkerMid, CSSPropertyMarker, marker, important); - addProperty(CSSPropertyMarkerEnd, CSSPropertyMarker, marker, important); + addProperty(CSSPropertyMarkerStart, CSSPropertyMarker, *marker, important); + addProperty(CSSPropertyMarkerMid, CSSPropertyMarker, *marker, important); + addProperty(CSSPropertyMarkerEnd, CSSPropertyMarker, *marker, important); return true; } case CSSPropertyFlex: @@ -5098,10 +5098,10 @@ CSSPrimitiveValue* verticalRadii[4] = { 0 }; if (!consumeRadii(horizontalRadii, verticalRadii, m_range, m_context.mode(), unresolvedProperty == CSSPropertyAliasWebkitBorderRadius)) return false; - addProperty(CSSPropertyBorderTopLeftRadius, CSSPropertyBorderRadius, CSSValuePair::create(horizontalRadii[0], verticalRadii[0], CSSValuePair::DropIdenticalValues), important); - addProperty(CSSPropertyBorderTopRightRadius, CSSPropertyBorderRadius, CSSValuePair::create(horizontalRadii[1], verticalRadii[1], CSSValuePair::DropIdenticalValues), important); - addProperty(CSSPropertyBorderBottomRightRadius, CSSPropertyBorderRadius, CSSValuePair::create(horizontalRadii[2], verticalRadii[2], CSSValuePair::DropIdenticalValues), important); - addProperty(CSSPropertyBorderBottomLeftRadius, CSSPropertyBorderRadius, CSSValuePair::create(horizontalRadii[3], verticalRadii[3], CSSValuePair::DropIdenticalValues), important); + addProperty(CSSPropertyBorderTopLeftRadius, CSSPropertyBorderRadius, *CSSValuePair::create(horizontalRadii[0], verticalRadii[0], CSSValuePair::DropIdenticalValues), important); + addProperty(CSSPropertyBorderTopRightRadius, CSSPropertyBorderRadius, *CSSValuePair::create(horizontalRadii[1], verticalRadii[1], CSSValuePair::DropIdenticalValues), important); + addProperty(CSSPropertyBorderBottomRightRadius, CSSPropertyBorderRadius, *CSSValuePair::create(horizontalRadii[2], verticalRadii[2], CSSValuePair::DropIdenticalValues), important); + addProperty(CSSPropertyBorderBottomLeftRadius, CSSPropertyBorderRadius, *CSSValuePair::create(horizontalRadii[3], verticalRadii[3], CSSValuePair::DropIdenticalValues), important); return true; } case CSSPropertyBorderColor: @@ -5136,8 +5136,8 @@ CSSValue* resultY = nullptr; if (!consumeBackgroundPosition(m_range, m_context, UnitlessQuirk::Allow, resultX, resultY) || !m_range.atEnd()) return false; - addProperty(property == CSSPropertyBackgroundPosition ? CSSPropertyBackgroundPositionX : CSSPropertyWebkitMaskPositionX, property, resultX, important); - addProperty(property == CSSPropertyBackgroundPosition ? CSSPropertyBackgroundPositionY : CSSPropertyWebkitMaskPositionY, property, resultY, important); + addProperty(property == CSSPropertyBackgroundPosition ? CSSPropertyBackgroundPositionX : CSSPropertyWebkitMaskPositionX, property, *resultX, important); + addProperty(property == CSSPropertyBackgroundPosition ? CSSPropertyBackgroundPositionY : CSSPropertyWebkitMaskPositionY, property, *resultY, important); return true; } case CSSPropertyBackgroundRepeat: @@ -5147,8 +5147,8 @@ bool implicit = false; if (!consumeRepeatStyle(m_range, resultX, resultY, implicit) || !m_range.atEnd()) return false; - addProperty(property == CSSPropertyBackgroundRepeat ? CSSPropertyBackgroundRepeatX : CSSPropertyWebkitMaskRepeatX, property, resultX, important, implicit); - addProperty(property == CSSPropertyBackgroundRepeat ? CSSPropertyBackgroundRepeatY : CSSPropertyWebkitMaskRepeatY, property, resultY, important, implicit); + addProperty(property == CSSPropertyBackgroundRepeat ? CSSPropertyBackgroundRepeatX : CSSPropertyWebkitMaskRepeatX, property, *resultX, important, implicit); + addProperty(property == CSSPropertyBackgroundRepeat ? CSSPropertyBackgroundRepeatY : CSSPropertyWebkitMaskRepeatY, property, *resultY, important, implicit); return true; } case CSSPropertyBackground: @@ -5163,8 +5163,8 @@ return false; if (!columnGap) columnGap = rowGap; - addProperty(CSSPropertyGridRowGap, CSSPropertyGridGap, rowGap, important); - addProperty(CSSPropertyGridColumnGap, CSSPropertyGridGap, columnGap, important); + addProperty(CSSPropertyGridRowGap, CSSPropertyGridGap, *rowGap, important); + addProperty(CSSPropertyGridColumnGap, CSSPropertyGridGap, *columnGap, important); return true; } case CSSPropertyGridColumn:
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h index f2d605ac..ecd2bcb 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h +++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.h
@@ -61,8 +61,8 @@ bool parseViewportDescriptor(CSSPropertyID propId, bool important); bool parseFontFaceDescriptor(CSSPropertyID); - void addProperty(CSSPropertyID, CSSPropertyID, CSSValue*, bool important, bool implicit = false); - void addExpandedPropertyForValue(CSSPropertyID propId, CSSValue*, bool); + void addProperty(CSSPropertyID, CSSPropertyID, const CSSValue&, bool important, bool implicit = false); + void addExpandedPropertyForValue(CSSPropertyID propId, const CSSValue&, bool); bool consumeBorder(bool important);
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp index be7e022..bd5c532c 100644 --- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp +++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderConverter.cpp
@@ -750,6 +750,7 @@ result.angle += primitiveValue.computeDegrees(); } } + result.angle = clampTo<float>(result.angle); return result; }
diff --git a/third_party/WebKit/Source/core/dom/CommonDefinitions.idl b/third_party/WebKit/Source/core/dom/CommonDefinitions.idl index 30bb95f..8646c795 100644 --- a/third_party/WebKit/Source/core/dom/CommonDefinitions.idl +++ b/third_party/WebKit/Source/core/dom/CommonDefinitions.idl
@@ -6,3 +6,7 @@ typedef (ArrayBuffer or ArrayBufferView) BufferSource; typedef unsigned long long DOMTimeStamp; + +// typedefs used in multiple files. + +typedef object JSON;
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index 02cf58a..f1cda58 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -100,6 +100,7 @@ #include "core/dom/StaticNodeList.h" #include "core/dom/StyleChangeReason.h" #include "core/dom/StyleEngine.h" +#include "core/dom/TaskRunnerHelper.h" #include "core/dom/TouchList.h" #include "core/dom/TransformSource.h" #include "core/dom/TreeWalker.h" @@ -361,7 +362,7 @@ { DCHECK(element.hasEditableStyle()); - return element.document().frame() && element.rootEditableElement(); + return element.document().frame() && rootEditableElement(element); } uint64_t Document::s_globalTreeVersion = 0; @@ -445,7 +446,7 @@ , m_compositorPendingAnimations(new CompositorPendingAnimations()) , m_templateDocumentHost(nullptr) , m_didAssociateFormControlsTimer(this, &Document::didAssociateFormControlsTimerFired) - , m_timers(timerTaskRunner()->adoptClone()) + , m_timers(TaskRunnerHelper::getTimerTaskRunner(this)->adoptClone()) , m_hasViewportUnits(false) , m_parserSyncPolicy(AllowAsynchronousParsing) , m_nodeCount(0) @@ -602,11 +603,6 @@ return m_rootScrollerController->get(); } -const Element* Document::effectiveRootScroller() const -{ - return m_rootScrollerController->effectiveRootScroller(); -} - bool Document::isViewportScrollCallback(const ScrollStateCallback* callback) { if (!callback) @@ -1582,10 +1578,12 @@ documentElement()->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::FontSizeChange)); } + EOverflowAnchor overflowAnchor = AnchorAuto; EOverflow overflowX = OverflowAuto; EOverflow overflowY = OverflowAuto; float columnGap = 0; if (overflowStyle) { + overflowAnchor = overflowStyle->overflowAnchor(); overflowX = overflowStyle->overflowX(); overflowY = overflowStyle->overflowY(); // Visible overflow on the viewport is meaningless, and the spec says to treat it as 'auto': @@ -1593,6 +1591,8 @@ overflowX = OverflowAuto; if (overflowY == OverflowVisible) overflowY = OverflowAuto; + if (overflowAnchor == AnchorVisible) + overflowAnchor = AnchorAuto; // Column-gap is (ab)used by the current paged overflow implementation (in lack of other // ways to specify gaps between pages), so we have to propagate it too. columnGap = overflowStyle->columnGap(); @@ -1607,6 +1607,7 @@ || documentStyle->visitedDependentColor(CSSPropertyBackgroundColor) != backgroundColor || documentStyle->backgroundLayers() != backgroundLayers || documentStyle->imageRendering() != imageRendering + || documentStyle->overflowAnchor() != overflowAnchor || documentStyle->overflowX() != overflowX || documentStyle->overflowY() != overflowY || documentStyle->columnGap() != columnGap @@ -1618,6 +1619,7 @@ newStyle->setBackgroundColor(backgroundColor); newStyle->accessBackgroundLayers() = backgroundLayers; newStyle->setImageRendering(imageRendering); + newStyle->setOverflowAnchor(overflowAnchor); newStyle->setOverflowX(overflowX); newStyle->setOverflowY(overflowY); newStyle->setColumnGap(columnGap); @@ -2144,8 +2146,6 @@ ScriptForbiddenScope forbidScript; view()->dispose(); m_markers->prepareForDestruction(); - if (LocalDOMWindow* window = this->domWindow()) - window->willDetachDocumentFromFrame(); m_lifecycle.advanceTo(DocumentLifecycle::Stopping); @@ -3026,7 +3026,7 @@ void Document::didLoadAllScriptBlockingResources() { - loadingTaskRunner()->postTask(BLINK_FROM_HERE, m_executeScriptsWaitingForResourcesTask->cancelAndCreate()); + TaskRunnerHelper::getLoadingTaskRunner(this)->postTask(BLINK_FROM_HERE, m_executeScriptsWaitingForResourcesTask->cancelAndCreate()); if (isHTMLDocument() && body()) { // For HTML if we have no more stylesheets to load and we're past the body @@ -3565,7 +3565,7 @@ if (newFocusedElement) updateStyleAndLayoutTreeForNode(newFocusedElement); if (newFocusedElement && newFocusedElement->isFocusable()) { - if (newFocusedElement->isRootEditableElement() && !acceptsEditingFocus(*newFocusedElement)) { + if (isRootEditableElement(*newFocusedElement) && !acceptsEditingFocus(*newFocusedElement)) { // delegate blocks focus change focusChangeBlocked = true; goto SetFocusedElementDone; @@ -3613,7 +3613,7 @@ } } - if (m_focusedElement->isRootEditableElement()) + if (isRootEditableElement(*m_focusedElement)) frame()->spellChecker().didBeginEditing(m_focusedElement.get()); // eww, I suck. set the qt focus correctly @@ -4170,10 +4170,15 @@ const KURL Document::firstPartyForCookies() const { + // TODO(mkwst): This doesn't properly handle HTML Import documents. + // If this is an imported document, grab its master document's first-party: if (importsController() && importsController()->master() && importsController()->master() != this) return importsController()->master()->firstPartyForCookies(); + if (!frame()) + return SecurityOrigin::urlWithUniqueSecurityOrigin(); + // TODO(mkwst): This doesn't correctly handle sandboxed documents; we want to look at their URL, // but we can't because we don't know what it is. Frame* top = frame()->tree().top(); @@ -5876,39 +5881,6 @@ return isSecureContextImpl(privilegeContextCheck); } -WebTaskRunner* Document::loadingTaskRunner() const -{ - if (frame()) - return frame()->frameScheduler()->loadingTaskRunner(); - if (m_importsController) - return m_importsController->master()->loadingTaskRunner(); - if (m_contextDocument) - return m_contextDocument->loadingTaskRunner(); - return Platform::current()->currentThread()->scheduler()->loadingTaskRunner(); -} - -WebTaskRunner* Document::timerTaskRunner() const -{ - if (frame()) - return m_frame->frameScheduler()->timerTaskRunner(); - if (m_importsController) - return m_importsController->master()->timerTaskRunner(); - if (m_contextDocument) - return m_contextDocument->timerTaskRunner(); - return Platform::current()->currentThread()->scheduler()->timerTaskRunner(); -} - -WebTaskRunner* Document::unthrottledTaskRunner() const -{ - if (frame()) - return m_frame->frameScheduler()->unthrottledTaskRunner(); - if (m_importsController) - return m_importsController->master()->unthrottledTaskRunner(); - if (m_contextDocument) - return m_contextDocument->unthrottledTaskRunner(); - return Platform::current()->currentThread()->getWebTaskRunner(); -} - void Document::enforceInsecureRequestPolicy(WebInsecureRequestPolicy policy) { // Combine the new policy with the existing policy, as a base policy may be
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h index 27a0cd1..fdfa383 100644 --- a/third_party/WebKit/Source/core/dom/Document.h +++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -1072,10 +1072,6 @@ SnapCoordinator* snapCoordinator(); - WebTaskRunner* loadingTaskRunner() const; - WebTaskRunner* timerTaskRunner() const; - WebTaskRunner* unthrottledTaskRunner() const; - void enforceInsecureRequestPolicy(WebInsecureRequestPolicy); bool mayContainV0Shadow() const { return m_mayContainV0Shadow; } @@ -1088,7 +1084,7 @@ void initializeRootScroller(ViewportScrollCallback*); Element* rootScroller() const; void setRootScroller(Element*, ExceptionState&); - const Element* effectiveRootScroller() const; + RootScrollerController* rootScrollerController() const { return m_rootScrollerController.get(); } // TODO(bokan): Temporarily added to allow ScrollCustomization to properly // opt out for wheel scrolls. crbug.com/623079.
diff --git a/third_party/WebKit/Source/core/dom/DocumentParserTiming.cpp b/third_party/WebKit/Source/core/dom/DocumentParserTiming.cpp index 795a22aa..2909028 100644 --- a/third_party/WebKit/Source/core/dom/DocumentParserTiming.cpp +++ b/third_party/WebKit/Source/core/dom/DocumentParserTiming.cpp
@@ -59,6 +59,7 @@ DEFINE_TRACE(DocumentParserTiming) { visitor->trace(m_document); + Supplement<Document>::trace(visitor); } DocumentParserTiming::DocumentParserTiming(Document& document)
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp index 67e29c95..b35cf91 100644 --- a/third_party/WebKit/Source/core/dom/Element.cpp +++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -121,6 +121,7 @@ #include "core/page/Page.h" #include "core/page/PointerLockController.h" #include "core/page/SpatialNavigation.h" +#include "core/page/scrolling/RootScrollerController.h" #include "core/page/scrolling/ScrollCustomizationCallbacks.h" #include "core/page/scrolling/ScrollState.h" #include "core/page/scrolling/ScrollStateCallback.h" @@ -565,7 +566,7 @@ // We should only ever scroll the effective root scroller this way when the // page removes the default applyScroll (ViewportScrollCallback). - if (document().effectiveRootScroller() == this) + if (document().rootScrollerController()->effectiveRootScroller() == this) boxToScroll = document().layoutView(); else if (layoutObject()) boxToScroll = toLayoutBox(layoutObject()); @@ -598,6 +599,10 @@ void Element::callApplyScroll(ScrollState& scrollState) { + // Hits ASSERTs when trying to determine whether we need to scroll on main + // or CC. http://crbug.com/625676. + DisableCompositingQueryAsserts disabler; + ScrollStateCallback* callback = scrollCustomizationCallbacks().getApplyScroll(this); // TODO(bokan): Need to add tests before we allow calling custom callbacks @@ -2425,7 +2430,7 @@ { if (selectionBehavior == SelectionBehaviorOnFocus::None) return; - if (isRootEditableElement()) { + if (isRootEditableElement(*this)) { LocalFrame* frame = document().frame(); if (!frame) return; @@ -2465,7 +2470,7 @@ // it won't be focusable. Furthermore, supportsFocus cannot just return true // always or else tabIndex() will change for all HTML elements. return hasElementFlag(TabIndexWasSetExplicitly) - || isRootEditableElement() + || isRootEditableElement(*this) || (isShadowHost(this) && authorShadowRoot() && authorShadowRoot()->delegatesFocus()) || supportsSpatialNavigationFocus(); } @@ -3631,7 +3636,7 @@ style->setProperty(propertyID, value, false); } -void Element::addPropertyToPresentationAttributeStyle(MutableStylePropertySet* style, CSSPropertyID propertyID, CSSValue* value) +void Element::addPropertyToPresentationAttributeStyle(MutableStylePropertySet* style, CSSPropertyID propertyID, const CSSValue* value) { DCHECK(isStyledElement()); style->setProperty(propertyID, value);
diff --git a/third_party/WebKit/Source/core/dom/Element.h b/third_party/WebKit/Source/core/dom/Element.h index 1f21fca..6d27407 100644 --- a/third_party/WebKit/Source/core/dom/Element.h +++ b/third_party/WebKit/Source/core/dom/Element.h
@@ -587,7 +587,7 @@ void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, CSSValueID identifier); void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, double value, CSSPrimitiveValue::UnitType); void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, const String& value); - void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, CSSValue*); + void addPropertyToPresentationAttributeStyle(MutableStylePropertySet*, CSSPropertyID, const CSSValue*); InsertionNotificationRequest insertedInto(ContainerNode*) override; void removedFrom(ContainerNode*) override;
diff --git a/third_party/WebKit/Source/core/dom/Fullscreen.cpp b/third_party/WebKit/Source/core/dom/Fullscreen.cpp index 030f37b..0c73478 100644 --- a/third_party/WebKit/Source/core/dom/Fullscreen.cpp +++ b/third_party/WebKit/Source/core/dom/Fullscreen.cpp
@@ -198,7 +198,7 @@ : ContextLifecycleObserver(&document) , m_fullScreenLayoutObject(nullptr) , m_eventQueueTimer(this, &Fullscreen::eventQueueTimerFired) - , m_forCrossProcessAncestor(false) + , m_forCrossProcessDescendant(false) { document.setHasFullscreenSupplement(); } @@ -224,11 +224,11 @@ } -void Fullscreen::requestFullscreen(Element& element, RequestType requestType, bool forCrossProcessAncestor) +void Fullscreen::requestFullscreen(Element& element, RequestType requestType, bool forCrossProcessDescendant) { // Use counters only need to be incremented in the process of the actual // fullscreen element. - if (!forCrossProcessAncestor) { + if (!forCrossProcessDescendant) { if (document()->isSecureContext()) { UseCounter::count(document(), UseCounter::FullscreenSecureOrigin); } else { @@ -259,10 +259,10 @@ // - an activation behavior is currently being processed whose click event was trusted, or // - the event listener for a trusted click event is being handled. // - // If |forCrossProcessAncestor| is true, requestFullscreen was already - // called on an element in another process, and getting here means that - // it already passed the user gesture check. - if (!UserGestureIndicator::utilizeUserGesture() && !forCrossProcessAncestor) { + // If |forCrossProcessDescendant| is true, requestFullscreen + // was already called on a descendant element in another process, and + // getting here means that it already passed the user gesture check. + if (!UserGestureIndicator::utilizeUserGesture() && !forCrossProcessDescendant) { String message = ExceptionMessages::failedToExecute("requestFullScreen", "Element", "API can only be initiated by a user gesture."); document()->addConsoleMessage( @@ -331,7 +331,7 @@ // 4. Otherwise, do nothing for this document. It stays the same. } while (++current != docs.end()); - m_forCrossProcessAncestor = forCrossProcessAncestor; + m_forCrossProcessDescendant = forCrossProcessDescendant; // 5. Return, and run the remaining steps asynchronously. // 6. Optionally, perform some animation. @@ -483,7 +483,7 @@ return fullscreenIsAllowedForAllOwners(document) && fullscreenIsSupported(document); } -void Fullscreen::didEnterFullScreenForElement(Element* element) +void Fullscreen::didEnterFullscreenForElement(Element* element) { DCHECK(element); if (!document()->isActive()) @@ -505,13 +505,18 @@ m_savedPlaceholderComputedStyle = ComputedStyle::clone(layoutObject->styleRef()); } - // TODO(alexmos): When |m_forCrossProcessAncestor| is true, some of + // TODO(alexmos): When |m_forCrossProcessDescendant| is true, some of // this layout work has already been done in another process, so it should // not be necessary to repeat it here. if (m_fullScreenElement != document()->documentElement()) LayoutFullScreen::wrapLayoutObject(layoutObject, layoutObject ? layoutObject->parent() : 0, document()); - if (m_forCrossProcessAncestor) { + // When |m_forCrossProcessDescendant| is true, m_fullScreenElement + // corresponds to the HTMLFrameOwnerElement for the out-of-process iframe + // that contains the actual fullscreen element. Hence, it must also set + // the ContainsFullScreenElement flag (so that it gains the + // -webkit-full-screen-ancestor style). + if (m_forCrossProcessDescendant) { DCHECK(m_fullScreenElement->isFrameOwnerElement()); DCHECK(toHTMLFrameOwnerElement(m_fullScreenElement)->contentFrame()->isRemoteFrame()); m_fullScreenElement->setContainsFullScreenElement(true); @@ -533,7 +538,7 @@ m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); } -void Fullscreen::didExitFullScreenForElement() +void Fullscreen::didExitFullscreen() { if (!m_fullScreenElement) return; @@ -543,7 +548,7 @@ m_fullScreenElement->willStopBeingFullscreenElement(); - if (m_forCrossProcessAncestor) + if (m_forCrossProcessDescendant) m_fullScreenElement->setContainsFullScreenElement(false); m_fullScreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false); @@ -567,7 +572,7 @@ DCHECK(exitingDocument); from(*exitingDocument).m_eventQueueTimer.startOneShot(0, BLINK_FROM_HERE); - m_forCrossProcessAncestor = false; + m_forCrossProcessDescendant = false; } void Fullscreen::setFullScreenLayoutObject(LayoutFullScreen* layoutObject) @@ -610,7 +615,7 @@ event = createEvent(EventTypeNames::webkitfullscreenchange, *target); } m_eventQueue.append(event); - // NOTE: The timer is started in didEnterFullScreenForElement/didExitFullScreenForElement. + // NOTE: The timer is started in didEnterFullscreenForElement/didExitFullscreen. } void Fullscreen::enqueueErrorEvent(Element& element, RequestType requestType)
diff --git a/third_party/WebKit/Source/core/dom/Fullscreen.h b/third_party/WebKit/Source/core/dom/Fullscreen.h index a624c20..b67a4a9 100644 --- a/third_party/WebKit/Source/core/dom/Fullscreen.h +++ b/third_party/WebKit/Source/core/dom/Fullscreen.h
@@ -67,9 +67,10 @@ PrefixedRequest, }; - // |forCrossProcessAncestor| is used in OOPIF scenarios and is set to true - // when fullscreen is requested for an out-of-process descendant element. - void requestFullscreen(Element&, RequestType, bool forCrossProcessAncestor = false); + // |forCrossProcessDescendant| is used in OOPIF scenarios and is set to + // true when fullscreen is requested for an out-of-process descendant + // element. + void requestFullscreen(Element&, RequestType, bool forCrossProcessDescendant = false); static void fullyExitFullscreen(Document&); void exitFullscreen(); @@ -77,14 +78,8 @@ static bool fullscreenEnabled(Document&); Element* fullscreenElement() const { return !m_fullScreenElementStack.isEmpty() ? m_fullScreenElementStack.last().first.get() : 0; } - // |isAncestorOfFullscreenElement| is used in OOPIF scenarios and is set to - // true when these functions are called to enter/exit fullscreen for an - // out-of-process descendant element. In this case, we enter fullscreen - // for its (local) iframe container and make sure to also set the - // ContainsFullScreenElement flag on it (so that it gains the - // -webkit-full-screen-ancestor style). - void didEnterFullScreenForElement(Element*); - void didExitFullScreenForElement(); + void didEnterFullscreenForElement(Element*); + void didExitFullscreen(); void setFullScreenLayoutObject(LayoutFullScreen*); LayoutFullScreen* fullScreenLayoutObject() const { return m_fullScreenLayoutObject; } @@ -93,8 +88,9 @@ void elementRemoved(Element&); // Returns true if the current fullscreen element stack corresponds to a - // container for an actual fullscreen element in an out-of-process iframe. - bool forCrossProcessAncestor() { return m_forCrossProcessAncestor; } + // container for an actual fullscreen element in a descendant + // out-of-process iframe. + bool forCrossProcessDescendant() { return m_forCrossProcessDescendant; } // Mozilla API Element* webkitCurrentFullScreenElement() const { return m_fullScreenElement.get(); } @@ -136,7 +132,7 @@ // change if https://crbug.com/161068 is fixed so that cross-process // postMessage can carry user gestures. If that happens, this should be // moved to be part of |m_fullScreenElementStack|. - bool m_forCrossProcessAncestor; + bool m_forCrossProcessDescendant; }; inline bool Fullscreen::isActiveFullScreenElement(const Element& element)
diff --git a/third_party/WebKit/Source/core/dom/MessagePort.cpp b/third_party/WebKit/Source/core/dom/MessagePort.cpp index 92e9fac..567c32d 100644 --- a/third_party/WebKit/Source/core/dom/MessagePort.cpp +++ b/third_party/WebKit/Source/core/dom/MessagePort.cpp
@@ -62,7 +62,7 @@ MessagePort::~MessagePort() { - close(); + DCHECK(!m_started || !isEntangled()); if (m_scriptStateForConversion) m_scriptStateForConversion->disposePerContextData(); } @@ -117,7 +117,7 @@ WebMessagePortChannelUniquePtr MessagePort::disentangle() { DCHECK(m_entangledChannel); - m_entangledChannel->setClient(0); + m_entangledChannel->setClient(nullptr); return std::move(m_entangledChannel); } @@ -139,6 +139,7 @@ if (m_started) return; + m_entangledChannel->setClient(this); m_started = true; messageAvailable(); } @@ -146,7 +147,7 @@ void MessagePort::close() { if (isEntangled()) - m_entangledChannel->setClient(0); + m_entangledChannel->setClient(nullptr); m_closed = true; } @@ -157,7 +158,6 @@ DCHECK(getExecutionContext()); m_entangledChannel = std::move(remote); - m_entangledChannel->setClient(this); } const AtomicString& MessagePort::interfaceName() const
diff --git a/third_party/WebKit/Source/core/dom/Node.cpp b/third_party/WebKit/Source/core/dom/Node.cpp index 84a8cea6..64c7afee 100644 --- a/third_party/WebKit/Source/core/dom/Node.cpp +++ b/third_party/WebKit/Source/core/dom/Node.cpp
@@ -557,10 +557,6 @@ for (const Node& node : NodeTraversal::inclusiveAncestorsOf(*this)) { if ((node.isHTMLElement() || node.isDocumentNode()) && node.layoutObject()) { - // Elements with user-select: all style are considered atomic - // therefore non editable. - if (nodeIsUserSelectAll(&node) && treatment == UserSelectAllIsAlwaysNonEditable) - return false; switch (node.layoutObject()->style()->userModify()) { case READ_ONLY: return false; @@ -1107,29 +1103,32 @@ return parentOrShadowHostNode(); } -bool Node::isRootEditableElement() const +// TODO(yoichio): Move to core/editing +bool isRootEditableElement(const Node& node) { - return hasEditableStyle() && isElementNode() && (!parentNode() || !parentNode()->hasEditableStyle() - || !parentNode()->isElementNode() || this == document().body()); + return node.hasEditableStyle() && node.isElementNode() && (!node.parentNode() || !node.parentNode()->hasEditableStyle() + || !node.parentNode()->isElementNode() || &node == node.document().body()); } -Element* Node::rootEditableElement(EditableType editableType) const +// TODO(yoichio): Move to core/editing +Element* rootEditableElement(const Node& node, EditableType editableType) { if (editableType == HasEditableAXRole) { - if (AXObjectCache* cache = document().existingAXObjectCache()) - return const_cast<Element*>(cache->rootAXEditableElement(this)); + if (AXObjectCache* cache = node.document().existingAXObjectCache()) + return const_cast<Element*>(cache->rootAXEditableElement(&node)); } - return rootEditableElement(); + return rootEditableElement(node); } -Element* Node::rootEditableElement() const +// TODO(yoichio): Move to core/editing +Element* rootEditableElement(const Node& node) { const Node* result = nullptr; - for (const Node* n = this; n && n->hasEditableStyle(); n = n->parentNode()) { + for (const Node* n = &node; n && n->hasEditableStyle(); n = n->parentNode()) { if (n->isElementNode()) result = n; - if (document().body() == n) + if (node.document().body() == n) break; } return toElement(const_cast<Node*>(result));
diff --git a/third_party/WebKit/Source/core/dom/Node.h b/third_party/WebKit/Source/core/dom/Node.h index ad8cbb4..a3f8ef6 100644 --- a/third_party/WebKit/Source/core/dom/Node.h +++ b/third_party/WebKit/Source/core/dom/Node.h
@@ -335,10 +335,6 @@ virtual bool canContainRangeEndPoint() const { return false; } - bool isRootEditableElement() const; - Element* rootEditableElement() const; - Element* rootEditableElement(EditableType) const; - // For <link> and <style> elements. virtual bool sheetLoaded() { return true; } enum LoadedSheetErrorStatus { @@ -894,6 +890,11 @@ return node; } +// TODO(yoichio): Move to core/editing +CORE_EXPORT bool isRootEditableElement(const Node&); +CORE_EXPORT Element* rootEditableElement(const Node&); +CORE_EXPORT Element* rootEditableElement(const Node&, EditableType); + // Allow equality comparisons of Nodes by reference or pointer, interchangeably. DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES_REFCOUNTED(Node)
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp index a8337a8d..edb8edc3 100644 --- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp +++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
@@ -132,21 +132,20 @@ // FIXME: This function is not HTML5 compliant. These belong in the MIME registry as "text/javascript<version>" entries. typedef HashSet<String, CaseFoldingHash> LanguageSet; - DEFINE_STATIC_LOCAL(LanguageSet, languages, ()); - if (languages.isEmpty()) { - languages.add("javascript"); - languages.add("javascript1.0"); - languages.add("javascript1.1"); - languages.add("javascript1.2"); - languages.add("javascript1.3"); - languages.add("javascript1.4"); - languages.add("javascript1.5"); - languages.add("javascript1.6"); - languages.add("javascript1.7"); - languages.add("livescript"); - languages.add("ecmascript"); - languages.add("jscript"); - } + DEFINE_STATIC_LOCAL(LanguageSet, languages, ({ + "javascript", + "javascript1.0", + "javascript1.1", + "javascript1.2", + "javascript1.3", + "javascript1.4", + "javascript1.5", + "javascript1.6", + "javascript1.7", + "livescript", + "ecmascript", + "jscript", + })); return languages.contains(language); } @@ -355,7 +354,7 @@ UseCounter::count(frame, feature); } -bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode, double* compilationFinishTime) +bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode) { DCHECK(m_alreadyStarted); @@ -427,7 +426,7 @@ // Create a script from the script element node, using the script // block's source and the script block's type. // Note: This is where the script is compiled and actually executed. - frame->script().executeScriptInMainWorld(sourceCode, accessControlStatus, compilationFinishTime); + frame->script().executeScriptInMainWorld(sourceCode, accessControlStatus); if (isHTMLScriptLoader(m_element) || isSVGScriptLoader(m_element)) { DCHECK(contextDocument->currentScript() == m_element);
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.h b/third_party/WebKit/Source/core/dom/ScriptLoader.h index 0af9f42..24f3ebd 100644 --- a/third_party/WebKit/Source/core/dom/ScriptLoader.h +++ b/third_party/WebKit/Source/core/dom/ScriptLoader.h
@@ -55,7 +55,7 @@ String scriptCharset() const { return m_characterEncoding; } String scriptContent() const; // Returns false if and only if execution was blocked. - bool executeScript(const ScriptSourceCode&, double* compilationFinishTime = 0); + bool executeScript(const ScriptSourceCode&); virtual void execute(); // XML parser calls these
diff --git a/third_party/WebKit/Source/core/dom/ScriptRunner.cpp b/third_party/WebKit/Source/core/dom/ScriptRunner.cpp index be56e65..317ce05e 100644 --- a/third_party/WebKit/Source/core/dom/ScriptRunner.cpp +++ b/third_party/WebKit/Source/core/dom/ScriptRunner.cpp
@@ -149,7 +149,7 @@ { switch (executionType) { case ASYNC_EXECUTION: { - // RELEASE_ASSERT makes us crash in a controlled way in error cases + // SECURITY_CHECK makes us crash in a controlled way in error cases // where the ScriptLoader is associated with the wrong ScriptRunner // (otherwise we'd cause a use-after-free in ~ScriptRunner when it tries // to detach).
diff --git a/third_party/WebKit/Source/core/dom/SelectorQuery.cpp b/third_party/WebKit/Source/core/dom/SelectorQuery.cpp index 212d353..c739f889 100644 --- a/third_party/WebKit/Source/core/dom/SelectorQuery.cpp +++ b/third_party/WebKit/Source/core/dom/SelectorQuery.cpp
@@ -27,6 +27,7 @@ #include "core/dom/SelectorQuery.h" #include "bindings/core/v8/ExceptionState.h" +#include "core/HTMLNames.h" #include "core/css/SelectorChecker.h" #include "core/css/parser/CSSParser.h" #include "core/dom/Document.h" @@ -41,6 +42,8 @@ namespace blink { +using namespace HTMLNames; + struct SingleElementSelectorQueryTrait { typedef Element* OutputType; static const bool shouldOnlyMatchFirstElement = true; @@ -444,11 +447,17 @@ } } -const CSSSelector* SelectorDataList::selectorForIdLookup(const CSSSelector& firstSelector) const +static const CSSSelector* selectorForIdLookup(const CSSSelector& firstSelector) { for (const CSSSelector* selector = &firstSelector; selector; selector = selector->tagHistory()) { if (selector->match() == CSSSelector::Id) return selector; + // We only use the fast path when in standards mode where #id selectors + // are case sensitive, so we need the same behavior for [id=value]. + if (selector->match() == CSSSelector::AttributeExact + && selector->attribute() == idAttr + && selector->attributeMatch() == CSSSelector::CaseSensitive) + return selector; if (selector->relation() != CSSSelector::SubSelector) break; } @@ -473,11 +482,12 @@ } DCHECK_EQ(m_selectors.size(), 1u); + DCHECK(!rootNode.document().inQuirksMode()); const CSSSelector& selector = *m_selectors[0]; const CSSSelector& firstSelector = selector; - // Fast path for querySelector*('#id'), querySelector*('tag#id'). + // Fast path for querySelector*('#id'), querySelector*('tag#id'), querySelector*('tag[id=example]'). if (const CSSSelector* idSelector = selectorForIdLookup(firstSelector)) { const AtomicString& idToMatch = idSelector->value(); if (rootNode.treeScope().containsMultipleElementsWithId(idToMatch)) {
diff --git a/third_party/WebKit/Source/core/dom/SelectorQuery.h b/third_party/WebKit/Source/core/dom/SelectorQuery.h index 2dc05bf4..b5ceaa3f 100644 --- a/third_party/WebKit/Source/core/dom/SelectorQuery.h +++ b/third_party/WebKit/Source/core/dom/SelectorQuery.h
@@ -79,7 +79,6 @@ void executeSlowTraversingShadowTree(ContainerNode& rootNode, typename SelectorQueryTrait::OutputType&) const; template <typename SelectorQueryTrait> void execute(ContainerNode& rootNode, typename SelectorQueryTrait::OutputType&) const; - const CSSSelector* selectorForIdLookup(const CSSSelector&) const; Vector<const CSSSelector*> m_selectors; bool m_usesDeepCombinatorOrShadowPseudo : 1;
diff --git a/third_party/WebKit/Source/core/dom/TaskRunnerHelper.cpp b/third_party/WebKit/Source/core/dom/TaskRunnerHelper.cpp new file mode 100644 index 0000000..48f58f8 --- /dev/null +++ b/third_party/WebKit/Source/core/dom/TaskRunnerHelper.cpp
@@ -0,0 +1,46 @@ +// 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 "core/dom/TaskRunnerHelper.h" + +#include "core/dom/Document.h" +#include "core/frame/LocalFrame.h" +#include "public/platform/Platform.h" +#include "public/platform/WebFrameScheduler.h" +#include "public/platform/WebTaskRunner.h" +#include "public/platform/WebThread.h" + +namespace blink { + +WebTaskRunner* TaskRunnerHelper::getUnthrottledTaskRunner(LocalFrame* frame) +{ + return frame ? frame->frameScheduler()->unthrottledTaskRunner() : Platform::current()->currentThread()->getWebTaskRunner(); +} + +WebTaskRunner* TaskRunnerHelper::getTimerTaskRunner(LocalFrame* frame) +{ + return frame ? frame->frameScheduler()->timerTaskRunner() : Platform::current()->currentThread()->getWebTaskRunner(); +} + +WebTaskRunner* TaskRunnerHelper::getLoadingTaskRunner(LocalFrame* frame) +{ + return frame ? frame->frameScheduler()->loadingTaskRunner() : Platform::current()->currentThread()->getWebTaskRunner(); +} + +WebTaskRunner* TaskRunnerHelper::getUnthrottledTaskRunner(Document* document) +{ + return getUnthrottledTaskRunner(document ? document->frame() : nullptr); +} + +WebTaskRunner* TaskRunnerHelper::getTimerTaskRunner(Document* document) +{ + return getTimerTaskRunner(document ? document->frame() : nullptr); +} + +WebTaskRunner* TaskRunnerHelper::getLoadingTaskRunner(Document* document) +{ + return getLoadingTaskRunner(document ? document->frame() : nullptr); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/TaskRunnerHelper.h b/third_party/WebKit/Source/core/dom/TaskRunnerHelper.h new file mode 100644 index 0000000..d3a5b19 --- /dev/null +++ b/third_party/WebKit/Source/core/dom/TaskRunnerHelper.h
@@ -0,0 +1,29 @@ +// 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 TaskRunnerHelper_h +#define TaskRunnerHelper_h + +#include "wtf/Allocator.h" + +namespace blink { + +class Document; +class LocalFrame; +class WebTaskRunner; + +class TaskRunnerHelper final { + STATIC_ONLY(TaskRunnerHelper); +public: + static WebTaskRunner* getUnthrottledTaskRunner(LocalFrame*); + static WebTaskRunner* getTimerTaskRunner(LocalFrame*); + static WebTaskRunner* getLoadingTaskRunner(LocalFrame*); + static WebTaskRunner* getUnthrottledTaskRunner(Document*); + static WebTaskRunner* getTimerTaskRunner(Document*); + static WebTaskRunner* getLoadingTaskRunner(Document*); +}; + +} // namespace blink + +#endif
diff --git a/third_party/WebKit/Source/core/dom/custom/CustomElement.cpp b/third_party/WebKit/Source/core/dom/custom/CustomElement.cpp index bab2bec..16d712fb 100644 --- a/third_party/WebKit/Source/core/dom/custom/CustomElement.cpp +++ b/third_party/WebKit/Source/core/dom/custom/CustomElement.cpp
@@ -60,18 +60,16 @@ return false; // https://html.spec.whatwg.org/multipage/scripting.html#valid-custom-element-name - DEFINE_STATIC_LOCAL(HashSet<AtomicString>, hyphenContainingElementNames, ()); - if (hyphenContainingElementNames.isEmpty()) { - hyphenContainingElementNames.add("annotation-xml"); - hyphenContainingElementNames.add("color-profile"); - hyphenContainingElementNames.add("font-face"); - hyphenContainingElementNames.add("font-face-src"); - hyphenContainingElementNames.add("font-face-uri"); - hyphenContainingElementNames.add("font-face-format"); - hyphenContainingElementNames.add("font-face-name"); - hyphenContainingElementNames.add("missing-glyph"); - } - + DEFINE_STATIC_LOCAL(HashSet<AtomicString>, hyphenContainingElementNames, ({ + "annotation-xml", + "color-profile", + "font-face", + "font-face-src", + "font-face-uri", + "font-face-format", + "font-face-name", + "missing-glyph", + })); return !hyphenContainingElementNames.contains(name); }
diff --git a/third_party/WebKit/Source/core/editing/EditingStyle.cpp b/third_party/WebKit/Source/core/editing/EditingStyle.cpp index 503a7757..a1d63ab 100644 --- a/third_party/WebKit/Source/core/editing/EditingStyle.cpp +++ b/third_party/WebKit/Source/core/editing/EditingStyle.cpp
@@ -1249,6 +1249,10 @@ if (!m_mutableStyle) return; + // TODO(yosin): The use of updateStyleAndLayoutIgnorePendingStylesheets + // needs to be audited. see http://crbug.com/590369 for more details. + element->document().updateStyleAndLayoutIgnorePendingStylesheetsForNode(element); + // 1. Remove style from matched rules because style remain without repeating it in inline style declaration MutableStylePropertySet* styleFromMatchedRules = styleFromMatchedRulesForElement(element, StyleResolver::AllButEmptyCSSRules); if (styleFromMatchedRules && !styleFromMatchedRules->isEmpty())
diff --git a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp index b578e7a..7731eb25 100644 --- a/third_party/WebKit/Source/core/editing/EditingUtilities.cpp +++ b/third_party/WebKit/Source/core/editing/EditingUtilities.cpp
@@ -339,7 +339,7 @@ if (isDisplayInsideTable(node)) node = node->parentNode(); - return node->rootEditableElement(editableType); + return rootEditableElement(*node, editableType); } Element* rootEditableElementOf(const PositionInFlatTree& p, EditableType editableType) @@ -351,7 +351,7 @@ Element* rootEditableElementOf(const VisiblePosition& visiblePosition) { Node* anchorNode = visiblePosition.deepEquivalent().anchorNode(); - return anchorNode ? anchorNode->rootEditableElement() : nullptr; + return anchorNode ? rootEditableElement(*anchorNode) : nullptr; } // Finds the enclosing element until which the tree can be split. @@ -913,9 +913,9 @@ static HTMLElement* firstInSpecialElement(const Position& pos) { - Element* rootEditableElement = pos.computeContainerNode()->rootEditableElement(); + Element* element = rootEditableElement(*pos.computeContainerNode()); for (Node& runner : NodeTraversal::inclusiveAncestorsOf(*pos.anchorNode())) { - if (runner.rootEditableElement() != rootEditableElement) + if (rootEditableElement(runner) != element) break; if (isSpecialHTMLElement(runner)) { HTMLElement* specialElement = toHTMLElement(&runner); @@ -932,9 +932,9 @@ static HTMLElement* lastInSpecialElement(const Position& pos) { - Element* rootEditableElement = pos.computeContainerNode()->rootEditableElement(); + Element* element = rootEditableElement(*pos.computeContainerNode()); for (Node& runner : NodeTraversal::inclusiveAncestorsOf(*pos.anchorNode())) { - if (runner.rootEditableElement() != rootEditableElement) + if (rootEditableElement(runner) != element) break; if (isSpecialHTMLElement(runner)) { HTMLElement* specialElement = toHTMLElement(&runner); @@ -955,7 +955,7 @@ if (!n) return pos; Position result = Position::inParentBeforeNode(*n); - if (result.isNull() || result.anchorNode()->rootEditableElement() != pos.anchorNode()->rootEditableElement()) + if (result.isNull() || rootEditableElement(*result.anchorNode()) != rootEditableElement(*pos.anchorNode())) return pos; if (containingSpecialElement) *containingSpecialElement = n; @@ -968,7 +968,7 @@ if (!n) return pos; Position result = Position::inParentAfterNode(*n); - if (result.isNull() || result.anchorNode()->rootEditableElement() != pos.anchorNode()->rootEditableElement()) + if (result.isNull() || rootEditableElement(*result.anchorNode()) != rootEditableElement(*pos.anchorNode())) return pos; if (containingSpecialElement) *containingSpecialElement = n; @@ -1175,10 +1175,10 @@ Node* highestNodeToRemoveInPruning(Node* node, Node* excludeNode) { Node* previousNode = nullptr; - Element* rootEditableElement = node ? node->rootEditableElement() : nullptr; + Element* element = node ? rootEditableElement(*node) : nullptr; for (; node; node = node->parentNode()) { if (LayoutObject* layoutObject = node->layoutObject()) { - if (!layoutObject->canHaveChildren() || hasARenderedDescendant(node, previousNode) || rootEditableElement == node || excludeNode == node) + if (!layoutObject->canHaveChildren() || hasARenderedDescendant(node, previousNode) || element == node || excludeNode == node) return previousNode; } previousNode = node; @@ -1285,7 +1285,7 @@ return firstList->hasTagName(secondList->tagQName()) // make sure the list types match (ol vs. ul) && firstList->hasEditableStyle() && secondList->hasEditableStyle() // both lists are editable - && firstList->rootEditableElement() == secondList->rootEditableElement() // don't cross editing boundaries + && rootEditableElement(*firstList) == rootEditableElement(*secondList) // don't cross editing boundaries && isVisiblyAdjacent(Position::inParentAfterNode(*firstList), Position::inParentBeforeNode(*secondList)); // Make sure there is no visible content between this li and the previous list } @@ -1416,7 +1416,7 @@ if (position.isNull()) return Position(); - Element* fromRootEditableElement = position.anchorNode()->rootEditableElement(); + Element* fromRootEditableElement = rootEditableElement(*position.anchorNode()); bool atStartOfLine = isStartOfLine(createVisiblePosition(position, affinity)); bool rendered = isVisuallyEquivalentCandidate(position); @@ -1428,7 +1428,7 @@ // |CodePoint|. currentPos = previousPositionOf(currentPos, PositionMoveType::CodeUnit); - if (currentPos.anchorNode()->rootEditableElement() != fromRootEditableElement) + if (rootEditableElement(*currentPos.anchorNode()) != fromRootEditableElement) return position; if (atStartOfLine || !rendered) {
diff --git a/third_party/WebKit/Source/core/editing/Editor.cpp b/third_party/WebKit/Source/core/editing/Editor.cpp index 46f0e4e9..a80cb34f 100644 --- a/third_party/WebKit/Source/core/editing/Editor.cpp +++ b/third_party/WebKit/Source/core/editing/Editor.cpp
@@ -311,7 +311,7 @@ VisiblePosition start = createVisiblePosition(range.startPosition()); VisiblePosition previous = previousPositionOf(start); // FIXME: We sometimes allow deletions at the start of editable roots, like when the caret is in an empty list item. - if (previous.isNull() || previous.deepEquivalent().anchorNode()->rootEditableElement() != startContainer->rootEditableElement()) + if (previous.isNull() || rootEditableElement(*previous.deepEquivalent().anchorNode()) != rootEditableElement(*startContainer)) return false; } return true; @@ -1378,6 +1378,9 @@ frame().selection().setShouldShowBlockCursor(m_overwriteModeEnabled); } +// TODO(tkent): This is a workaround of some crash bugs in the editing code, +// which assumes a document has a valid HTML structure. We should make the +// editing code more robust, and should remove this hack. crbug.com/580941. void Editor::tidyUpHTMLStructure(Document& document) { // hasEditableStyle() needs up-to-date ComputedStyle. @@ -1403,6 +1406,7 @@ // non-<html> root elements under <body>, and the <body> works as // rootEditableElement. document.addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, "document.execCommand() doesn't work with an invalid HTML structure. It is corrected automatically.")); + UseCounter::count(document, UseCounter::ExecCommandAltersHTMLStructure); Element* root = HTMLHtmlElement::create(document); if (existingHead)
diff --git a/third_party/WebKit/Source/core/editing/InputMethodController.cpp b/third_party/WebKit/Source/core/editing/InputMethodController.cpp index 0bd3b86d..695b8c39 100644 --- a/third_party/WebKit/Source/core/editing/InputMethodController.cpp +++ b/third_party/WebKit/Source/core/editing/InputMethodController.cpp
@@ -399,6 +399,10 @@ if (!rootEditableElement) return; + // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited. + // see http://crbug.com/590369 for more details. + rootEditableElement->document().updateStyleAndLayoutIgnorePendingStylesheets(); + // In case of exceeding the right boundary. // If both |value1| and |value2| exceed right boundary, // PlainTextRange(value1, value2)::createRange() will return a default @@ -436,6 +440,10 @@ if (!editable) return; + // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited. + // see http://crbug.com/590369 for more details. + editable->document().updateStyleAndLayoutIgnorePendingStylesheets(); + const EphemeralRange range = PlainTextRange(compositionStart, compositionEnd).createRange(*editable); if (range.isNull()) return; @@ -501,6 +509,10 @@ if (!rootEditableElement) return false; + // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited. + // see http://crbug.com/590369 for more details. + rootEditableElement->document().updateStyleAndLayoutIgnorePendingStylesheets(); + const EphemeralRange range = selectionOffsets.createRange(*rootEditableElement); if (range.isNull()) return false;
diff --git a/third_party/WebKit/Source/core/editing/PlainTextRange.cpp b/third_party/WebKit/Source/core/editing/PlainTextRange.cpp index 553978d..adf72eb1 100644 --- a/third_party/WebKit/Source/core/editing/PlainTextRange.cpp +++ b/third_party/WebKit/Source/core/editing/PlainTextRange.cpp
@@ -83,10 +83,6 @@ behaviorFlags |= TextIteratorEmitsCharactersBetweenAllVisiblePositions; auto range = EphemeralRange::rangeOfContents(scope); - // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited. - // see http://crbug.com/590369 for more details. - scope.document().updateStyleAndLayoutIgnorePendingStylesheets(); - TextIterator it(range.startPosition(), range.endPosition(), behaviorFlags); // FIXME: the atEnd() check shouldn't be necessary, workaround for
diff --git a/third_party/WebKit/Source/core/editing/SelectionController.cpp b/third_party/WebKit/Source/core/editing/SelectionController.cpp index f29f07d..c6fe984 100644 --- a/third_party/WebKit/Source/core/editing/SelectionController.cpp +++ b/third_party/WebKit/Source/core/editing/SelectionController.cpp
@@ -87,6 +87,10 @@ Node* rootUserSelectAll = EditingInFlatTreeStrategy::rootUserSelectAllForNode(targetNode); if (!rootUserSelectAll) return selection; + if (rootUserSelectAll->isHTMLElement() && toHTMLElement(rootUserSelectAll)->isTextFormControl()) + return selection; + if (rootUserSelectAll->layoutObject()->style()->userModify() != READ_ONLY) + return selection; VisibleSelectionInFlatTree newSelection(selection); newSelection.setBase(mostBackwardCaretPosition(PositionInFlatTree::beforeNode(rootUserSelectAll), CanCrossEditingBoundary));
diff --git a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp index 6bc2b81..5684cc4 100644 --- a/third_party/WebKit/Source/core/editing/VisibleSelection.cpp +++ b/third_party/WebKit/Source/core/editing/VisibleSelection.cpp
@@ -588,7 +588,7 @@ { while (node) { if (node->hasEditableStyle()) - return node->rootEditableElement(); + return rootEditableElement(*node); if (isHTMLBodyElement(*node)) break; node = node->parentNode();
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp index 797c2e75..ddeb9512 100644 --- a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp +++ b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
@@ -1336,7 +1336,7 @@ // Could not find a previous line. This means we must already be on the first line. // Move to the start of the content in this block, which effectively moves us // to the start of the line we're on. - Element* rootElement = node->hasEditableStyle(editableType) ? node->rootEditableElement(editableType) : node->document().documentElement(); + Element* rootElement = node->hasEditableStyle(editableType) ? rootEditableElement(*node, editableType) : node->document().documentElement(); if (!rootElement) return VisiblePosition(); return VisiblePosition::firstPositionInNode(rootElement); @@ -1392,7 +1392,7 @@ // Could not find a next line. This means we must already be on the last line. // Move to the end of the content in this block, which effectively moves us // to the end of the line we're on. - Element* rootElement = node->hasEditableStyle(editableType) ? node->rootEditableElement(editableType) : node->document().documentElement(); + Element* rootElement = node->hasEditableStyle(editableType) ? rootEditableElement(*node, editableType) : node->document().documentElement(); if (!rootElement) return VisiblePosition(); return VisiblePosition::lastPositionInNode(rootElement);
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp index a298222..26702c8 100644 --- a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
@@ -302,6 +302,11 @@ nextParagraphStart = nextPositionOf(endOfParagraph(paragraphStart)); } + // Update style and layout again, since added or removed styles could have + // affected the layout. We need clean layout in order to compute + // plain-text ranges below. + document().updateStyleAndLayoutIgnorePendingStylesheets(); + EphemeralRange startEphemeralRange = PlainTextRange(startIndex).createRangeForSelection(toContainerNode(scope)); if (startEphemeralRange.isNull()) return; @@ -763,7 +768,7 @@ // e.g. When applying font-size: large on <font color="blue">hello</font>, we need to include the font element in our run // to generate <font color="blue" size="4">hello</font> instead of <font color="blue"><font size="4">hello</font></font> Range* range = Range::create(startNode->document(), start, end); - Element* editableRoot = startNode->rootEditableElement(); + Element* editableRoot = rootEditableElement(*startNode); if (startNode != editableRoot) { while (editableRoot && startNode->parentNode() != editableRoot && isNodeVisiblyContainedWithin(*startNode->parentNode(), *range)) startNode = startNode->parentNode();
diff --git a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp index ae58cce..b074fa8c 100644 --- a/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/CompositeEditCommand.cpp
@@ -1065,7 +1065,7 @@ Node* lastNode = nullptr; Node* outerNode = passedOuterNode; - if (outerNode->isRootEditableElement()) { + if (isRootEditableElement(*outerNode)) { lastNode = blockElement; } else { lastNode = outerNode->cloneNode(isDisplayInsideTable(outerNode)); @@ -1365,6 +1365,10 @@ Element* documentElement = document().documentElement(); if (!documentElement) return; + + // We need clean layout in order to compute plain-text ranges below. + document().updateStyleAndLayoutIgnorePendingStylesheets(); + // Fragment creation (using createMarkup) incorrectly uses regular spaces // instead of nbsps for some spaces that were rendered (11475), which causes // spaces to be collapsed during the move operation. This results in a call @@ -1394,7 +1398,7 @@ if (!listNode || (!isHTMLUListElement(*listNode) && !isHTMLOListElement(*listNode)) || !listNode->hasEditableStyle() - || listNode == emptyListItem->rootEditableElement()) + || listNode == rootEditableElement(*emptyListItem)) return false; HTMLElement* newBlock = nullptr;
diff --git a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp index 075873b..f632afe 100644 --- a/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/DeleteSelectionCommand.cpp
@@ -369,7 +369,7 @@ } } - if (isTableStructureNode(node) || node->isRootEditableElement()) { + if (isTableStructureNode(node) || isRootEditableElement(*node)) { // Do not remove an element of table structure; remove its contents. // Likewise for the root editable element. Node* child = node->firstChild(); @@ -441,12 +441,12 @@ Node* nextNode = NodeTraversal::next(*node); if (isHTMLStyleElement(*node) || isHTMLLinkElement(*node)) { nextNode = NodeTraversal::nextSkippingChildren(*node); - Element* rootEditableElement = node->rootEditableElement(); - if (rootEditableElement) { + Element* element = rootEditableElement(*node); + if (element) { removeNode(node, editingState); if (editingState->isAborted()) return; - appendNode(node, rootEditableElement, editingState); + appendNode(node, element, editingState); if (editingState->isAborted()) return; } @@ -809,7 +809,7 @@ void DeleteSelectionCommand::removeRedundantBlocks(EditingState* editingState) { Node* node = m_endingPosition.computeContainerNode(); - Element* rootElement = node->rootEditableElement(); + Element* rootElement = rootEditableElement(*node); while (node != rootElement) { if (isRemovableBlock(node)) { @@ -840,8 +840,8 @@ TextAffinity affinity = m_selectionToDelete.affinity(); Position downstreamEnd = mostForwardCaretPosition(m_selectionToDelete.end()); - bool rootWillStayOpenWithoutPlaceholder = downstreamEnd.computeContainerNode() == downstreamEnd.computeContainerNode()->rootEditableElement() - || (downstreamEnd.computeContainerNode()->isTextNode() && downstreamEnd.computeContainerNode()->parentNode() == downstreamEnd.computeContainerNode()->rootEditableElement()); + bool rootWillStayOpenWithoutPlaceholder = downstreamEnd.computeContainerNode() == rootEditableElement(*downstreamEnd.computeContainerNode()) + || (downstreamEnd.computeContainerNode()->isTextNode() && downstreamEnd.computeContainerNode()->parentNode() == rootEditableElement(*downstreamEnd.computeContainerNode())); bool lineBreakAtEndOfSelectionToDelete = lineBreakExistsAtVisiblePosition(m_selectionToDelete.visibleEnd()); m_needPlaceholder = !rootWillStayOpenWithoutPlaceholder && isStartOfParagraph(m_selectionToDelete.visibleStart(), CanCrossEditingBoundary)
diff --git a/third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp b/third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp index 131dbf6..44442099 100644 --- a/third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp
@@ -124,8 +124,8 @@ if (!commonAncestor) return 0; - Element* rootEditableElement = range->startContainer()->rootEditableElement(); - if (!rootEditableElement || commonAncestor->contains(rootEditableElement)) + Element* element = rootEditableElement(*range->startContainer()); + if (!element || commonAncestor->contains(element)) return 0; return commonAncestor->isElementNode() ? toElement(commonAncestor) : 0; @@ -133,31 +133,30 @@ bool isElementForFormatBlock(const QualifiedName& tagName) { - DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, blockTags, ()); - if (blockTags.isEmpty()) { - blockTags.add(addressTag); - blockTags.add(articleTag); - blockTags.add(asideTag); - blockTags.add(blockquoteTag); - blockTags.add(ddTag); - blockTags.add(divTag); - blockTags.add(dlTag); - blockTags.add(dtTag); - blockTags.add(footerTag); - blockTags.add(h1Tag); - blockTags.add(h2Tag); - blockTags.add(h3Tag); - blockTags.add(h4Tag); - blockTags.add(h5Tag); - blockTags.add(h6Tag); - blockTags.add(headerTag); - blockTags.add(hgroupTag); - blockTags.add(mainTag); - blockTags.add(navTag); - blockTags.add(pTag); - blockTags.add(preTag); - blockTags.add(sectionTag); - } + DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, blockTags, ({ + addressTag, + articleTag, + asideTag, + blockquoteTag, + ddTag, + divTag, + dlTag, + dtTag, + footerTag, + h1Tag, + h2Tag, + h3Tag, + h4Tag, + h5Tag, + h6Tag, + headerTag, + hgroupTag, + mainTag, + navTag, + pTag, + preTag, + sectionTag, + })); return blockTags.contains(tagName); }
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp index 9797b95..d9dc694 100644 --- a/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/InsertListCommand.cpp
@@ -187,6 +187,11 @@ if (!singleParagraphResult) break; if (endOfSelection.isNull() || endOfSelection.isOrphan() || startOfLastParagraph.isNull() || startOfLastParagraph.isOrphan()) { + + // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited. + // see http://crbug.com/590369 for more details. + document().updateStyleAndLayoutIgnorePendingStylesheets(); + endOfSelection = visiblePositionForIndex(indexForEndOfSelection, scopeForEndOfSelection); // If endOfSelection is null, then some contents have been deleted from the document. // This should never happen and if it did, exit early immediately because we've lost the loop invariant.
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp index ea6d016..01099906 100644 --- a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
@@ -218,7 +218,7 @@ // Create block to be inserted. Element* blockToInsert = nullptr; - if (startBlock->isRootEditableElement()) { + if (isRootEditableElement(*startBlock)) { blockToInsert = createDefaultParagraphElement(document()); nestNewBlock = true; } else if (shouldUseDefaultParagraphElement(startBlock)) {
diff --git a/third_party/WebKit/Source/core/editing/commands/RemoveFormatCommand.cpp b/third_party/WebKit/Source/core/editing/commands/RemoveFormatCommand.cpp index a86ae4e..fb81be6 100644 --- a/third_party/WebKit/Source/core/editing/commands/RemoveFormatCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/RemoveFormatCommand.cpp
@@ -47,33 +47,32 @@ static bool isElementForRemoveFormatCommand(const Element* element) { - DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, elements, ()); - if (elements.isEmpty()) { - elements.add(acronymTag); - elements.add(bTag); - elements.add(bdoTag); - elements.add(bigTag); - elements.add(citeTag); - elements.add(codeTag); - elements.add(dfnTag); - elements.add(emTag); - elements.add(fontTag); - elements.add(iTag); - elements.add(insTag); - elements.add(kbdTag); - elements.add(nobrTag); - elements.add(qTag); - elements.add(sTag); - elements.add(sampTag); - elements.add(smallTag); - elements.add(strikeTag); - elements.add(strongTag); - elements.add(subTag); - elements.add(supTag); - elements.add(ttTag); - elements.add(uTag); - elements.add(varTag); - } + DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, elements, ({ + acronymTag, + bTag, + bdoTag, + bigTag, + citeTag, + codeTag, + dfnTag, + emTag, + fontTag, + iTag, + insTag, + kbdTag, + nobrTag, + qTag, + sTag, + sampTag, + smallTag, + strikeTag, + strongTag, + subTag, + supTag, + ttTag, + uTag, + varTag, + })); return elements.contains(element->tagQName()); }
diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp index 2e6cbfa2..73649d9d 100644 --- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
@@ -613,57 +613,56 @@ static bool isProhibitedParagraphChild(const AtomicString& name) { // https://dvcs.w3.org/hg/editing/raw-file/57abe6d3cb60/editing.html#prohibited-paragraph-child - DEFINE_STATIC_LOCAL(HashSet<AtomicString>, elements, ()); - if (elements.isEmpty()) { - elements.add(addressTag.localName()); - elements.add(articleTag.localName()); - elements.add(asideTag.localName()); - elements.add(blockquoteTag.localName()); - elements.add(captionTag.localName()); - elements.add(centerTag.localName()); - elements.add(colTag.localName()); - elements.add(colgroupTag.localName()); - elements.add(ddTag.localName()); - elements.add(detailsTag.localName()); - elements.add(dirTag.localName()); - elements.add(divTag.localName()); - elements.add(dlTag.localName()); - elements.add(dtTag.localName()); - elements.add(fieldsetTag.localName()); - elements.add(figcaptionTag.localName()); - elements.add(figureTag.localName()); - elements.add(footerTag.localName()); - elements.add(formTag.localName()); - elements.add(h1Tag.localName()); - elements.add(h2Tag.localName()); - elements.add(h3Tag.localName()); - elements.add(h4Tag.localName()); - elements.add(h5Tag.localName()); - elements.add(h6Tag.localName()); - elements.add(headerTag.localName()); - elements.add(hgroupTag.localName()); - elements.add(hrTag.localName()); - elements.add(liTag.localName()); - elements.add(listingTag.localName()); - elements.add(mainTag.localName()); // Missing in the specification. - elements.add(menuTag.localName()); - elements.add(navTag.localName()); - elements.add(olTag.localName()); - elements.add(pTag.localName()); - elements.add(plaintextTag.localName()); - elements.add(preTag.localName()); - elements.add(sectionTag.localName()); - elements.add(summaryTag.localName()); - elements.add(tableTag.localName()); - elements.add(tbodyTag.localName()); - elements.add(tdTag.localName()); - elements.add(tfootTag.localName()); - elements.add(thTag.localName()); - elements.add(theadTag.localName()); - elements.add(trTag.localName()); - elements.add(ulTag.localName()); - elements.add(xmpTag.localName()); - } + DEFINE_STATIC_LOCAL(HashSet<AtomicString>, elements, ({ + addressTag.localName(), + articleTag.localName(), + asideTag.localName(), + blockquoteTag.localName(), + captionTag.localName(), + centerTag.localName(), + colTag.localName(), + colgroupTag.localName(), + ddTag.localName(), + detailsTag.localName(), + dirTag.localName(), + divTag.localName(), + dlTag.localName(), + dtTag.localName(), + fieldsetTag.localName(), + figcaptionTag.localName(), + figureTag.localName(), + footerTag.localName(), + formTag.localName(), + h1Tag.localName(), + h2Tag.localName(), + h3Tag.localName(), + h4Tag.localName(), + h5Tag.localName(), + h6Tag.localName(), + headerTag.localName(), + hgroupTag.localName(), + hrTag.localName(), + liTag.localName(), + listingTag.localName(), + mainTag.localName(), // Missing in the specification. + menuTag.localName(), + navTag.localName(), + olTag.localName(), + pTag.localName(), + plaintextTag.localName(), + preTag.localName(), + sectionTag.localName(), + summaryTag.localName(), + tableTag.localName(), + tbodyTag.localName(), + tdTag.localName(), + tfootTag.localName(), + thTag.localName(), + theadTag.localName(), + trTag.localName(), + ulTag.localName(), + xmpTag.localName(), + })); return elements.contains(name); }
diff --git a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp index 8e56bf043..fbd532e7 100644 --- a/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/TypingCommand.cpp
@@ -147,10 +147,10 @@ String newText = text; if (Node* startNode = selectionForInsertion.start().computeContainerNode()) { - if (startNode->rootEditableElement()) { + if (rootEditableElement(*startNode)) { // Send BeforeTextInsertedEvent. The event handler will update text if necessary. BeforeTextInsertedEvent* evt = BeforeTextInsertedEvent::create(text); - startNode->rootEditableElement()->dispatchEvent(evt); + rootEditableElement(*startNode)->dispatchEvent(evt); newText = evt->text(); } }
diff --git a/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.cpp b/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.cpp index 0efee04..0bf8481 100644 --- a/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.cpp +++ b/third_party/WebKit/Source/core/editing/spellcheck/SpellCheckRequester.cpp
@@ -47,7 +47,7 @@ : m_requester(nullptr) , m_checkingRange(checkingRange) , m_paragraphRange(paragraphRange) - , m_rootEditableElement(m_checkingRange->startContainer()->rootEditableElement()) + , m_rootEditableElement(blink::rootEditableElement(*m_checkingRange->startContainer())) , m_requestData(unrequestedTextCheckingSequence, text, mask, processType, documentMarkersInRange, documentMarkerOffsets) , m_requestNumber(requestNumber) { @@ -84,7 +84,7 @@ { if (checkingRange.isNull()) return nullptr; - if (!checkingRange.startPosition().computeContainerNode()->rootEditableElement()) + if (!blink::rootEditableElement(*checkingRange.startPosition().computeContainerNode())) return nullptr; String text = plainText(checkingRange, TextIteratorEmitsObjectReplacementCharacter);
diff --git a/third_party/WebKit/Source/core/events/EventAliases.in b/third_party/WebKit/Source/core/events/EventAliases.in index 7e9078b..6b7c454 100644 --- a/third_party/WebKit/Source/core/events/EventAliases.in +++ b/third_party/WebKit/Source/core/events/EventAliases.in
@@ -7,7 +7,6 @@ MutationEvents ImplementedAs=MutationEvent OrientationEvent ImplementedAs=Event, RuntimeEnabled=OrientationEventEnabled SVGEvents ImplementedAs=Event -SVGZoomEvents ImplementedAs=SVGZoomEvent UIEvents ImplementedAs=UIEvent WebKitTransitionEvent ImplementedAs=TransitionEvent
diff --git a/third_party/WebKit/Source/core/fetch/CrossOriginAccessControl.cpp b/third_party/WebKit/Source/core/fetch/CrossOriginAccessControl.cpp index dcb52929..77f5867 100644 --- a/third_party/WebKit/Source/core/fetch/CrossOriginAccessControl.cpp +++ b/third_party/WebKit/Source/core/fetch/CrossOriginAccessControl.cpp
@@ -43,24 +43,16 @@ namespace blink { -static std::unique_ptr<HTTPHeaderSet> createAllowedCrossOriginResponseHeadersSet() -{ - std::unique_ptr<HTTPHeaderSet> headerSet = wrapUnique(new HashSet<String, CaseFoldingHash>); - - headerSet->add("cache-control"); - headerSet->add("content-language"); - headerSet->add("content-type"); - headerSet->add("expires"); - headerSet->add("last-modified"); - headerSet->add("pragma"); - - return headerSet; -} - bool isOnAccessControlResponseHeaderWhitelist(const String& name) { - DEFINE_THREAD_SAFE_STATIC_LOCAL(HTTPHeaderSet, allowedCrossOriginResponseHeaders, (createAllowedCrossOriginResponseHeadersSet().release())); - + DEFINE_THREAD_SAFE_STATIC_LOCAL(HTTPHeaderSet, allowedCrossOriginResponseHeaders, (new HTTPHeaderSet({ + "cache-control", + "content-language", + "content-type", + "expires", + "last-modified", + "pragma", + }))); return allowedCrossOriginResponseHeaders.contains(name); }
diff --git a/third_party/WebKit/Source/core/fetch/FetchContext.cpp b/third_party/WebKit/Source/core/fetch/FetchContext.cpp index ca03599..5429ade 100644 --- a/third_party/WebKit/Source/core/fetch/FetchContext.cpp +++ b/third_party/WebKit/Source/core/fetch/FetchContext.cpp
@@ -47,10 +47,6 @@ { } -void FetchContext::setFirstPartyForCookies(ResourceRequest&) -{ -} - CachePolicy FetchContext::getCachePolicy() const { return CachePolicyVerify; @@ -121,4 +117,8 @@ { } +void FetchContext::populateRequestData(ResourceRequest&) +{ +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/fetch/FetchContext.h b/third_party/WebKit/Source/core/fetch/FetchContext.h index 7a8400f..b3de9b7b 100644 --- a/third_party/WebKit/Source/core/fetch/FetchContext.h +++ b/third_party/WebKit/Source/core/fetch/FetchContext.h
@@ -71,7 +71,6 @@ virtual void countClientHintsViewportWidth() { } virtual void addAdditionalRequestHeaders(ResourceRequest&, FetchResourceType); - virtual void setFirstPartyForCookies(ResourceRequest&); virtual CachePolicy getCachePolicy() const; virtual WebCachePolicy resourceRequestCachePolicy(const ResourceRequest&, Resource::Type, FetchRequest::DeferOption) const; @@ -107,6 +106,7 @@ virtual void upgradeInsecureRequest(ResourceRequest&); virtual void addClientHintsIfNecessary(FetchRequest&); virtual void addCSPHeaderIfNecessary(Resource::Type, FetchRequest&); + virtual void populateRequestData(ResourceRequest&); virtual MHTMLArchive* archive() const { return nullptr; }
diff --git a/third_party/WebKit/Source/core/fetch/FetchUtils.cpp b/third_party/WebKit/Source/core/fetch/FetchUtils.cpp index ef2c8848..d199685 100644 --- a/third_party/WebKit/Source/core/fetch/FetchUtils.cpp +++ b/third_party/WebKit/Source/core/fetch/FetchUtils.cpp
@@ -45,27 +45,29 @@ : m_proxyHeaderPrefix("proxy-") , m_secHeaderPrefix("sec-") { - m_fixedNames.add("accept-charset"); - m_fixedNames.add("accept-encoding"); - m_fixedNames.add("access-control-request-headers"); - m_fixedNames.add("access-control-request-method"); - m_fixedNames.add("connection"); - m_fixedNames.add("content-length"); - m_fixedNames.add("cookie"); - m_fixedNames.add("cookie2"); - m_fixedNames.add("date"); - m_fixedNames.add("dnt"); - m_fixedNames.add("expect"); - m_fixedNames.add("host"); - m_fixedNames.add("keep-alive"); - m_fixedNames.add("origin"); - m_fixedNames.add("referer"); - m_fixedNames.add("te"); - m_fixedNames.add("trailer"); - m_fixedNames.add("transfer-encoding"); - m_fixedNames.add("upgrade"); - m_fixedNames.add("user-agent"); - m_fixedNames.add("via"); + m_fixedNames = { + "accept-charset", + "accept-encoding", + "access-control-request-headers", + "access-control-request-method", + "connection", + "content-length", + "cookie", + "cookie2", + "date", + "dnt", + "expect", + "host", + "keep-alive", + "origin", + "referer", + "te", + "trailer", + "transfer-encoding", + "upgrade", + "user-agent", + "via", + }; } const ForbiddenHeaderNames& ForbiddenHeaderNames::get()
diff --git a/third_party/WebKit/Source/core/fetch/ImageResource.cpp b/third_party/WebKit/Source/core/fetch/ImageResource.cpp index c10b9a96..908f97b 100644 --- a/third_party/WebKit/Source/core/fetch/ImageResource.cpp +++ b/third_party/WebKit/Source/core/fetch/ImageResource.cpp
@@ -115,6 +115,20 @@ Resource::markClientsAndObserversFinished(); } +void ImageResource::ensureImage() +{ + if (m_data && !m_image && !errorOccurred()) { + createImage(); + m_image->setData(m_data, true); + } +} + +void ImageResource::didAddClient(ResourceClient* client) +{ + ensureImage(); + Resource::didAddClient(client); +} + void ImageResource::addObserver(ImageResourceObserver* observer) { willAddClientOrObserver(); @@ -124,10 +138,7 @@ if (isCacheValidator()) return; - if (m_data && !m_image && !errorOccurred()) { - createImage(); - m_image->setData(m_data, true); - } + ensureImage(); if (m_image && !m_image->isNull()) { observer->imageChanged(this); @@ -511,14 +522,17 @@ void ImageResource::reloadIfLoFi(ResourceFetcher* fetcher) { - if (!m_response.httpHeaderField("chrome-proxy").contains("q=low")) + if (m_resourceRequest.loFiState() != WebURLRequest::LoFiOn) + return; + if (isLoaded() && !m_response.httpHeaderField("chrome-proxy").contains("q=low")) return; m_resourceRequest.setCachePolicy(WebCachePolicy::BypassingCache); m_resourceRequest.setLoFiState(WebURLRequest::LoFiOff); if (isLoading()) m_loader->cancel(); - else - updateImageAndClearBuffer(); + clear(); + m_data.clear(); + notifyObservers(); setStatus(NotStarted); fetcher->startLoad(this); }
diff --git a/third_party/WebKit/Source/core/fetch/ImageResource.h b/third_party/WebKit/Source/core/fetch/ImageResource.h index da0995f..55e869f 100644 --- a/third_party/WebKit/Source/core/fetch/ImageResource.h +++ b/third_party/WebKit/Source/core/fetch/ImageResource.h
@@ -91,6 +91,8 @@ // the Lo-Fi state set to off and bypassing the cache. void reloadIfLoFi(ResourceFetcher*); + void didAddClient(ResourceClient*) override; + void addObserver(ImageResourceObserver*); void removeObserver(ImageResourceObserver*); bool hasClientsOrObservers() const override { return Resource::hasClientsOrObservers() || !m_observers.isEmpty() || !m_finishedObservers.isEmpty(); } @@ -158,6 +160,8 @@ // If not null, changeRect is the changed part of the image. void notifyObservers(const IntRect* changeRect = nullptr); + void ensureImage(); + void checkNotify() override; void markClientsAndObserversFinished() override;
diff --git a/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp b/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp index daf35bd..6fb9c90 100644 --- a/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp +++ b/third_party/WebKit/Source/core/fetch/ImageResourceTest.cpp
@@ -334,7 +334,9 @@ { KURL testURL(ParsedURLString, "http://www.test.com/cancelTest.html"); URLTestHelpers::registerMockedURLLoad(testURL, "cancelTest.html", "text/html"); - ImageResource* cachedImage = ImageResource::create(ResourceRequest(testURL)); + ResourceRequest request = ResourceRequest(testURL); + request.setLoFiState(WebURLRequest::LoFiOn); + ImageResource* cachedImage = ImageResource::create(request); cachedImage->setStatus(Resource::Pending); Persistent<MockImageResourceClient> client = new MockImageResourceClient(cachedImage); @@ -354,21 +356,26 @@ ASSERT_EQ(client->imageChangedCount(), 2); ASSERT_TRUE(client->notifyFinishedCalled()); ASSERT_TRUE(cachedImage->getImage()->isBitmapImage()); + EXPECT_EQ(1, cachedImage->getImage()->width()); + EXPECT_EQ(1, cachedImage->getImage()->height()); cachedImage->reloadIfLoFi(fetcher); ASSERT_FALSE(cachedImage->errorOccurred()); ASSERT_FALSE(cachedImage->resourceBuffer()); - ASSERT_TRUE(cachedImage->hasImage()); + ASSERT_FALSE(cachedImage->hasImage()); ASSERT_EQ(client->imageChangedCount(), 3); + Vector<unsigned char> jpeg2 = jpegImage2(); cachedImage->loader()->didReceiveResponse(nullptr, WrappedResourceResponse(resourceResponse), nullptr); - cachedImage->loader()->didReceiveData(nullptr, reinterpret_cast<const char*>(jpeg.data()), jpeg.size(), jpeg.size()); - cachedImage->loader()->didFinishLoading(nullptr, 0.0, jpeg.size()); + cachedImage->loader()->didReceiveData(nullptr, reinterpret_cast<const char*>(jpeg2.data()), jpeg2.size(), jpeg2.size()); + cachedImage->loader()->didFinishLoading(nullptr, 0.0, jpeg2.size()); ASSERT_FALSE(cachedImage->errorOccurred()); ASSERT_TRUE(cachedImage->hasImage()); ASSERT_FALSE(cachedImage->getImage()->isNull()); ASSERT_TRUE(client->notifyFinishedCalled()); ASSERT_TRUE(cachedImage->getImage()->isBitmapImage()); + EXPECT_EQ(50, cachedImage->getImage()->width()); + EXPECT_EQ(50, cachedImage->getImage()->height()); } TEST(ImageResourceTest, SVGImage) @@ -574,4 +581,41 @@ EXPECT_EQ(300, imageResource->getImage()->height()); } +// Tests for pruning. + +TEST(ImageResourceTest, AddClientAfterPrune) +{ + KURL url(ParsedURLString, "http://127.0.0.1:8000/foo"); + ImageResource* imageResource = ImageResource::create(ResourceRequest(url)); + + // Adds a ResourceClient but not ImageResourceObserver. + Persistent<MockResourceClient> client1 = new MockResourceClient(imageResource); + + receiveResponse(imageResource, url, "image/jpeg", jpegImage()); + + EXPECT_FALSE(imageResource->errorOccurred()); + ASSERT_TRUE(imageResource->hasImage()); + EXPECT_FALSE(imageResource->getImage()->isNull()); + EXPECT_EQ(1, imageResource->getImage()->width()); + EXPECT_EQ(1, imageResource->getImage()->height()); + EXPECT_TRUE(client1->notifyFinishedCalled()); + + client1->removeAsClient(); + + EXPECT_FALSE(imageResource->hasClientsOrObservers()); + + imageResource->prune(); + + EXPECT_FALSE(imageResource->hasImage()); + + // Re-adds a ResourceClient but not ImageResourceObserver. + Persistent<MockResourceClient> client2 = new MockResourceClient(imageResource); + + ASSERT_TRUE(imageResource->hasImage()); + EXPECT_FALSE(imageResource->getImage()->isNull()); + EXPECT_EQ(1, imageResource->getImage()->width()); + EXPECT_EQ(1, imageResource->getImage()->height()); + EXPECT_TRUE(client2->notifyFinishedCalled()); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/fetch/RawResource.cpp b/third_party/WebKit/Source/core/fetch/RawResource.cpp index d6cfe576..94989229 100644 --- a/third_party/WebKit/Source/core/fetch/RawResource.cpp +++ b/third_party/WebKit/Source/core/fetch/RawResource.cpp
@@ -205,19 +205,18 @@ static bool shouldIgnoreHeaderForCacheReuse(AtomicString headerName) { // FIXME: This list of headers that don't affect cache policy almost certainly isn't complete. - DEFINE_STATIC_LOCAL(HashSet<AtomicString>, m_headers, ()); - if (m_headers.isEmpty()) { - m_headers.add("Cache-Control"); - m_headers.add("If-Modified-Since"); - m_headers.add("If-None-Match"); - m_headers.add("Origin"); - m_headers.add("Pragma"); - m_headers.add("Purpose"); - m_headers.add("Referer"); - m_headers.add("User-Agent"); - m_headers.add(HTTPNames::X_DevTools_Emulate_Network_Conditions_Client_Id); - } - return m_headers.contains(headerName); + DEFINE_STATIC_LOCAL(HashSet<AtomicString>, headers, ({ + "Cache-Control", + "If-Modified-Since", + "If-None-Match", + "Origin", + "Pragma", + "Purpose", + "Referer", + "User-Agent", + HTTPNames::X_DevTools_Emulate_Network_Conditions_Client_Id, + })); + return headers.contains(headerName); } static bool isCacheableHTTPMethod(const AtomicString& method)
diff --git a/third_party/WebKit/Source/core/fetch/Resource.cpp b/third_party/WebKit/Source/core/fetch/Resource.cpp index 20b69e38..4a0065a8 100644 --- a/third_party/WebKit/Source/core/fetch/Resource.cpp +++ b/third_party/WebKit/Source/core/fetch/Resource.cpp
@@ -618,7 +618,7 @@ builder.append(", Finished="); builder.appendNumber(m_finishedClients.size()); } - builder.append(")"); + builder.append(')'); } if (m_loader) { if (!builder.isEmpty()) @@ -630,7 +630,7 @@ builder.append(' '); builder.append("m_preloadCount("); builder.appendNumber(m_preloadCount); - builder.append(")"); + builder.append(')'); } if (memoryCache()->contains(this)) { if (!builder.isEmpty())
diff --git a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp index 125574198..57a9738 100644 --- a/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp +++ b/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp
@@ -410,6 +410,7 @@ { ASSERT(request.options().synchronousPolicy == RequestAsynchronously || factory.type() == Resource::Raw || factory.type() == Resource::XSLStyleSheet); + context().populateRequestData(request.mutableResourceRequest()); if (request.resourceRequest().httpHeaderField("Upgrade-Insecure-Requests") != AtomicString("1")) context().upgradeInsecureRequest(request.mutableResourceRequest()); context().addClientHintsIfNecessary(request);
diff --git a/third_party/WebKit/Source/core/fileapi/File.idl b/third_party/WebKit/Source/core/fileapi/File.idl index 69c41cf0..8277597 100644 --- a/third_party/WebKit/Source/core/fileapi/File.idl +++ b/third_party/WebKit/Source/core/fileapi/File.idl
@@ -25,7 +25,6 @@ // https://w3c.github.io/FileAPI/#file -typedef (ArrayBuffer or ArrayBufferView or Blob or USVString) BlobPart; [ // TODO(jsbell): fileName parameter has [EnsureUTF16] in the spec; use // USVString? https://github.com/w3c/FileAPI/issues/9
diff --git a/third_party/WebKit/Source/core/fileapi/FileReader.cpp b/third_party/WebKit/Source/core/fileapi/FileReader.cpp index 648352e..f1d3237 100644 --- a/third_party/WebKit/Source/core/fileapi/FileReader.cpp +++ b/third_party/WebKit/Source/core/fileapi/FileReader.cpp
@@ -45,6 +45,7 @@ #include "wtf/CurrentTime.h" #include "wtf/Deque.h" #include "wtf/HashSet.h" +#include "wtf/TemporaryChange.h" #include "wtf/text/CString.h" namespace blink { @@ -199,6 +200,7 @@ , ActiveDOMObject(context) , m_state(EMPTY) , m_loadingState(LoadingStateNone) + , m_stillFiringEvents(false) , m_readType(FileReaderLoader::ReadAsBinaryString) , m_lastProgressNotificationTimeMS(0) { @@ -227,7 +229,7 @@ bool FileReader::hasPendingActivity() const { - return m_state == LOADING; + return m_state == LOADING || m_stillFiringEvents; } void FileReader::readAsArrayBuffer(Blob* blob, ExceptionState& exceptionState) @@ -341,6 +343,7 @@ void FileReader::doAbort() { ASSERT(m_state != DONE); + TemporaryChange<bool> firingEvents(m_stillFiringEvents, true); terminate(); @@ -380,6 +383,7 @@ void FileReader::didStartLoading() { + TemporaryChange<bool> firingEvents(m_stillFiringEvents, true); fireEvent(EventTypeNames::loadstart); } @@ -390,6 +394,7 @@ if (!m_lastProgressNotificationTimeMS) { m_lastProgressNotificationTimeMS = now; } else if (now - m_lastProgressNotificationTimeMS > progressNotificationIntervalMS) { + TemporaryChange<bool> firingEvents(m_stillFiringEvents, true); fireEvent(EventTypeNames::progress); m_lastProgressNotificationTimeMS = now; } @@ -401,6 +406,13 @@ return; ASSERT(m_loadingState == LoadingStateLoading); + // TODO(jochen): When we set m_state to DONE below, we still need to fire + // the load and loadend events. To avoid GC to collect this FileReader, we + // use this separate variable to keep the wrapper of this FileReader alive. + // An alternative would be to keep any active DOM object alive that is on + // the stack. + TemporaryChange<bool> firingEvents(m_stillFiringEvents, true); + // It's important that we change m_loadingState before firing any events // since any of the events could call abort(), which internally checks // if we're still loading (therefore we need abort process) or not. @@ -425,6 +437,9 @@ { if (m_loadingState == LoadingStateAborted) return; + + TemporaryChange<bool> firingEvents(m_stillFiringEvents, true); + ASSERT(m_loadingState == LoadingStateLoading); m_loadingState = LoadingStateNone;
diff --git a/third_party/WebKit/Source/core/fileapi/FileReader.h b/third_party/WebKit/Source/core/fileapi/FileReader.h index de7bee0d..d960570c 100644 --- a/third_party/WebKit/Source/core/fileapi/FileReader.h +++ b/third_party/WebKit/Source/core/fileapi/FileReader.h
@@ -123,6 +123,7 @@ LoadingStateAborted }; LoadingState m_loadingState; + bool m_stillFiringEvents; String m_blobType; RefPtr<BlobDataHandle> m_blobDataHandle;
diff --git a/third_party/WebKit/Source/core/frame/DOMWindowProperty.cpp b/third_party/WebKit/Source/core/frame/DOMWindowProperty.cpp index 6fc921d..9133780 100644 --- a/third_party/WebKit/Source/core/frame/DOMWindowProperty.cpp +++ b/third_party/WebKit/Source/core/frame/DOMWindowProperty.cpp
@@ -52,13 +52,6 @@ m_frame = nullptr; } -void DOMWindowProperty::willDetachGlobalObjectFromFrame() -{ - // If the property is getting this callback it must have been - // created with a LocalFrame and it should still have it. - ASSERT(m_frame); -} - DEFINE_TRACE(DOMWindowProperty) { visitor->trace(m_frame);
diff --git a/third_party/WebKit/Source/core/frame/DOMWindowProperty.h b/third_party/WebKit/Source/core/frame/DOMWindowProperty.h index e7e71459..b24b51d 100644 --- a/third_party/WebKit/Source/core/frame/DOMWindowProperty.h +++ b/third_party/WebKit/Source/core/frame/DOMWindowProperty.h
@@ -39,7 +39,6 @@ explicit DOMWindowProperty(LocalFrame*); virtual void willDestroyGlobalObjectInFrame(); - virtual void willDetachGlobalObjectFromFrame(); LocalFrame* frame() const { return m_frame; }
diff --git a/third_party/WebKit/Source/core/frame/Deprecation.cpp b/third_party/WebKit/Source/core/frame/Deprecation.cpp index 424639e..33642f8 100644 --- a/third_party/WebKit/Source/core/frame/Deprecation.cpp +++ b/third_party/WebKit/Source/core/frame/Deprecation.cpp
@@ -180,7 +180,7 @@ return replacedBy("'console.markTimeline'", "'console.timeStamp'"); case UseCounter::FileError: - return "FileError is deprecated. Please use the 'name' or 'message' attributes of DOMError rather than 'code'."; + return String::format("'FileError is deprecated and will be removed in %s. Please use the 'name' or 'message' attributes of the error rather than 'code'. See https://www.chromestatus.com/features/6687420359639040 for more details.", milestoneString(54)); case UseCounter::CSSStyleSheetInsertRuleOptionalArg: return "Calling CSSStyleSheet.insertRule() with one argument is deprecated. Please pass the index argument as well: insertRule(x, 0)."; @@ -255,7 +255,7 @@ return "'getMatchedCSSRules()' is deprecated. For more help, check https://code.google.com/p/chromium/issues/detail?id=437569#c2"; case UseCounter::PrefixedImageSmoothingEnabled: - return replacedBy("'CanvasRenderingContext2D.webkitImageSmoothingEnabled'", "'CanvasRenderingContext2D.imageSmoothingEnabled'"); + return replacedWillBeRemoved("'CanvasRenderingContext2D.webkitImageSmoothingEnabled'", "'CanvasRenderingContext2D.imageSmoothingEnabled'", 55, "5639849247768576"); case UseCounter::AudioListenerDopplerFactor: return dopplerWillBeRemoved("'AudioListener.dopplerFactor'", 55, "5238926818148352"); @@ -343,12 +343,6 @@ case UseCounter::V8TouchEvent_InitTouchEvent_Method: return replacedWillBeRemoved("'TouchEvent.initTouchEvent'", "the TouchEvent constructor", 53, "5730982598541312"); - case UseCounter::ObjectObserve: - return willBeRemoved("'Object.observe'", 50, "6147094632988672"); - - case UseCounter::SVGZoomEvent: - return willBeRemoved("'SVGZoomEvent'", 52, "5760883808534528"); - case UseCounter::WebAnimationHyphenatedProperty: return "Hyphenated property names in Web Animations keyframes are invalid and therefore ignored. Please use camelCase instead.";
diff --git a/third_party/WebKit/Source/core/frame/Frame.cpp b/third_party/WebKit/Source/core/frame/Frame.cpp index 4a92e16..1c763fe 100644 --- a/third_party/WebKit/Source/core/frame/Frame.cpp +++ b/third_party/WebKit/Source/core/frame/Frame.cpp
@@ -78,17 +78,6 @@ m_host = nullptr; } -void Frame::detachChildren() -{ - typedef HeapVector<Member<Frame>> FrameVector; - FrameVector childrenToDetach; - childrenToDetach.reserveCapacity(tree().childCount()); - for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling()) - childrenToDetach.append(child); - for (const auto& child : childrenToDetach) - child->detach(FrameDetachType::Remove); -} - void Frame::disconnectOwnerElement() { if (m_owner) {
diff --git a/third_party/WebKit/Source/core/frame/Frame.h b/third_party/WebKit/Source/core/frame/Frame.h index 423e882..2fe7895 100644 --- a/third_party/WebKit/Source/core/frame/Frame.h +++ b/third_party/WebKit/Source/core/frame/Frame.h
@@ -81,7 +81,6 @@ virtual void reload(FrameLoadType, ClientRedirectPolicy) = 0; virtual void detach(FrameDetachType); - void detachChildren(); void disconnectOwnerElement(); virtual bool shouldClose() = 0;
diff --git a/third_party/WebKit/Source/core/frame/FrameConsole.cpp b/third_party/WebKit/Source/core/frame/FrameConsole.cpp index 99f33fe..ad42cc69 100644 --- a/third_party/WebKit/Source/core/frame/FrameConsole.cpp +++ b/third_party/WebKit/Source/core/frame/FrameConsole.cpp
@@ -31,7 +31,6 @@ #include "bindings/core/v8/SourceLocation.h" #include "core/frame/FrameHost.h" #include "core/inspector/ConsoleMessage.h" -#include "core/inspector/IdentifiersFactory.h" #include "core/inspector/MainThreadDebugger.h" #include "core/page/ChromeClient.h" #include "core/page/Page.h" @@ -58,18 +57,7 @@ // TODO(dgozman): drop this check, it's left here to preserve tests output. if (!m_frame->document()) return false; - MainThreadDebugger* debugger = MainThreadDebugger::instance(); - return debugger->debugger()->addConsoleMessage( - debugger->contextGroupId(m_frame), - consoleMessage->source(), - consoleMessage->level(), - consoleMessage->message(), - consoleMessage->location()->url(), - consoleMessage->location()->lineNumber(), - consoleMessage->location()->columnNumber(), - consoleMessage->location()->cloneStackTrace(), - consoleMessage->location()->scriptId(), - IdentifiersFactory::requestId(consoleMessage->requestIdentifier())); + return MainThreadDebugger::instance()->addConsoleMessage(m_frame, consoleMessage); } void FrameConsole::reportMessageToClient(ConsoleMessage* consoleMessage) @@ -95,14 +83,10 @@ frame().chromeClient().addMessageToConsole(m_frame, consoleMessage->source(), consoleMessage->level(), consoleMessage->message(), consoleMessage->location()->lineNumber(), url, stackTrace); } -void FrameConsole::reportWorkerMessage(ConsoleMessage* consoleMessage) +void FrameConsole::addMessageFromWorker(ConsoleMessage* consoleMessage, const String& workerId) { reportMessageToClient(consoleMessage); -} - -void FrameConsole::adoptWorkerMessage(ConsoleMessage* consoleMessage) -{ - addMessageToStorage(consoleMessage); + addMessageToStorage(ConsoleMessage::createFromWorker(consoleMessage->level(), consoleMessage->message(), consoleMessage->location() ? consoleMessage->location()->clone() : nullptr, workerId)); } void FrameConsole::reportResourceResponseReceived(DocumentLoader* loader, unsigned long requestIdentifier, const ResourceResponse& response)
diff --git a/third_party/WebKit/Source/core/frame/FrameConsole.h b/third_party/WebKit/Source/core/frame/FrameConsole.h index b345c332..7f305e4 100644 --- a/third_party/WebKit/Source/core/frame/FrameConsole.h +++ b/third_party/WebKit/Source/core/frame/FrameConsole.h
@@ -51,12 +51,11 @@ } void addMessage(ConsoleMessage*); + void addMessageFromWorker(ConsoleMessage*, const String& workerId); + bool addMessageToStorage(ConsoleMessage*); void reportMessageToClient(ConsoleMessage*); - void reportWorkerMessage(ConsoleMessage*); - void adoptWorkerMessage(ConsoleMessage*); - void reportResourceResponseReceived(DocumentLoader*, unsigned long requestIdentifier, const ResourceResponse&); void clearMessages();
diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp index e00f514..a62d1cd 100644 --- a/third_party/WebKit/Source/core/frame/FrameView.cpp +++ b/third_party/WebKit/Source/core/frame/FrameView.cpp
@@ -79,6 +79,7 @@ #include "core/page/FrameTree.h" #include "core/page/Page.h" #include "core/page/scrolling/ChildViewportScrollCallback.h" +#include "core/page/scrolling/RootScrollerController.h" #include "core/page/scrolling/RootViewportScrollCallback.h" #include "core/page/scrolling/ScrollingCoordinator.h" #include "core/paint/FramePainter.h" @@ -822,7 +823,7 @@ if (!m_scrollAnchor.hasScroller()) m_scrollAnchor.setScroller(m_viewportScrollableArea ? m_viewportScrollableArea : this); - if (RuntimeEnabledFeatures::scrollAnchoringEnabled()) + if (shouldPerformScrollAnchoring()) m_scrollAnchor.save(); } @@ -2121,7 +2122,7 @@ scrollToFragmentAnchor(); // TODO(skobes): Figure out interactions between scroll anchor, fragment anchor, and history restoration. - if (RuntimeEnabledFeatures::scrollAnchoringEnabled()) + if (shouldPerformScrollAnchoring()) m_scrollAnchor.restore(); sendResizeEventIfNeeded(); @@ -2518,6 +2519,9 @@ || targetState == DocumentLifecycle::PrePaintClean || targetState == DocumentLifecycle::PaintClean); + if (!m_frame->document()->isActive()) + return; + TemporaryChange<DocumentLifecycle::LifecycleState> targetStateScope(m_currentUpdateLifecyclePhasesTargetState, targetState); if (shouldThrottleRendering()) { @@ -2556,6 +2560,7 @@ if (view.compositor()->inCompositingMode()) scrollingCoordinator()->updateAfterCompositingChangeIfNeeded(); + m_frame->document()->rootScrollerController()->didUpdateCompositing(); updateCompositedSelectionIfNeeded(); } } @@ -2634,8 +2639,21 @@ void FrameView::synchronizedPaintRecursively(GraphicsLayer* graphicsLayer) { - if (graphicsLayer->drawsContent()) + if (graphicsLayer->drawsContent()) { + // Usually this is not needed because the PaintLayer will setup the chunk properties + // altogether. However in debug builds the GraphicsLayer could paint debug background before + // we ever reach the PaintLayer. + if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { + PaintChunkProperties properties; + properties.transform = m_rootTransform; + properties.clip = m_rootClip; + properties.effect = m_rootEffect; + graphicsLayer->getPaintController().updateCurrentPaintChunkProperties(properties); + } graphicsLayer->paint(nullptr); + if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) + graphicsLayer->getPaintController().updateCurrentPaintChunkProperties(PaintChunkProperties()); + } if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { if (GraphicsLayer* maskLayer = graphicsLayer->maskLayer()) @@ -2683,7 +2701,7 @@ void FrameView::updateStyleAndLayoutIfNeededRecursiveInternal() { - if (shouldThrottleRendering()) + if (shouldThrottleRendering() || !m_frame->document()->isActive()) return; ScopedFrameBlamer frameBlamer(m_frame); @@ -3155,7 +3173,7 @@ Page* page = frame().page(); if (!page || !page->settings().deviceSupportsMouse()) return; - page->chromeClient().setCursor(cursor, m_frame->localFrameRoot()); + page->chromeClient().setCursor(cursor, m_frame); } void FrameView::frameRectsChanged() @@ -4082,7 +4100,7 @@ return layoutViewItem.isNull() ? nullptr : layoutViewItem.getScrollableArea(); } -LayoutObject* FrameView::viewportLayoutObject() +LayoutObject* FrameView::viewportLayoutObject() const { if (Document* document = frame().document()) { if (Element* element = document->viewportDefiningElement()) @@ -4264,10 +4282,4 @@ return m_subtreeThrottled || (m_hiddenForThrottling && m_crossOriginForThrottling); } -LayoutBox& FrameView::boxForScrollControlPaintInvalidation() const -{ - ASSERT(!layoutViewItem().isNull()); - return *layoutView(); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/FrameView.h b/third_party/WebKit/Source/core/frame/FrameView.h index e9c1059..776e1b9f 100644 --- a/third_party/WebKit/Source/core/frame/FrameView.h +++ b/third_party/WebKit/Source/core/frame/FrameView.h
@@ -40,6 +40,7 @@ #include "platform/geometry/LayoutRect.h" #include "platform/graphics/Color.h" #include "platform/graphics/paint/ClipPaintPropertyNode.h" +#include "platform/graphics/paint/EffectPaintPropertyNode.h" #include "platform/graphics/paint/TransformPaintPropertyNode.h" #include "platform/scroll/ScrollTypes.h" #include "platform/scroll/Scrollbar.h" @@ -377,7 +378,6 @@ IntPoint maximumScrollPosition() const override; // ScrollableArea interface - void scrollControlWasSetNeedsPaintInvalidation() override { } void getTickmarks(Vector<IntRect>&) const override; IntRect scrollableAreaBoundingBox() const override; bool scrollAnimatorEnabled() const override; @@ -600,6 +600,15 @@ void setContentClip(PassRefPtr<ClipPaintPropertyNode> contentClip) { m_contentClip = contentClip; } ClipPaintPropertyNode* contentClip() const { return m_contentClip.get(); } + void setRootTransform(PassRefPtr<TransformPaintPropertyNode> rootTransform) { m_rootTransform = rootTransform; } + TransformPaintPropertyNode* rootTransform() const { return m_rootTransform.get(); } + + void setRootClip(PassRefPtr<ClipPaintPropertyNode> rootClip) { m_rootClip = rootClip; } + ClipPaintPropertyNode* rootClip() const { return m_rootClip.get(); } + + void setRootEffect(PassRefPtr<EffectPaintPropertyNode> rootEffect) { m_rootEffect = rootEffect; } + EffectPaintPropertyNode* rootEffect() const { return m_rootEffect.get(); } + // TODO(ojan): Merge this with IntersectionObserver once it lands. IntRect computeVisibleArea(); @@ -757,7 +766,7 @@ std::unique_ptr<TracedValue> analyzerCounters(); // LayoutObject for the viewport-defining element (see Document::viewportDefiningElement). - LayoutObject* viewportLayoutObject(); + LayoutObject* viewportLayoutObject() const; void collectAnnotatedRegions(LayoutObject&, Vector<AnnotatedRegionValue>&) const; @@ -770,7 +779,6 @@ void updateThrottlingStatus(); // PaintInvalidationCapableScrollableArea - LayoutBox& boxForScrollControlPaintInvalidation() const override; LayoutScrollbarPart* resizer() const override { return nullptr; } void checkLayoutInvalidationIsAllowed() const; @@ -910,6 +918,12 @@ // TODO(trchen): This will not be needed once settings->rootLayerScrolls() is enabled. RefPtr<ClipPaintPropertyNode> m_contentClip; + // These nodes represent the root nodes of each property tree. + // Only the root frame should create them and they will be no-op. + RefPtr<TransformPaintPropertyNode> m_rootTransform; + RefPtr<ClipPaintPropertyNode> m_rootClip; + RefPtr<EffectPaintPropertyNode> m_rootEffect; + // This is set on the local root frame view only. DocumentLifecycle::LifecycleState m_currentUpdateLifecyclePhasesTargetState;
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp index bbfdb511..70c27125 100644 --- a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp +++ b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp
@@ -20,6 +20,18 @@ static const char* imageOrientationFlipY = "flipY"; static const char* imageBitmapOptionNone = "none"; +namespace { + +struct ParsedOptions { + bool flipY = false; + bool premultiplyAlpha = true; + bool shouldScaleInput = false; + unsigned resizeWidth = 0; + unsigned resizeHeight = 0; + IntRect cropRect; + SkFilterQuality resizeQuality = kLow_SkFilterQuality; +}; + // The following two functions are helpers used in cropImage static inline IntRect normalizeRect(const IntRect& rect) { @@ -35,6 +47,61 @@ return frameBitmap.colorType() == kN32_SkColorType; } +ParsedOptions parseOptions(const ImageBitmapOptions& options, Optional<IntRect> cropRect, IntSize sourceSize) +{ + ParsedOptions parsedOptions; + if (options.imageOrientation() == imageOrientationFlipY) { + parsedOptions.flipY = true; + } else { + parsedOptions.flipY = false; + DCHECK(options.imageOrientation() == imageBitmapOptionNone); + } + if (options.premultiplyAlpha() == imageBitmapOptionNone) { + parsedOptions.premultiplyAlpha = false; + } else { + parsedOptions.premultiplyAlpha = true; + DCHECK(options.premultiplyAlpha() == "default" || options.premultiplyAlpha() == "premultiply"); + } + + int sourceWidth = sourceSize.width(); + int sourceHeight = sourceSize.height(); + if (!options.hasResizeWidth() && !options.hasResizeHeight()) { + parsedOptions.resizeWidth = sourceWidth; + parsedOptions.resizeHeight = sourceHeight; + } else if (options.hasResizeWidth() && options.hasResizeHeight()) { + parsedOptions.resizeWidth = options.resizeWidth(); + parsedOptions.resizeHeight = options.resizeHeight(); + } else if (options.hasResizeWidth() && !options.hasResizeHeight()) { + parsedOptions.resizeWidth = options.resizeWidth(); + parsedOptions.resizeHeight = ceil(static_cast<float>(options.resizeWidth()) / sourceWidth * sourceHeight); + } else { + parsedOptions.resizeHeight = options.resizeHeight(); + parsedOptions.resizeWidth = ceil(static_cast<float>(options.resizeHeight()) / sourceHeight * sourceWidth); + } + if (!cropRect) { + parsedOptions.cropRect = IntRect(0, 0, parsedOptions.resizeWidth, parsedOptions.resizeHeight); + } else { + parsedOptions.cropRect = normalizeRect(*cropRect); + } + if (static_cast<int>(parsedOptions.resizeWidth) == sourceWidth && static_cast<int>(parsedOptions.resizeHeight) == sourceHeight) { + parsedOptions.shouldScaleInput = false; + return parsedOptions; + } + parsedOptions.shouldScaleInput = true; + + if (options.resizeQuality() == "high") + parsedOptions.resizeQuality = kHigh_SkFilterQuality; + else if (options.resizeQuality() == "medium") + parsedOptions.resizeQuality = kMedium_SkFilterQuality; + else if (options.resizeQuality() == "pixelated") + parsedOptions.resizeQuality = kNone_SkFilterQuality; + else + parsedOptions.resizeQuality = kLow_SkFilterQuality; + return parsedOptions; +} + +} // namespace + static std::unique_ptr<uint8_t[]> copySkImageData(SkImage* input, const SkImageInfo& info) { std::unique_ptr<uint8_t[]> dstPixels = wrapArrayUnique(new uint8_t[input->width() * input->height() * info.bytesPerPixel()]); @@ -113,30 +180,48 @@ return fromSkSp(SkImage::MakeFromBitmap(bitmap)); } +bool ImageBitmap::isResizeOptionValid(const ImageBitmapOptions& options, ExceptionState& exceptionState) +{ + if ((options.hasResizeWidth() && options.resizeWidth() == 0) || (options.hasResizeHeight() && options.resizeHeight() == 0)) { + exceptionState.throwDOMException(InvalidStateError, "The resizeWidth or/and resizeHeight is equal to 0."); + return false; + } + return true; +} + +bool ImageBitmap::isSourceSizeValid(int sourceWidth, int sourceHeight, ExceptionState& exceptionState) +{ + if (!sourceWidth || !sourceHeight) { + exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sourceWidth ? "height" : "width")); + return false; + } + return true; +} + // The parameter imageFormat indicates whether the first parameter "image" is unpremultiplied or not. // imageFormat = PremultiplyAlpha means the image is in premuliplied format // For example, if the image is already in unpremultiplied format and we want the created ImageBitmap // in the same format, then we don't need to use the ImageDecoder to decode the image. -static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const IntRect& cropRect, bool flipY, bool premultiplyAlpha, AlphaDisposition imageFormat = PremultiplyAlpha, ImageDecoder::GammaAndColorProfileOption colorSpaceOp = ImageDecoder::GammaAndColorProfileApplied) +static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const ParsedOptions& parsedOptions, AlphaDisposition imageFormat = PremultiplyAlpha, ImageDecoder::GammaAndColorProfileOption colorSpaceOp = ImageDecoder::GammaAndColorProfileApplied) { ASSERT(image); IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); - const IntRect srcRect = intersection(imgRect, cropRect); + const IntRect srcRect = intersection(imgRect, parsedOptions.cropRect); // In the case when cropRect doesn't intersect the source image and it requires a umpremul image // We immediately return a transparent black image with cropRect.size() - if (srcRect.isEmpty() && !premultiplyAlpha) { - SkImageInfo info = SkImageInfo::Make(cropRect.width(), cropRect.height(), kN32_SkColorType, kUnpremul_SkAlphaType); - std::unique_ptr<uint8_t[]> dstPixels = wrapArrayUnique(new uint8_t[cropRect.width() * cropRect.height() * info.bytesPerPixel()]()); - return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(dstPixels), cropRect.width() * info.bytesPerPixel())); + if (srcRect.isEmpty() && !parsedOptions.premultiplyAlpha) { + SkImageInfo info = SkImageInfo::Make(parsedOptions.cropRect.width(), parsedOptions.cropRect.height(), kN32_SkColorType, kUnpremul_SkAlphaType); + std::unique_ptr<uint8_t[]> dstPixels = wrapArrayUnique(new uint8_t[parsedOptions.cropRect.width() * parsedOptions.cropRect.height() * info.bytesPerPixel()]()); + return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(dstPixels), parsedOptions.cropRect.width() * info.bytesPerPixel())); } RefPtr<SkImage> skiaImage = image->imageForCurrentFrame(); // Attempt to get raw unpremultiplied image data, executed only when skiaImage is premultiplied. - if ((((!premultiplyAlpha && !skiaImage->isOpaque()) || !skiaImage) && image->data() && imageFormat == PremultiplyAlpha) || colorSpaceOp == ImageDecoder::GammaAndColorProfileIgnored) { + if ((((!parsedOptions.premultiplyAlpha && !skiaImage->isOpaque()) || !skiaImage) && image->data() && imageFormat == PremultiplyAlpha) || colorSpaceOp == ImageDecoder::GammaAndColorProfileIgnored) { std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create(*(image->data()), - premultiplyAlpha ? ImageDecoder::AlphaPremultiplied : ImageDecoder::AlphaNotPremultiplied, + parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied : ImageDecoder::AlphaNotPremultiplied, colorSpaceOp)); if (!decoder) return nullptr; @@ -146,36 +231,43 @@ return nullptr; } - if (cropRect == srcRect) { + if (parsedOptions.cropRect == srcRect) { RefPtr<SkImage> croppedSkImage = fromSkSp(skiaImage->makeSubset(srcRect)); - if (flipY) - return StaticBitmapImage::create(flipSkImageVertically(croppedSkImage.get(), premultiplyAlpha ? PremultiplyAlpha : DontPremultiplyAlpha)); + if (parsedOptions.flipY) + return StaticBitmapImage::create(flipSkImageVertically(croppedSkImage.get(), parsedOptions.premultiplyAlpha ? PremultiplyAlpha : DontPremultiplyAlpha)); // Special case: The first parameter image is unpremul but we need to turn it into premul. - if (premultiplyAlpha && imageFormat == DontPremultiplyAlpha) + if (parsedOptions.premultiplyAlpha && imageFormat == DontPremultiplyAlpha) return StaticBitmapImage::create(unPremulSkImageToPremul(croppedSkImage.get())); // Call preroll to trigger image decoding. croppedSkImage->preroll(); return StaticBitmapImage::create(croppedSkImage.release()); } - sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(cropRect.width(), cropRect.height()); + sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(parsedOptions.cropRect.width(), parsedOptions.cropRect.height()); if (!surface) return nullptr; if (srcRect.isEmpty()) return StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot())); - SkScalar dstLeft = std::min(0, -cropRect.x()); - SkScalar dstTop = std::min(0, -cropRect.y()); - if (cropRect.x() < 0) - dstLeft = -cropRect.x(); - if (cropRect.y() < 0) - dstTop = -cropRect.y(); - surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop); + SkScalar dstLeft = std::min(0, -parsedOptions.cropRect.x()); + SkScalar dstTop = std::min(0, -parsedOptions.cropRect.y()); + if (parsedOptions.cropRect.x() < 0) + dstLeft = -parsedOptions.cropRect.x(); + if (parsedOptions.cropRect.y() < 0) + dstTop = -parsedOptions.cropRect.y(); + if (parsedOptions.shouldScaleInput) { + SkRect drawDstRect = SkRect::MakeXYWH(dstLeft, dstTop, parsedOptions.resizeWidth, parsedOptions.resizeHeight); + SkPaint paint; + paint.setFilterQuality(parsedOptions.resizeQuality); + surface->getCanvas()->drawImageRect(skiaImage.get(), drawDstRect, &paint); + } else { + surface->getCanvas()->drawImage(skiaImage.get(), dstLeft, dstTop); + } skiaImage = fromSkSp(surface->makeImageSnapshot()); - if (flipY) + if (parsedOptions.flipY) skiaImage = flipSkImageVertically(skiaImage.get(), PremultiplyAlpha); - if (premultiplyAlpha) { + if (parsedOptions.premultiplyAlpha) { if (imageFormat == PremultiplyAlpha) return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.get())); return StaticBitmapImage::create(skiaImage.release()); @@ -183,16 +275,15 @@ return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); } -ImageBitmap::ImageBitmap(HTMLImageElement* image, const IntRect& cropRect, Document* document, const ImageBitmapOptions& options) +ImageBitmap::ImageBitmap(HTMLImageElement* image, Optional<IntRect> cropRect, Document* document, const ImageBitmapOptions& options) { - bool flipY; - bool premultiplyAlpha; - parseOptions(options, flipY, premultiplyAlpha); + RefPtr<Image> input = image->cachedImage()->getImage(); + ParsedOptions parsedOptions = parseOptions(options, cropRect, image->bitmapSourceSize()); if (options.colorSpaceConversion() == "none") - m_image = cropImage(image->cachedImage()->getImage(), cropRect, flipY, premultiplyAlpha, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileIgnored); + m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileIgnored); else - m_image = cropImage(image->cachedImage()->getImage(), cropRect, flipY, premultiplyAlpha, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileApplied); + m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileApplied); if (!m_image) return; // In the case where the source image is lazy-decoded, m_image may not be in @@ -205,57 +296,61 @@ m_image = StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot())); } m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin())); - m_image->setPremultiplied(premultiplyAlpha); + m_image->setPremultiplied(parsedOptions.premultiplyAlpha); } -ImageBitmap::ImageBitmap(HTMLVideoElement* video, const IntRect& cropRect, Document* document, const ImageBitmapOptions& options) +ImageBitmap::ImageBitmap(HTMLVideoElement* video, Optional<IntRect> cropRect, Document* document, const ImageBitmapOptions& options) { IntSize playerSize; if (video->webMediaPlayer()) playerSize = video->webMediaPlayer()->naturalSize(); + // TODO(xidachen); implement the resize option. + ParsedOptions parsedOptions = parseOptions(options, cropRect, video->bitmapSourceSize()); + IntRect videoRect = IntRect(IntPoint(), playerSize); - IntRect srcRect = intersection(cropRect, videoRect); - std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(cropRect.size(), NonOpaque, DoNotInitializeImagePixels); + IntRect srcRect = intersection(parsedOptions.cropRect, videoRect); + std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(parsedOptions.cropRect.size(), NonOpaque, DoNotInitializeImagePixels); if (!buffer) return; - IntPoint dstPoint = IntPoint(std::max(0, -cropRect.x()), std::max(0, -cropRect.y())); + IntPoint dstPoint = IntPoint(std::max(0, -parsedOptions.cropRect.x()), std::max(0, -parsedOptions.cropRect.y())); video->paintCurrentFrame(buffer->canvas(), IntRect(dstPoint, srcRect.size()), nullptr); - bool flipY; - bool premultiplyAlpha; - parseOptions(options, flipY, premultiplyAlpha); - - if (flipY || !premultiplyAlpha) { + if (parsedOptions.flipY || !parsedOptions.premultiplyAlpha) { RefPtr<SkImage> skiaImage = buffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown); - if (flipY) + if (parsedOptions.flipY) skiaImage = flipSkImageVertically(skiaImage.get(), PremultiplyAlpha); - if (!premultiplyAlpha) + if (!parsedOptions.premultiplyAlpha) skiaImage = premulSkImageToUnPremul(skiaImage.get()); m_image = StaticBitmapImage::create(skiaImage.release()); } else { m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown)); } m_image->setOriginClean(!video->wouldTaintOrigin(document->getSecurityOrigin())); - m_image->setPremultiplied(premultiplyAlpha); + m_image->setPremultiplied(parsedOptions.premultiplyAlpha); } -ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, const IntRect& cropRect, const ImageBitmapOptions& options) +ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, Optional<IntRect> cropRect, const ImageBitmapOptions& options) { ASSERT(canvas->isPaintable()); - bool flipY; - bool premultiplyAlpha; - parseOptions(options, flipY, premultiplyAlpha); + RefPtr<Image> input = canvas->copiedImage(BackBuffer, PreferAcceleration); + ParsedOptions parsedOptions = parseOptions(options, cropRect, canvas->bitmapSourceSize()); - // canvas is always premultiplied, so set the last parameter to true and convert to un-premul later - m_image = cropImage(canvas->copiedImage(BackBuffer, PreferAcceleration).get(), cropRect, flipY, true); + bool isPremultiplyAlphaReverted = false; + if (!parsedOptions.premultiplyAlpha) { + parsedOptions.premultiplyAlpha = true; + isPremultiplyAlphaReverted = true; + } + m_image = cropImage(input.get(), parsedOptions); if (!m_image) return; - if (!premultiplyAlpha) + if (isPremultiplyAlphaReverted) { + parsedOptions.premultiplyAlpha = false; m_image = StaticBitmapImage::create(premulSkImageToUnPremul(m_image->imageForCurrentFrame().get())); + } m_image->setOriginClean(canvas->originClean()); - m_image->setPremultiplied(premultiplyAlpha); + m_image->setPremultiplied(parsedOptions.premultiplyAlpha); } ImageBitmap::ImageBitmap(std::unique_ptr<uint8_t[]> data, uint32_t width, uint32_t height, bool isImageBitmapPremultiplied, bool isImageBitmapOriginClean) @@ -266,44 +361,44 @@ m_image->setOriginClean(isImageBitmapOriginClean); } -ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect, const ImageBitmapOptions& options) +ImageBitmap::ImageBitmap(ImageData* data, Optional<IntRect> cropRect, const ImageBitmapOptions& options) { - bool flipY; - bool premultiplyAlpha; - parseOptions(options, flipY, premultiplyAlpha); - IntRect srcRect = intersection(cropRect, IntRect(IntPoint(), data->size())); + // TODO(xidachen): implement the resize option + IntRect dataSrcRect = IntRect(IntPoint(), data->size()); + ParsedOptions parsedOptions = parseOptions(options, cropRect, data->bitmapSourceSize()); + IntRect srcRect = cropRect ? intersection(parsedOptions.cropRect, dataSrcRect) : dataSrcRect; // treat non-premultiplyAlpha as a special case - if (!premultiplyAlpha) { + if (!parsedOptions.premultiplyAlpha) { unsigned char* srcAddr = data->data()->data(); int srcHeight = data->size().height(); - int dstHeight = cropRect.height(); + int dstHeight = parsedOptions.cropRect.height(); // TODO (xidachen): skia doesn't support SkImage::NewRasterCopy from a kRGBA color type. // For now, we swap R and B channel and uses kBGRA color type. - SkImageInfo info = SkImageInfo::Make(cropRect.width(), dstHeight, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType); + SkImageInfo info = SkImageInfo::Make(parsedOptions.cropRect.width(), dstHeight, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType); int srcPixelBytesPerRow = info.bytesPerPixel() * data->size().width(); - int dstPixelBytesPerRow = info.bytesPerPixel() * cropRect.width(); - if (cropRect == IntRect(IntPoint(), data->size())) { - swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, flipY); + int dstPixelBytesPerRow = info.bytesPerPixel() * parsedOptions.cropRect.width(); + if (parsedOptions.cropRect == IntRect(IntPoint(), data->size())) { + swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOptions.flipY); m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy(SkPixmap(info, srcAddr, dstPixelBytesPerRow)))); // restore the original ImageData - swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, flipY); + swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOptions.flipY); } else { std::unique_ptr<uint8_t[]> copiedDataBuffer = wrapArrayUnique(new uint8_t[dstHeight * dstPixelBytesPerRow]()); if (!srcRect.isEmpty()) { - IntPoint srcPoint = IntPoint((cropRect.x() > 0) ? cropRect.x() : 0, (cropRect.y() > 0) ? cropRect.y() : 0); - IntPoint dstPoint = IntPoint((cropRect.x() >= 0) ? 0 : -cropRect.x(), (cropRect.y() >= 0) ? 0 : -cropRect.y()); + IntPoint srcPoint = IntPoint((parsedOptions.cropRect.x() > 0) ? parsedOptions.cropRect.x() : 0, (parsedOptions.cropRect.y() > 0) ? parsedOptions.cropRect.y() : 0); + IntPoint dstPoint = IntPoint((parsedOptions.cropRect.x() >= 0) ? 0 : -parsedOptions.cropRect.x(), (parsedOptions.cropRect.y() >= 0) ? 0 : -parsedOptions.cropRect.y()); int copyHeight = srcHeight - srcPoint.y(); - if (cropRect.height() < copyHeight) - copyHeight = cropRect.height(); + if (parsedOptions.cropRect.height() < copyHeight) + copyHeight = parsedOptions.cropRect.height(); int copyWidth = data->size().width() - srcPoint.x(); - if (cropRect.width() < copyWidth) - copyWidth = cropRect.width(); + if (parsedOptions.cropRect.width() < copyWidth) + copyWidth = parsedOptions.cropRect.width(); for (int i = 0; i < copyHeight; i++) { int srcStartCopyPosition = (i + srcPoint.y()) * srcPixelBytesPerRow + srcPoint.x() * info.bytesPerPixel(); int srcEndCopyPosition = srcStartCopyPosition + copyWidth * info.bytesPerPixel(); int dstStartCopyPosition; - if (flipY) + if (parsedOptions.flipY) dstStartCopyPosition = (dstHeight -1 - dstPoint.y() - i) * dstPixelBytesPerRow + dstPoint.x() * info.bytesPerPixel(); else dstStartCopyPosition = (dstPoint.y() + i) * dstPixelBytesPerRow + dstPoint.x() * info.bytesPerPixel(); @@ -319,11 +414,11 @@ } m_image = StaticBitmapImage::create(newSkImageFromRaster(info, std::move(copiedDataBuffer), dstPixelBytesPerRow)); } - m_image->setPremultiplied(premultiplyAlpha); + m_image->setPremultiplied(parsedOptions.premultiplyAlpha); return; } - std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(cropRect.size(), NonOpaque, DoNotInitializeImagePixels); + std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(parsedOptions.cropRect.size(), NonOpaque, DoNotInitializeImagePixels); if (!buffer) return; @@ -332,40 +427,43 @@ return; } - IntPoint dstPoint = IntPoint(std::min(0, -cropRect.x()), std::min(0, -cropRect.y())); - if (cropRect.x() < 0) - dstPoint.setX(-cropRect.x()); - if (cropRect.y() < 0) - dstPoint.setY(-cropRect.y()); + IntPoint dstPoint = IntPoint(std::min(0, -parsedOptions.cropRect.x()), std::min(0, -parsedOptions.cropRect.y())); + if (parsedOptions.cropRect.x() < 0) + dstPoint.setX(-parsedOptions.cropRect.x()); + if (parsedOptions.cropRect.y() < 0) + dstPoint.setY(-parsedOptions.cropRect.y()); buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), srcRect, dstPoint); - if (flipY) + if (parsedOptions.flipY) m_image = StaticBitmapImage::create(flipSkImageVertically(buffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown).get(), PremultiplyAlpha)); else m_image = StaticBitmapImage::create(buffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown)); } -ImageBitmap::ImageBitmap(ImageBitmap* bitmap, const IntRect& cropRect, const ImageBitmapOptions& options) +ImageBitmap::ImageBitmap(ImageBitmap* bitmap, Optional<IntRect> cropRect, const ImageBitmapOptions& options) { - bool flipY; - bool premultiplyAlpha; - parseOptions(options, flipY, premultiplyAlpha); - m_image = cropImage(bitmap->bitmapImage(), cropRect, flipY, premultiplyAlpha, bitmap->isPremultiplied() ? PremultiplyAlpha : DontPremultiplyAlpha); + RefPtr<Image> input = bitmap->bitmapImage(); + if (!input) + return; + ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()); + + m_image = cropImage(input.get(), parsedOptions, bitmap->isPremultiplied() ? PremultiplyAlpha : DontPremultiplyAlpha); if (!m_image) return; m_image->setOriginClean(bitmap->originClean()); - m_image->setPremultiplied(premultiplyAlpha); + m_image->setPremultiplied(parsedOptions.premultiplyAlpha); } -ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, const IntRect& cropRect, const ImageBitmapOptions& options) +ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, Optional<IntRect> cropRect, const ImageBitmapOptions& options) { - bool flipY; - bool premultiplyAlpha; - parseOptions(options, flipY, premultiplyAlpha); - m_image = cropImage(image.get(), cropRect, flipY, premultiplyAlpha, DontPremultiplyAlpha); + bool originClean = image->originClean(); + RefPtr<Image> input = image; + ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()); + + m_image = cropImage(input.get(), parsedOptions, DontPremultiplyAlpha); if (!m_image) return; - m_image->setOriginClean(image->originClean()); - m_image->setPremultiplied(premultiplyAlpha); + m_image->setOriginClean(originClean); + m_image->setPremultiplied(parsedOptions.premultiplyAlpha); } ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) @@ -389,40 +487,34 @@ { } -ImageBitmap* ImageBitmap::create(HTMLImageElement* image, const IntRect& cropRect, Document* document, const ImageBitmapOptions& options) +ImageBitmap* ImageBitmap::create(HTMLImageElement* image, Optional<IntRect> cropRect, Document* document, const ImageBitmapOptions& options) { - IntRect normalizedCropRect = normalizeRect(cropRect); - return new ImageBitmap(image, normalizedCropRect, document, options); + return new ImageBitmap(image, cropRect, document, options); } -ImageBitmap* ImageBitmap::create(HTMLVideoElement* video, const IntRect& cropRect, Document* document, const ImageBitmapOptions& options) +ImageBitmap* ImageBitmap::create(HTMLVideoElement* video, Optional<IntRect> cropRect, Document* document, const ImageBitmapOptions& options) { - IntRect normalizedCropRect = normalizeRect(cropRect); - return new ImageBitmap(video, normalizedCropRect, document, options); + return new ImageBitmap(video, cropRect, document, options); } -ImageBitmap* ImageBitmap::create(HTMLCanvasElement* canvas, const IntRect& cropRect, const ImageBitmapOptions& options) +ImageBitmap* ImageBitmap::create(HTMLCanvasElement* canvas, Optional<IntRect> cropRect, const ImageBitmapOptions& options) { - IntRect normalizedCropRect = normalizeRect(cropRect); - return new ImageBitmap(canvas, normalizedCropRect, options); + return new ImageBitmap(canvas, cropRect, options); } -ImageBitmap* ImageBitmap::create(ImageData* data, const IntRect& cropRect, const ImageBitmapOptions& options) +ImageBitmap* ImageBitmap::create(ImageData* data, Optional<IntRect> cropRect, const ImageBitmapOptions& options) { - IntRect normalizedCropRect = normalizeRect(cropRect); - return new ImageBitmap(data, normalizedCropRect, options); + return new ImageBitmap(data, cropRect, options); } -ImageBitmap* ImageBitmap::create(ImageBitmap* bitmap, const IntRect& cropRect, const ImageBitmapOptions& options) +ImageBitmap* ImageBitmap::create(ImageBitmap* bitmap, Optional<IntRect> cropRect, const ImageBitmapOptions& options) { - IntRect normalizedCropRect = normalizeRect(cropRect); - return new ImageBitmap(bitmap, normalizedCropRect, options); + return new ImageBitmap(bitmap, cropRect, options); } -ImageBitmap* ImageBitmap::create(PassRefPtr<StaticBitmapImage> image, const IntRect& cropRect, const ImageBitmapOptions& options) +ImageBitmap* ImageBitmap::create(PassRefPtr<StaticBitmapImage> image, Optional<IntRect> cropRect, const ImageBitmapOptions& options) { - IntRect normalizedCropRect = normalizeRect(cropRect); - return new ImageBitmap(image, normalizedCropRect, options); + return new ImageBitmap(image, cropRect, options); } ImageBitmap* ImageBitmap::create(PassRefPtr<StaticBitmapImage> image) @@ -490,29 +582,14 @@ return IntSize(m_image->width(), m_image->height()); } -ScriptPromise ImageBitmap::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, int sx, int sy, int sw, int sh, const ImageBitmapOptions& options, ExceptionState& exceptionState) +ScriptPromise ImageBitmap::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, Optional<IntRect> cropRect, const ImageBitmapOptions& options, ExceptionState& exceptionState) { - if (!sw || !sh) { - exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width")); + if ((cropRect && !isSourceSizeValid(cropRect->width(), cropRect->height(), exceptionState)) + || !isSourceSizeValid(width(), height(), exceptionState)) return ScriptPromise(); - } - return ImageBitmapSource::fulfillImageBitmap(scriptState, create(this, IntRect(sx, sy, sw, sh), options)); -} - -void ImageBitmap::parseOptions(const ImageBitmapOptions& options, bool& flipY, bool& premultiplyAlpha) -{ - if (options.imageOrientation() == imageOrientationFlipY) { - flipY = true; - } else { - flipY = false; - ASSERT(options.imageOrientation() == imageBitmapOptionNone); - } - if (options.premultiplyAlpha() == imageBitmapOptionNone) { - premultiplyAlpha = false; - } else { - premultiplyAlpha = true; - ASSERT(options.premultiplyAlpha() == "default" || options.premultiplyAlpha() == "premultiply"); - } + if (!isResizeOptionValid(options, exceptionState)) + return ScriptPromise(); + return ImageBitmapSource::fulfillImageBitmap(scriptState, create(this, cropRect, options)); } PassRefPtr<Image> ImageBitmap::getSourceImageForCanvas(SourceImageStatus* status, AccelerationHint, SnapshotReason, const FloatSize&) const
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.h b/third_party/WebKit/Source/core/frame/ImageBitmap.h index bb5aa15..7ba09e41 100644 --- a/third_party/WebKit/Source/core/frame/ImageBitmap.h +++ b/third_party/WebKit/Source/core/frame/ImageBitmap.h
@@ -38,19 +38,21 @@ class CORE_EXPORT ImageBitmap final : public GarbageCollectedFinalized<ImageBitmap>, public ScriptWrappable, public CanvasImageSource, public ImageBitmapSource { DEFINE_WRAPPERTYPEINFO(); public: - static ImageBitmap* create(HTMLImageElement*, const IntRect&, Document*, const ImageBitmapOptions& = ImageBitmapOptions()); - static ImageBitmap* create(HTMLVideoElement*, const IntRect&, Document*, const ImageBitmapOptions& = ImageBitmapOptions()); - static ImageBitmap* create(HTMLCanvasElement*, const IntRect&, const ImageBitmapOptions& = ImageBitmapOptions()); - static ImageBitmap* create(ImageData*, const IntRect&, const ImageBitmapOptions& = ImageBitmapOptions()); - static ImageBitmap* create(ImageBitmap*, const IntRect&, const ImageBitmapOptions& = ImageBitmapOptions()); + static ImageBitmap* create(HTMLImageElement*, Optional<IntRect>, Document*, const ImageBitmapOptions& = ImageBitmapOptions()); + static ImageBitmap* create(HTMLVideoElement*, Optional<IntRect>, Document*, const ImageBitmapOptions& = ImageBitmapOptions()); + static ImageBitmap* create(HTMLCanvasElement*, Optional<IntRect>, const ImageBitmapOptions& = ImageBitmapOptions()); + static ImageBitmap* create(ImageData*, Optional<IntRect>, const ImageBitmapOptions& = ImageBitmapOptions()); + static ImageBitmap* create(ImageBitmap*, Optional<IntRect>, const ImageBitmapOptions& = ImageBitmapOptions()); static ImageBitmap* create(PassRefPtr<StaticBitmapImage>); - static ImageBitmap* create(PassRefPtr<StaticBitmapImage>, const IntRect&, const ImageBitmapOptions& = ImageBitmapOptions()); + static ImageBitmap* create(PassRefPtr<StaticBitmapImage>, Optional<IntRect>, const ImageBitmapOptions& = ImageBitmapOptions()); static ImageBitmap* create(WebExternalTextureMailbox&); // This function is called by structured-cloning an ImageBitmap. // isImageBitmapPremultiplied indicates whether the original ImageBitmap is premultiplied or not. // isImageBitmapOriginClean indicates whether the original ImageBitmap is origin clean or not. static ImageBitmap* create(std::unique_ptr<uint8_t[]> data, uint32_t width, uint32_t height, bool isImageBitmapPremultiplied, bool isImageBitmapOriginClean); static PassRefPtr<SkImage> getSkImageFromDecoder(std::unique_ptr<ImageDecoder>); + static bool isResizeOptionValid(const ImageBitmapOptions&, ExceptionState&); + static bool isSourceSizeValid(int sourceWidth, int sourceHeight, ExceptionState&); // Type and helper function required by CallbackPromiseAdapter: using WebType = sk_sp<SkImage>; @@ -82,23 +84,21 @@ // ImageBitmapSource implementation IntSize bitmapSourceSize() const override { return size(); } - ScriptPromise createImageBitmap(ScriptState*, EventTarget&, int sx, int sy, int sw, int sh, const ImageBitmapOptions&, ExceptionState&) override; + ScriptPromise createImageBitmap(ScriptState*, EventTarget&, Optional<IntRect>, const ImageBitmapOptions&, ExceptionState&) override; DECLARE_VIRTUAL_TRACE(); private: - ImageBitmap(HTMLImageElement*, const IntRect&, Document*, const ImageBitmapOptions&); - ImageBitmap(HTMLVideoElement*, const IntRect&, Document*, const ImageBitmapOptions&); - ImageBitmap(HTMLCanvasElement*, const IntRect&, const ImageBitmapOptions&); - ImageBitmap(ImageData*, const IntRect&, const ImageBitmapOptions&); - ImageBitmap(ImageBitmap*, const IntRect&, const ImageBitmapOptions&); + ImageBitmap(HTMLImageElement*, Optional<IntRect>, Document*, const ImageBitmapOptions&); + ImageBitmap(HTMLVideoElement*, Optional<IntRect>, Document*, const ImageBitmapOptions&); + ImageBitmap(HTMLCanvasElement*, Optional<IntRect>, const ImageBitmapOptions&); + ImageBitmap(ImageData*, Optional<IntRect>, const ImageBitmapOptions&); + ImageBitmap(ImageBitmap*, Optional<IntRect>, const ImageBitmapOptions&); ImageBitmap(PassRefPtr<StaticBitmapImage>); - ImageBitmap(PassRefPtr<StaticBitmapImage>, const IntRect&, const ImageBitmapOptions&); + ImageBitmap(PassRefPtr<StaticBitmapImage>, Optional<IntRect>, const ImageBitmapOptions&); ImageBitmap(WebExternalTextureMailbox&); ImageBitmap(std::unique_ptr<uint8_t[]> data, uint32_t width, uint32_t height, bool isImageBitmapPremultiplied, bool isImageBitmapOriginClean); - void parseOptions(const ImageBitmapOptions&, bool&, bool&); - RefPtr<StaticBitmapImage> m_image; bool m_isNeutered = false; };
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmapTest.cpp b/third_party/WebKit/Source/core/frame/ImageBitmapTest.cpp index 6027353..6919c835 100644 --- a/third_party/WebKit/Source/core/frame/ImageBitmapTest.cpp +++ b/third_party/WebKit/Source/core/frame/ImageBitmapTest.cpp
@@ -84,18 +84,18 @@ ImageResource* image = ImageResource::create(StaticBitmapImage::create(m_image).get()); imageElement->setImageResource(image); + Optional<IntRect> cropRect = IntRect(0, 0, m_image->width(), m_image->height()); ImageBitmap* imageBitmapNoCrop = ImageBitmap::create(imageElement, - IntRect(0, 0, m_image->width(), m_image->height()), - &(imageElement->document()), defaultOptions); + cropRect, &(imageElement->document()), defaultOptions); + cropRect = IntRect(m_image->width() / 2, m_image->height() / 2, m_image->width() / 2, m_image->height() / 2); ImageBitmap* imageBitmapInteriorCrop = ImageBitmap::create(imageElement, - IntRect(m_image->width() / 2, m_image->height() / 2, m_image->width() / 2, m_image->height() / 2), - &(imageElement->document()), defaultOptions); + cropRect, &(imageElement->document()), defaultOptions); + cropRect = IntRect(-m_image->width() / 2, -m_image->height() / 2, m_image->width(), m_image->height()); ImageBitmap* imageBitmapExteriorCrop = ImageBitmap::create(imageElement, - IntRect(-m_image->width() / 2, -m_image->height() / 2, m_image->width(), m_image->height()), - &(imageElement->document()), defaultOptions); + cropRect, &(imageElement->document()), defaultOptions); + cropRect = IntRect(-m_image->width(), -m_image->height(), m_image->width(), m_image->height()); ImageBitmap* imageBitmapOutsideCrop = ImageBitmap::create(imageElement, - IntRect(-m_image->width(), -m_image->height(), m_image->width(), m_image->height()), - &(imageElement->document()), defaultOptions); + cropRect, &(imageElement->document()), defaultOptions); ASSERT_EQ(imageBitmapNoCrop->bitmapImage()->imageForCurrentFrame(), imageElement->cachedImage()->getImage()->imageForCurrentFrame()); ASSERT_NE(imageBitmapInteriorCrop->bitmapImage()->imageForCurrentFrame(), imageElement->cachedImage()->getImage()->imageForCurrentFrame()); @@ -114,9 +114,9 @@ image->setImageResource(originalImageResource); const ImageBitmapOptions defaultOptions; + Optional<IntRect> cropRect = IntRect(0, 0, m_image->width(), m_image->height()); ImageBitmap* imageBitmap = ImageBitmap::create(image, - IntRect(0, 0, m_image->width(), m_image->height()), - &(image->document()), defaultOptions); + cropRect, &(image->document()), defaultOptions); ASSERT_EQ(imageBitmap->bitmapImage()->imageForCurrentFrame(), originalImageResource->getImage()->imageForCurrentFrame()); ImageResource* newImageResource = ImageResource::create(
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp index a0980bf9..19537c9 100644 --- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp +++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.cpp
@@ -104,11 +104,6 @@ } // LocalFrameLifecycleObserver overrides: - void willDetachFrameHost() override - { - m_window->willDetachFrameHost(); - } - void contextDestroyed() override { m_window->frameDestroyed(); @@ -495,11 +490,6 @@ return document() ? document()->mediaQueryMatcher().matchMedia(media) : nullptr; } -void LocalDOMWindow::willDetachFrameHost() -{ - frame()->host()->eventHandlerRegistry().didRemoveAllEventHandlers(*this); -} - void LocalDOMWindow::frameDestroyed() { willDestroyDocumentInFrame(); @@ -514,12 +504,6 @@ domWindowProperty->willDestroyGlobalObjectInFrame(); } -void LocalDOMWindow::willDetachDocumentFromFrame() -{ - for (const auto& domWindowProperty : m_properties) - domWindowProperty->willDetachGlobalObjectFromFrame(); -} - void LocalDOMWindow::registerProperty(DOMWindowProperty* property) { m_properties.add(property);
diff --git a/third_party/WebKit/Source/core/frame/LocalDOMWindow.h b/third_party/WebKit/Source/core/frame/LocalDOMWindow.h index 663e29e..d1db19f 100644 --- a/third_party/WebKit/Source/core/frame/LocalDOMWindow.h +++ b/third_party/WebKit/Source/core/frame/LocalDOMWindow.h
@@ -193,8 +193,6 @@ // recurse on its child frames. void sendOrientationChangeEvent(); - void willDetachDocumentFromFrame(); - EventQueue* getEventQueue() const; void enqueueWindowEvent(Event*); void enqueueDocumentEvent(Event*);
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp index ebf4ce703..8c9fb0d 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp +++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -31,6 +31,7 @@ #include "bindings/core/v8/ScriptController.h" #include "core/InstrumentingAgents.h" +#include "core/dom/ChildFrameDisconnector.h" #include "core/dom/DocumentType.h" #include "core/dom/StyleChangeReason.h" #include "core/editing/EditingUtilities.h" @@ -239,6 +240,8 @@ } // namespace +template class CORE_TEMPLATE_EXPORT Supplement<LocalFrame>; + LocalFrame* LocalFrame::create(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner, ServiceRegistry* serviceRegistry) { LocalFrame* frame = new LocalFrame(client, host, owner, serviceRegistry ? serviceRegistry : ServiceRegistry::getEmptyServiceRegistry()); @@ -404,13 +407,25 @@ // back to FrameLoaderClient via WindowProxy. script().clearForClose(); setView(nullptr); - willDetachFrameHost(); - InspectorInstrumentation::frameDetachedFromParent(this); - Frame::detach(type); + + m_host->eventHandlerRegistry().didRemoveAllEventHandlers(*localDOMWindow()); // Signal frame destruction here rather than in the destructor. // Main motivation is to avoid being dependent on its exact timing (Oilpan.) LocalFrameLifecycleNotifier::notifyContextDestroyed(); + + // TODO: Page should take care of updating focus/scrolling instead of Frame. + // TODO: It's unclear as to why this is called more than once, but it is, + // so page() could be null. + if (page() && page()->focusController().focusedFrame() == this) + page()->focusController().setFocusedFrame(nullptr); + + if (page() && page()->scrollingCoordinator() && m_view) + page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get()); + + InspectorInstrumentation::frameDetachedFromParent(this); + Frame::detach(type); + m_supplements.clear(); WeakIdentifierMap<LocalFrame>::notifyObjectDestroyed(this); } @@ -447,18 +462,12 @@ return m_loader.shouldClose(); } -void LocalFrame::willDetachFrameHost() +void LocalFrame::detachChildren() { - LocalFrameLifecycleNotifier::notifyWillDetachFrameHost(); + DCHECK(m_loader.stateMachine()->creatingInitialEmptyDocument() || document()); - // FIXME: Page should take care of updating focus/scrolling instead of Frame. - // FIXME: It's unclear as to why this is called more than once, but it is, - // so page() could be null. - if (page() && page()->focusController().focusedFrame() == this) - page()->focusController().setFocusedFrame(nullptr); - - if (page() && page()->scrollingCoordinator() && m_view) - page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get()); + if (Document* document = this->document()) + ChildFrameDisconnector(*document).disconnect(); } void LocalFrame::setDOMWindow(LocalDOMWindow* domWindow)
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.h b/third_party/WebKit/Source/core/frame/LocalFrame.h index 2165cca6..5e22840 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrame.h +++ b/third_party/WebKit/Source/core/frame/LocalFrame.h
@@ -78,7 +78,9 @@ class WebFrameHostScheduler; class WebFrameScheduler; -class CORE_EXPORT LocalFrame : public Frame, public LocalFrameLifecycleNotifier, public Supplementable<LocalFrame> { +extern template class CORE_EXTERN_TEMPLATE_EXPORT Supplement<LocalFrame>; + +class CORE_EXPORT LocalFrame final : public Frame, public LocalFrameLifecycleNotifier, public Supplementable<LocalFrame> { USING_GARBAGE_COLLECTED_MIXIN(LocalFrame); public: static LocalFrame* create(FrameLoaderClient*, FrameHost*, FrameOwner*, ServiceRegistry* = nullptr); @@ -104,7 +106,7 @@ bool prepareForCommit() override; void didChangeVisibilityState() override; - void willDetachFrameHost(); + void detachChildren(); LocalDOMWindow* localDOMWindow() const; void setDOMWindow(LocalDOMWindow*);
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameLifecycleNotifier.cpp b/third_party/WebKit/Source/core/frame/LocalFrameLifecycleNotifier.cpp deleted file mode 100644 index 1c741bc..0000000 --- a/third_party/WebKit/Source/core/frame/LocalFrameLifecycleNotifier.cpp +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "core/frame/LocalFrameLifecycleNotifier.h" - -#include "core/frame/LocalFrameLifecycleObserver.h" - -namespace blink { - -void LocalFrameLifecycleNotifier::notifyWillDetachFrameHost() -{ - TemporaryChange<IterationState> scope(m_iterationState, AllowingNone); - for (LocalFrameLifecycleObserver* observer : m_observers) - observer->willDetachFrameHost(); -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameLifecycleNotifier.h b/third_party/WebKit/Source/core/frame/LocalFrameLifecycleNotifier.h index e2a18cd0..0a9c8343 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameLifecycleNotifier.h +++ b/third_party/WebKit/Source/core/frame/LocalFrameLifecycleNotifier.h
@@ -15,8 +15,6 @@ class LocalFrame; class CORE_EXPORT LocalFrameLifecycleNotifier : public LifecycleNotifier<LocalFrame, LocalFrameLifecycleObserver> { -public: - void notifyWillDetachFrameHost(); }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameLifecycleObserver.h b/third_party/WebKit/Source/core/frame/LocalFrameLifecycleObserver.h index 7fa60acf..7dbe92d 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameLifecycleObserver.h +++ b/third_party/WebKit/Source/core/frame/LocalFrameLifecycleObserver.h
@@ -37,7 +37,6 @@ class CORE_EXPORT LocalFrameLifecycleObserver : public LifecycleObserver<LocalFrame, LocalFrameLifecycleObserver> { public: - virtual void willDetachFrameHost() { } virtual void contextDestroyed() { setContext(nullptr);
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrame.cpp b/third_party/WebKit/Source/core/frame/RemoteFrame.cpp index f7eb7a0..0c3c253a 100644 --- a/third_party/WebKit/Source/core/frame/RemoteFrame.cpp +++ b/third_party/WebKit/Source/core/frame/RemoteFrame.cpp
@@ -196,4 +196,15 @@ client()->advanceFocus(type, source); } +void RemoteFrame::detachChildren() +{ + using FrameVector = HeapVector<Member<Frame>>; + FrameVector childrenToDetach; + childrenToDetach.reserveCapacity(tree().childCount()); + for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling()) + childrenToDetach.append(child); + for (const auto& child : childrenToDetach) + child->detach(FrameDetachType::Remove); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/frame/RemoteFrame.h b/third_party/WebKit/Source/core/frame/RemoteFrame.h index ebd1fe4..dbdcdd6 100644 --- a/third_party/WebKit/Source/core/frame/RemoteFrame.h +++ b/third_party/WebKit/Source/core/frame/RemoteFrame.h
@@ -22,7 +22,7 @@ class WindowProxyManager; struct FrameLoadRequest; -class CORE_EXPORT RemoteFrame: public Frame { +class CORE_EXPORT RemoteFrame final : public Frame { public: static RemoteFrame* create(RemoteFrameClient*, FrameHost*, FrameOwner*); @@ -71,6 +71,8 @@ bool isLocalFrame() const override { return false; } bool isRemoteFrame() const override { return true; } + void detachChildren(); + Member<RemoteFrameView> m_view; Member<RemoteSecurityContext> m_securityContext; Member<RemoteDOMWindow> m_domWindow;
diff --git a/third_party/WebKit/Source/core/frame/Settings.in b/third_party/WebKit/Source/core/frame/Settings.in index 02251c7..79630435 100644 --- a/third_party/WebKit/Source/core/frame/Settings.in +++ b/third_party/WebKit/Source/core/frame/Settings.in
@@ -411,3 +411,7 @@ # Use default interpolation quality to scale bitmap images if quality is not determined # in other ways. This can help us writing reftests containing scaled images. useDefaultImageInterpolationQuality initial=false + +# Variant of the ParseHTMLOnMainThread experiment. One experiment immediately +# tokenizes input bytes. The default is to tokenize with a post task. +parseHTMLOnMainThreadSyncTokenize initial=false
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.cpp b/third_party/WebKit/Source/core/frame/UseCounter.cpp index ee400dc..06bdc29 100644 --- a/third_party/WebKit/Source/core/frame/UseCounter.cpp +++ b/third_party/WebKit/Source/core/frame/UseCounter.cpp
@@ -565,6 +565,7 @@ case CSSPropertyFontVariantNumeric: return 535; case CSSPropertyTextSizeAdjust: return 536; case CSSPropertyAliasWebkitTextSizeAdjust: return 537; + case CSSPropertyOverflowAnchor: return 538; // 1. Add new features above this line (don't change the assigned numbers of the existing // items). @@ -581,8 +582,8 @@ return 0; } - -static int maximumCSSSampleId() { return 537; } +// Make sure update_use_counter_css.py was run which updates histograms.xml. +static int maximumCSSSampleId() { return 538; } static EnumerationHistogram& featureObserverHistogram() {
diff --git a/third_party/WebKit/Source/core/frame/UseCounter.h b/third_party/WebKit/Source/core/frame/UseCounter.h index 5708f12..e52ab821 100644 --- a/third_party/WebKit/Source/core/frame/UseCounter.h +++ b/third_party/WebKit/Source/core/frame/UseCounter.h
@@ -625,7 +625,6 @@ CSSKeyframesRuleAnonymousIndexedGetter = 785, V8Screen_AvailLeft_AttributeGetter = 786, V8Screen_AvailTop_AttributeGetter = 787, - ObjectObserve = 788, V8SVGFEConvolveMatrixElement_PreserveAlpha_AttributeGetter = 791, V8SVGStyleElement_Disabled_AttributeGetter = 798, V8SVGStyleElement_Disabled_AttributeSetter = 799, @@ -1034,7 +1033,6 @@ HTMLMediaElement = 1229, HTMLMediaElementInDocument = 1230, HTMLMediaElementControlsAttribute = 1231, - SVGZoomEvent = 1232, V8Animation_Oncancel_AttributeGetter = 1233, V8Animation_Oncancel_AttributeSetter = 1234, V8HTMLCommentInExternalScript = 1235, @@ -1245,6 +1243,7 @@ BeforeInstallPromptEventUserChoice = 1437, BeforeInstallPromptEventPreventDefault = 1438, BeforeInstallPromptEventPrompt = 1439, + ExecCommandAltersHTMLStructure = 1440, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp b/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp index b4283a1..cb52019 100644 --- a/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp +++ b/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp
@@ -53,7 +53,7 @@ bool equalHosts = equalIgnoringCase(host, m_host); if (m_hostWildcard == HasWildcard) { - match = host.endsWith("." + m_host, TextCaseInsensitive); + match = host.endsWith(String("." + m_host), TextCaseInsensitive); // Chrome used to, incorrectly, match *.x.y to x.y. This was fixed, but // the following count measures when a match fails that would have
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp index 4dede477..3f58a3d 100644 --- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -36,6 +36,7 @@ #include "core/dom/Element.h" #include "core/dom/ElementTraversal.h" #include "core/dom/ExceptionCode.h" +#include "core/dom/TaskRunnerHelper.h" #include "core/fileapi/File.h" #include "core/frame/ImageBitmap.h" #include "core/frame/LocalFrame.h" @@ -680,7 +681,7 @@ if (!isPaintable()) { // If the canvas element's bitmap has no pixels - document().unthrottledTaskRunner()->postTask(BLINK_FROM_HERE, WTF::bind(&BlobCallback::handleEvent, wrapPersistent(callback), nullptr)); + TaskRunnerHelper::getUnthrottledTaskRunner(&document())->postTask(BLINK_FROM_HERE, WTF::bind(&BlobCallback::handleEvent, wrapPersistent(callback), nullptr)); return; } @@ -697,7 +698,7 @@ ImageData* imageData = toImageData(BackBuffer, SnapshotReasonToBlob); - CanvasAsyncBlobCreator* asyncCreator = CanvasAsyncBlobCreator::create(imageData->data(), encodingMimeType, imageData->size(), callback, startTime); + CanvasAsyncBlobCreator* asyncCreator = CanvasAsyncBlobCreator::create(imageData->data(), encodingMimeType, imageData->size(), callback, startTime, &document()); bool useIdlePeriodScheduling = (encodingMimeType != "image/webp"); asyncCreator->scheduleAsyncBlobCreation(useIdlePeriodScheduling, quality); @@ -1105,14 +1106,15 @@ return IntSize(width(), height()); } -ScriptPromise HTMLCanvasElement::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, int sx, int sy, int sw, int sh, const ImageBitmapOptions& options, ExceptionState& exceptionState) +ScriptPromise HTMLCanvasElement::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, Optional<IntRect> cropRect, const ImageBitmapOptions& options, ExceptionState& exceptionState) { DCHECK(eventTarget.toLocalDOMWindow()); - if (!sw || !sh) { - exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width")); + if ((cropRect && !ImageBitmap::isSourceSizeValid(cropRect->width(), cropRect->height(), exceptionState)) + || !ImageBitmap::isSourceSizeValid(bitmapSourceSize().width(), bitmapSourceSize().height(), exceptionState)) return ScriptPromise(); - } - return ImageBitmapSource::fulfillImageBitmap(scriptState, isPaintable() ? ImageBitmap::create(this, IntRect(sx, sy, sw, sh), options) : nullptr); + if (!ImageBitmap::isResizeOptionValid(options, exceptionState)) + return ScriptPromise(); + return ImageBitmapSource::fulfillImageBitmap(scriptState, isPaintable() ? ImageBitmap::create(this, cropRect, options) : nullptr); } bool HTMLCanvasElement::isOpaque() const
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h index 4abe0c5..16c26409 100644 --- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h +++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h
@@ -183,7 +183,7 @@ // ImageBitmapSource implementation IntSize bitmapSourceSize() const override; - ScriptPromise createImageBitmap(ScriptState*, EventTarget&, int sx, int sy, int sw, int sh, const ImageBitmapOptions&, ExceptionState&) override; + ScriptPromise createImageBitmap(ScriptState*, EventTarget&, Optional<IntRect> cropRect, const ImageBitmapOptions&, ExceptionState&) override; DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/core/html/HTMLElement.cpp b/third_party/WebKit/Source/core/html/HTMLElement.cpp index 5160f599..c65115f 100644 --- a/third_party/WebKit/Source/core/html/HTMLElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLElement.cpp
@@ -737,7 +737,8 @@ while (node) { // Skip bdi, script, style and text form controls. if (equalIgnoringCase(node->nodeName(), "bdi") || isHTMLScriptElement(*node) || isHTMLStyleElement(*node) - || (node->isElementNode() && toElement(node)->isTextFormControl())) { + || (node->isElementNode() && toElement(node)->isTextFormControl()) + || (node->isElementNode() && toElement(node)->shadowPseudoId() == "-webkit-input-placeholder")) { node = FlatTreeTraversal::nextSkippingChildren(*node, this); continue; }
diff --git a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp index 7511b30..2647b3b 100644 --- a/third_party/WebKit/Source/core/html/HTMLImageElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLImageElement.cpp
@@ -687,14 +687,15 @@ imageLoader().updateFromElement(ImageLoader::UpdateForcedReload, m_referrerPolicy); } -ScriptPromise HTMLImageElement::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, int sx, int sy, int sw, int sh, const ImageBitmapOptions& options, ExceptionState& exceptionState) +ScriptPromise HTMLImageElement::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, Optional<IntRect> cropRect, const ImageBitmapOptions& options, ExceptionState& exceptionState) { ASSERT(eventTarget.toLocalDOMWindow()); - if (!sw || !sh) { - exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width")); + if ((cropRect && !ImageBitmap::isSourceSizeValid(cropRect->width(), cropRect->height(), exceptionState)) + || !ImageBitmap::isSourceSizeValid(bitmapSourceSize().width(), bitmapSourceSize().height(), exceptionState)) return ScriptPromise(); - } - return ImageBitmapSource::fulfillImageBitmap(scriptState, ImageBitmap::create(this, IntRect(sx, sy, sw, sh), eventTarget.toLocalDOMWindow()->document(), options)); + if (!ImageBitmap::isResizeOptionValid(options, exceptionState)) + return ScriptPromise(); + return ImageBitmapSource::fulfillImageBitmap(scriptState, ImageBitmap::create(this, cropRect, eventTarget.toLocalDOMWindow()->document(), options)); } void HTMLImageElement::selectSourceURL(ImageLoader::UpdateFromElementBehavior behavior)
diff --git a/third_party/WebKit/Source/core/html/HTMLImageElement.h b/third_party/WebKit/Source/core/html/HTMLImageElement.h index a98b4ce..4f9c8eb3 100644 --- a/third_party/WebKit/Source/core/html/HTMLImageElement.h +++ b/third_party/WebKit/Source/core/html/HTMLImageElement.h
@@ -120,7 +120,7 @@ // ImageBitmapSource implementation IntSize bitmapSourceSize() const override; - ScriptPromise createImageBitmap(ScriptState*, EventTarget&, int sx, int sy, int sw, int sh, const ImageBitmapOptions&, ExceptionState&) override; + ScriptPromise createImageBitmap(ScriptState*, EventTarget&, Optional<IntRect> cropRect, const ImageBitmapOptions&, ExceptionState&) override; protected: explicit HTMLImageElement(Document&, HTMLFormElement* = 0, bool createdByParser = false);
diff --git a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp index bf54245..1fc1315 100644 --- a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
@@ -683,7 +683,6 @@ // When the link element is created by scripts, load the stylesheets asynchronously but in high priority. bool lowPriority = !mediaQueryMatches || m_owner->isAlternate(); FetchRequest request = builder.build(lowPriority); - request.setContentSecurityPolicyNonce(m_owner->fastGetAttribute(HTMLNames::nonceAttr)); CrossOriginAttributeValue crossOrigin = crossOriginAttributeValue(m_owner->fastGetAttribute(HTMLNames::crossoriginAttr)); if (crossOrigin != CrossOriginAttributeNotSet) { request.setCrossOriginAccessControl(document().getSecurityOrigin(), crossOrigin);
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp index 02edf50..507c4d83 100644 --- a/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.cpp
@@ -123,31 +123,6 @@ return m_multiple ? selectMultiple : selectOne; } -void HTMLSelectElement::optionSelectedByUser(int optionIndex, bool fireOnChangeNow, bool allowMultipleSelection) -{ - // User interaction such as mousedown events can cause list box select - // elements to send change events. This produces that same behavior for - // changes triggered by other code running on behalf of the user. - if (!usesMenuList()) { - updateSelectedState(item(optionIndex), allowMultipleSelection, false); - setNeedsValidityCheck(); - if (fireOnChangeNow) - listBoxOnChange(); - return; - } - - // Bail out if this index is already the selected one, to avoid running - // unnecessary JavaScript that can mess up autofill when there is no actual - // change (see https://bugs.webkit.org/show_bug.cgi?id=35256 and - // <rdar://7467917>). The selectOption function does not behave this way, - // possibly because other callers need a change event even in cases where - // the selected option is not change. - if (optionIndex == selectedIndex()) - return; - - selectOption(item(optionIndex), DeselectOtherOptions | MakeOptionDirty | (fireOnChangeNow ? DispatchInputAndChangeEvent : 0)); -} - bool HTMLSelectElement::hasPlaceholderLabelOption() const { // The select element has no placeholder label option if it has an attribute @@ -208,18 +183,18 @@ return validationMessage(); } -void HTMLSelectElement::listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow) +void HTMLSelectElement::selectMultipleOptionsByPopup(const Vector<int>& listIndices) { - if (!multiple()) { - optionSelectedByUser(listToOptionIndex(listIndex), fireOnChangeNow, false); - } else { - HTMLElement* element = listItems()[listIndex]; - if (isHTMLOptionElement(element)) - updateSelectedState(toHTMLOptionElement(element), allowMultiplySelections, shift); - setNeedsValidityCheck(); - if (fireOnChangeNow) - listBoxOnChange(); + DCHECK(usesMenuList()); + DCHECK(!multiple()); + for (size_t i = 0; i < listIndices.size(); ++i) { + bool addSelectionIfNotFirst = i > 0; + if (HTMLOptionElement* option = optionAtListIndex(listIndices[i])) + updateSelectedState(option, addSelectionIfNotFirst, false); } + setNeedsValidityCheck(); + // TODO(tkent): Using listBoxOnChange() is very confusing. + listBoxOnChange(); } bool HTMLSelectElement::usesMenuList() const @@ -505,6 +480,16 @@ return isRequired(); } +HTMLOptionElement* HTMLSelectElement::optionAtListIndex(int listIndex) const +{ + if (listIndex < 0) + return nullptr; + const ListItems& items = listItems(); + if (static_cast<size_t>(listIndex) >= items.size() || !isHTMLOptionElement(items[listIndex])) + return nullptr; + return toHTMLOptionElement(items[listIndex]); +} + // Returns the 1st valid OPTION |skip| items from |listIndex| in direction // |direction| if there is one. // Otherwise, it returns the valid OPTION closest to that boundary which is past @@ -1082,7 +1067,7 @@ int HTMLSelectElement::listToOptionIndex(int listIndex) const { const ListItems& items = listItems(); - if (listIndex < 0 || listIndex >= static_cast<int>(items.size()) || !isHTMLOptionElement(*items[listIndex])) + if (!optionAtListIndex(listIndex)) return -1; // Actual index of option not counting OPTGROUP entries that may be in list. @@ -1169,10 +1154,7 @@ if (itemsSize == 0) return; - for (auto& item : items) { - if (isHTMLOptionElement(item)) - toHTMLOptionElement(item)->setSelectedState(false); - } + selectOption(nullptr, DeselectOtherOptions); // The saved state should have at least one value and an index. ASSERT(state.valueSize() >= 2); @@ -1267,8 +1249,8 @@ return; // Save the selection so it can be compared to the new selection when // dispatching change events during selectOption, which gets called from - // valueChanged, which gets called after the user makes a selection from the - // menu. + // selectOptionByPopup, which gets called after the user makes a selection + // from the menu. saveLastSelection(); showPopup(); event->setDefaultHandled(); @@ -1386,8 +1368,8 @@ } else { // Save the selection so it can be compared to the new selection // when we call onChange during selectOption, which gets called - // from valueChanged, which gets called after the user makes a - // selection from the menu. + // from selectOptionByPopup, which gets called after the user + // makes a selection from the menu. saveLastSelection(); // TODO(lanwei): Will check if we need to add // InputDeviceCapabilities here when select menu list gets @@ -1698,9 +1680,10 @@ { const ListItems& items = listItems(); for (size_t i = items.size(); i;) { - HTMLElement* element = items[--i]; - if (isHTMLOptionElement(*element) && toHTMLOptionElement(element)->selected()) - return toHTMLOptionElement(element); + if (HTMLOptionElement* option = optionAtListIndex(--i)) { + if (option->selected()) + return option; + } } return nullptr; } @@ -1717,11 +1700,11 @@ String HTMLSelectElement::optionAtIndex(int index) const { - const ListItems& items = listItems(); - HTMLElement* element = items[index]; - if (!isHTMLOptionElement(*element) || toHTMLOptionElement(element)->isDisabledFormControl()) - return String(); - return toHTMLOptionElement(element)->displayLabel(); + if (HTMLOptionElement* option = optionAtListIndex(index)) { + if (!option->isDisabledFormControl()) + return option->displayLabel(); + } + return String(); } void HTMLSelectElement::typeAheadFind(KeyboardEvent* event) @@ -1729,10 +1712,7 @@ int index = m_typeAhead.handleEvent(event, TypeAhead::MatchPrefix | TypeAhead::CycleFirstChar); if (index < 0) return; - HTMLOptionElement* option = nullptr; - if (static_cast<size_t>(index) < listItems().size() && isHTMLOptionElement(listItems()[index])) - option = toHTMLOptionElement(listItems()[index]); - selectOption(option, DeselectOtherOptions | MakeOptionDirty | DispatchInputAndChangeEvent); + selectOption(optionAtListIndex(index), DeselectOtherOptions | MakeOptionDirty | DispatchInputAndChangeEvent); if (!usesMenuList()) listBoxOnChange(); } @@ -1912,8 +1892,8 @@ HTMLOptionElement* HTMLSelectElement::optionToBeShown() const { - if (m_indexToSelectOnCancel >= 0 && static_cast<size_t>(m_indexToSelectOnCancel) < listItems().size() && isHTMLOptionElement(listItems()[m_indexToSelectOnCancel])) - return toHTMLOptionElement(listItems()[m_indexToSelectOnCancel]); + if (HTMLOptionElement* option = optionAtListIndex(m_indexToSelectOnCancel)) + return option; if (m_suggestedOption) return m_suggestedOption; // TODO(tkent): We should not call optionToBeShown() in multiple() case. @@ -1923,8 +1903,9 @@ return m_lastOnChangeOption; } -void HTMLSelectElement::valueChanged(unsigned listIndex) +void HTMLSelectElement::selectOptionByPopup(int listIndex) { + DCHECK(usesMenuList()); // Check to ensure a page navigation has not occurred while the popup was // up. Document& doc = document(); @@ -1932,13 +1913,23 @@ return; setIndexToSelectOnCancel(-1); - optionSelectedByUser(listToOptionIndex(listIndex), true); + + HTMLOptionElement* option = optionAtListIndex(listIndex); + // Bail out if this index is already the selected one, to avoid running + // unnecessary JavaScript that can mess up autofill when there is no actual + // change (see https://bugs.webkit.org/show_bug.cgi?id=35256 and + // <rdar://7467917>). The selectOption function does not behave this way, + // possibly because other callers need a change event even in cases where + // the selected option is not change. + if (option == selectedOption()) + return; + selectOption(option, DeselectOtherOptions | MakeOptionDirty | DispatchInputAndChangeEvent); } void HTMLSelectElement::popupDidCancel() { if (m_indexToSelectOnCancel >= 0) - valueChanged(m_indexToSelectOnCancel); + selectOptionByPopup(m_indexToSelectOnCancel); } void HTMLSelectElement::provisionalSelectionChanged(unsigned listIndex)
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElement.h b/third_party/WebKit/Source/core/html/HTMLSelectElement.h index 37055b45..f4fa8c787 100644 --- a/third_party/WebKit/Source/core/html/HTMLSelectElement.h +++ b/third_party/WebKit/Source/core/html/HTMLSelectElement.h
@@ -56,8 +56,6 @@ int selectedIndex() const; void setSelectedIndex(int); - void optionSelectedByUser(int index, bool dispatchChangeEvent, bool allowMultipleSelection = false); - // For ValidityState String validationMessage() const override; bool valueMissing() const override; @@ -114,8 +112,6 @@ void scrollToSelection(); void scrollToOption(HTMLOptionElement*); - void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow = true); - bool canSelectAll() const; void selectAll(); int listToOptionIndex(int listIndex) const; @@ -153,7 +149,8 @@ LayoutUnit clientPaddingLeft() const; // Text starting offset in RTL. LayoutUnit clientPaddingRight() const; - void valueChanged(unsigned listIndex); + void selectOptionByPopup(int listIndex); + void selectMultipleOptionsByPopup(const Vector<int>& listIndices); // A popup is canceled when the popup was hidden without selecting an item. void popupDidCancel(); // Provisional selection is a selection made using arrow keys or type ahead. @@ -244,6 +241,9 @@ void setIndexToSelectOnCancel(int listIndex); void setSuggestedOption(HTMLOptionElement*); + // Returns nullptr if listIndex is out of bounds, or it doesn't point an + // HTMLOptionElement. + HTMLOptionElement* optionAtListIndex(int listIndex) const; enum SkipDirection { SkipBackwards = -1, SkipForwards = 1
diff --git a/third_party/WebKit/Source/core/html/HTMLSelectElementTest.cpp b/third_party/WebKit/Source/core/html/HTMLSelectElementTest.cpp index 1b94a3d..2b8044b 100644 --- a/third_party/WebKit/Source/core/html/HTMLSelectElementTest.cpp +++ b/third_party/WebKit/Source/core/html/HTMLSelectElementTest.cpp
@@ -102,6 +102,38 @@ EXPECT_TRUE(opt3->selected()); } +TEST_F(HTMLSelectElementTest, RestoreUnmatchedFormControlState) +{ + // We had a bug that selectedOption() and m_lastOnChangeOption were + // mismatched in optionToBeShown(). It happened when + // restoreFormControlState() couldn't find matched OPTIONs. + // crbug.com/627833. + + document().documentElement()->setInnerHTML("<select id='sel'>" + "<option selected>Default</option>" + "<option id='2'>222</option>" + "</select>", ASSERT_NO_EXCEPTION); + document().view()->updateAllLifecyclePhases(); + Element* element = document().getElementById("sel"); + HTMLFormControlElementWithState* select = toHTMLSelectElement(element); + HTMLOptionElement* opt2 = toHTMLOptionElement(document().getElementById("2")); + + toHTMLSelectElement(element)->setSelectedIndex(1); + // Save the current state. + FormControlState selectState = select->saveFormControlState(); + EXPECT_EQ(2U, selectState.valueSize()); + + // Reset the status. + select->reset(); + ASSERT_FALSE(opt2->selected()); + element->removeChild(opt2); + + // Restore + select->restoreFormControlState(selectState); + EXPECT_EQ(-1, toHTMLSelectElement(element)->selectedIndex()); + EXPECT_EQ(nullptr, toHTMLSelectElement(element)->optionToBeShown()); +} + TEST_F(HTMLSelectElementTest, ElementRectRelativeToViewport) { document().documentElement()->setInnerHTML("<select style='position:fixed; top:12.3px; height:24px; -webkit-appearance:none;'><option>o1</select>", ASSERT_NO_EXCEPTION);
diff --git a/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp b/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp index 04ae3c0f..7aaf6d0 100644 --- a/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLVideoElement.cpp
@@ -327,7 +327,7 @@ return IntSize(videoWidth(), videoHeight()); } -ScriptPromise HTMLVideoElement::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, int sx, int sy, int sw, int sh, const ImageBitmapOptions& options, ExceptionState& exceptionState) +ScriptPromise HTMLVideoElement::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, Optional<IntRect> cropRect, const ImageBitmapOptions& options, ExceptionState& exceptionState) { DCHECK(eventTarget.toLocalDOMWindow()); if (getNetworkState() == HTMLMediaElement::NETWORK_EMPTY) { @@ -338,11 +338,12 @@ exceptionState.throwDOMException(InvalidStateError, "The provided element's player has no current data."); return ScriptPromise(); } - if (!sw || !sh) { - exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width")); + if ((cropRect && !ImageBitmap::isSourceSizeValid(cropRect->width(), cropRect->height(), exceptionState)) + || !ImageBitmap::isSourceSizeValid(bitmapSourceSize().width(), bitmapSourceSize().height(), exceptionState)) return ScriptPromise(); - } - return ImageBitmapSource::fulfillImageBitmap(scriptState, ImageBitmap::create(this, IntRect(sx, sy, sw, sh), eventTarget.toLocalDOMWindow()->document(), options)); + if (!ImageBitmap::isResizeOptionValid(options, exceptionState)) + return ScriptPromise(); + return ImageBitmapSource::fulfillImageBitmap(scriptState, ImageBitmap::create(this, cropRect, eventTarget.toLocalDOMWindow()->document(), options)); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/HTMLVideoElement.h b/third_party/WebKit/Source/core/html/HTMLVideoElement.h index f6c45f2..56df0a12 100644 --- a/third_party/WebKit/Source/core/html/HTMLVideoElement.h +++ b/third_party/WebKit/Source/core/html/HTMLVideoElement.h
@@ -90,7 +90,7 @@ // ImageBitmapSource implementation IntSize bitmapSourceSize() const override; - ScriptPromise createImageBitmap(ScriptState*, EventTarget&, int sx, int sy, int sw, int sh, const ImageBitmapOptions&, ExceptionState&) override; + ScriptPromise createImageBitmap(ScriptState*, EventTarget&, Optional<IntRect> cropRect, const ImageBitmapOptions&, ExceptionState&) override; private: HTMLVideoElement(Document&);
diff --git a/third_party/WebKit/Source/core/html/ImageData.cpp b/third_party/WebKit/Source/core/html/ImageData.cpp index 5cf5773..68e82d6 100644 --- a/third_party/WebKit/Source/core/html/ImageData.cpp +++ b/third_party/WebKit/Source/core/html/ImageData.cpp
@@ -146,17 +146,18 @@ return new ImageData(IntSize(width, height), data); } -ScriptPromise ImageData::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, int sx, int sy, int sw, int sh, const ImageBitmapOptions& options, ExceptionState& exceptionState) +ScriptPromise ImageData::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, Optional<IntRect> cropRect, const ImageBitmapOptions& options, ExceptionState& exceptionState) { - if (!sw || !sh) { - exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width")); + if ((cropRect && !ImageBitmap::isSourceSizeValid(cropRect->width(), cropRect->height(), exceptionState)) + || !ImageBitmap::isSourceSizeValid(bitmapSourceSize().width(), bitmapSourceSize().height(), exceptionState)) return ScriptPromise(); - } if (data()->bufferBase()->isNeutered()) { exceptionState.throwDOMException(InvalidStateError, "The source data has been neutered."); return ScriptPromise(); } - return ImageBitmapSource::fulfillImageBitmap(scriptState, ImageBitmap::create(this, IntRect(sx, sy, sw, sh), options)); + if (!ImageBitmap::isResizeOptionValid(options, exceptionState)) + return ScriptPromise(); + return ImageBitmapSource::fulfillImageBitmap(scriptState, ImageBitmap::create(this, cropRect, options)); } v8::Local<v8::Object> ImageData::associateWithWrapper(v8::Isolate* isolate, const WrapperTypeInfo* wrapperType, v8::Local<v8::Object> wrapper)
diff --git a/third_party/WebKit/Source/core/html/ImageData.h b/third_party/WebKit/Source/core/html/ImageData.h index 71905d1..4000134 100644 --- a/third_party/WebKit/Source/core/html/ImageData.h +++ b/third_party/WebKit/Source/core/html/ImageData.h
@@ -59,7 +59,7 @@ // ImageBitmapSource implementation IntSize bitmapSourceSize() const override { return m_size; } - ScriptPromise createImageBitmap(ScriptState*, EventTarget&, int sx, int sy, int sw, int sh, const ImageBitmapOptions&, ExceptionState&) override; + ScriptPromise createImageBitmap(ScriptState*, EventTarget&, Optional<IntRect> cropRect, const ImageBitmapOptions&, ExceptionState&) override; DEFINE_INLINE_TRACE() {
diff --git a/third_party/WebKit/Source/core/html/LinkResource.cpp b/third_party/WebKit/Source/core/html/LinkResource.cpp index b213219..3a5b0fe 100644 --- a/third_party/WebKit/Source/core/html/LinkResource.cpp +++ b/third_party/WebKit/Source/core/html/LinkResource.cpp
@@ -78,7 +78,9 @@ FetchRequest LinkRequestBuilder::build(bool lowPriority) const { ResourceLoadPriority priority = lowPriority ? ResourceLoadPriorityVeryLow : ResourceLoadPriorityUnresolved; - return FetchRequest(ResourceRequest(m_owner->document().completeURL(m_url)), m_owner->localName(), m_charset, priority); + FetchRequest request(ResourceRequest(m_owner->document().completeURL(m_url)), m_owner->localName(), m_charset, priority); + request.setContentSecurityPolicyNonce(m_owner->fastGetAttribute(HTMLNames::nonceAttr)); + return request; } } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/RelList.cpp b/third_party/WebKit/Source/core/html/RelList.cpp index 3b4bd7d..a05e349 100644 --- a/third_party/WebKit/Source/core/html/RelList.cpp +++ b/third_party/WebKit/Source/core/html/RelList.cpp
@@ -37,28 +37,31 @@ m_relValues.set(value, SpaceSplitString::ShouldNotFoldCase); } -static RelList::SupportedTokens& supportedTokens() +static HashSet<AtomicString>& supportedTokens() { - DEFINE_STATIC_LOCAL(RelList::SupportedTokens, supportedValuesMap, ()); - if (supportedValuesMap.isEmpty()) { - supportedValuesMap.add("preload"); - supportedValuesMap.add("preconnect"); - supportedValuesMap.add("dns-prefetch"); - supportedValuesMap.add("stylesheet"); - supportedValuesMap.add("import"); - supportedValuesMap.add("icon"); - supportedValuesMap.add("alternate"); - supportedValuesMap.add("prefetch"); - supportedValuesMap.add("prerender"); - supportedValuesMap.add("next"); - supportedValuesMap.add("manifest"); - supportedValuesMap.add("apple-touch-icon"); - supportedValuesMap.add("apple-touch-icon-precomposed"); + DEFINE_STATIC_LOCAL(HashSet<AtomicString>, tokens, ()); + + if (tokens.isEmpty()) { + tokens = { + "preload", + "preconnect", + "dns-prefetch", + "stylesheet", + "import", + "icon", + "alternate", + "prefetch", + "prerender", + "next", + "manifest", + "apple-touch-icon", + "apple-touch-icon-precomposed", + }; if (RuntimeEnabledFeatures::linkServiceWorkerEnabled()) - supportedValuesMap.add("serviceworker"); + tokens.add("serviceworker"); } - return supportedValuesMap; + return tokens; } bool RelList::validateTokenValue(const AtomicString& tokenValue, ExceptionState&) const
diff --git a/third_party/WebKit/Source/core/html/RelList.h b/third_party/WebKit/Source/core/html/RelList.h index 0da3940..3c0a363 100644 --- a/third_party/WebKit/Source/core/html/RelList.h +++ b/third_party/WebKit/Source/core/html/RelList.h
@@ -27,8 +27,6 @@ DECLARE_VIRTUAL_TRACE(); - using SupportedTokens = HashSet<AtomicString>; - private: explicit RelList(Element*);
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp index 9df01a1..16f6e89 100644 --- a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp +++ b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.cpp
@@ -4,6 +4,8 @@ #include "core/html/canvas/CanvasAsyncBlobCreator.h" +#include "core/dom/Document.h" +#include "core/dom/TaskRunnerHelper.h" #include "core/fileapi/Blob.h" #include "platform/CrossThreadFunctional.h" #include "platform/Histogram.h" @@ -80,13 +82,14 @@ } // anonymous namespace -CanvasAsyncBlobCreator* CanvasAsyncBlobCreator::create(DOMUint8ClampedArray* unpremultipliedRGBAImageData, const String& mimeType, const IntSize& size, BlobCallback* callback, double startTime) +CanvasAsyncBlobCreator* CanvasAsyncBlobCreator::create(DOMUint8ClampedArray* unpremultipliedRGBAImageData, const String& mimeType, const IntSize& size, BlobCallback* callback, double startTime, Document* document) { - return new CanvasAsyncBlobCreator(unpremultipliedRGBAImageData, convertMimeTypeStringToEnum(mimeType), size, callback, startTime); + return new CanvasAsyncBlobCreator(unpremultipliedRGBAImageData, convertMimeTypeStringToEnum(mimeType), size, callback, startTime, document); } -CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(DOMUint8ClampedArray* data, MimeType mimeType, const IntSize& size, BlobCallback* callback, double startTime) +CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(DOMUint8ClampedArray* data, MimeType mimeType, const IntSize& size, BlobCallback* callback, double startTime, Document* document) : m_data(data) + , m_document(document) , m_size(size) , m_mimeType(mimeType) , m_callback(callback) @@ -215,7 +218,7 @@ toBlobPNGIdleEncodeCounter.count(m_elapsedTime * 1000000.0); if (isDeadlineNearOrPassed(deadlineSeconds)) { - Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback, wrapPersistent(this))); + TaskRunnerHelper::getUnthrottledTaskRunner(m_document)->postTask(BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback, wrapPersistent(this))); } else { this->createBlobAndInvokeCallback(); } @@ -236,7 +239,7 @@ DEFINE_STATIC_LOCAL(CustomCountHistogram, toBlobJPEGIdleEncodeCounter, ("Blink.Canvas.ToBlob.IdleEncodeDuration.JPEG", 0, 10000000, 50)); toBlobJPEGIdleEncodeCounter.count(m_elapsedTime * 1000000.0); if (isDeadlineNearOrPassed(deadlineSeconds)) { - Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback, wrapPersistent(this))); + TaskRunnerHelper::getUnthrottledTaskRunner(m_document)->postTask(BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback, wrapPersistent(this))); } else { this->createBlobAndInvokeCallback(); } @@ -301,7 +304,7 @@ toBlobWEBPCounter.count(elapsedTime * 1000000.0); } Blob* resultBlob = Blob::create(m_encodedImage->data(), m_encodedImage->size(), convertMimeTypeEnumToString(m_mimeType)); - Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, WTF::bind(&BlobCallback::handleEvent, wrapPersistent(m_callback.get()), wrapPersistent(resultBlob))); + TaskRunnerHelper::getUnthrottledTaskRunner(m_document)->postTask(BLINK_FROM_HERE, WTF::bind(&BlobCallback::handleEvent, wrapPersistent(m_callback.get()), wrapPersistent(resultBlob))); // Avoid unwanted retention, see dispose(). dispose(); } @@ -310,7 +313,7 @@ { ASSERT(isMainThread()); recordIdleTaskStatusHistogram(); - Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, WTF::bind(&BlobCallback::handleEvent, wrapPersistent(m_callback.get()), nullptr)); + TaskRunnerHelper::getUnthrottledTaskRunner(m_document)->postTask(BLINK_FROM_HERE, WTF::bind(&BlobCallback::handleEvent, wrapPersistent(m_callback.get()), nullptr)); // Avoid unwanted retention, see dispose(). dispose(); } @@ -321,11 +324,11 @@ ASSERT(m_mimeType == MimeTypeWebp); if (!ImageDataBuffer(m_size, m_data->data()).encodeImage("image/webp", quality, m_encodedImage.get())) { - Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, crossThreadBind(&BlobCallback::handleEvent, wrapCrossThreadPersistent(m_callback.get()), nullptr)); + TaskRunnerHelper::getUnthrottledTaskRunner(m_document)->postTask(BLINK_FROM_HERE, crossThreadBind(&BlobCallback::handleEvent, wrapCrossThreadPersistent(m_callback.get()), nullptr)); return; } - Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, crossThreadBind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback, wrapCrossThreadPersistent(this))); + TaskRunnerHelper::getUnthrottledTaskRunner(m_document)->postTask(BLINK_FROM_HERE, crossThreadBind(&CanvasAsyncBlobCreator::createBlobAndInvokeCallback, wrapCrossThreadPersistent(this))); } bool CanvasAsyncBlobCreator::initializePngStruct() @@ -362,7 +365,7 @@ if (m_mimeType == MimeTypePng) { if (initializePngStruct()) { - Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::encodeRowsPngOnMainThread, wrapPersistent(this))); + TaskRunnerHelper::getUnthrottledTaskRunner(m_document)->postTask(BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::encodeRowsPngOnMainThread, wrapPersistent(this))); } else { // Failing in initialization of png struct this->signalAlternativeCodePathFinishedForTesting(); @@ -370,7 +373,7 @@ } else { ASSERT(m_mimeType == MimeTypeJpeg); if (initializeJpegStruct(quality)) { - Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread, wrapPersistent(this))); + TaskRunnerHelper::getUnthrottledTaskRunner(m_document)->postTask(BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread, wrapPersistent(this))); } else { // Failing in initialization of jpeg struct this->signalAlternativeCodePathFinishedForTesting(); @@ -392,10 +395,10 @@ signalTaskSwitchInCompleteTimeoutEventForTesting(); if (m_mimeType == MimeTypePng) { - Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::encodeRowsPngOnMainThread, wrapPersistent(this))); + TaskRunnerHelper::getUnthrottledTaskRunner(m_document)->postTask(BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::encodeRowsPngOnMainThread, wrapPersistent(this))); } else { ASSERT(m_mimeType == MimeTypeJpeg); - Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread, wrapPersistent(this))); + TaskRunnerHelper::getUnthrottledTaskRunner(m_document)->postTask(BLINK_FROM_HERE, WTF::bind(&CanvasAsyncBlobCreator::encodeRowsJpegOnMainThread, wrapPersistent(this))); } } else { ASSERT(m_idleTaskStatus == IdleTaskFailed || m_idleTaskStatus == IdleTaskCompleted); @@ -406,7 +409,14 @@ void CanvasAsyncBlobCreator::postDelayedTaskToMainThread(const WebTraceLocation& location, std::unique_ptr<WTF::Closure> task, double delayMs) { DCHECK(isMainThread()); - Platform::current()->mainThread()->getWebTaskRunner()->postDelayedTask(location, std::move(task), delayMs); + TaskRunnerHelper::getUnthrottledTaskRunner(m_document)->postDelayedTask(location, std::move(task), delayMs); +} + +DEFINE_TRACE(CanvasAsyncBlobCreator) +{ + visitor->trace(m_document); + visitor->trace(m_data); + visitor->trace(m_callback); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.h b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.h index 913fe6e..0b97243 100644 --- a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.h +++ b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreator.h
@@ -13,12 +13,13 @@ namespace blink { -class PNGImageEncoderState; +class Document; class JPEGImageEncoderState; +class PNGImageEncoderState; class CORE_EXPORT CanvasAsyncBlobCreator : public GarbageCollectedFinalized<CanvasAsyncBlobCreator> { public: - static CanvasAsyncBlobCreator* create(DOMUint8ClampedArray* unpremultipliedRGBAImageData, const String& mimeType, const IntSize&, BlobCallback*, double); + static CanvasAsyncBlobCreator* create(DOMUint8ClampedArray* unpremultipliedRGBAImageData, const String& mimeType, const IntSize&, BlobCallback*, double, Document*); void scheduleAsyncBlobCreation(bool canUseIdlePeriodScheduling, const double& quality = 0.0); virtual ~CanvasAsyncBlobCreator(); enum MimeType { @@ -41,14 +42,10 @@ virtual void signalTaskSwitchInStartTimeoutEventForTesting() { } virtual void signalTaskSwitchInCompleteTimeoutEventForTesting() { } - DEFINE_INLINE_VIRTUAL_TRACE() - { - visitor->trace(m_data); - visitor->trace(m_callback); - } + DECLARE_VIRTUAL_TRACE(); protected: - CanvasAsyncBlobCreator(DOMUint8ClampedArray* data, MimeType, const IntSize&, BlobCallback*, double); + CanvasAsyncBlobCreator(DOMUint8ClampedArray* data, MimeType, const IntSize&, BlobCallback*, double, Document*); // Methods are virtual for unit testing virtual void scheduleInitiatePngEncoding(); virtual void scheduleInitiateJpegEncoding(const double&); @@ -73,6 +70,7 @@ Member<DOMUint8ClampedArray> m_data; std::unique_ptr<Vector<unsigned char>> m_encodedImage; int m_numRowsCompleted; + Member<Document> m_document; const IntSize m_size; size_t m_pixelRowStride;
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreatorTest.cpp b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreatorTest.cpp index 09c1972..dd4d5e8 100644 --- a/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreatorTest.cpp +++ b/third_party/WebKit/Source/core/html/canvas/CanvasAsyncBlobCreatorTest.cpp
@@ -18,7 +18,7 @@ class MockCanvasAsyncBlobCreator : public CanvasAsyncBlobCreator { public: MockCanvasAsyncBlobCreator(DOMUint8ClampedArray* data, const IntSize& size, MimeType mimeType) - : CanvasAsyncBlobCreator(data, mimeType, size, nullptr, 0) + : CanvasAsyncBlobCreator(data, mimeType, size, nullptr, 0, nullptr) { }
diff --git a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp index e9eb5f63..24816256 100644 --- a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp +++ b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.cpp
@@ -159,7 +159,7 @@ m_lastSeenEncodingData = encodingData; m_xssAuditor->setEncoding(encodingData.encoding()); - runOnMainThread(crossThreadBind(&HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser, m_parser, encodingData)); + runOnMainThread(&HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser, m_parser, encodingData); } if (decodedData.isEmpty()) @@ -317,7 +317,7 @@ chunkEnqueueTime.count(monotonicallyIncreasingTimeMS() - chunkStartTime); if (isEmpty) { - runOnMainThread(crossThreadBind(&HTMLDocumentParser::notifyPendingParsedChunks, m_parser)); + runOnMainThread(&HTMLDocumentParser::notifyPendingParsedChunks, m_parser); } m_pendingTokens = wrapUnique(new CompactHTMLTokenStream); @@ -328,12 +328,14 @@ // main parser deals with chunking up its own work. // TODO(csharrison): This is a pretty big hack because we don't actually need a // CrossThreadClosure in these cases. This is just experimental. -void BackgroundHTMLParser::runOnMainThread(std::unique_ptr<CrossThreadClosure> closure) +template <typename FunctionType, typename... Ps> +void BackgroundHTMLParser::runOnMainThread(FunctionType function, Ps&&... parameters) { - if (isMainThread()) - (*closure)(); - else - m_loadingTaskRunner->postTask(BLINK_FROM_HERE, std::move(closure)); + if (isMainThread()) { + (*WTF::bind(function, std::forward<Ps>(parameters)...))(); + } else { + m_loadingTaskRunner->postTask(BLINK_FROM_HERE, crossThreadBind(function, std::forward<Ps>(parameters)...)); + } } } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h index 85564bb..b7b7306 100644 --- a/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h +++ b/third_party/WebKit/Source/core/html/parser/BackgroundHTMLParser.h
@@ -98,7 +98,8 @@ void sendTokensToMainThread(); void updateDocument(const String& decodedData); - void runOnMainThread(std::unique_ptr<CrossThreadClosure>); + template <typename FunctionType, typename... Ps> + void runOnMainThread(FunctionType, Ps&&...); WeakPtrFactory<BackgroundHTMLParser> m_weakFactory; BackgroundHTMLInputStream m_input;
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp index 7acad44..33ce143 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp
@@ -32,6 +32,7 @@ #include "core/dom/DocumentFragment.h" #include "core/dom/DocumentType.h" #include "core/dom/Element.h" +#include "core/dom/ElementTraversal.h" #include "core/dom/ScriptLoader.h" #include "core/dom/TemplateContentDocumentFragment.h" #include "core/dom/Text.h" @@ -324,14 +325,19 @@ ASSERT(m_document->isHTMLDocument() || m_document->isXHTMLDocument()); } -void HTMLConstructionSite::initFragmentParsing(DocumentFragment* fragment) +void HTMLConstructionSite::initFragmentParsing(DocumentFragment* fragment, Element* contextElement) { + DCHECK(contextElement); DCHECK_EQ(m_document, &fragment->document()); DCHECK_EQ(m_inQuirksMode, fragment->document().inQuirksMode()); DCHECK(!m_isParsingFragment); + DCHECK(!m_form); m_attachmentRoot = fragment; m_isParsingFragment = true; + + if (!contextElement->document().isTemplateDocument()) + m_form = Traversal<HTMLFormElement>::firstAncestorOrSelf(*contextElement); } HTMLConstructionSite::~HTMLConstructionSite() @@ -366,13 +372,6 @@ m_attachmentRoot = nullptr; } -void HTMLConstructionSite::setForm(HTMLFormElement* form) -{ - // This method should only be needed for HTMLTreeBuilder in the fragment case. - ASSERT(!m_form); - m_form = form; -} - HTMLFormElement* HTMLConstructionSite::takeForm() { return m_form.release(); @@ -600,10 +599,12 @@ { HTMLElement* element = createHTMLElement(token); ASSERT(isHTMLFormElement(element)); - m_form = toHTMLFormElement(element); - m_form->setDemoted(isDemoted); - attachLater(currentNode(), m_form.get()); - m_openElements.push(HTMLStackItem::create(m_form.get(), token)); + HTMLFormElement* formElement = toHTMLFormElement(element); + if (!ownerDocumentForCurrentNode().isTemplateDocument()) + m_form = formElement; + formElement->setDemoted(isDemoted); + attachLater(currentNode(), formElement); + m_openElements.push(HTMLStackItem::create(formElement, token)); } void HTMLConstructionSite::insertHTMLElement(AtomicHTMLToken* token) @@ -751,7 +752,7 @@ Document& document = ownerDocumentForCurrentNode(); // Only associate the element with the current form if we're creating the new element // in a document with a browsing context (rather than in <template> contents). - HTMLFormElement* form = document.frame() ? m_form.get() : 0; + HTMLFormElement* form = document.frame() ? m_form.get() : nullptr; // FIXME: This can't use HTMLConstructionSite::createElement because we // have to pass the current form element. We should rework form association // to occur after construction to allow better code sharing here.
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.h b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.h index ea9952d..3d661623 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.h +++ b/third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.h
@@ -113,7 +113,7 @@ ~HTMLConstructionSite(); DECLARE_TRACE(); - void initFragmentParsing(DocumentFragment*); + void initFragmentParsing(DocumentFragment*, Element* contextElement); void detach(); @@ -196,8 +196,7 @@ Element* head() const { return m_head->element(); } HTMLStackItem* headStackItem() const { return m_head.get(); } - void setForm(HTMLFormElement*); - HTMLFormElement* form() const { return m_form.get(); } + bool isFormElementPointerNonNull() const { return m_form; } HTMLFormElement* takeForm(); ParserContentPolicy getParserContentPolicy() { return m_parserContentPolicy; } @@ -251,7 +250,9 @@ // and a Document in all other cases. Member<ContainerNode> m_attachmentRoot; + // https://html.spec.whatwg.org/multipage/syntax.html#head-element-pointer Member<HTMLStackItem> m_head; + // https://html.spec.whatwg.org/multipage/syntax.html#form-element-pointer Member<HTMLFormElement> m_form; mutable HTMLElementStack m_openElements; mutable HTMLFormattingElementList m_activeFormattingElements;
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp index d2552b0..7908a5d 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp
@@ -30,6 +30,7 @@ #include "core/css/resolver/StyleResolver.h" #include "core/dom/DocumentFragment.h" #include "core/dom/Element.h" +#include "core/dom/TaskRunnerHelper.h" #include "core/fetch/ResourceFetcher.h" #include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" @@ -111,7 +112,7 @@ , m_options(&document) , m_token(syncPolicy == ForceSynchronousParsing ? wrapUnique(new HTMLToken) : nullptr) , m_tokenizer(syncPolicy == ForceSynchronousParsing ? HTMLTokenizer::create(m_options) : nullptr) - , m_loadingTaskRunner(wrapUnique(document.loadingTaskRunner()->clone())) + , m_loadingTaskRunner(wrapUnique(TaskRunnerHelper::getLoadingTaskRunner(&document)->clone())) , m_parserScheduler(syncPolicy == AllowAsynchronousParsing ? HTMLParserScheduler::create(this, m_loadingTaskRunner.get()) : nullptr) , m_xssAuditorDelegate(&document) , m_weakFactory(this) @@ -314,13 +315,19 @@ // after the document element is created in documentElementAvailable(). ASSERT(m_queuedPreloads.isEmpty()); ASSERT(m_queuedDocumentWriteScripts.isEmpty()); + // Loop through the chunks to generate preloads before any + // document.write script evaluation takes place. Preloading these + // scripts is valuable and comparably cheap, while evaluating JS can be + // expensive. + for (auto& chunk : pendingChunks) { + m_preloader->takeAndPreload(chunk->preloads); + } for (auto& chunk : pendingChunks) { for (auto& index : chunk->likelyDocumentWriteScriptIndices) { const CompactHTMLToken& token = chunk->tokens->at(index); ASSERT(token.type() == HTMLToken::TokenType::Character); evaluateAndPreloadScriptForDocumentWrite(token.data()); } - m_preloader->takeAndPreload(chunk->preloads); } } @@ -403,7 +410,7 @@ m_input.current().clear(); // FIXME: This should be passed in instead of cleared. ASSERT(checkpoint->unparsedInput.isSafeToSendToAnotherThread()); - postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::resumeFrom, m_backgroundParser, passed(std::move(checkpoint)))); + postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::resumeFrom, m_backgroundParser, passed(std::move(checkpoint))); } size_t HTMLDocumentParser::processParsedChunkFromBackgroundParser(std::unique_ptr<ParsedChunk> popChunk) @@ -425,7 +432,7 @@ std::unique_ptr<CompactHTMLTokenStream> tokens = std::move(chunk->tokens); size_t elementTokenCount = 0; - postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::startedChunkWithCheckpoint, m_backgroundParser, chunk->inputCheckpoint)); + postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::startedChunkWithCheckpoint, m_backgroundParser, chunk->inputCheckpoint); for (const auto& xssInfo : chunk->xssInfos) { m_textPosition = xssInfo->m_textPosition; @@ -556,7 +563,7 @@ if (!m_haveBackgroundParser) startBackgroundParser(); - postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::forcePlaintextForTextDocument, m_backgroundParser)); + postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::forcePlaintextForTextDocument, m_backgroundParser); } else m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); } @@ -732,14 +739,15 @@ } ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); - postTaskToLookaheadParser(crossThreadBind( + postTaskToLookaheadParser( + Synchronous, &BackgroundHTMLParser::start, reference.release(), passed(std::move(config)), document()->url(), passed(CachedDocumentParameters::create(document())), MediaValuesCached::MediaValuesCachedData(*document()), - passed(wrapUnique(m_loadingTaskRunner->clone()))), Synchronous); + passed(wrapUnique(m_loadingTaskRunner->clone()))); } void HTMLDocumentParser::stopBackgroundParser() @@ -751,7 +759,7 @@ // Make this sync, as lsan triggers on some unittests if the task runner is // used. Note that these lifetimes will be much more concrete if // ParseHTMLOnMainThread lands (the lookahead parser will be a member). - postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::stop, m_backgroundParser), Synchronous); + postTaskToLookaheadParser(Synchronous, &BackgroundHTMLParser::stop, m_backgroundParser); m_weakFactory.revokeAll(); } @@ -859,7 +867,7 @@ if (m_haveBackgroundParser) { if (!m_input.haveSeenEndOfFile()) m_input.closeWithoutMarkingEndOfFile(); - postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::finish, m_backgroundParser)); + postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::finish, m_backgroundParser); return; } @@ -1025,7 +1033,8 @@ memcpy(buffer->data(), data, length); TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), "HTMLDocumentParser::appendBytes", "size", (unsigned)length); - postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::appendRawBytesFromMainThread, m_backgroundParser, passed(std::move(buffer)), bytesReceivedTime)); + LookaheadParserTaskSynchrony policy = document()->settings() && document()->settings()->parseHTMLOnMainThreadSyncTokenize() ? Synchronous : Asynchronous; + postTaskToLookaheadParser(policy, &BackgroundHTMLParser::appendRawBytesFromMainThread, m_backgroundParser, passed(std::move(buffer)), bytesReceivedTime); return; } @@ -1049,7 +1058,7 @@ return; } - postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::flush, m_backgroundParser)); + postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::flush, m_backgroundParser); } else { DecodedDataDocumentParser::flush(); } @@ -1061,20 +1070,21 @@ DecodedDataDocumentParser::setDecoder(std::move(decoder)); if (m_haveBackgroundParser) - postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::setDecoder, m_backgroundParser, passed(takeDecoder()))); + postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::setDecoder, m_backgroundParser, passed(takeDecoder())); } void HTMLDocumentParser::documentElementAvailable() { TRACE_EVENT0("blink,loader", "HTMLDocumentParser::documentElementAvailable"); DCHECK(document()->documentElement()); + if (!m_queuedPreloads.isEmpty()) + m_preloader->takeAndPreload(m_queuedPreloads); + for (const String& scriptSource : m_queuedDocumentWriteScripts) { evaluateAndPreloadScriptForDocumentWrite(scriptSource); } m_queuedDocumentWriteScripts.clear(); - if (!m_queuedPreloads.isEmpty()) - m_preloader->takeAndPreload(m_queuedPreloads); } std::unique_ptr<HTMLPreloadScanner> HTMLDocumentParser::createPreloadScanner() @@ -1125,10 +1135,11 @@ } } -void HTMLDocumentParser::postTaskToLookaheadParser(std::unique_ptr<CrossThreadClosure> closure, LookaheadParserTaskSynchrony synchronyPolicy) +template <typename FunctionType, typename... Ps> +void HTMLDocumentParser::postTaskToLookaheadParser(LookaheadParserTaskSynchrony synchronyPolicy, FunctionType function, Ps&&... parameters) { if (!RuntimeEnabledFeatures::parseHTMLOnMainThreadEnabled()) { - HTMLParserThread::shared()->postTask(std::move(closure)); + HTMLParserThread::shared()->postTask(crossThreadBind(function, std::forward<Ps>(parameters)...)); return; } @@ -1136,10 +1147,10 @@ // just post to the loading task runner. switch (synchronyPolicy) { case Synchronous: - (*closure)(); + (*WTF::bind(function, std::forward<Ps>(parameters)...))(); return; case Asynchronous: - m_loadingTaskRunner->postTask(BLINK_FROM_HERE, std::move(closure)); + m_loadingTaskRunner->postTask(BLINK_FROM_HERE, WTF::bind(function, std::forward<Ps>(parameters)...)); return; } NOTREACHED();
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h index 1b20554f..e5bfe85 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h +++ b/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h
@@ -189,10 +189,12 @@ Asynchronous, }; - // Setting |sync| to true will just call the closure. Note, this method is - // completely temporary as we need to maintain both threading - // implementations until the ParseHTMLOnMainThread experiment finishes. - void postTaskToLookaheadParser(std::unique_ptr<CrossThreadClosure>, LookaheadParserTaskSynchrony = Asynchronous); + // Setting |synchronyPolicy| to Synchronous will just call the function + // with the given parameters. Note, this method is completely temporary + // as we need to maintain both threading implementations until the + // ParseHTMLOnMainThread experiment finishes. + template <typename FunctionType, typename... Ps> + void postTaskToLookaheadParser(LookaheadParserTaskSynchrony synchronyPolicy, FunctionType, Ps&&... parameters); HTMLToken& token() { return *m_token; }
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp index 14ecba3..09e657f 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScanner.cpp
@@ -243,6 +243,7 @@ ReferrerPolicy referrerPolicy = (m_referrerPolicy != ReferrerPolicyDefault) ? m_referrerPolicy : documentReferrerPolicy; std::unique_ptr<PreloadRequest> request = PreloadRequest::create(initiatorFor(m_tagImpl), position, m_urlToLoad, predictedBaseURL, type, referrerPolicy, resourceWidth, clientHintsPreferences, requestType); request->setCrossOrigin(m_crossOrigin); + request->setNonce(m_nonce); request->setCharset(charset()); request->setDefer(m_defer); request->setIntegrityMetadata(m_integrityMetadata); @@ -258,6 +259,8 @@ setUrlToLoad(attributeValue, DisallowURLReplacement); else if (match(attributeName, crossoriginAttr)) setCrossOrigin(attributeValue); + else if (match(attributeName, nonceAttr)) + setNonce(attributeValue); else if (match(attributeName, asyncAttr)) setDefer(FetchRequest::LazyLoad); else if (match(attributeName, deferAttr)) @@ -315,6 +318,8 @@ m_matched &= mediaAttributeMatches(*m_mediaValues, attributeValue); } else if (match(attributeName, crossoriginAttr)) { setCrossOrigin(attributeValue); + } else if (match(attributeName, nonceAttr)) { + setNonce(attributeValue); } else if (match(attributeName, asAttr)) { m_asAttributeValue = attributeValue; } else if (match(attributeName, typeAttr)) { @@ -448,6 +453,11 @@ m_crossOrigin = crossOriginAttributeValue(corsSetting); } + void setNonce(const String& nonce) + { + m_nonce = nonce; + } + void setDefer(FetchRequest::DeferOption defer) { m_defer = defer; @@ -475,6 +485,7 @@ bool m_sourceSizeSet; FetchRequest::DeferOption m_defer; CrossOriginAttributeValue m_crossOrigin; + String m_nonce; Member<MediaValuesCached> m_mediaValues; bool m_referrerPolicySet; ReferrerPolicy m_referrerPolicy;
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerTest.cpp b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerTest.cpp index bc584d1e..a2f1aec 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerTest.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLPreloadScannerTest.cpp
@@ -44,6 +44,12 @@ ReferrerPolicy referrerPolicy; }; +struct NonceTestCase { + const char* baseURL; + const char* inputHTML; + const char* nonce; +}; + class MockHTMLResourcePreloader : public ResourcePreloader { public: void preloadRequestVerification(Resource::Type type, const char* url, const char* baseURL, int width, const ClientHintsPreferences& preferences) @@ -80,6 +86,15 @@ } } + void nonceRequestVerification(const char* nonce) + { + ASSERT_TRUE(m_preloadRequest.get()); + if (strlen(nonce)) + EXPECT_EQ(nonce, m_preloadRequest->nonce()); + else + EXPECT_TRUE(m_preloadRequest->nonce().isEmpty()); + } + protected: void preload(std::unique_ptr<PreloadRequest> preloadRequest, const NetworkHintsInterface&) override { @@ -171,6 +186,16 @@ preloader.preloadRequestVerification(testCase.type, testCase.preloadedURL, testCase.outputBaseURL, testCase.resourceWidth, testCase.referrerPolicy); } + void test(NonceTestCase testCase) + { + MockHTMLResourcePreloader preloader; + KURL baseURL(ParsedURLString, testCase.baseURL); + m_scanner->appendToEnd(String(testCase.inputHTML)); + m_scanner->scanAndPreload(&preloader, baseURL, nullptr); + + preloader.nonceRequestVerification(testCase.nonce); + } + private: std::unique_ptr<DummyPageHolder> m_dummyPageHolder; std::unique_ptr<HTMLPreloadScanner> m_scanner; @@ -374,6 +399,31 @@ test(testCase); } +TEST_F(HTMLPreloadScannerTest, testNonce) +{ + NonceTestCase testCases[] = { + { "http://example.test", "<script src='/script'></script>", "" }, + { "http://example.test", "<script src='/script' nonce=''></script>", "" }, + { "http://example.test", "<script src='/script' nonce='abc'></script>", "abc" }, + { "http://example.test", "<link rel='import' href='/import'>", "" }, + { "http://example.test", "<link rel='import' href='/import' nonce=''>", "" }, + { "http://example.test", "<link rel='import' href='/import' nonce='abc'>", "abc" }, + { "http://example.test", "<link rel='stylesheet' href='/style'>", "" }, + { "http://example.test", "<link rel='stylesheet' href='/style' nonce=''>", "" }, + { "http://example.test", "<link rel='stylesheet' href='/style' nonce='abc'>", "abc" }, + + // <img> doesn't support nonces: + { "http://example.test", "<img src='/image'>", "" }, + { "http://example.test", "<img src='/image' nonce=''>", "" }, + { "http://example.test", "<img src='/image' nonce='abc'>", "" }, + }; + + for (const auto& testCase : testCases) { + SCOPED_TRACE(testCase.inputHTML); + test(testCase); + } +} + // Tests that a document-level referrer policy (e.g. one set by HTTP // header) is applied for preload requests. TEST_F(HTMLPreloadScannerTest, testReferrerPolicyOnDocument)
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp b/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp index f5839e7..01c77ad 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLScriptRunner.cpp
@@ -32,6 +32,7 @@ #include "core/dom/Element.h" #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h" #include "core/dom/ScriptLoader.h" +#include "core/dom/TaskRunnerHelper.h" #include "core/events/Event.h" #include "core/fetch/ScriptResource.h" #include "core/frame/LocalFrame.h" @@ -358,7 +359,7 @@ if (m_document->frame()) { ScriptState* scriptState = ScriptState::forMainWorld(m_document->frame()); if (scriptState) - ScriptStreamer::startStreaming(m_parserBlockingScript.get(), ScriptStreamer::ParsingBlocking, m_document->frame()->settings(), scriptState, m_document->loadingTaskRunner()); + ScriptStreamer::startStreaming(m_parserBlockingScript.get(), ScriptStreamer::ParsingBlocking, m_document->frame()->settings(), scriptState, TaskRunnerHelper::getLoadingTaskRunner(m_document)); } m_parserBlockingScript->watchForLoad(this); @@ -374,7 +375,7 @@ if (m_document->frame() && !pendingScript->isReady()) { ScriptState* scriptState = ScriptState::forMainWorld(m_document->frame()); if (scriptState) - ScriptStreamer::startStreaming(pendingScript, ScriptStreamer::Deferred, m_document->frame()->settings(), scriptState, m_document->loadingTaskRunner()); + ScriptStreamer::startStreaming(pendingScript, ScriptStreamer::Deferred, m_document->frame()->settings(), scriptState, TaskRunnerHelper::getLoadingTaskRunner(m_document)); } ASSERT(pendingScript->resource());
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp b/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp index 7e8382c6..7461e3f6 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLTreeBuilder.cpp
@@ -38,6 +38,7 @@ #include "core/frame/UseCounter.h" #include "core/html/HTMLDocument.h" #include "core/html/HTMLFormElement.h" +#include "core/html/HTMLTemplateElement.h" #include "core/html/parser/AtomicHTMLToken.h" #include "core/html/parser/HTMLDocumentParser.h" #include "core/html/parser/HTMLParserIdioms.h" @@ -133,12 +134,6 @@ return tagName == aTag || isNonAnchorFormattingTag(tagName); } -static HTMLFormElement* closestFormAncestor(Element& element) -{ - ASSERT(isMainThread()); - return Traversal<HTMLFormElement>::firstAncestorOrSelf(element); -} - class HTMLTreeBuilder::CharacterTokenBuffer { WTF_MAKE_NONCOPYABLE(CharacterTokenBuffer); public: @@ -287,7 +282,7 @@ { ASSERT(isMainThread()); ASSERT(contextElement); - m_tree.initFragmentParsing(fragment); + m_tree.initFragmentParsing(fragment, contextElement); m_fragmentContext.init(fragment, contextElement); // Steps 4.2-4.6 of the HTML5 Fragment Case parsing algorithm: @@ -300,7 +295,6 @@ m_templateInsertionModes.append(TemplateContentsMode); resetInsertionModeAppropriately(); - m_tree.setForm(closestFormAncestor(*contextElement)); } HTMLTreeBuilder::~HTMLTreeBuilder() @@ -674,7 +668,7 @@ return; } if (token->name() == formTag) { - if (m_tree.form()) { + if (m_tree.isFormElementPointerNonNull() && !isParsingTemplateContents()) { parseError(token); return; } @@ -1039,7 +1033,7 @@ } if (token->name() == formTag) { parseError(token); - if (m_tree.form()) + if (m_tree.isFormElementPointerNonNull() && !isParsingTemplateContents()) return; m_tree.insertHTMLFormElement(token, true); m_tree.openElements()->pop(); @@ -1791,7 +1785,7 @@ m_tree.openElements()->popUntilPopped(token->name()); return; } - if (token->name() == formTag) { + if (token->name() == formTag && !isParsingTemplateContents()) { Element* node = m_tree.takeForm(); if (!node || !m_tree.openElements()->inScope(node)) { parseError(token);
diff --git a/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.cpp b/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.cpp index b3f5675..525ac2d 100644 --- a/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.cpp +++ b/third_party/WebKit/Source/core/html/parser/HTMLViewSourceParser.cpp
@@ -73,7 +73,10 @@ { if (!m_input.haveSeenEndOfFile()) m_input.markEndOfFile(); - pumpTokenizer(); + + if (!isDetached()) + pumpTokenizer(); + document()->finishedParsing(); }
diff --git a/third_party/WebKit/Source/core/html/parser/ParsedChunkQueue.cpp b/third_party/WebKit/Source/core/html/parser/ParsedChunkQueue.cpp index 7adda76..77ac1d90 100644 --- a/third_party/WebKit/Source/core/html/parser/ParsedChunkQueue.cpp +++ b/third_party/WebKit/Source/core/html/parser/ParsedChunkQueue.cpp
@@ -4,12 +4,38 @@ #include "core/html/parser/ParsedChunkQueue.h" +#include "platform/RuntimeEnabledFeatures.h" #include <algorithm> #include <memory> namespace blink { +namespace { + +// TODO(csharrison): Remove this temporary class when the ParseHTMLOnMainThread +// experiment ends. +class MaybeLocker { +public: + MaybeLocker(Mutex* mutex) + : m_mutex(mutex) + { + if (m_mutex) + m_mutex->lock(); + } + ~MaybeLocker() + { + if (m_mutex) + m_mutex->unlock(); + } + +private: + Mutex* m_mutex; +}; + +} // namespace + ParsedChunkQueue::ParsedChunkQueue() + : m_mutex(RuntimeEnabledFeatures::parseHTMLOnMainThreadEnabled() ? nullptr : new Mutex) { } @@ -19,7 +45,7 @@ bool ParsedChunkQueue::enqueue(std::unique_ptr<HTMLDocumentParser::ParsedChunk> chunk) { - MutexLocker locker(m_mutex); + MaybeLocker locker(m_mutex.get()); m_pendingTokenCount += chunk->tokens->size(); m_peakPendingTokenCount = std::max(m_peakPendingTokenCount, m_pendingTokenCount); @@ -33,7 +59,7 @@ void ParsedChunkQueue::clear() { - MutexLocker locker(m_mutex); + MaybeLocker locker(m_mutex.get()); m_pendingTokenCount = 0; m_pendingChunks.clear(); @@ -41,7 +67,7 @@ void ParsedChunkQueue::takeAll(Vector<std::unique_ptr<HTMLDocumentParser::ParsedChunk>>& vector) { - MutexLocker locker(m_mutex); + MaybeLocker locker(m_mutex.get()); ASSERT(vector.isEmpty()); m_pendingChunks.swap(vector); @@ -49,13 +75,13 @@ size_t ParsedChunkQueue::peakPendingChunkCount() { - MutexLocker locker(m_mutex); + MaybeLocker locker(m_mutex.get()); return m_peakPendingChunkCount; } size_t ParsedChunkQueue::peakPendingTokenCount() { - MutexLocker locker(m_mutex); + MaybeLocker locker(m_mutex.get()); return m_peakPendingTokenCount; }
diff --git a/third_party/WebKit/Source/core/html/parser/ParsedChunkQueue.h b/third_party/WebKit/Source/core/html/parser/ParsedChunkQueue.h index b28e324..bfa964b1 100644 --- a/third_party/WebKit/Source/core/html/parser/ParsedChunkQueue.h +++ b/third_party/WebKit/Source/core/html/parser/ParsedChunkQueue.h
@@ -42,7 +42,7 @@ private: ParsedChunkQueue(); - Mutex m_mutex; + std::unique_ptr<Mutex> m_mutex; Vector<std::unique_ptr<HTMLDocumentParser::ParsedChunk>> m_pendingChunks; size_t m_peakPendingChunkCount = 0; size_t m_peakPendingTokenCount = 0;
diff --git a/third_party/WebKit/Source/core/html/parser/PreloadRequest.cpp b/third_party/WebKit/Source/core/html/parser/PreloadRequest.cpp index 8093323..0071af1 100644 --- a/third_party/WebKit/Source/core/html/parser/PreloadRequest.cpp +++ b/third_party/WebKit/Source/core/html/parser/PreloadRequest.cpp
@@ -47,6 +47,7 @@ request.setResourceWidth(m_resourceWidth); request.clientHintsPreferences().updateFrom(m_clientHintsPreferences); request.setIntegrityMetadata(m_integrityMetadata); + request.setContentSecurityPolicyNonce(m_nonce); if (m_requestType == RequestTypeLinkRelPreload) request.setLinkPreload(true);
diff --git a/third_party/WebKit/Source/core/html/parser/PreloadRequest.h b/third_party/WebKit/Source/core/html/parser/PreloadRequest.h index 9154fff2..c4ac3a38 100644 --- a/third_party/WebKit/Source/core/html/parser/PreloadRequest.h +++ b/third_party/WebKit/Source/core/html/parser/PreloadRequest.h
@@ -46,6 +46,10 @@ { return m_crossOrigin; } + + void setNonce(const String& nonce) { m_nonce = nonce.isolatedCopy(); } + const String& nonce() const { return m_nonce; } + Resource::Type resourceType() const { return m_resourceType; } const String& resourceURL() const { return m_resourceURL; } @@ -97,6 +101,7 @@ String m_charset; Resource::Type m_resourceType; CrossOriginAttributeValue m_crossOrigin; + String m_nonce; double m_discoveryTime; FetchRequest::DeferOption m_defer; FetchRequest::ResourceWidth m_resourceWidth;
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp index 6949fe78..d8ad4a89 100644 --- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp +++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.cpp
@@ -86,8 +86,12 @@ return nullptr; } -ScriptPromise ImageBitmapFactories::createImageBitmapFromBlob(ScriptState* scriptState, EventTarget& eventTarget, ImageBitmapSource* bitmapSource, const IntRect& cropRect, const ImageBitmapOptions& options) +ScriptPromise ImageBitmapFactories::createImageBitmapFromBlob(ScriptState* scriptState, EventTarget& eventTarget, ImageBitmapSource* bitmapSource, Optional<IntRect> cropRect, const ImageBitmapOptions& options, ExceptionState& exceptionState) { + if (cropRect && !ImageBitmap::isSourceSizeValid(cropRect->width(), cropRect->height(), exceptionState)) + return ScriptPromise(); + if (!ImageBitmap::isResizeOptionValid(options, exceptionState)) + return ScriptPromise(); Blob* blob = static_cast<Blob*>(bitmapSource); ImageBitmapLoader* loader = ImageBitmapFactories::ImageBitmapLoader::create(from(eventTarget), cropRect, options, scriptState); ScriptPromise promise = loader->promise(); @@ -103,10 +107,7 @@ ImageBitmapSource* bitmapSourceInternal = toImageBitmapSourceInternal(bitmapSource, exceptionState, false); if (!bitmapSourceInternal) return ScriptPromise(); - if (bitmapSourceInternal->isBlob()) - return createImageBitmapFromBlob(scriptState, eventTarget, bitmapSourceInternal, IntRect(), options); - IntSize srcSize = bitmapSourceInternal->bitmapSourceSize(); - return createImageBitmap(scriptState, eventTarget, bitmapSourceInternal, 0, 0, srcSize.width(), srcSize.height(), options, exceptionState); + return createImageBitmap(scriptState, eventTarget, bitmapSourceInternal, Optional<IntRect>(), options, exceptionState); } ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, const ImageBitmapSourceUnion& bitmapSource, int sx, int sy, int sw, int sh, const ImageBitmapOptions& options, ExceptionState& exceptionState) @@ -116,20 +117,16 @@ ImageBitmapSource* bitmapSourceInternal = toImageBitmapSourceInternal(bitmapSource, exceptionState, true); if (!bitmapSourceInternal) return ScriptPromise(); - return createImageBitmap(scriptState, eventTarget, bitmapSourceInternal, sx, sy, sw, sh, options, exceptionState); + Optional<IntRect> cropRect = IntRect(sx, sy, sw, sh); + return createImageBitmap(scriptState, eventTarget, bitmapSourceInternal, cropRect, options, exceptionState); } -ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, ImageBitmapSource* bitmapSource, int sx, int sy, int sw, int sh, const ImageBitmapOptions& options, ExceptionState& exceptionState) +ScriptPromise ImageBitmapFactories::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, ImageBitmapSource* bitmapSource, Optional<IntRect> cropRect, const ImageBitmapOptions& options, ExceptionState& exceptionState) { - if (bitmapSource->isBlob()) { - if (!sw || !sh) { - exceptionState.throwDOMException(IndexSizeError, String::format("The source %s provided is 0.", sw ? "height" : "width")); - return ScriptPromise(); - } - return createImageBitmapFromBlob(scriptState, eventTarget, bitmapSource, IntRect(sx, sy, sw, sh), options); - } + if (bitmapSource->isBlob()) + return createImageBitmapFromBlob(scriptState, eventTarget, bitmapSource, cropRect, options, exceptionState); - return bitmapSource->createImageBitmap(scriptState, eventTarget, sx, sy, sw, sh, options, exceptionState); + return bitmapSource->createImageBitmap(scriptState, eventTarget, cropRect, options, exceptionState); } const char* ImageBitmapFactories::supplementName() @@ -168,7 +165,7 @@ m_pendingLoaders.remove(loader); } -ImageBitmapFactories::ImageBitmapLoader::ImageBitmapLoader(ImageBitmapFactories& factory, const IntRect& cropRect, ScriptState* scriptState, const ImageBitmapOptions& options) +ImageBitmapFactories::ImageBitmapLoader::ImageBitmapLoader(ImageBitmapFactories& factory, Optional<IntRect> cropRect, ScriptState* scriptState, const ImageBitmapOptions& options) : m_loader(FileReaderLoader::ReadAsArrayBuffer, this) , m_factory(&factory) , m_resolver(ScriptPromiseResolver::create(scriptState)) @@ -220,19 +217,19 @@ if (arrayBuffer->byteLength() >= longTaskByteLengthThreshold) taskSize = BackgroundTaskRunner::TaskSizeLongRunningTask; WebTaskRunner* taskRunner = Platform::current()->currentThread()->getWebTaskRunner(); - BackgroundTaskRunner::postOnBackgroundThread(BLINK_FROM_HERE, crossThreadBind(&ImageBitmapFactories::ImageBitmapLoader::decodeImageOnDecoderThread, wrapCrossThreadPersistent(this), crossThreadUnretained(taskRunner), wrapCrossThreadPersistent(arrayBuffer)), taskSize); + BackgroundTaskRunner::postOnBackgroundThread(BLINK_FROM_HERE, crossThreadBind(&ImageBitmapFactories::ImageBitmapLoader::decodeImageOnDecoderThread, wrapCrossThreadPersistent(this), crossThreadUnretained(taskRunner), wrapCrossThreadPersistent(arrayBuffer), m_options.premultiplyAlpha(), m_options.colorSpaceConversion()), taskSize); } -void ImageBitmapFactories::ImageBitmapLoader::decodeImageOnDecoderThread(WebTaskRunner* taskRunner, DOMArrayBuffer* arrayBuffer) +void ImageBitmapFactories::ImageBitmapLoader::decodeImageOnDecoderThread(WebTaskRunner* taskRunner, DOMArrayBuffer* arrayBuffer, const String& premultiplyAlphaOption, const String& colorSpaceConversionOption) { ASSERT(!isMainThread()); RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(static_cast<char*>(arrayBuffer->data()), static_cast<size_t>(arrayBuffer->byteLength())); ImageDecoder::AlphaOption alphaOp = ImageDecoder::AlphaPremultiplied; - if (m_options.premultiplyAlpha() == "none") + if (premultiplyAlphaOption == "none") alphaOp = ImageDecoder::AlphaNotPremultiplied; ImageDecoder::GammaAndColorProfileOption colorSpaceOp = ImageDecoder::GammaAndColorProfileApplied; - if (m_options.colorSpaceConversion() == "none") + if (colorSpaceConversionOption == "none") colorSpaceOp = ImageDecoder::GammaAndColorProfileIgnored; std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create(*sharedBuffer, alphaOp, colorSpaceOp)); RefPtr<SkImage> frame; @@ -253,10 +250,6 @@ RefPtr<StaticBitmapImage> image = StaticBitmapImage::create(frame); image->setOriginClean(true); - if (!m_cropRect.width() && !m_cropRect.height()) { - // No cropping variant was called. - m_cropRect = IntRect(IntPoint(), image->size()); - } ImageBitmap* imageBitmap = ImageBitmap::create(image, m_cropRect, m_options); if (imageBitmap && imageBitmap->bitmapImage()) {
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h index d17c2cc..de3f72a 100644 --- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h +++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapFactories.h
@@ -61,8 +61,8 @@ public: static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, const ImageBitmapSourceUnion&, const ImageBitmapOptions&, ExceptionState&); static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, const ImageBitmapSourceUnion&, int sx, int sy, int sw, int sh, const ImageBitmapOptions&, ExceptionState&); - static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, ImageBitmapSource*, int sx, int sy, int sw, int sh, const ImageBitmapOptions&, ExceptionState&); - static ScriptPromise createImageBitmapFromBlob(ScriptState*, EventTarget&, ImageBitmapSource*, const IntRect&, const ImageBitmapOptions&); + static ScriptPromise createImageBitmap(ScriptState*, EventTarget&, ImageBitmapSource*, Optional<IntRect> cropRect, const ImageBitmapOptions&, ExceptionState&); + static ScriptPromise createImageBitmapFromBlob(ScriptState*, EventTarget&, ImageBitmapSource*, Optional<IntRect> cropRect, const ImageBitmapOptions&, ExceptionState&); virtual ~ImageBitmapFactories() { } @@ -74,7 +74,7 @@ private: class ImageBitmapLoader final : public GarbageCollectedFinalized<ImageBitmapLoader>, public FileReaderLoaderClient { public: - static ImageBitmapLoader* create(ImageBitmapFactories& factory, const IntRect& cropRect, const ImageBitmapOptions& options, ScriptState* scriptState) + static ImageBitmapLoader* create(ImageBitmapFactories& factory, Optional<IntRect> cropRect, const ImageBitmapOptions& options, ScriptState* scriptState) { return new ImageBitmapLoader(factory, cropRect, scriptState, options); } @@ -87,12 +87,12 @@ ~ImageBitmapLoader() override { } private: - ImageBitmapLoader(ImageBitmapFactories&, const IntRect&, ScriptState*, const ImageBitmapOptions&); + ImageBitmapLoader(ImageBitmapFactories&, Optional<IntRect> cropRect, ScriptState*, const ImageBitmapOptions&); void rejectPromise(); void scheduleAsyncImageBitmapDecoding(DOMArrayBuffer*); - void decodeImageOnDecoderThread(WebTaskRunner*, DOMArrayBuffer*); + void decodeImageOnDecoderThread(WebTaskRunner*, DOMArrayBuffer*, const String& premultiplyAlphaOption, const String& colorSpaceConversionOption); void resolvePromiseOnOriginalThread(PassRefPtr<SkImage>); // FileReaderLoaderClient @@ -104,7 +104,7 @@ FileReaderLoader m_loader; Member<ImageBitmapFactories> m_factory; Member<ScriptPromiseResolver> m_resolver; - IntRect m_cropRect; + Optional<IntRect> m_cropRect; ImageBitmapOptions m_options; };
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapOptions.idl b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapOptions.idl index 68b9d2f..e83c42ef 100644 --- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapOptions.idl +++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapOptions.idl
@@ -7,8 +7,12 @@ enum ImageOrientation { "none", "flipY" }; enum PremultiplyAlpha { "none", "premultiply", "default" }; enum ColorSpaceConversion { "none", "default" }; +[RuntimeEnabled=ExperimentalCanvasFeatures] enum ResizeQuality { "pixelated", "low", "medium", "high" }; dictionary ImageBitmapOptions { ImageOrientation imageOrientation = "none"; PremultiplyAlpha premultiplyAlpha = "default"; ColorSpaceConversion colorSpaceConversion = "default"; + [RuntimeEnabled=ExperimentalCanvasFeatures, EnforceRange] unsigned long? resizeWidth; + [RuntimeEnabled=ExperimentalCanvasFeatures, EnforceRange] unsigned long? resizeHeight; + [RuntimeEnabled=ExperimentalCanvasFeatures] ResizeQuality resizeQuality = "low"; };
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapSource.cpp b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapSource.cpp index 850e3627..b776048 100644 --- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapSource.cpp +++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapSource.cpp
@@ -21,7 +21,7 @@ return promise; } -ScriptPromise ImageBitmapSource::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, int sx, int sy, int sw, int sh, const ImageBitmapOptions& options, ExceptionState& exceptionState) +ScriptPromise ImageBitmapSource::createImageBitmap(ScriptState* scriptState, EventTarget& eventTarget, Optional<IntRect> cropRect, const ImageBitmapOptions& options, ExceptionState& exceptionState) { return ScriptPromise(); }
diff --git a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapSource.h b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapSource.h index 4e15f7f..0d1c78d 100644 --- a/third_party/WebKit/Source/core/imagebitmap/ImageBitmapSource.h +++ b/third_party/WebKit/Source/core/imagebitmap/ImageBitmapSource.h
@@ -10,7 +10,9 @@ #include "bindings/core/v8/ScriptState.h" #include "core/CoreExport.h" #include "core/dom/ExceptionCode.h" +#include "platform/geometry/IntRect.h" #include "platform/geometry/IntSize.h" +#include "third_party/WebKit/Source/wtf/Optional.h" namespace blink { @@ -20,7 +22,7 @@ class CORE_EXPORT ImageBitmapSource { public: virtual IntSize bitmapSourceSize() const { return IntSize(); } - virtual ScriptPromise createImageBitmap(ScriptState*, EventTarget&, int sx, int sy, int sw, int sh, const ImageBitmapOptions&, ExceptionState&); + virtual ScriptPromise createImageBitmap(ScriptState*, EventTarget&, Optional<IntRect>, const ImageBitmapOptions&, ExceptionState&); virtual bool isBlob() const { return false; }
diff --git a/third_party/WebKit/Source/core/input/ScrollManager.cpp b/third_party/WebKit/Source/core/input/ScrollManager.cpp index 4ca7998..33e6f466a 100644 --- a/third_party/WebKit/Source/core/input/ScrollManager.cpp +++ b/third_party/WebKit/Source/core/input/ScrollManager.cpp
@@ -16,6 +16,7 @@ #include "core/page/AutoscrollController.h" #include "core/page/Page.h" #include "core/page/scrolling/OverscrollController.h" +#include "core/page/scrolling/RootScrollerController.h" #include "core/page/scrolling/ScrollState.h" #include "core/paint/PaintLayer.h" #include "platform/PlatformGestureEvent.h" @@ -194,10 +195,6 @@ if (document->layoutViewItem().isNull()) return WebInputEventResult::NotHandled; - FrameView* view = m_frame->view(); - if (!view) - return WebInputEventResult::NotHandled; - // If there's no layoutObject on the node, send the event to the nearest ancestor with a layoutObject. // Needed for <option> and <optgroup> elements so we can touch scroll <select>s while (m_scrollGestureHandlingNode && !m_scrollGestureHandlingNode->layoutObject()) @@ -350,12 +347,15 @@ if (!node.isElementNode()) return false; - return node.isSameNode(m_frame->document()->effectiveRootScroller()); + return node.isSameNode(m_frame->document()->rootScrollerController()->effectiveRootScroller()); } WebInputEventResult ScrollManager::handleGestureScrollEvent(const PlatformGestureEvent& gestureEvent) { + if (!m_frame->view()) + return WebInputEventResult::NotHandled; + Node* eventTarget = nullptr; Scrollbar* scrollbar = nullptr; if (gestureEvent.type() != PlatformEvent::GestureScrollBegin) {
diff --git a/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp b/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp index 446c84c..f1584a95 100644 --- a/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp +++ b/third_party/WebKit/Source/core/inspector/ConsoleMessage.cpp
@@ -18,6 +18,7 @@ return consoleMessage; } +// static ConsoleMessage* ConsoleMessage::create(MessageSource source, MessageLevel level, const String& message, std::unique_ptr<SourceLocation> location) { return new ConsoleMessage(source, level, message, std::move(location)); @@ -29,6 +30,14 @@ return ConsoleMessage::create(source, level, message, SourceLocation::capture()); } +// static +ConsoleMessage* ConsoleMessage::createFromWorker(MessageLevel level, const String& message, std::unique_ptr<SourceLocation> location, const String& workerId) +{ + ConsoleMessage* consoleMessage = ConsoleMessage::create(WorkerMessageSource, level, message, std::move(location)); + consoleMessage->m_workerId = workerId; + return consoleMessage; +} + ConsoleMessage::ConsoleMessage(MessageSource source, MessageLevel level, const String& message, @@ -76,6 +85,11 @@ return m_message; } +const String& ConsoleMessage::workerId() const +{ + return m_workerId; +} + DEFINE_TRACE(ConsoleMessage) { }
diff --git a/third_party/WebKit/Source/core/inspector/ConsoleMessage.h b/third_party/WebKit/Source/core/inspector/ConsoleMessage.h index 4d0b11f..d6e316d9 100644 --- a/third_party/WebKit/Source/core/inspector/ConsoleMessage.h +++ b/third_party/WebKit/Source/core/inspector/ConsoleMessage.h
@@ -29,6 +29,9 @@ // This method captures current location. static ConsoleMessage* createForRequest(MessageSource, MessageLevel, const String& message, const String& url, unsigned long requestIdentifier); + // This creates message from WorkerMessageSource. + static ConsoleMessage* createFromWorker(MessageLevel, const String& message, std::unique_ptr<SourceLocation>, const String& workerId); + ~ConsoleMessage(); SourceLocation* location() const; @@ -37,6 +40,7 @@ MessageSource source() const; MessageLevel level() const; const String& message() const; + const String& workerId() const; DECLARE_TRACE(); @@ -49,6 +53,7 @@ std::unique_ptr<SourceLocation> m_location; unsigned long m_requestIdentifier; double m_timestamp; + String m_workerId; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp index 8ffa771b..3c4a778 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp
@@ -129,7 +129,7 @@ { Decimal decimal = Decimal::fromDouble(keyframe->offset() * 100); String offset = decimal.toString(); - offset.append("%"); + offset.append('%'); std::unique_ptr<protocol::Animation::KeyframeStyle> keyframeObject = protocol::Animation::KeyframeStyle::create() .setOffset(offset) @@ -375,7 +375,7 @@ ScriptState::Scope scope(scriptState); m_v8Session->releaseObjectGroup("animation"); - *result = m_v8Session->wrapObject(scriptState->context(), toV8(animation, scriptState->context()->Global(), scriptState->isolate()), "animation"); + *result = m_v8Session->wrapObject(scriptState->context(), toV8(animation, scriptState->context()->Global(), scriptState->isolate()), "animation", false); if (!*result) *errorString = "Element not associated with a document."; }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp index d1679c3c..b9f6f8f 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMAgent.cpp
@@ -2053,7 +2053,7 @@ return nullptr; ScriptState::Scope scope(scriptState); - return m_v8Session->wrapObject(scriptState->context(), nodeV8Value(scriptState->context(), node), objectGroup); + return m_v8Session->wrapObject(scriptState->context(), nodeV8Value(scriptState->context(), node), objectGroup, false); } bool InspectorDOMAgent::pushDocumentUponHandlelessOperation(ErrorString* errorString)
diff --git a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp index 8316c404..224fc37 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorDOMDebuggerAgent.cpp
@@ -466,11 +466,11 @@ .setPassive(info.passive) .setLocation(std::move(location)).build(); if (!objectGroupId.isEmpty()) { - value->setHandler(m_v8Session->wrapObject(context, function, objectGroupId)); - value->setOriginalHandler(m_v8Session->wrapObject(context, info.handler, objectGroupId)); + value->setHandler(m_v8Session->wrapObject(context, function, objectGroupId, false)); + value->setOriginalHandler(m_v8Session->wrapObject(context, info.handler, objectGroupId, false)); v8::Local<v8::Function> removeFunction; if (info.removeFunction.ToLocal(&removeFunction)) - value->setRemoveFunction(m_v8Session->wrapObject(context, removeFunction, objectGroupId)); + value->setRemoveFunction(m_v8Session->wrapObject(context, removeFunction, objectGroupId, false)); } return value; }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.cpp b/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.cpp index 14b60e3..11df652 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorInstrumentation.cpp
@@ -174,7 +174,7 @@ bool isDebuggerPaused(LocalFrame*) { - return MainThreadDebugger::instance()->debugger()->isPaused(); + return MainThreadDebugger::instance()->isPaused(); } void didReceiveResourceResponseButCanceled(LocalFrame* frame, DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r, Resource* resource)
diff --git a/third_party/WebKit/Source/core/inspector/InspectorSession.cpp b/third_party/WebKit/Source/core/inspector/InspectorSession.cpp index b83ad56..5044d5c 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorSession.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorSession.cpp
@@ -163,11 +163,6 @@ m_client->profilingStopped(); } -void InspectorSession::consoleEnabled() -{ - m_client->consoleEnabled(); -} - void InspectorSession::consoleCleared() { m_client->consoleCleared();
diff --git a/third_party/WebKit/Source/core/inspector/InspectorSession.h b/third_party/WebKit/Source/core/inspector/InspectorSession.h index 3f31c00..8a9abbe 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorSession.h +++ b/third_party/WebKit/Source/core/inspector/InspectorSession.h
@@ -37,7 +37,6 @@ virtual void resumeStartup() { } virtual void profilingStarted() { } virtual void profilingStopped() { } - virtual void consoleEnabled() { } virtual void consoleCleared() { } virtual ~Client() {} }; @@ -68,7 +67,6 @@ bool canExecuteScripts() override; void profilingStarted() override; void profilingStopped() override; - void consoleEnabled() override; void consoleCleared() override; Client* m_client;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp b/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp index 0698b14..1fdc7f4 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorStyleSheet.cpp
@@ -646,20 +646,20 @@ StringBuilder builder; builder.append(styleRule->selectorText()); - builder.append("{"); + builder.append('{'); for (unsigned i = 0; i < propertyNames.size(); ++i) { String name = propertyNames.at(i); - builder.append(" "); + builder.append(' '); builder.append(name); - builder.append(":"); + builder.append(':'); builder.append(style->getPropertyValue(name)); if (!style->getPropertyPriority(name).isEmpty()) { - builder.append(" "); + builder.append(' '); builder.append(style->getPropertyPriority(name)); } - builder.append(";"); + builder.append(';'); } - builder.append("}"); + builder.append('}'); return builder.toString(); }
diff --git a/third_party/WebKit/Source/core/inspector/MainThreadDebugger.cpp b/third_party/WebKit/Source/core/inspector/MainThreadDebugger.cpp index e8c6b9c..11826ccc 100644 --- a/third_party/WebKit/Source/core/inspector/MainThreadDebugger.cpp +++ b/third_party/WebKit/Source/core/inspector/MainThreadDebugger.cpp
@@ -82,6 +82,8 @@ MainThreadDebugger::MainThreadDebugger(v8::Isolate* isolate) : ThreadDebugger(isolate) , m_taskRunner(wrapUnique(new InspectorTaskRunner())) + , m_paused(false) + , m_muteConsoleCount(0) { MutexLocker locker(creationMutex()); ASSERT(!s_instance); @@ -125,9 +127,30 @@ void MainThreadDebugger::exceptionThrown(LocalFrame* frame, const String& errorMessage, std::unique_ptr<SourceLocation> location) { + if (m_muteConsoleCount) + return; debugger()->exceptionThrown(contextGroupId(frame), errorMessage, location->url(), location->lineNumber(), location->columnNumber(), location->cloneStackTrace(), location->scriptId()); } +bool MainThreadDebugger::addConsoleMessage(LocalFrame* frame, ConsoleMessage* consoleMessage) +{ + if (m_muteConsoleCount) + return false; + debugger()->addConsoleMessage( + contextGroupId(frame), + consoleMessage->source(), + consoleMessage->level(), + consoleMessage->message(), + consoleMessage->location()->url(), + consoleMessage->location()->lineNumber(), + consoleMessage->location()->columnNumber(), + consoleMessage->location()->cloneStackTrace(), + consoleMessage->location()->scriptId(), + IdentifiersFactory::requestId(consoleMessage->requestIdentifier()), + consoleMessage->workerId()); + return true; +} + int MainThreadDebugger::contextGroupId(LocalFrame* frame) { LocalFrame* localFrameRoot = frame->localFrameRoot(); @@ -158,6 +181,7 @@ if (!pausedFrame) return; ASSERT(pausedFrame == pausedFrame->localFrameRoot()); + m_paused = true; if (UserGestureToken* token = UserGestureIndicator::currentToken()) token->setPauseInDebugger(); @@ -168,6 +192,7 @@ void MainThreadDebugger::quitMessageLoopOnPause() { + m_paused = false; if (m_clientMessageLoop) m_clientMessageLoop->quitNow(); } @@ -175,11 +200,13 @@ void MainThreadDebugger::muteWarningsAndDeprecations() { UseCounter::muteForInspector(); + m_muteConsoleCount++; } void MainThreadDebugger::unmuteWarningsAndDeprecations() { UseCounter::unmuteForInspector(); + m_muteConsoleCount--; } bool MainThreadDebugger::callingContextCanAccessContext(v8::Local<v8::Context> calling, v8::Local<v8::Context> target)
diff --git a/third_party/WebKit/Source/core/inspector/MainThreadDebugger.h b/third_party/WebKit/Source/core/inspector/MainThreadDebugger.h index 9c649e4..9ef345d9 100644 --- a/third_party/WebKit/Source/core/inspector/MainThreadDebugger.h +++ b/third_party/WebKit/Source/core/inspector/MainThreadDebugger.h
@@ -41,6 +41,7 @@ namespace blink { +class ConsoleMessage; class LocalFrame; class SecurityOrigin; class SourceLocation; @@ -64,6 +65,7 @@ InspectorTaskRunner* taskRunner() const { return m_taskRunner.get(); } bool isWorker() override { return false; } + bool isPaused() const { return m_paused; } void setClientMessageLoop(std::unique_ptr<ClientMessageLoop>); // TODO(dgozman): by making this method virtual, we can move many methods to ThreadDebugger and avoid some duplication. Should be careful about performance. int contextGroupId(LocalFrame*); @@ -71,6 +73,7 @@ void contextCreated(ScriptState*, LocalFrame*, SecurityOrigin*); void contextWillBeDestroyed(ScriptState*); void exceptionThrown(LocalFrame*, const String& errorMessage, std::unique_ptr<SourceLocation>); + bool addConsoleMessage(LocalFrame*, ConsoleMessage*); void installAdditionalCommandLineAPI(v8::Local<v8::Context>, v8::Local<v8::Object>) override; @@ -88,6 +91,8 @@ std::unique_ptr<ClientMessageLoop> m_clientMessageLoop; std::unique_ptr<InspectorTaskRunner> m_taskRunner; + bool m_paused; + int m_muteConsoleCount; static MainThreadDebugger* s_instance;
diff --git a/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp b/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp index 80e3085..e938a9a 100644 --- a/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp +++ b/third_party/WebKit/Source/core/inspector/ThreadDebugger.cpp
@@ -298,9 +298,7 @@ V8EventListenerInfoList listenerInfo; // eventListeners call can produce message on ErrorEvent during lazy event listener compilation. debugger->muteWarningsAndDeprecations(); - debugger->debugger()->muteConsole(); InspectorDOMDebuggerAgent::eventListenersInfoForTarget(isolate, info[0], listenerInfo); - debugger->debugger()->unmuteConsole(); debugger->unmuteWarningsAndDeprecations(); v8::Local<v8::Object> result = v8::Object::New(isolate);
diff --git a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp index dcd248a..fcd952fa0 100644 --- a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp +++ b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.cpp
@@ -96,11 +96,6 @@ m_workerGlobalScope->thread()->stopRunningDebuggerTasksOnPauseOnWorkerThread(); } -void WorkerInspectorController::consoleEnabled() -{ - m_workerGlobalScope->thread()->workerReportingProxy().postWorkerConsoleAgentEnabled(); -} - void WorkerInspectorController::sendProtocolMessage(int sessionId, int callId, const String& response, const String& state) { // Worker messages are wrapped, no need to handle callId or state.
diff --git a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.h b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.h index db6969b9..3e0fcb3 100644 --- a/third_party/WebKit/Source/core/inspector/WorkerInspectorController.h +++ b/third_party/WebKit/Source/core/inspector/WorkerInspectorController.h
@@ -71,7 +71,6 @@ // InspectorSession::Client implementation. void sendProtocolMessage(int sessionId, int callId, const String& response, const String& state) override; void resumeStartup() override; - void consoleEnabled() override; WorkerThreadDebugger* m_debugger; Member<WorkerGlobalScope> m_workerGlobalScope;
diff --git a/third_party/WebKit/Source/core/inspector/WorkerThreadDebugger.cpp b/third_party/WebKit/Source/core/inspector/WorkerThreadDebugger.cpp index 9aaf4a3..e5f734e 100644 --- a/third_party/WebKit/Source/core/inspector/WorkerThreadDebugger.cpp +++ b/third_party/WebKit/Source/core/inspector/WorkerThreadDebugger.cpp
@@ -34,6 +34,7 @@ #include "bindings/core/v8/SourceLocation.h" #include "bindings/core/v8/V8ScriptRunner.h" #include "core/inspector/ConsoleMessage.h" +#include "core/inspector/IdentifiersFactory.h" #include "core/workers/WorkerReportingProxy.h" #include "core/workers/WorkerThread.h" #include <v8.h> @@ -54,6 +55,7 @@ WorkerThreadDebugger::WorkerThreadDebugger(WorkerThread* workerThread, v8::Isolate* isolate) : ThreadDebugger(isolate) , m_workerThread(workerThread) + , m_muteConsoleCount(0) { } @@ -73,9 +75,29 @@ void WorkerThreadDebugger::exceptionThrown(const String& errorMessage, std::unique_ptr<SourceLocation> location) { + if (m_muteConsoleCount) + return; debugger()->exceptionThrown(workerContextGroupId, errorMessage, location->url(), location->lineNumber(), location->columnNumber(), location->cloneStackTrace(), location->scriptId()); } +void WorkerThreadDebugger::addConsoleMessage(ConsoleMessage* consoleMessage) +{ + if (m_muteConsoleCount) + return; + debugger()->addConsoleMessage( + workerContextGroupId, + consoleMessage->source(), + consoleMessage->level(), + consoleMessage->message(), + consoleMessage->location()->url(), + consoleMessage->location()->lineNumber(), + consoleMessage->location()->columnNumber(), + consoleMessage->location()->cloneStackTrace(), + consoleMessage->location()->scriptId(), + IdentifiersFactory::requestId(consoleMessage->requestIdentifier()), + consoleMessage->workerId()); +} + int WorkerThreadDebugger::contextGroupId() { return workerContextGroupId; @@ -92,6 +114,16 @@ m_workerThread->stopRunningDebuggerTasksOnPauseOnWorkerThread(); } +void WorkerThreadDebugger::muteWarningsAndDeprecations() +{ + m_muteConsoleCount++; +} + +void WorkerThreadDebugger::unmuteWarningsAndDeprecations() +{ + m_muteConsoleCount--; +} + bool WorkerThreadDebugger::callingContextCanAccessContext(v8::Local<v8::Context> calling, v8::Local<v8::Context> target) { return true;
diff --git a/third_party/WebKit/Source/core/inspector/WorkerThreadDebugger.h b/third_party/WebKit/Source/core/inspector/WorkerThreadDebugger.h index ba96fd9..eeea0aca 100644 --- a/third_party/WebKit/Source/core/inspector/WorkerThreadDebugger.h +++ b/third_party/WebKit/Source/core/inspector/WorkerThreadDebugger.h
@@ -36,6 +36,7 @@ namespace blink { +class ConsoleMessage; class SourceLocation; class WorkerThread; @@ -51,12 +52,13 @@ void contextCreated(v8::Local<v8::Context>); void contextWillBeDestroyed(v8::Local<v8::Context>); void exceptionThrown(const String& errorMessage, std::unique_ptr<SourceLocation>); + void addConsoleMessage(ConsoleMessage*); // V8DebuggerClient implementation. void runMessageLoopOnPause(int contextGroupId) override; void quitMessageLoopOnPause() override; - void muteWarningsAndDeprecations() override { }; - void unmuteWarningsAndDeprecations() override { }; + void muteWarningsAndDeprecations() override; + void unmuteWarningsAndDeprecations() override; bool callingContextCanAccessContext(v8::Local<v8::Context> calling, v8::Local<v8::Context> target) override; v8::Local<v8::Context> ensureDefaultContextInGroup(int contextGroupId) override; @@ -65,6 +67,7 @@ private: WorkerThread* m_workerThread; + int m_muteConsoleCount; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp index 04c701c37..5ef43ac 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlock.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBlock.cpp
@@ -364,7 +364,8 @@ { LayoutAnalyzer::Scope analyzer(*this); - bool needsScrollAnchoring = RuntimeEnabledFeatures::scrollAnchoringEnabled() && hasOverflowClip(); + bool needsScrollAnchoring = hasOverflowClip() + && getScrollableArea()->shouldPerformScrollAnchoring(); if (needsScrollAnchoring) getScrollableArea()->scrollAnchor().save(); @@ -790,7 +791,7 @@ if (view() && view()->selectionStart()) { Node* startElement = view()->selectionStart()->node(); - if (startElement && startElement->rootEditableElement() == node()) + if (startElement && rootEditableElement(*startElement) == node()) return true; } @@ -1409,7 +1410,7 @@ if (!node()) return false; - if (node()->isRootEditableElement()) + if (isRootEditableElement(*node())) return true; if (node()->isShadowRoot() && isHTMLInputElement(toShadowRoot(node())->host()))
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp index f8daa687..dba4a46e 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlowLine.cpp
@@ -1878,7 +1878,7 @@ { LayoutUnit endPadding = hasOverflowClip() ? paddingEnd() : LayoutUnit(); // FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to. - if (hasOverflowClip() && !endPadding && node() && node()->isRootEditableElement() && style()->isLeftToRightDirection()) + if (hasOverflowClip() && !endPadding && node() && isRootEditableElement(*node()) && style()->isLeftToRightDirection()) endPadding = LayoutUnit(1); for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) { addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding));
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp index 4fc4b88d..bd3dd55b 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -991,15 +991,11 @@ return true; LayoutSize offset = LayoutSize(-scrolledContentOffset()); - if (UNLIKELY(hasFlippedBlocksWritingMode())) - offset.setWidth(-offset.width()); rect.move(offset); if (applyOverflowClip == ApplyNonScrollOverflowClip && scrollsOverflow()) return true; - flipForWritingMode(rect); - LayoutRect clipRect = overflowClipRect(LayoutPoint()); bool doesIntersect; @@ -1009,8 +1005,6 @@ rect.intersect(clipRect); doesIntersect = !rect.isEmpty(); } - if (doesIntersect) - flipForWritingMode(rect); return doesIntersect; } @@ -2043,34 +2037,25 @@ { inflateVisualRectForReflectionAndFilter(rect); - if (ancestor == this) { - // The final rect returned is always in the physical coordinate space of the ancestor. - flipForWritingMode(rect); + if (ancestor == this) return true; - } bool ancestorSkipped; bool filterOrReflectionSkipped; LayoutObject* container = this->container(ancestor, &ancestorSkipped, &filterOrReflectionSkipped); + LayoutBox* localContainingBlock = containingBlock(); + // Skip table row because cells and rows are in the same coordinate space. + if (container->isTableRow()) { + DCHECK(isTableCell()); + localContainingBlock = toLayoutBox(container->parent()); + container = container->parent(); + } if (!container) return true; if (filterOrReflectionSkipped) inflateVisualRectForReflectionAndFilterUnderContainer(rect, *container, ancestor); - // The rect we compute at each step is shifted by our x/y offset in the parent container's coordinate space. - // Only when we cross a writing mode boundary will we have to possibly flipForWritingMode (to convert into a more - // appropriate offset corner for the enclosing container). - if (isWritingModeRoot()) { - flipForWritingMode(rect); - // Then flip rect currently in physical direction to container's block direction. - if (container->styleRef().isFlippedBlocksWritingMode()) - rect.setX(m_frameRect.width() - rect.maxX()); - } - - LayoutPoint topLeft = rect.location(); - topLeft.move(locationOffset()); - // We are now in our parent container's coordinate space. Apply our transform to obtain a bounding box // in the parent's coordinate space that encloses us. if (hasLayer() && layer()->transform()) { @@ -2078,9 +2063,12 @@ // the transform since we don't know the desired subpixel accumulation at this point, and the transform may // include a scale. rect = LayoutRect(layer()->transform()->mapRect(enclosingIntRect(rect))); - topLeft = rect.location(); - topLeft.move(locationOffset()); } + LayoutPoint topLeft = rect.location(); + // TODO(wkorman): Look into and document why this conditional is needed. + // Currently present following logic in PaintLayer::updateLayerPosition. + if (!(isInline() && isLayoutInline())) + topLeft.moveBy(topLeftLocation(localContainingBlock)); const ComputedStyle& styleToUse = styleRef(); EPosition position = styleToUse.position(); @@ -2102,7 +2090,7 @@ return false; if (ancestorSkipped) { - // If the ancestor is below o, then we need to map the rect into ancestor's coordinates. + // If the ancestor is below the container, then we need to map the rect into ancestor's coordinates. LayoutSize containerOffset = ancestor->offsetFromAncestorContainer(container); rect.move(-containerOffset); // If the ancestor is fixed, then the rect is already in its coordinates so doesn't need viewport-adjusting. @@ -2916,13 +2904,14 @@ LayoutObject* cb = isOutOfFlowPositioned() ? container() : containingBlock(); while (cb->isAnonymous()) cb = cb->containingBlock(); - LayoutUnit stretchedFlexHeight(-1); + LayoutUnit stretchedHeight(-1); if (cb->isLayoutBlock()) { LayoutBlock* block = toLayoutBlock(cb); block->addPercentHeightDescendant(const_cast<LayoutBox*>(this)); if (block->isFlexItem()) - stretchedFlexHeight = toLayoutFlexibleBox(block->parent())->childLogicalHeightForPercentageResolution(*block); - + stretchedHeight = toLayoutFlexibleBox(block->parent())->childLogicalHeightForPercentageResolution(*block); + else if (block->isGridItem() && block->hasOverrideLogicalContentHeight()) + stretchedHeight = block->overrideLogicalContentHeight(); } if (cb->isOutOfFlowPositioned() && cb->style()->height().isAuto() && !(cb->style()->top().isAuto() || cb->style()->bottom().isAuto())) { @@ -2941,8 +2930,10 @@ LayoutUnit availableHeight; if (isOutOfFlowPositioned()) { availableHeight = containingBlockLogicalHeightForPositioned(toLayoutBoxModelObject(cb)); - } else if (stretchedFlexHeight != -1) { - availableHeight = stretchedFlexHeight; + } else if (stretchedHeight != -1) { + availableHeight = stretchedHeight; + } else if (isGridItem() && hasOverrideContainingBlockLogicalHeight()) { + availableHeight = overrideContainingBlockContentLogicalHeight(); } else { availableHeight = containingBlockLogicalHeightForContent(IncludeMarginBorderPadding); // It is necessary to use the border-box to match WinIE's broken @@ -4475,12 +4466,12 @@ return LayoutPoint(point.x() + size().width() - child->size().width() - (2 * child->location().x()), point.y()); } -LayoutPoint LayoutBox::topLeftLocation() const +LayoutPoint LayoutBox::topLeftLocation(const LayoutBox* flippedBlocksContainer) const { - LayoutBlock* containerBlock = containingBlock(); - if (!containerBlock || containerBlock == this) + const LayoutBox* containerBox = flippedBlocksContainer ? flippedBlocksContainer : containingBlock(); + if (!containerBox || containerBox == this) return location(); - return containerBlock->flipForWritingModeForChild(this, location()); + return containerBox->flipForWritingModeForChild(this, location()); } bool LayoutBox::hasRelativeLogicalWidth() const
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.h b/third_party/WebKit/Source/core/layout/LayoutBox.h index ca52d25..631a6a1 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBox.h +++ b/third_party/WebKit/Source/core/layout/LayoutBox.h
@@ -873,9 +873,11 @@ return; rect.setX(m_frameRect.width() - rect.maxX()); } - // These represent your location relative to your container as a physical offset. - // In layout related methods you almost always want the logical location (e.g. x() and y()). - LayoutPoint topLeftLocation() const; + // These represent your location relative to your container as a physical + // offset. In layout related methods you almost always want the logical + // location (e.g. x() and y()). Passing |container| causes flipped-block + // flipping w.r.t. that container, or containingBlock() otherwise. + LayoutPoint topLeftLocation(const LayoutBox* flippedBlocksContainer = nullptr) const; LayoutSize topLeftLocationOffset() const { return toLayoutSize(topLeftLocation()); } LayoutRect logicalVisualOverflowRectForPropagation(const ComputedStyle&) const;
diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp index 3f70ca65..5390b736 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp
@@ -555,7 +555,7 @@ return cb; } -bool LayoutBoxModelObject::hasAutoHeightOrContainingBlockWithAutoHeight() const +bool LayoutBoxModelObject::hasAutoHeightOrContainingBlockWithAutoHeight(bool checkingContainingBlock) const { const LayoutBox* thisBox = isBox() ? toLayoutBox(this) : nullptr; Length logicalHeightLength = style()->logicalHeight(); @@ -567,6 +567,12 @@ if (flexBox.childLogicalHeightForPercentageResolution(*thisBox) != LayoutUnit(-1)) return false; } + if (thisBox && thisBox->isGridItem()) { + if (checkingContainingBlock && thisBox->hasOverrideLogicalContentHeight()) + return false; + if (!checkingContainingBlock && thisBox->hasOverrideContainingBlockLogicalHeight()) + return false; + } if (logicalHeightLength.isAuto()) return true; @@ -575,10 +581,15 @@ // If the height of the containing block computes to 'auto', then it hasn't been 'specified explicitly'. if (cb) - return cb->hasAutoHeightOrContainingBlockWithAutoHeight(); + return cb->hasAutoHeightOrContainingBlockWithAutoHeight(true); return false; } +bool LayoutBoxModelObject::hasAutoHeightOrContainingBlockWithAutoHeight() const +{ + return hasAutoHeightOrContainingBlockWithAutoHeight(false); +} + LayoutSize LayoutBoxModelObject::relativePositionOffset() const { LayoutSize offset = accumulateInFlowPositionOffsets();
diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.h b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.h index 95b027df..be67ec6 100644 --- a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.h +++ b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.h
@@ -376,6 +376,8 @@ return *m_rareData.get(); } + bool hasAutoHeightOrContainingBlockWithAutoHeight(bool checkingContainingBlock) const; + // The PaintLayer associated with this object. // |m_layer| can be nullptr depending on the return value of layerTypeRequired(). std::unique_ptr<PaintLayer> m_layer;
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp index 7bdedffe..bed1c2f 100644 --- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.cpp
@@ -90,6 +90,7 @@ : LayoutBlock(element) , m_orderIterator(this) , m_numberOfInFlowChildrenOnFirstLine(-1) + , m_hasDefiniteHeight(SizeDefiniteness::Unknown) { ASSERT(!childrenInline()); } @@ -380,6 +381,10 @@ updateAfterLayout(); clearNeedsLayout(); + + // We have to reset this, because changes to our ancestors' style + // can affect this value. + m_hasDefiniteHeight = SizeDefiniteness::Unknown; } void LayoutFlexibleBox::paintChildren(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) const @@ -769,9 +774,13 @@ if (flexBasis.isAuto()) return false; if (flexBasis.hasPercent()) { - return isColumnFlow() ? - child.computePercentageLogicalHeight(flexBasis) != -1 : - true; + if (!isColumnFlow() || m_hasDefiniteHeight == SizeDefiniteness::Definite) + return true; + if (m_hasDefiniteHeight == SizeDefiniteness::Indefinite) + return false; + bool definite = child.computePercentageLogicalHeight(flexBasis) != -1; + m_hasDefiniteHeight = definite ? SizeDefiniteness::Definite : SizeDefiniteness::Indefinite; + return definite; } return true; } @@ -781,9 +790,13 @@ if (length.isAuto()) return false; if (length.hasPercent()) { - return hasOrthogonalFlow(child) ? - true : - child.computePercentageLogicalHeight(length) != -1; + if (hasOrthogonalFlow(child) || m_hasDefiniteHeight == SizeDefiniteness::Definite) + return true; + if (m_hasDefiniteHeight == SizeDefiniteness::Indefinite) + return false; + bool definite = child.computePercentageLogicalHeight(length) != -1; + m_hasDefiniteHeight = definite ? SizeDefiniteness::Definite : SizeDefiniteness::Indefinite; + return definite; } // TODO(cbiesinger): Eventually we should support other types of sizes here. Requires updating // computeMainSizeFromAspectRatioUsing. @@ -1147,7 +1160,6 @@ // If flex basis had a percentage, our size is guaranteed to be definite or the flex item's // size could not be definite. // Otherwise, we make up a percentage to check whether we have a definite size. - // TODO(cbiesinger): cache this somewhere if (!mainAxisLengthIsDefinite(child, Length(0, Percent))) return LayoutUnit(-1); }
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h index 905efe6..9ea7c01 100644 --- a/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h +++ b/third_party/WebKit/Source/core/layout/LayoutFlexibleBox.h
@@ -99,6 +99,10 @@ TopToBottomWritingMode, RightToLeftWritingMode, LeftToRightWritingMode, BottomToTopWritingMode }; + enum class SizeDefiniteness { + Definite, Indefinite, Unknown + }; + struct FlexItem; struct LineContext; @@ -200,6 +204,9 @@ mutable OrderIterator m_orderIterator; int m_numberOfInFlowChildrenOnFirstLine; + + // This is SizeIsUnknown outside of layoutBlock() + mutable SizeDefiniteness m_hasDefiniteHeight; }; DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutFlexibleBox, isFlexibleBox());
diff --git a/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp b/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp index a95a49a71..a27ce47 100644 --- a/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutFlowThread.cpp
@@ -102,9 +102,7 @@ // |rect| is a layout rectangle, where the block direction coordinate is flipped for writing // mode. fragmentsBoundingBox(), on the other hand, works on physical rectangles, so we need to // flip the rectangle before and after calling it. - flipForWritingMode(rect); rect = fragmentsBoundingBox(rect); - flipForWritingMode(rect); return LayoutBlockFlow::mapToVisualRectInAncestorSpace(ancestor, rect, visualRectFlags); }
diff --git a/third_party/WebKit/Source/core/layout/LayoutFrame.cpp b/third_party/WebKit/Source/core/layout/LayoutFrame.cpp index 7f019f2..768bd03 100644 --- a/third_party/WebKit/Source/core/layout/LayoutFrame.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutFrame.cpp
@@ -24,7 +24,10 @@ #include "core/layout/LayoutFrame.h" #include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" #include "core/html/HTMLFrameElement.h" +#include "core/input/EventHandler.h" +#include "core/style/CursorData.h" namespace blink { @@ -40,6 +43,23 @@ return FrameEdgeInfo(element->noResize(), element->hasFrameBorder()); } +void LayoutFrame::imageChanged(WrappedImagePtr image, const IntRect*) +{ + if (const CursorList* cursors = style()->cursors()) { + for (const CursorData& cursor : *cursors) { + if (cursor.image() && cursor.image()->cachedImage() == image) { + if (LocalFrame* frame = this->frame()) { + // Cursor update scheduling is done by the local root, which is the main frame if there + // are no RemoteFrame ancestors in the frame tree. Use of localFrameRoot() is + // discouraged but will change when cursor update scheduling is moved from EventHandler + // to PageEventHandler. + frame->localFrameRoot()->eventHandler().scheduleCursorUpdate(); + } + } + } + } +} + void LayoutFrame::updateFromElement() { if (parent() && parent()->isFrameSet())
diff --git a/third_party/WebKit/Source/core/layout/LayoutFrame.h b/third_party/WebKit/Source/core/layout/LayoutFrame.h index 8753c6c9..8f0b728 100644 --- a/third_party/WebKit/Source/core/layout/LayoutFrame.h +++ b/third_party/WebKit/Source/core/layout/LayoutFrame.h
@@ -36,6 +36,8 @@ FrameEdgeInfo edgeInfo() const; + void imageChanged(WrappedImagePtr, const IntRect* = nullptr) override; + const char* name() const override { return "LayoutFrame"; } private:
diff --git a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp index 6d8864e4..82ece97e 100644 --- a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
@@ -516,7 +516,7 @@ GridSizingData sizingData(gridColumnCount(), gridRowCount()); sizingData.freeSpaceForDirection(ForColumns) = LayoutUnit(); sizingData.sizingOperation = IntrinsicSizeComputation; - const_cast<LayoutGrid*>(this)->computeUsedBreadthOfGridTracks(ForColumns, sizingData, minLogicalWidth, maxLogicalWidth); + computeUsedBreadthOfGridTracks(ForColumns, sizingData, minLogicalWidth, maxLogicalWidth); LayoutUnit totalGuttersSize = guttersSize(ForColumns, sizingData.columnTracks.size()); minLogicalWidth += totalGuttersSize; @@ -567,7 +567,7 @@ return track.baseSize() / std::max<double>(1, flexFactor); } -void LayoutGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection direction, GridSizingData& sizingData, LayoutUnit& baseSizesWithoutMaximization, LayoutUnit& growthLimitsWithoutMaximization) +void LayoutGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection direction, GridSizingData& sizingData, LayoutUnit& baseSizesWithoutMaximization, LayoutUnit& growthLimitsWithoutMaximization) const { LayoutUnit& freeSpace = sizingData.freeSpaceForDirection(direction); const LayoutUnit initialFreeSpace = freeSpace; @@ -840,7 +840,7 @@ return child.isHorizontalWritingMode() != isHorizontalWritingMode(); } -LayoutUnit LayoutGrid::logicalHeightForChild(LayoutBox& child, GridSizingData& sizingData) +LayoutUnit LayoutGrid::logicalHeightForChild(LayoutBox& child, GridSizingData& sizingData) const { GridTrackSizingDirection childBlockDirection = flowAwareDirectionForChild(child, ForRows); SubtreeLayoutScope layoutScope(child); @@ -864,7 +864,7 @@ return !isOrthogonalChild(child) ? direction : (direction == ForColumns ? ForRows : ForColumns); } -LayoutUnit LayoutGrid::minSizeForChild(LayoutBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData) +LayoutUnit LayoutGrid::minSizeForChild(LayoutBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData) const { GridTrackSizingDirection childInlineDirection = flowAwareDirectionForChild(child, ForColumns); bool isRowAxis = direction == childInlineDirection; @@ -885,7 +885,7 @@ return child.computeLogicalHeightUsing(MinSize, childMinSize, child.intrinsicLogicalHeight()) + child.marginLogicalHeight() + child.scrollbarLogicalHeight(); } -bool LayoutGrid::updateOverrideContainingBlockContentSizeForChild(LayoutBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData) +bool LayoutGrid::updateOverrideContainingBlockContentSizeForChild(LayoutBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData) const { LayoutUnit overrideSize = gridAreaBreadthForChild(child, direction, sizingData); if (hasOverrideContainingBlockContentSizeForChild(child, direction) && overrideContainingBlockContentSizeForChild(child, direction) == overrideSize) @@ -895,7 +895,7 @@ return true; } -LayoutUnit LayoutGrid::minContentForChild(LayoutBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData) +LayoutUnit LayoutGrid::minContentForChild(LayoutBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData) const { GridTrackSizingDirection childInlineDirection = flowAwareDirectionForChild(child, ForColumns); if (direction == childInlineDirection) { @@ -924,7 +924,7 @@ return logicalHeightForChild(child, sizingData); } -LayoutUnit LayoutGrid::maxContentForChild(LayoutBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData) +LayoutUnit LayoutGrid::maxContentForChild(LayoutBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData) const { GridTrackSizingDirection childInlineDirection = flowAwareDirectionForChild(child, ForColumns); if (direction == childInlineDirection) { @@ -986,7 +986,7 @@ return false; } -void LayoutGrid::resolveContentBasedTrackSizingFunctions(GridTrackSizingDirection direction, GridSizingData& sizingData) +void LayoutGrid::resolveContentBasedTrackSizingFunctions(GridTrackSizingDirection direction, GridSizingData& sizingData) const { sizingData.itemsSortedByIncreasingSpan.shrink(0); if (!m_gridItemArea.isEmpty()) { @@ -1027,7 +1027,7 @@ } } -void LayoutGrid::resolveContentBasedTrackSizingFunctionsForNonSpanningItems(GridTrackSizingDirection direction, const GridSpan& span, LayoutBox& gridItem, GridTrack& track, GridSizingData& sizingData) +void LayoutGrid::resolveContentBasedTrackSizingFunctionsForNonSpanningItems(GridTrackSizingDirection direction, const GridSpan& span, LayoutBox& gridItem, GridTrack& track, GridSizingData& sizingData) const { const size_t trackPosition = span.startLine(); GridTrackSize trackSize = gridTrackSize(direction, trackPosition, sizingData.sizingOperation); @@ -1150,7 +1150,7 @@ ASSERT_NOT_REACHED(); } -LayoutUnit LayoutGrid::currentItemSizeForTrackSizeComputationPhase(TrackSizeComputationPhase phase, LayoutBox& gridItem, GridTrackSizingDirection direction, GridSizingData& sizingData) +LayoutUnit LayoutGrid::currentItemSizeForTrackSizeComputationPhase(TrackSizeComputationPhase phase, LayoutBox& gridItem, GridTrackSizingDirection direction, GridSizingData& sizingData) const { switch (phase) { case ResolveIntrinsicMinimums: @@ -1171,7 +1171,7 @@ } template <TrackSizeComputationPhase phase> -void LayoutGrid::resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizingDirection direction, GridSizingData& sizingData, const GridItemsSpanGroupRange& gridItemsWithSpan) +void LayoutGrid::resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizingDirection direction, GridSizingData& sizingData, const GridItemsSpanGroupRange& gridItemsWithSpan) const { Vector<GridTrack>& tracks = (direction == ForColumns) ? sizingData.columnTracks : sizingData.rowTracks; for (const auto& trackIndex : sizingData.contentSizedTracksIndex) { @@ -1232,7 +1232,7 @@ } template <TrackSizeComputationPhase phase> -void LayoutGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, const Vector<GridTrack*>* growBeyondGrowthLimitsTracks, GridSizingData& sizingData, LayoutUnit& availableLogicalSpace) +void LayoutGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, const Vector<GridTrack*>* growBeyondGrowthLimitsTracks, GridSizingData& sizingData, LayoutUnit& availableLogicalSpace) const { ASSERT(availableLogicalSpace >= 0);
diff --git a/third_party/WebKit/Source/core/layout/LayoutGrid.h b/third_party/WebKit/Source/core/layout/LayoutGrid.h index 2b7f531..b4aff8a9 100644 --- a/third_party/WebKit/Source/core/layout/LayoutGrid.h +++ b/third_party/WebKit/Source/core/layout/LayoutGrid.h
@@ -121,10 +121,10 @@ class GridIterator; struct GridSizingData; enum SizingOperation { TrackSizing, IntrinsicSizeComputation }; - void computeUsedBreadthOfGridTracks(GridTrackSizingDirection, GridSizingData&, LayoutUnit& baseSizesWithoutMaximization, LayoutUnit& growthLimitsWithoutMaximization); + void computeUsedBreadthOfGridTracks(GridTrackSizingDirection, GridSizingData&, LayoutUnit& baseSizesWithoutMaximization, LayoutUnit& growthLimitsWithoutMaximization) const; LayoutUnit computeUsedBreadthOfMinLength(const GridLength&, LayoutUnit maxBreadth) const; LayoutUnit computeUsedBreadthOfMaxLength(const GridLength&, LayoutUnit usedBreadth, LayoutUnit maxBreadth) const; - void resolveContentBasedTrackSizingFunctions(GridTrackSizingDirection, GridSizingData&); + void resolveContentBasedTrackSizingFunctions(GridTrackSizingDirection, GridSizingData&) const; void ensureGridSize(size_t maximumRowSize, size_t maximumColumnSize); void insertItemIntoGrid(LayoutBox&, const GridArea&); @@ -153,10 +153,10 @@ void populateGridPositionsForDirection(GridSizingData&, GridTrackSizingDirection); typedef struct GridItemsSpanGroupRange GridItemsSpanGroupRange; - LayoutUnit currentItemSizeForTrackSizeComputationPhase(TrackSizeComputationPhase, LayoutBox&, GridTrackSizingDirection, GridSizingData&); - void resolveContentBasedTrackSizingFunctionsForNonSpanningItems(GridTrackSizingDirection, const GridSpan&, LayoutBox& gridItem, GridTrack&, GridSizingData&); - template <TrackSizeComputationPhase> void resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizingDirection, GridSizingData&, const GridItemsSpanGroupRange&); - template <TrackSizeComputationPhase> void distributeSpaceToTracks(Vector<GridTrack*>&, const Vector<GridTrack*>* growBeyondGrowthLimitsTracks, GridSizingData&, LayoutUnit& availableLogicalSpace); + LayoutUnit currentItemSizeForTrackSizeComputationPhase(TrackSizeComputationPhase, LayoutBox&, GridTrackSizingDirection, GridSizingData&) const; + void resolveContentBasedTrackSizingFunctionsForNonSpanningItems(GridTrackSizingDirection, const GridSpan&, LayoutBox& gridItem, GridTrack&, GridSizingData&) const; + template <TrackSizeComputationPhase> void resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizingDirection, GridSizingData&, const GridItemsSpanGroupRange&) const; + template <TrackSizeComputationPhase> void distributeSpaceToTracks(Vector<GridTrack*>&, const Vector<GridTrack*>* growBeyondGrowthLimitsTracks, GridSizingData&, LayoutUnit& availableLogicalSpace) const; typedef HashSet<size_t, DefaultHash<size_t>::Hash, WTF::UnsignedWithZeroKeyHashTraits<size_t>> TrackIndexSet; double computeFlexFactorUnitSize(const Vector<GridTrack>&, GridTrackSizingDirection, double flexFactorSum, LayoutUnit& leftOverSpace, const Vector<size_t, 8>& flexibleTracksIndexes, std::unique_ptr<TrackIndexSet> tracksToTreatAsInflexible = nullptr) const; @@ -165,11 +165,11 @@ const GridTrackSize& rawGridTrackSize(GridTrackSizingDirection, size_t) const; GridTrackSize gridTrackSize(GridTrackSizingDirection, size_t, SizingOperation = TrackSizing) const; - bool updateOverrideContainingBlockContentSizeForChild(LayoutBox&, GridTrackSizingDirection, GridSizingData&); - LayoutUnit logicalHeightForChild(LayoutBox&, GridSizingData&); - LayoutUnit minSizeForChild(LayoutBox&, GridTrackSizingDirection, GridSizingData&); - LayoutUnit minContentForChild(LayoutBox&, GridTrackSizingDirection, GridSizingData&); - LayoutUnit maxContentForChild(LayoutBox&, GridTrackSizingDirection, GridSizingData&); + bool updateOverrideContainingBlockContentSizeForChild(LayoutBox&, GridTrackSizingDirection, GridSizingData&) const; + LayoutUnit logicalHeightForChild(LayoutBox&, GridSizingData&) const; + LayoutUnit minSizeForChild(LayoutBox&, GridTrackSizingDirection, GridSizingData&) const; + LayoutUnit minContentForChild(LayoutBox&, GridTrackSizingDirection, GridSizingData&) const; + LayoutUnit maxContentForChild(LayoutBox&, GridTrackSizingDirection, GridSizingData&) const; GridAxisPosition columnAxisPositionForChild(const LayoutBox&) const; GridAxisPosition rowAxisPositionForChild(const LayoutBox&) const; LayoutUnit rowAxisOffsetForChild(const LayoutBox&, GridSizingData&) const;
diff --git a/third_party/WebKit/Source/core/layout/LayoutInline.cpp b/third_party/WebKit/Source/core/layout/LayoutInline.cpp index 5d11e8f..d46577ff 100644 --- a/third_party/WebKit/Source/core/layout/LayoutInline.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutInline.cpp
@@ -1104,9 +1104,12 @@ // its controlClipRect will be wrong. For overflow clip we use the values cached by the layer. rect.setLocation(topLeft); - if (container->isBox() && !toLayoutBox(container)->mapScrollingContentsRectToBoxSpace(rect, container == ancestor ? ApplyNonScrollOverflowClip : ApplyOverflowClip, visualRectFlags)) + LayoutBox* containerBox = container->isBox() ? toLayoutBox(container) : nullptr; + if (containerBox && !containerBox->mapScrollingContentsRectToBoxSpace(rect, container == ancestor ? ApplyNonScrollOverflowClip : ApplyOverflowClip, visualRectFlags)) return false; + if (containerBox) + containerBox->flipForWritingMode(rect); return container->mapToVisualRectInAncestorSpace(ancestor, rect, visualRectFlags); }
diff --git a/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp b/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp index af5a325..842318f 100644 --- a/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutMenuList.cpp
@@ -263,7 +263,8 @@ void LayoutMenuList::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const { - logicalHeight = m_innerBlockHeight + borderAndPaddingHeight(); + if (style()->hasAppearance()) + logicalHeight = m_innerBlockHeight + borderAndPaddingHeight(); LayoutBox::computeLogicalHeight(logicalHeight, logicalTop, computedValues); }
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp index c258042..08e8b52a 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp
@@ -1567,15 +1567,20 @@ bool LayoutObject::mapToVisualRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, VisualRectFlags visualRectFlags) const { // For any layout object that doesn't override this method (the main example is LayoutText), - // the rect is assumed to be in the coordinate space of the object's parent. + // the rect is assumed to be in the parent's coordinate space, except for container flip. if (ancestor == this) return true; if (LayoutObject* parent = this->parent()) { - if (parent->isBox() && !toLayoutBox(parent)->mapScrollingContentsRectToBoxSpace(rect, parent == ancestor ? ApplyNonScrollOverflowClip : ApplyOverflowClip, visualRectFlags)) - return false; - + if (parent->isBox()) { + LayoutBox* parentBox = toLayoutBox(parent); + if (!parentBox->mapScrollingContentsRectToBoxSpace(rect, parent == ancestor ? ApplyNonScrollOverflowClip : ApplyOverflowClip, visualRectFlags)) + return false; + // Never flip for SVG as it handles writing modes itself. + if (!isSVG()) + parentBox->flipForWritingMode(rect); + } return parent->mapToVisualRectInAncestorSpace(ancestor, rect, visualRectFlags); } return true; @@ -1893,6 +1898,7 @@ updateImage(oldBoxReflectMaskImage, newBoxReflectMaskImage); updateShapeImage(oldStyle ? oldStyle->shapeOutside() : 0, m_style->shapeOutside()); + updateCursorImages(oldStyle ? oldStyle->cursors() : nullptr, m_style->cursors()); bool doesNotNeedLayoutOrPaintInvalidation = !m_parent; @@ -2117,6 +2123,20 @@ } } +void LayoutObject::updateCursorImages(const CursorList* oldCursors, const CursorList* newCursors) +{ + if (oldCursors && newCursors && *oldCursors == *newCursors) + return; + + if (newCursors) { + for (const CursorData& cursorNew : *newCursors) { + if (cursorNew.image()) + cursorNew.image()->addClient(this); + } + } + removeCursorImageClient(oldCursors); +} + void LayoutObject::updateImage(StyleImage* oldImage, StyleImage* newImage) { if (oldImage != newImage) { @@ -2646,6 +2666,7 @@ m_style->boxReflect()->mask().image()->removeClient(this); removeShapeImageClient(m_style->shapeOutside()); + removeCursorImageClient(m_style->cursors()); } if (frameView()) @@ -2831,6 +2852,16 @@ shapeImage->removeClient(this); } +void LayoutObject::removeCursorImageClient(const CursorList* cursorList) +{ + if (!cursorList) + return; + for (const CursorData& cursor : *cursorList) { + if (cursor.image()) + cursor.image()->removeClient(this); + } +} + PositionWithAffinity LayoutObject::positionForPoint(const LayoutPoint&) { return createPositionWithAffinity(caretMinOffset());
diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.h b/third_party/WebKit/Source/core/layout/LayoutObject.h index cee1ba1..33277e6 100644 --- a/third_party/WebKit/Source/core/layout/LayoutObject.h +++ b/third_party/WebKit/Source/core/layout/LayoutObject.h
@@ -1617,6 +1617,7 @@ void updateShapeImage(const ShapeValue*, const ShapeValue*); void updateFillImages(const FillLayer* oldLayers, const FillLayer& newLayers); + void updateCursorImages(const CursorList* oldCursors, const CursorList* newCursors); void setNeedsOverflowRecalcAfterStyleChange(); @@ -1651,6 +1652,7 @@ Color selectionColor(int colorProperty, const GlobalPaintFlags) const; void removeShapeImageClient(ShapeValue*); + void removeCursorImageClient(const CursorList*); #if ENABLE(ASSERT) void checkBlockPositionedObjectsNeedLayout();
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp b/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp index e6fa743..1aba914 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutTableCell.cpp
@@ -360,15 +360,6 @@ return LayoutRect(-location.x(), -location.y(), location.x() + std::max(size().width() + right, selfVisualOverflowRect.maxX()), location.y() + std::max(size().height() + bottom, selfVisualOverflowRect.maxY())); } -bool LayoutTableCell::mapToVisualRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& r, VisualRectFlags visualRectFlags) const -{ - if (ancestor == this) - return true; - if (parent()) - r.moveBy(-parentBox()->location()); // Rows are in the same coordinate space, so don't add their offset in. - return LayoutBlockFlow::mapToVisualRectInAncestorSpace(ancestor, r, visualRectFlags); -} - int LayoutTableCell::cellBaselinePosition() const { // <http://www.w3.org/TR/2007/CR-CSS21-20070719/tables.html#height-layout>: The baseline of a cell is the baseline of
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableCell.h b/third_party/WebKit/Source/core/layout/LayoutTableCell.h index dba89847..0eccd0c 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTableCell.h +++ b/third_party/WebKit/Source/core/layout/LayoutTableCell.h
@@ -301,7 +301,6 @@ LayoutSize offsetFromContainer(const LayoutObject*) const override; LayoutRect localOverflowRectForPaintInvalidation() const override; - bool mapToVisualRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect&, VisualRectFlags = DefaultVisualRectFlags) const override; int borderHalfLeft(bool outer) const; int borderHalfRight(bool outer) const;
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp b/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp index 160e3ebc..2d726bc 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp
@@ -53,14 +53,6 @@ section()->setNeedsCellRecalc(); } -static bool borderWidthChanged(const ComputedStyle* oldStyle, const ComputedStyle* newStyle) -{ - return oldStyle->borderLeftWidth() != newStyle->borderLeftWidth() - || oldStyle->borderTopWidth() != newStyle->borderTopWidth() - || oldStyle->borderRightWidth() != newStyle->borderRightWidth() - || oldStyle->borderBottomWidth() != newStyle->borderBottomWidth(); -} - void LayoutTableRow::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle) { ASSERT(style()->display() == TABLE_ROW); @@ -77,13 +69,14 @@ if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border()) table->invalidateCollapsedBorders(); - if (table && oldStyle && diff.needsFullLayout() && needsLayout() && table->collapseBorders() && borderWidthChanged(oldStyle, style())) { + if (table && oldStyle && diff.needsFullLayout() && needsLayout() && table->collapseBorders() && oldStyle->border().sizeEquals(style()->border())) { // If the border width changes on a row, we need to make sure the cells in the row know to lay out again. // This only happens when borders are collapsed, since they end up affecting the border sides of the cell // itself. for (LayoutBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) { if (!childBox->isTableCell()) continue; + // TODO(dgrogan) Add a layout test showing that setChildNeedsLayout is needed instead of setNeedsLayout. childBox->setChildNeedsLayout(); childBox->setPreferredLogicalWidthsDirty(MarkOnlyThis); }
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp index 0ae4fb469..ff50a66c 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
@@ -126,6 +126,10 @@ LayoutTable* table = this->table(); if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border()) table->invalidateCollapsedBorders(); + + if (table && oldStyle && diff.needsFullLayout() && needsLayout() && table->collapseBorders() && oldStyle->border() != style()->border()) { + markAllCellsWidthsDirtyAndOrNeedsLayout(MarkDirtyAndNeedsLayout); + } } void LayoutTableSection::willBeRemovedFromTree() @@ -1221,6 +1225,20 @@ return childrenOverflowChanged; } +void LayoutTableSection::markAllCellsWidthsDirtyAndOrNeedsLayout(WhatToMarkAllCells whatToMark) +{ + for (unsigned i = 0; i < numRows(); i++) { + LayoutTableRow* row = rowLayoutObjectAt(i); + if (!row) + continue; + for (LayoutTableCell* cell = row->firstCell(); cell; cell = cell->nextCell()) { + cell->setPreferredLogicalWidthsDirty(); + if (whatToMark == MarkDirtyAndNeedsLayout) + cell->setChildNeedsLayout(); + } + } +} + int LayoutTableSection::calcBlockDirectionOuterBorder(BlockBorderSide side) const { unsigned totalCols = table()->numEffectiveColumns();
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.h b/third_party/WebKit/Source/core/layout/LayoutTableSection.h index 549a253..edd70aa 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTableSection.h +++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.h
@@ -115,6 +115,8 @@ void layoutRows(); void computeOverflowFromCells(); bool recalcChildOverflowAfterStyleChange(); + enum WhatToMarkAllCells { MarkDirtyOnly, MarkDirtyAndNeedsLayout }; + void markAllCellsWidthsDirtyAndOrNeedsLayout(WhatToMarkAllCells); LayoutTable* table() const { return toLayoutTable(parent()); } @@ -226,6 +228,7 @@ } const LayoutTableCell* primaryCellAt(unsigned row, unsigned effectiveColumn) const { return const_cast<LayoutTableSection*>(this)->primaryCellAt(row, effectiveColumn); } + // Returns null for cells with a rowspan that exceed the last row. Possibly others. LayoutTableRow* rowLayoutObjectAt(unsigned row) { return m_grid[row].rowLayoutObject; } const LayoutTableRow* rowLayoutObjectAt(unsigned row) const { return m_grid[row].rowLayoutObject; }
diff --git a/third_party/WebKit/Source/core/layout/LayoutTextControl.cpp b/third_party/WebKit/Source/core/layout/LayoutTextControl.cpp index 0b87e69..e183ae8 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTextControl.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutTextControl.cpp
@@ -189,8 +189,15 @@ // from the width of a '0'. This only seems to apply to a fixed number of Mac fonts, // but, in order to get similar rendering across platforms, we do this check for // all platforms. -bool LayoutTextControl::hasValidAvgCharWidth(const AtomicString& family) +bool LayoutTextControl::hasValidAvgCharWidth(const SimpleFontData* font, const AtomicString& family) { + // Some fonts match avgCharWidth to CJK full-width characters. + // Heuristic check to avoid such fonts. + DCHECK(font); + const FontMetrics& metrics = font->getFontMetrics(); + if (metrics.hasZeroWidth() && font->avgCharWidth() > metrics.zeroWidth() * 1.7) + return false; + static HashSet<AtomicString>* fontFamiliesWithInvalidCharWidthMap = nullptr; if (family.isEmpty()) @@ -209,10 +216,10 @@ float LayoutTextControl::getAvgCharWidth(const AtomicString& family) const { const Font& font = style()->font(); - if (hasValidAvgCharWidth(family)) { - ASSERT(font.primaryFont()); - return roundf(font.primaryFont()->avgCharWidth()); - } + + const SimpleFontData* primaryFont = font.primaryFont(); + if (primaryFont && hasValidAvgCharWidth(primaryFont, family)) + return roundf(primaryFont->avgCharWidth()); const UChar ch = '0'; const String str = String(&ch, 1);
diff --git a/third_party/WebKit/Source/core/layout/LayoutTextControl.h b/third_party/WebKit/Source/core/layout/LayoutTextControl.h index 221d2d7..002c6cd 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTextControl.h +++ b/third_party/WebKit/Source/core/layout/LayoutTextControl.h
@@ -58,7 +58,7 @@ float scaleEmToUnits(int x) const; - static bool hasValidAvgCharWidth(const AtomicString& family); + static bool hasValidAvgCharWidth(const SimpleFontData*, const AtomicString& family); virtual float getAvgCharWidth(const AtomicString& family) const; virtual LayoutUnit preferredContentLogicalWidth(float charWidth) const = 0; virtual LayoutUnit computeControlLogicalHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const = 0;
diff --git a/third_party/WebKit/Source/core/layout/LayoutTextControlSingleLine.cpp b/third_party/WebKit/Source/core/layout/LayoutTextControlSingleLine.cpp index 47e6e63..138efd02 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTextControlSingleLine.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutTextControlSingleLine.cpp
@@ -231,15 +231,16 @@ LayoutUnit result = LayoutUnit::fromFloatCeil(charWidth * factor); float maxCharWidth = 0.f; - AtomicString family = styleRef().font().getFontDescription().family().family(); + const Font& font = style()->font(); + AtomicString family = font.getFontDescription().family().family(); // Match the default system font to the width of MS Shell Dlg, the default // font for textareas in Firefox, Safari Win and IE for some encodings (in // IE, the default font is encoding specific). 4027 is the (xMax - xMin) // value in the "head" font table for MS Shell Dlg. if (LayoutTheme::theme().needsHackForTextControlWithFontFamily(family)) maxCharWidth = scaleEmToUnits(4027); - else if (hasValidAvgCharWidth(family)) - maxCharWidth = roundf(styleRef().font().primaryFont()->maxCharWidth()); + else if (hasValidAvgCharWidth(font.primaryFont(), family)) + maxCharWidth = roundf(font.primaryFont()->maxCharWidth()); // For text inputs, IE adds some extra width. if (maxCharWidth > 0.f)
diff --git a/third_party/WebKit/Source/core/layout/LayoutView.cpp b/third_party/WebKit/Source/core/layout/LayoutView.cpp index 0fc2e451..0496404 100644 --- a/third_party/WebKit/Source/core/layout/LayoutView.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutView.cpp
@@ -448,9 +448,6 @@ bool LayoutView::mapToVisualRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, MapCoordinatesFlags mode, VisualRectFlags visualRectFlags) const { - // Convert the rect into the physical coordinates space of this LayoutView. - flipForWritingMode(rect); - if (mode & IsFixed) adjustOffsetForFixedPosition(rect);
diff --git a/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp b/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp index c3076c4..14c00546 100644 --- a/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp +++ b/third_party/WebKit/Source/core/layout/PaintInvalidationState.cpp
@@ -389,6 +389,13 @@ static void slowMapToVisualRectInAncestorSpace(const LayoutObject& object, const LayoutBoxModelObject& ancestor, LayoutRect& rect) { + // TODO(wkorman): The flip below is required because visual rects are + // currently in "physical coordinates with flipped block-flow direction" + // (see LayoutBoxModelObject.h) but we need them to be in physical + // coordinates. + if (object.isBox()) + toLayoutBox(&object)->flipForWritingMode(rect); + if (object.isLayoutView()) toLayoutView(object).mapToVisualRectInAncestorSpace(&ancestor, rect, InputIsInFrameCoordinates, DefaultVisualRectFlags); else
diff --git a/third_party/WebKit/Source/core/layout/README.md b/third_party/WebKit/Source/core/layout/README.md index 61cbadac..d6943942 100644 --- a/third_party/WebKit/Source/core/layout/README.md +++ b/third_party/WebKit/Source/core/layout/README.md
@@ -77,3 +77,7 @@ overflow rect |<--------------------->| + +## Coordinate Spaces + +TODO(wkorman): Document writing mode, particularly flipped blocks.
diff --git a/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp b/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp index a916ee5..d16bbed 100644 --- a/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp +++ b/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp
@@ -79,14 +79,16 @@ LayoutRect localBounds; if (layoutObject->isBox()) { localBounds = toLayoutBox(layoutObject)->borderBoxRect(); - // borderBoxRect doesn't include overflow content and floats. - LayoutUnit maxHeight = std::max(localBounds.height(), toLayoutBox(layoutObject)->layoutOverflowRect().height()); - if (layoutObject->isLayoutBlockFlow() && toLayoutBlockFlow(layoutObject)->containsFloats()) { - // Note that lowestFloatLogicalBottom doesn't include floating - // grandchildren. - maxHeight = std::max(maxHeight, toLayoutBlockFlow(layoutObject)->lowestFloatLogicalBottom()); + if (!layoutObject->hasOverflowClip()) { + // borderBoxRect doesn't include overflow content and floats. + LayoutUnit maxHeight = std::max(localBounds.height(), toLayoutBox(layoutObject)->layoutOverflowRect().height()); + if (layoutObject->isLayoutBlockFlow() && toLayoutBlockFlow(layoutObject)->containsFloats()) { + // Note that lowestFloatLogicalBottom doesn't include floating + // grandchildren. + maxHeight = std::max(maxHeight, toLayoutBlockFlow(layoutObject)->lowestFloatLogicalBottom()); + } + localBounds.setHeight(maxHeight); } - localBounds.setHeight(maxHeight); } else if (layoutObject->isText()) { // TODO(skobes): Use first and last InlineTextBox only? for (InlineTextBox* box = toLayoutText(layoutObject)->firstTextBox(); box; box = box->nextTextBox())
diff --git a/third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp b/third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp index 2fb1618..a290f73e 100644 --- a/third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp +++ b/third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp
@@ -155,6 +155,45 @@ EXPECT_EQ(nullptr, scrollAnchor(lViewport).anchorObject()); } +// Test that we ignore the clipped content when computing visibility otherwise +// we may end up with an anchor that we think is in the viewport but is not. +TEST_F(ScrollAnchorTest, ClippedScrollersSkipped) +{ + setBodyInnerHTML( + "<style>" + " body { height: 2000px; }" + " #scroller { overflow: scroll; width: 500px; height: 300px; }" + " .anchor {" + " position:relative; height: 100px; width: 150px;" + " background-color: #afa; border: 1px solid gray;" + " }" + " #forceScrolling { height: 500px; background-color: #fcc; }" + "</style>" + "<div id='scroller'>" + " <div id='innerChanger'></div>" + " <div id='innerAnchor' class='anchor'></div>" + " <div id='forceScrolling'></div>" + "</div>" + "<div id='outerChanger'></div>" + "<div id='outerAnchor' class='anchor'></div>"); + + ScrollableArea* scroller = scrollerForElement(document().getElementById("scroller")); + ScrollableArea* viewport = layoutViewport(); + + document().getElementById("scroller")->setScrollTop(100); + scrollLayoutViewport(DoubleSize(0, 350)); + + setHeight(document().getElementById("innerChanger"), 200); + setHeight(document().getElementById("outerChanger"), 150); + + EXPECT_EQ(300, scroller->scrollPosition().y()); + EXPECT_EQ(document().getElementById("innerAnchor")->layoutObject(), + scrollAnchor(scroller).anchorObject()); + EXPECT_EQ(500, viewport->scrollPosition().y()); + EXPECT_EQ(document().getElementById("outerAnchor")->layoutObject(), + scrollAnchor(viewport).anchorObject()); +} + TEST_F(ScrollAnchorTest, FractionalOffsetsAreRoundedBeforeComparing) { setBodyInnerHTML( @@ -469,6 +508,85 @@ scrollAnchor(viewport).anchorObject()); } +TEST_F(ScrollAnchorTest, OptOutBody) +{ + setBodyInnerHTML( + "<style>" + " body { height: 2000px; overflow-anchor: none; }" + " #scroller { overflow: scroll; width: 500px; height: 300px; }" + " .anchor {" + " position:relative; height: 100px; width: 150px;" + " background-color: #afa; border: 1px solid gray;" + " }" + " #forceScrolling { height: 500px; background-color: #fcc; }" + "</style>" + "<div id='outerChanger'></div>" + "<div id='outerAnchor' class='anchor'></div>" + "<div id='scroller'>" + " <div id='innerChanger'></div>" + " <div id='innerAnchor' class='anchor'></div>" + " <div id='forceScrolling'></div>" + "</div>"); + + ScrollableArea* scroller = scrollerForElement(document().getElementById("scroller")); + ScrollableArea* viewport = layoutViewport(); + + document().getElementById("scroller")->setScrollTop(100); + scrollLayoutViewport(DoubleSize(0, 100)); + + setHeight(document().getElementById("innerChanger"), 200); + setHeight(document().getElementById("outerChanger"), 150); + + // Scroll anchoring should apply within #scroller. + EXPECT_EQ(300, scroller->scrollPosition().y()); + EXPECT_EQ(document().getElementById("innerAnchor")->layoutObject(), + scrollAnchor(scroller).anchorObject()); + // Scroll anchoring should not apply within main frame. + EXPECT_EQ(100, viewport->scrollPosition().y()); + EXPECT_EQ(nullptr, scrollAnchor(viewport).anchorObject()); +} + +TEST_F(ScrollAnchorTest, OptOutScrollingDiv) +{ + setBodyInnerHTML( + "<style>" + " body { height: 2000px; }" + " #scroller {" + " overflow: scroll; width: 500px; height: 300px;" + " overflow-anchor: none;" + " }" + " .anchor {" + " position:relative; height: 100px; width: 150px;" + " background-color: #afa; border: 1px solid gray;" + " }" + " #forceScrolling { height: 500px; background-color: #fcc; }" + "</style>" + "<div id='outerChanger'></div>" + "<div id='outerAnchor' class='anchor'></div>" + "<div id='scroller'>" + " <div id='innerChanger'></div>" + " <div id='innerAnchor' class='anchor'></div>" + " <div id='forceScrolling'></div>" + "</div>"); + + ScrollableArea* scroller = scrollerForElement(document().getElementById("scroller")); + ScrollableArea* viewport = layoutViewport(); + + document().getElementById("scroller")->setScrollTop(100); + scrollLayoutViewport(DoubleSize(0, 100)); + + setHeight(document().getElementById("innerChanger"), 200); + setHeight(document().getElementById("outerChanger"), 150); + + // Scroll anchoring should not apply within #scroller. + EXPECT_EQ(100, scroller->scrollPosition().y()); + EXPECT_EQ(nullptr, scrollAnchor(scroller).anchorObject()); + // Scroll anchoring should apply within main frame. + EXPECT_EQ(250, viewport->scrollPosition().y()); + EXPECT_EQ(document().getElementById("outerAnchor")->layoutObject(), + scrollAnchor(viewport).anchorObject()); +} + class ScrollAnchorCornerTest : public ScrollAnchorTest { protected: void checkCorner(const AtomicString& id, Corner corner, DoublePoint startPos, DoubleSize expectedAdjustment)
diff --git a/third_party/WebKit/Source/core/layout/TableLayoutAlgorithmFixed.cpp b/third_party/WebKit/Source/core/layout/TableLayoutAlgorithmFixed.cpp index 9fc6eb4..caa76258 100644 --- a/third_party/WebKit/Source/core/layout/TableLayoutAlgorithmFixed.cpp +++ b/third_party/WebKit/Source/core/layout/TableLayoutAlgorithmFixed.cpp
@@ -326,15 +326,8 @@ // (see calcWidthArray above.) This optimization is preferred to always // computing the logical widths we never intended to use. m_table->recalcSectionsIfNeeded(); - for (LayoutTableSection* section = m_table->topNonEmptySection(); section; section = m_table->sectionBelow(section)) { - for (unsigned i = 0; i < section->numRows(); i++) { - LayoutTableRow* row = section->rowLayoutObjectAt(i); - if (!row) - continue; - for (LayoutTableCell* cell = row->firstCell(); cell; cell = cell->nextCell()) - cell->setPreferredLogicalWidthsDirty(); - } - } + for (LayoutTableSection* section = m_table->topNonEmptySection(); section; section = m_table->sectionBelow(section)) + section->markAllCellsWidthsDirtyAndOrNeedsLayout(LayoutTableSection::MarkDirtyOnly); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp b/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp index 416f838..1436b16 100644 --- a/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp +++ b/third_party/WebKit/Source/core/layout/VisualRectMappingTest.cpp
@@ -171,11 +171,18 @@ EXPECT_EQ(LayoutRect(-40, 0, 140, 70), overflowRect); LayoutRect rect = overflowRect; + // TODO(wkorman): The calls to flipForWritingMode() here and in other test + // cases below are necessary because mapToVisualRectInAncestorSpace() + // currently expects the input rect to be in "physical coordinates" (*not* + // "physical coordinates with flipped block-flow direction"), see + // LayoutBoxModelObject.h. + target->flipForWritingMode(rect); EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(target, rect)); // This rect is in physical coordinates of target. EXPECT_EQ(LayoutRect(0, 0, 140, 70), rect); rect = overflowRect; + target->flipForWritingMode(rect); EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(&layoutView(), rect)); EXPECT_EQ(LayoutRect(222, 111, 140, 70), rect); checkPaintInvalidationStateRectMapping(rect, overflowRect, *target, layoutView(), layoutView()); @@ -197,16 +204,19 @@ EXPECT_EQ(LayoutRect(-40, 0, 140, 110), targetOverflowRect); LayoutRect rect = targetOverflowRect; + target->flipForWritingMode(rect); EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(target, rect)); // This rect is in physical coordinates of target. EXPECT_EQ(LayoutRect(0, 0, 140, 110), rect); LayoutBlock* container = toLayoutBlock(getLayoutObjectByElementId("container")); rect = targetOverflowRect; + target->flipForWritingMode(rect); EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(container, rect)); // 100 is the physical x location of target in container. EXPECT_EQ(LayoutRect(100, 0, 140, 110), rect); rect = targetOverflowRect; + target->flipForWritingMode(rect); EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(&layoutView(), rect)); EXPECT_EQ(LayoutRect(322, 111, 140, 110), rect); checkPaintInvalidationStateRectMapping(rect, targetOverflowRect, *target, layoutView(), layoutView()); @@ -214,9 +224,11 @@ LayoutRect containerOverflowRect = container->localOverflowRectForPaintInvalidation(); EXPECT_EQ(LayoutRect(0, 0, 200, 100), containerOverflowRect); rect = containerOverflowRect; + container->flipForWritingMode(rect); EXPECT_TRUE(container->mapToVisualRectInAncestorSpace(container, rect)); EXPECT_EQ(LayoutRect(0, 0, 200, 100), rect); rect = containerOverflowRect; + container->flipForWritingMode(rect); EXPECT_TRUE(container->mapToVisualRectInAncestorSpace(&layoutView(), rect)); EXPECT_EQ(LayoutRect(222, 111, 200, 100), rect); checkPaintInvalidationStateRectMapping(rect, containerOverflowRect, *container, layoutView(), layoutView()); @@ -303,11 +315,13 @@ EXPECT_EQ(LayoutRect(-40, 0, 140, 110), targetOverflowRect); LayoutRect rect = targetOverflowRect; + target->flipForWritingMode(rect); EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(target, rect)); // This rect is in physical coordinates of target. EXPECT_EQ(LayoutRect(0, 0, 140, 110), rect); rect = targetOverflowRect; + target->flipForWritingMode(rect); EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(container, rect)); // -2 = target_physical_x(100) + container_border_left(40) - scroll_left(142) // 3 = target_y(0) + container_border_top(10) - scroll_top(7) @@ -315,6 +329,7 @@ EXPECT_EQ(LayoutRect(-2, 3, 140, 110), rect); rect = targetOverflowRect; + target->flipForWritingMode(rect); EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(&layoutView(), rect)); // (-2, 3, 140, 100) is first clipped by container's overflow clip, to (40, 10, 50, 80), // then is added by container's offset in LayoutView (111, 222). @@ -330,10 +345,12 @@ EXPECT_EQ(LayoutRect(0, 0, 110, 120), containerOverflowRect); rect = containerOverflowRect; + container->flipForWritingMode(rect); EXPECT_TRUE(container->mapToVisualRectInAncestorSpace(container, rect)); EXPECT_EQ(LayoutRect(0, 0, 110, 120), rect); rect = containerOverflowRect; + container->flipForWritingMode(rect); EXPECT_TRUE(container->mapToVisualRectInAncestorSpace(&layoutView(), rect)); // TODO(crbug.com/600039): rect.x() should be 222 (left), but is offset by extra horizontal // border-widths because of layout error. @@ -398,11 +415,13 @@ EXPECT_EQ(LayoutRect(-40, 0, 140, 110), targetOverflowRect); LayoutRect rect = targetOverflowRect; + target->flipForWritingMode(rect); EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(target, rect)); // This rect is in physical coordinates of target. EXPECT_EQ(LayoutRect(0, 0, 140, 110), rect); rect = targetOverflowRect; + target->flipForWritingMode(rect); EXPECT_TRUE(target->mapToVisualRectInAncestorSpace(container, rect)); // 58 = target_physical_x(100) + container_border_left(40) - scroll_left(58) // The other sides of the rect are clipped by container's overflow clip.
diff --git a/third_party/WebKit/Source/core/layout/api/LayoutItem.h b/third_party/WebKit/Source/core/layout/api/LayoutItem.h index 83d85a99..50f24bd8 100644 --- a/third_party/WebKit/Source/core/layout/api/LayoutItem.h +++ b/third_party/WebKit/Source/core/layout/api/LayoutItem.h
@@ -32,12 +32,13 @@ LayoutItem() : m_layoutObject(0) { } - // TODO(leviw): This should be an UnspecifiedBoolType, but + // TODO(leviw): This should be "explicit operator bool", but // using this operator allows the API to be landed in pieces. // https://crbug.com/499321 operator LayoutObject*() const { return m_layoutObject; } - // TODO(pilgrim): Remove this when we replace the operator above with UnspecifiedBoolType. + // TODO(pilgrim): Remove this when we replace the operator above with + // operator bool. bool isNull() const { return !m_layoutObject;
diff --git a/third_party/WebKit/Source/core/layout/api/LineLayoutItem.h b/third_party/WebKit/Source/core/layout/api/LineLayoutItem.h index 46c7fe7..70fed8d 100644 --- a/third_party/WebKit/Source/core/layout/api/LineLayoutItem.h +++ b/third_party/WebKit/Source/core/layout/api/LineLayoutItem.h
@@ -47,8 +47,7 @@ LineLayoutItem() : m_layoutObject(0) { } - typedef LayoutObject* LineLayoutItem::*UnspecifiedBoolType; - operator UnspecifiedBoolType() const { return m_layoutObject ? &LineLayoutItem::m_layoutObject : nullptr; } + explicit operator bool() const { return m_layoutObject; } bool isEqual(const LayoutObject* layoutObject) const {
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp index 4dc1e45..dd5482a 100644 --- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp +++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp
@@ -229,7 +229,7 @@ graphicsLayer->setCompositingReasons(reasons); graphicsLayer->setSquashingDisallowedReasons(squashingDisallowedReasons); - if (Node* owningNode = m_owningLayer.layoutObject()->generatingNode()) + if (Node* owningNode = m_owningLayer.layoutObject()->node()) graphicsLayer->setOwnerNodeId(DOMNodeIds::idForNode(owningNode)); return graphicsLayer; @@ -1547,7 +1547,7 @@ uint32_t primaryMutableProperties = CompositorMutableProperty::kNone; uint32_t scrollMutableProperties = CompositorMutableProperty::kNone; - Node* owningNode = m_owningLayer.layoutObject()->generatingNode(); + Node* owningNode = m_owningLayer.layoutObject()->node(); Element* owningElement = nullptr; if (owningNode && owningNode->isElementNode()) owningElement = toElement(owningNode); @@ -1661,7 +1661,7 @@ // Inner layer which renders the content that scrolls. m_scrollingContentsLayer = createGraphicsLayer(CompositingReasonLayerForScrollingContents); - if (Node* owningNode = m_owningLayer.layoutObject()->generatingNode()) { + if (Node* owningNode = m_owningLayer.layoutObject()->node()) { m_scrollingContentsLayer->setElementId(createCompositorElementId(DOMNodeIds::idForNode(owningNode), CompositorSubElementId::Scroll)); m_scrollingContentsLayer->setCompositorMutableProperties(CompositorMutableProperty::kScrollLeft | CompositorMutableProperty::kScrollTop); } @@ -2298,9 +2298,6 @@ // Start with the bounds of the graphics layer in the space of the anchor LayoutObject. FloatRect graphicsLayerBoundsInObjectSpace(graphicsLayerBounds); graphicsLayerBoundsInObjectSpace.move(offsetFromAnchorLayoutObject); - // The object space means including writing mode flip. - if (anchorLayoutObject->isBox()) - toLayoutBox(anchorLayoutObject)->flipForWritingMode(graphicsLayerBoundsInObjectSpace); // Now map the bounds to its visible content rect in screen space, including applying clips along the way. LayoutRect visibleContentRect(graphicsLayerBoundsInObjectSpace);
diff --git a/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp b/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp index c08de88..b44a02c 100644 --- a/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp +++ b/third_party/WebKit/Source/core/layout/compositing/PaintLayerCompositor.cpp
@@ -1018,7 +1018,7 @@ IntRect overflowRect = m_layoutView.pixelSnappedLayoutOverflowRect(); m_rootContentLayer->setSize(FloatSize(overflowRect.maxX(), overflowRect.maxY())); m_rootContentLayer->setPosition(FloatPoint()); - m_rootContentLayer->setOwnerNodeId(DOMNodeIds::idForNode(m_layoutView.generatingNode())); + m_rootContentLayer->setOwnerNodeId(DOMNodeIds::idForNode(m_layoutView.node())); // FIXME: with rootLayerScrolls, we probably don't even need m_rootContentLayer? if (!(settings && settings->rootLayerScrolls())) {
diff --git a/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp b/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp index c668bdb..1332771 100644 --- a/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp +++ b/third_party/WebKit/Source/core/layout/svg/SVGResources.cpp
@@ -48,91 +48,79 @@ static HashSet<AtomicString>& clipperFilterMaskerTags() { - DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ()); - if (s_tagList.isEmpty()) { + DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ({ // "container elements": http://www.w3.org/TR/SVG11/intro.html#TermContainerElement // "graphics elements" : http://www.w3.org/TR/SVG11/intro.html#TermGraphicsElement - s_tagList.add(aTag.localName()); - s_tagList.add(circleTag.localName()); - s_tagList.add(ellipseTag.localName()); - s_tagList.add(gTag.localName()); - s_tagList.add(imageTag.localName()); - s_tagList.add(lineTag.localName()); - s_tagList.add(markerTag.localName()); - s_tagList.add(maskTag.localName()); - s_tagList.add(pathTag.localName()); - s_tagList.add(polygonTag.localName()); - s_tagList.add(polylineTag.localName()); - s_tagList.add(rectTag.localName()); - s_tagList.add(svgTag.localName()); - s_tagList.add(textTag.localName()); - s_tagList.add(useTag.localName()); - + aTag.localName(), + circleTag.localName(), + ellipseTag.localName(), + gTag.localName(), + imageTag.localName(), + lineTag.localName(), + markerTag.localName(), + maskTag.localName(), + pathTag.localName(), + polygonTag.localName(), + polylineTag.localName(), + rectTag.localName(), + svgTag.localName(), + textTag.localName(), + useTag.localName(), // Not listed in the definitions is the clipPath element, the SVG spec says though: // The "clipPath" element or any of its children can specify property "clip-path". // So we have to add clipPathTag here, otherwhise clip-path on clipPath will fail. // (Already mailed SVG WG, waiting for a solution) - s_tagList.add(clipPathTag.localName()); - + clipPathTag.localName(), // Not listed in the definitions are the text content elements, though filter/clipper/masker on tspan/text/.. is allowed. // (Already mailed SVG WG, waiting for a solution) - s_tagList.add(textPathTag.localName()); - s_tagList.add(tspanTag.localName()); - + textPathTag.localName(), + tspanTag.localName(), // Not listed in the definitions is the foreignObject element, but clip-path // is a supported attribute. - s_tagList.add(foreignObjectTag.localName()); - + foreignObjectTag.localName(), // Elements that we ignore, as it doesn't make any sense. // defs, pattern, switch (FIXME: Mail SVG WG about these) // symbol (is converted to a svg element, when referenced by use, we can safely ignore it.) - } - + })); return s_tagList; } bool SVGResources::supportsMarkers(const SVGElement& element) { - DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ()); - if (s_tagList.isEmpty()) { - s_tagList.add(lineTag.localName()); - s_tagList.add(pathTag.localName()); - s_tagList.add(polygonTag.localName()); - s_tagList.add(polylineTag.localName()); - } - + DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ({ + lineTag.localName(), + pathTag.localName(), + polygonTag.localName(), + polylineTag.localName(), + })); return s_tagList.contains(element.localName()); } static HashSet<AtomicString>& fillAndStrokeTags() { - DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ()); - if (s_tagList.isEmpty()) { - s_tagList.add(circleTag.localName()); - s_tagList.add(ellipseTag.localName()); - s_tagList.add(lineTag.localName()); - s_tagList.add(pathTag.localName()); - s_tagList.add(polygonTag.localName()); - s_tagList.add(polylineTag.localName()); - s_tagList.add(rectTag.localName()); - s_tagList.add(textTag.localName()); - s_tagList.add(textPathTag.localName()); - s_tagList.add(tspanTag.localName()); - } - + DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ({ + circleTag.localName(), + ellipseTag.localName(), + lineTag.localName(), + pathTag.localName(), + polygonTag.localName(), + polylineTag.localName(), + rectTag.localName(), + textTag.localName(), + textPathTag.localName(), + tspanTag.localName(), + })); return s_tagList; } static HashSet<AtomicString>& chainableResourceTags() { - DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ()); - if (s_tagList.isEmpty()) { - s_tagList.add(linearGradientTag.localName()); - s_tagList.add(filterTag.localName()); - s_tagList.add(patternTag.localName()); - s_tagList.add(radialGradientTag.localName()); - } - + DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ({ + linearGradientTag.localName(), + filterTag.localName(), + patternTag.localName(), + radialGradientTag.localName(), + })); return s_tagList; }
diff --git a/third_party/WebKit/Source/core/loader/BeaconLoader.cpp b/third_party/WebKit/Source/core/loader/BeaconLoader.cpp index f84f614e..8f79891 100644 --- a/third_party/WebKit/Source/core/loader/BeaconLoader.cpp +++ b/third_party/WebKit/Source/core/loader/BeaconLoader.cpp
@@ -172,7 +172,7 @@ request.setHTTPHeaderField(HTTPNames::Cache_Control, "max-age=0"); request.setAllowStoredCredentials(true); frame->document()->fetcher()->context().addAdditionalRequestHeaders(request, FetchSubresource); - frame->document()->fetcher()->context().setFirstPartyForCookies(request); + frame->document()->fetcher()->context().populateRequestData(request); if (MixedContentChecker::shouldBlockFetch(frame, request, request.url())) return false;
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp index 7838ecc..5d0b11f 100644 --- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp +++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -198,12 +198,6 @@ frame()->loader().applyUserAgent(request); } -void FrameFetchContext::setFirstPartyForCookies(ResourceRequest& request) -{ - if (frame()->tree().top()->isLocalFrame()) - request.setFirstPartyForCookies(toLocalFrame(frame()->tree().top())->document()->firstPartyForCookies()); -} - CachePolicy FrameFetchContext::getCachePolicy() const { if (m_document && m_document->loadEventFinished()) @@ -748,6 +742,27 @@ fetchRequest.mutableResourceRequest().addHTTPHeaderField("CSP", "active"); } +void FrameFetchContext::populateRequestData(ResourceRequest& request) +{ + if (!m_document) + return; + + if (request.firstPartyForCookies().isNull()) { + request.setFirstPartyForCookies(m_document + ? m_document->firstPartyForCookies() + : SecurityOrigin::urlWithUniqueSecurityOrigin()); + } + + // Subresource requests inherit their requestor origin from |m_document| directly. + // Top-level and nested frame types are taken care of in 'FrameLoadRequest()'. + // Auxiliary frame types in 'createWindow()' and 'FrameLoader::load'. + if (request.frameType() == WebURLRequest::FrameTypeNone && !request.requestorOrigin()) { + request.setRequestorOrigin(m_document->isSandboxed(SandboxOrigin) + ? SecurityOrigin::create(m_document->url()) + : m_document->getSecurityOrigin()); + } +} + MHTMLArchive* FrameFetchContext::archive() const { ASSERT(!isMainFrame());
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.h b/third_party/WebKit/Source/core/loader/FrameFetchContext.h index 281f18f..6920bfb9 100644 --- a/third_party/WebKit/Source/core/loader/FrameFetchContext.h +++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.h
@@ -67,7 +67,6 @@ bool isLiveContext() { return true; } void addAdditionalRequestHeaders(ResourceRequest&, FetchResourceType) override; - void setFirstPartyForCookies(ResourceRequest&) override; CachePolicy getCachePolicy() const override; WebCachePolicy resourceRequestCachePolicy(const ResourceRequest&, Resource::Type, FetchRequest::DeferOption) const override; void dispatchDidChangeResourcePriority(unsigned long identifier, ResourceLoadPriority, int intraPriorityValue) override; @@ -102,6 +101,7 @@ void upgradeInsecureRequest(ResourceRequest&) override; void addClientHintsIfNecessary(FetchRequest&) override; void addCSPHeaderIfNecessary(Resource::Type, FetchRequest&) override; + void populateRequestData(ResourceRequest&) override; MHTMLArchive* archive() const override;
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp index c9e1ebff..d8c3e17 100644 --- a/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp +++ b/third_party/WebKit/Source/core/loader/FrameFetchContextTest.cpp
@@ -448,6 +448,66 @@ EXPECT_EQ(WebCachePolicy::BypassingCache, childFetchContext->resourceRequestCachePolicy(request, Resource::MainResource, FetchRequest::NoDefer)); } +TEST_F(FrameFetchContextTest, PopulateRequestData) +{ + struct TestCase { + const char* documentURL; + bool documentSandboxed; + const char* requestorOrigin; // "" => nullptr, "null" => unique origin + WebURLRequest::FrameType frameType; + const char* serializedOrigin; // "" => nullptr, "null" => unique origin + } cases[] = { + // No document origin => unique request origin + { "", false, "", WebURLRequest::FrameTypeNone, "null" }, + { "", true, "", WebURLRequest::FrameTypeNone, "null" }, + + // Document origin => request origin + { "http://example.test", false, "", WebURLRequest::FrameTypeNone, "http://example.test" }, + { "http://example.test", true, "", WebURLRequest::FrameTypeNone, "http://example.test" }, + + // If the request already has a requestor origin, then 'populateRequestData' leaves it alone: + { "http://example.test", false, "http://not-example.test", WebURLRequest::FrameTypeNone, "http://not-example.test" }, + { "http://example.test", true, "http://not-example.test", WebURLRequest::FrameTypeNone, "http://not-example.test" }, + + // If the request's frame type is not 'none', then 'populateRequestData' leaves it alone: + { "http://example.test", false, "", WebURLRequest::FrameTypeTopLevel, "" }, + { "http://example.test", false, "", WebURLRequest::FrameTypeAuxiliary, "" }, + { "http://example.test", false, "", WebURLRequest::FrameTypeNested, "" }, + }; + + for (const auto& test : cases) { + SCOPED_TRACE(::testing::Message() << test.documentURL << " => " << test.serializedOrigin); + // Set up a new document to ensure sandbox flags are cleared: + dummyPageHolder = DummyPageHolder::create(IntSize(500, 500)); + dummyPageHolder->page().setDeviceScaleFactor(1.0); + document = toHTMLDocument(&dummyPageHolder->document()); + FrameFetchContext::provideDocumentToContext(*fetchContext, document.get()); + + // Setup the test: + document->setURL(KURL(ParsedURLString, test.documentURL)); + document->setSecurityOrigin(SecurityOrigin::create(document->url())); + + if (test.documentSandboxed) + document->enforceSandboxFlags(SandboxOrigin); + + ResourceRequest request("http://example.test/"); + request.setFrameType(test.frameType); + if (strlen(test.requestorOrigin) == 0) + request.setRequestorOrigin(nullptr); + else + request.setRequestorOrigin(SecurityOrigin::create(KURL(ParsedURLString, test.requestorOrigin))); + + // Compare the populated |requestorOrigin| against |test.serializedOrigin| + fetchContext->populateRequestData(request); + if (strlen(test.serializedOrigin) == 0) + EXPECT_EQ(nullptr, request.requestorOrigin().get()); + else + EXPECT_EQ(String(test.serializedOrigin), request.requestorOrigin()->toString()); + + EXPECT_EQ(document->firstPartyForCookies(), request.firstPartyForCookies()); + } +} + TEST_F(FrameFetchContextTest, ModifyPriorityForLowPriorityIframes) { Settings* settings = document->frame()->settings();
diff --git a/third_party/WebKit/Source/core/loader/FrameLoadRequest.cpp b/third_party/WebKit/Source/core/loader/FrameLoadRequest.cpp index 9c4ad94..4dd89cf2 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoadRequest.cpp +++ b/third_party/WebKit/Source/core/loader/FrameLoadRequest.cpp
@@ -53,10 +53,22 @@ if (originDocument) { m_resourceRequest.setRequestorOrigin(SecurityOrigin::create(originDocument->url())); - } else { - if (m_resourceRequest.frameType() == WebURLRequest::FrameTypeTopLevel) { - m_resourceRequest.setRequestorOrigin(SecurityOrigin::create(resourceRequest.url())); - } + return; + } + + // If we don't have an origin document, and we're going to throw away the response data + // regardless, set the requestor to a unique origin. + if (m_substituteData.isValid()) { + m_resourceRequest.setRequestorOrigin(SecurityOrigin::createUnique()); + return; + } + + // If we're dealing with a top-level request, use the origin of the requested URL as the initiator. + // + // TODO(mkwst): This should be `nullptr`. https://crbug.com/625969 + if (m_resourceRequest.frameType() == WebURLRequest::FrameTypeTopLevel) { + m_resourceRequest.setRequestorOrigin(SecurityOrigin::create(resourceRequest.url())); + return; } }
diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp index 9aef6de6..3488d75 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp +++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp
@@ -1542,6 +1542,9 @@ if (!m_frame->script().canExecuteScripts(NotAboutToExecuteScript)) return; + Settings* settings = m_frame->settings(); + if (settings && settings->forceMainWorldInitialization()) + m_frame->script().initializeMainWorld(); InspectorInstrumentation::didClearDocumentOfWindowObject(m_frame); if (m_dispatchingDidClearWindowObjectInMainWorld)
diff --git a/third_party/WebKit/Source/core/loader/PingLoader.cpp b/third_party/WebKit/Source/core/loader/PingLoader.cpp index 24b9b7a..bbb409e 100644 --- a/third_party/WebKit/Source/core/loader/PingLoader.cpp +++ b/third_party/WebKit/Source/core/loader/PingLoader.cpp
@@ -62,7 +62,7 @@ { request.setRequestContext(WebURLRequest::RequestContextPing); frame->document()->fetcher()->context().addAdditionalRequestHeaders(request, FetchSubresource); - frame->document()->fetcher()->context().setFirstPartyForCookies(request); + frame->document()->fetcher()->context().populateRequestData(request); } void PingLoader::loadImage(LocalFrame* frame, const KURL& url)
diff --git a/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.cpp b/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.cpp index aafc6c9..446036a 100644 --- a/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.cpp +++ b/third_party/WebKit/Source/core/origin_trials/OriginTrialContext.cpp
@@ -388,6 +388,7 @@ DEFINE_TRACE(OriginTrialContext) { visitor->trace(m_host); + Supplement<ExecutionContext>::trace(visitor); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/page/FocusController.cpp b/third_party/WebKit/Source/core/page/FocusController.cpp index f0388e2a..c7d11a22 100644 --- a/third_party/WebKit/Source/core/page/FocusController.cpp +++ b/third_party/WebKit/Source/core/page/FocusController.cpp
@@ -1021,7 +1021,7 @@ static bool relinquishesEditingFocus(const Element& element) { DCHECK(element.hasEditableStyle()); - return element.document().frame() && element.rootEditableElement(); + return element.document().frame() && rootEditableElement(element); } static void clearSelectionIfNeeded(LocalFrame* oldFocusedFrame, LocalFrame* newFocusedFrame, Element* newFocusedElement) @@ -1068,7 +1068,7 @@ return true; // FIXME: Might want to disable this check for caretBrowsing - if (oldFocusedElement && oldFocusedElement->isRootEditableElement() && !relinquishesEditingFocus(*oldFocusedElement)) + if (oldFocusedElement && isRootEditableElement(*oldFocusedElement) && !relinquishesEditingFocus(*oldFocusedElement)) return false; m_page->chromeClient().willSetInputMethodState();
diff --git a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp index 9bac01d..4d4f495f 100644 --- a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp +++ b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp
@@ -9,11 +9,14 @@ #include "core/frame/FrameHost.h" #include "core/frame/FrameView.h" #include "core/frame/TopControls.h" +#include "core/frame/VisualViewport.h" #include "core/layout/LayoutBox.h" +#include "core/page/ChromeClient.h" #include "core/page/Page.h" #include "core/page/scrolling/OverscrollController.h" #include "core/page/scrolling/ViewportScrollCallback.h" #include "core/paint/PaintLayerScrollableArea.h" +#include "platform/graphics/GraphicsLayer.h" #include "platform/scroll/ScrollableArea.h" namespace blink { @@ -160,6 +163,34 @@ return true; } +void RootScrollerController::didUpdateCompositing() +{ + FrameHost& frameHost = *m_document->frameHost(); + + // Let the compositor-side counterpart know about this change. + if (m_document->isInMainFrame()) + frameHost.chromeClient().registerViewportLayers(); +} + +GraphicsLayer* RootScrollerController::rootScrollerLayer() +{ + if (!m_effectiveRootScroller) + return nullptr; + + ScrollableArea* area = scrollableAreaFor(*m_effectiveRootScroller); + + if (!area) + return nullptr; + + GraphicsLayer* graphicsLayer = area->layerForScrolling(); + + // TODO(bokan): We should assert graphicsLayer here and + // RootScrollerController should do whatever needs to happen to ensure + // the root scroller gets composited. + + return graphicsLayer; +} + Element* RootScrollerController::defaultEffectiveRootScroller() { DCHECK(m_document);
diff --git a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h index dd497226..557102b 100644 --- a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h +++ b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h
@@ -12,6 +12,7 @@ class Document; class Element; +class GraphicsLayer; class ViewportScrollCallback; // Manages the root scroller associated with a given document. The root scroller @@ -70,6 +71,12 @@ // replaced by the defualt root scroller. void didUpdateLayout(); + // This class needs to be informed of changes to compositing so that it can + // update the compositor when the effective root scroller changes. + void didUpdateCompositing(); + + GraphicsLayer* rootScrollerLayer(); + // TODO(bokan): Temporarily exposed to allow ScrollCustomization to // differentiate between real custom callback and the built-in viewport // apply scroll.
diff --git a/third_party/WebKit/Source/core/paint/FramePainter.cpp b/third_party/WebKit/Source/core/paint/FramePainter.cpp index de5bcce..8ec3b8e 100644 --- a/third_party/WebKit/Source/core/paint/FramePainter.cpp +++ b/third_party/WebKit/Source/core/paint/FramePainter.cpp
@@ -95,7 +95,7 @@ { Document* document = frameView().frame().document(); - if (frameView().shouldThrottleRendering()) + if (frameView().shouldThrottleRendering() || !document->isActive()) return; #ifndef NDEBUG @@ -124,6 +124,8 @@ } frameView().checkDoesNotNeedLayout(); + // TODO(wangxianzhu): The following check should be stricter, but currently this is blocked + // by the svg root issue (crbug.com/442939). ASSERT(document->lifecycle().state() >= DocumentLifecycle::CompositingClean); TRACE_EVENT1("devtools.timeline", "Paint", "data", InspectorPaintEvent::data(layoutView, LayoutRect(rect), 0));
diff --git a/third_party/WebKit/Source/core/paint/ImagePainter.cpp b/third_party/WebKit/Source/core/paint/ImagePainter.cpp index 203c6880..ad19b3f9 100644 --- a/third_party/WebKit/Source/core/paint/ImagePainter.cpp +++ b/third_party/WebKit/Source/core/paint/ImagePainter.cpp
@@ -19,7 +19,6 @@ #include "core/paint/PaintInfo.h" #include "platform/geometry/LayoutPoint.h" #include "platform/graphics/Path.h" -#include "platform/graphics/paint/ClipRecorder.h" namespace blink { @@ -102,46 +101,51 @@ context.drawRect(paintRect); } } else if (cWidth > 0 && cHeight > 0) { + if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, m_layoutImage, paintInfo.phase)) + return; + LayoutRect contentRect = m_layoutImage.contentBoxRect(); contentRect.moveBy(paintOffset); LayoutRect paintRect = m_layoutImage.replacedContentRect(); paintRect.moveBy(paintOffset); - Optional<ClipRecorder> clipRecorder; - if (!contentRect.contains(paintRect)) { - // TODO(fmalita): can we get rid of this clip and adjust the image src/dst rect instead? - clipRecorder.emplace(context, m_layoutImage, paintInfo.displayItemTypeForClipping(), pixelSnappedIntRect(contentRect)); - } - - if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, m_layoutImage, paintInfo.phase)) - return; - LayoutObjectDrawingRecorder drawingRecorder(context, m_layoutImage, paintInfo.phase, contentRect); - paintIntoRect(context, paintRect); + paintIntoRect(context, paintRect, contentRect); } } -void ImagePainter::paintIntoRect(GraphicsContext& context, const LayoutRect& rect) +void ImagePainter::paintIntoRect(GraphicsContext& context, const LayoutRect& destRect, const LayoutRect& contentRect) { if (!m_layoutImage.imageResource()->hasImage() || m_layoutImage.imageResource()->errorOccurred()) return; // FIXME: should we just ASSERT these conditions? (audit all callers). - IntRect alignedRect = pixelSnappedIntRect(rect); - if (alignedRect.width() <= 0 || alignedRect.height() <= 0) + IntRect pixelSnappedDestRect = pixelSnappedIntRect(destRect); + if (pixelSnappedDestRect.isEmpty()) return; - RefPtr<Image> image = m_layoutImage.imageResource()->image(alignedRect.size(), m_layoutImage.style()->effectiveZoom()); + RefPtr<Image> image = m_layoutImage.imageResource()->image(pixelSnappedDestRect.size(), m_layoutImage.style()->effectiveZoom()); if (!image || image->isNull()) return; // FIXME: why is interpolation quality selection not included in the Instrumentation reported cost of drawing an image? - InterpolationQuality interpolationQuality = BoxPainter::chooseInterpolationQuality(m_layoutImage, image.get(), image.get(), LayoutSize(alignedRect.size())); + InterpolationQuality interpolationQuality = BoxPainter::chooseInterpolationQuality(m_layoutImage, image.get(), image.get(), LayoutSize(pixelSnappedDestRect.size())); + + FloatRect srcRect = image->rect(); + // If the content rect requires clipping, adjust |srcRect| and |pixelSnappedDestRect| over using a clip. + if (!contentRect.contains(destRect)) { + IntRect pixelSnappedContentRect = pixelSnappedIntRect(contentRect); + pixelSnappedContentRect.intersect(pixelSnappedDestRect); + if (pixelSnappedContentRect.isEmpty()) + return; + srcRect = mapRect(pixelSnappedContentRect, pixelSnappedDestRect, srcRect); + pixelSnappedDestRect = pixelSnappedContentRect; + } TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage", "data", InspectorPaintImageEvent::data(m_layoutImage)); InterpolationQuality previousInterpolationQuality = context.imageInterpolationQuality(); context.setImageInterpolationQuality(interpolationQuality); - context.drawImage(image.get(), alignedRect, nullptr, SkXfermode::kSrcOver_Mode, + context.drawImage(image.get(), pixelSnappedDestRect, &srcRect, SkXfermode::kSrcOver_Mode, LayoutObject::shouldRespectImageOrientation(&m_layoutImage)); context.setImageInterpolationQuality(previousInterpolationQuality); }
diff --git a/third_party/WebKit/Source/core/paint/ImagePainter.h b/third_party/WebKit/Source/core/paint/ImagePainter.h index fce4d61..287dc59e 100644 --- a/third_party/WebKit/Source/core/paint/ImagePainter.h +++ b/third_party/WebKit/Source/core/paint/ImagePainter.h
@@ -22,7 +22,10 @@ void paint(const PaintInfo&, const LayoutPoint& paintOffset); void paintReplaced(const PaintInfo&, const LayoutPoint& paintOffset); - void paintIntoRect(GraphicsContext&, const LayoutRect&); + + // Paint the image into |destRect|, after clipping by |contentRect|. Both |destRect| and + // |contentRect| should be in local coordinates plus the paint offset. + void paintIntoRect(GraphicsContext&, const LayoutRect& destRect, const LayoutRect& contentRect); private: void paintAreaElementFocusRing(const PaintInfo&, const LayoutPoint& paintOffset);
diff --git a/third_party/WebKit/Source/core/paint/LayoutObjectDrawingRecorderTest.cpp b/third_party/WebKit/Source/core/paint/LayoutObjectDrawingRecorderTest.cpp index c0eb0e53..abc9a5a 100644 --- a/third_party/WebKit/Source/core/paint/LayoutObjectDrawingRecorderTest.cpp +++ b/third_party/WebKit/Source/core/paint/LayoutObjectDrawingRecorderTest.cpp
@@ -76,9 +76,7 @@ drawNothing(context, layoutView(), PaintPhaseSelfBlockBackgroundOnly, bound); drawRect(context, layoutView(), PaintPhaseForeground, bound); - EXPECT_DISPLAY_LIST(rootPaintController().newDisplayItemList(), 2, - TestDisplayItem(layoutView(), DisplayItem::drawingTypeToCachedDrawingType(DisplayItem::paintPhaseToDrawingType(PaintPhaseSelfBlockBackgroundOnly))), - TestDisplayItem(layoutView(), DisplayItem::drawingTypeToCachedDrawingType(DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground)))); + EXPECT_EQ(2, numCachedNewItems()); rootPaintController().commitNewDisplayItems();
diff --git a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h index 83a1cf4..db2c9b1 100644 --- a/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h +++ b/third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h
@@ -75,6 +75,8 @@ return false; } + int numCachedNewItems() { return rootPaintController().m_numCachedNewItems; } + private: bool m_originalSlimmingPaintInvalidationEnabled; bool m_originalSlimmingPaintV2Enabled; @@ -129,11 +131,8 @@ // Shorter names for frequently used display item types in tests. const DisplayItem::Type backgroundType = DisplayItem::BoxDecorationBackground; -const DisplayItem::Type cachedBackgroundType = DisplayItem::drawingTypeToCachedDrawingType(backgroundType); const DisplayItem::Type foregroundType = DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground); -const DisplayItem::Type cachedForegroundType = DisplayItem::drawingTypeToCachedDrawingType(foregroundType); const DisplayItem::Type documentBackgroundType = DisplayItem::DocumentBackground; -const DisplayItem::Type cachedDocumentBackgroundType = DisplayItem::drawingTypeToCachedDrawingType(DisplayItem::DocumentBackground); } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp index f89da6ef..47b0cae 100644 --- a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp +++ b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp
@@ -19,7 +19,7 @@ { if (!scrollbar.isCustomScrollbar() && !(orientation == HorizontalScrollbar ? layerForHorizontalScrollbar() : layerForVerticalScrollbar())) - boxForScrollControlPaintInvalidation().slowSetPaintingLayerNeedsRepaintAndInvalidateDisplayItemClient(scrollbar, PaintInvalidationScroll); + layoutBox()->slowSetPaintingLayerNeedsRepaintAndInvalidateDisplayItemClient(scrollbar, PaintInvalidationScroll); ScrollableArea::willRemoveScrollbar(scrollbar, orientation); } @@ -42,7 +42,6 @@ } if (shouldInvalidateNewRect) { box.invalidatePaintUsingContainer(paintInvalidationContainer, newPaintInvalidationRect, PaintInvalidationScroll); - box.enclosingLayer()->setNeedsRepaint(); return true; } return false; @@ -99,7 +98,7 @@ void PaintInvalidationCapableScrollableArea::invalidatePaintOfScrollControlsIfNeeded(const PaintInvalidationState& paintInvalidationState) { - LayoutBox& box = boxForScrollControlPaintInvalidation(); + LayoutBox& box = *layoutBox(); invalidatePaintOfScrollbarIfNeeded(horizontalScrollbar(), layerForHorizontalScrollbar(), m_horizontalScrollbarPreviouslyWasOverlay, m_horizontalScrollbarPreviousPaintInvalidationRect, horizontalScrollbarNeedsPaintInvalidation(), box, paintInvalidationState); invalidatePaintOfScrollbarIfNeeded(verticalScrollbar(), layerForVerticalScrollbar(), m_verticalScrollbarPreviouslyWasOverlay, m_verticalScrollbarPreviousPaintInvalidationRect, verticalScrollbarNeedsPaintInvalidation(), box, paintInvalidationState); @@ -131,4 +130,15 @@ return fullBounds; } +void PaintInvalidationCapableScrollableArea::scrollControlWasSetNeedsPaintInvalidation() +{ + layoutBox()->setMayNeedPaintInvalidation(); +} + +bool PaintInvalidationCapableScrollableArea::shouldPerformScrollAnchoring() const +{ + return RuntimeEnabledFeatures::scrollAnchoringEnabled() + && layoutBox()->style()->overflowAnchor() != AnchorNone; +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.h b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.h index d58342ef..6d59980 100644 --- a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.h +++ b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.h
@@ -36,11 +36,14 @@ LayoutRect visualRectForScrollbarParts() const override; + bool shouldPerformScrollAnchoring() const override; + private: - virtual LayoutBox& boxForScrollControlPaintInvalidation() const = 0; virtual LayoutScrollbarPart* scrollCorner() const = 0; virtual LayoutScrollbarPart* resizer() const = 0; + void scrollControlWasSetNeedsPaintInvalidation() override; + bool m_horizontalScrollbarPreviouslyWasOverlay; bool m_verticalScrollbarPreviouslyWasOverlay; LayoutRect m_horizontalScrollbarPreviousPaintInvalidationRect;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp index a7789d7..5e9c5922 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerPainterTest.cpp
@@ -56,20 +56,11 @@ toHTMLElement(content1.node())->setAttribute(HTMLNames::styleAttr, "position: absolute; width: 100px; height: 100px; background-color: green"); document().view()->updateAllLifecyclePhasesExceptPaint(); - bool needsCommit = paintWithoutCommit(); + EXPECT_TRUE(paintWithoutCommit()); - EXPECT_DISPLAY_LIST(rootPaintController().newDisplayItemList(), 8, - TestDisplayItem(layoutView(), cachedDocumentBackgroundType), - TestDisplayItem(htmlLayer, DisplayItem::Subsequence), - TestDisplayItem(container1Layer, DisplayItem::Subsequence), - TestDisplayItem(container1, cachedBackgroundType), - TestDisplayItem(content1, backgroundType), - TestDisplayItem(container1Layer, DisplayItem::EndSubsequence), - TestDisplayItem(container2Layer, DisplayItem::CachedSubsequence), - TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence)); + EXPECT_EQ(6, numCachedNewItems()); - if (needsCommit) - commit(); + commit(); EXPECT_DISPLAY_LIST(rootPaintController().getDisplayItemList(), 11, TestDisplayItem(layoutView(), documentBackgroundType), @@ -139,28 +130,16 @@ document().view()->updateAllLifecyclePhasesExceptPaint(); IntRect newInterestRect(0, 100, 300, 1000); - bool needsCommit = paintWithoutCommit(&newInterestRect); + EXPECT_TRUE(paintWithoutCommit(&newInterestRect)); // Container1 becomes partly in the interest rect, but uses cached subsequence // because it was fully painted before; // Container2's intersection with the interest rect changes; // Content2b is out of the interest rect and outputs nothing; // Container3 becomes out of the interest rect and outputs empty subsequence pair.. - EXPECT_DISPLAY_LIST(rootPaintController().newDisplayItemList(), 11, - TestDisplayItem(layoutView(), cachedDocumentBackgroundType), - TestDisplayItem(htmlLayer, DisplayItem::Subsequence), - TestDisplayItem(container1Layer, DisplayItem::CachedSubsequence), - TestDisplayItem(container2Layer, DisplayItem::Subsequence), - TestDisplayItem(container2, cachedBackgroundType), - TestDisplayItem(content2a, cachedBackgroundType), - TestDisplayItem(content2b, backgroundType), - TestDisplayItem(container2Layer, DisplayItem::EndSubsequence), - TestDisplayItem(container3Layer, DisplayItem::Subsequence), - TestDisplayItem(container3Layer, DisplayItem::EndSubsequence), - TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence)); + EXPECT_EQ(7, numCachedNewItems()); - if (needsCommit) - commit(); + commit(); EXPECT_DISPLAY_LIST(rootPaintController().getDisplayItemList(), 14, TestDisplayItem(layoutView(), documentBackgroundType), @@ -215,20 +194,11 @@ toHTMLElement(content1.node())->setAttribute(HTMLNames::styleAttr, "position: absolute; width: 100px; height: 100px; background-color: green"); document().view()->updateAllLifecyclePhasesExceptPaint(); - bool needsCommit = paintWithoutCommit(&interestRect); + EXPECT_TRUE(paintWithoutCommit(&interestRect)); - EXPECT_DISPLAY_LIST(rootPaintController().newDisplayItemList(), 8, - TestDisplayItem(layoutView(), cachedDocumentBackgroundType), - TestDisplayItem(htmlLayer, DisplayItem::Subsequence), - TestDisplayItem(container1Layer, DisplayItem::Subsequence), - TestDisplayItem(container1, cachedBackgroundType), - TestDisplayItem(content1, backgroundType), - TestDisplayItem(container1Layer, DisplayItem::EndSubsequence), - TestDisplayItem(container2Layer, DisplayItem::CachedSubsequence), - TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence)); + EXPECT_EQ(6, numCachedNewItems()); - if (needsCommit) - commit(); + commit(); EXPECT_DISPLAY_LIST(rootPaintController().getDisplayItemList(), 11, TestDisplayItem(layoutView(), documentBackgroundType),
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp index 209a6ca..52b9388e 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.cpp
@@ -219,11 +219,6 @@ return layer()->hasCompositedLayerMapping() ? layer()->compositedLayerMapping()->layerForScrollCorner() : 0; } -void PaintLayerScrollableArea::scrollControlWasSetNeedsPaintInvalidation() -{ - box().setMayNeedPaintInvalidation(); -} - bool PaintLayerScrollableArea::shouldUseIntegerScrollOffset() const { Frame* frame = box().frame();
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h index 2aa1d6a..dd957916 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h +++ b/third_party/WebKit/Source/core/paint/PaintLayerScrollableArea.h
@@ -258,7 +258,6 @@ bool usesCompositedScrolling() const override; bool shouldScrollOnMainThread() const override; - void scrollControlWasSetNeedsPaintInvalidation() override; bool shouldUseIntegerScrollOffset() const override; bool isActive() const override; bool isScrollCornerVisible() const override; @@ -489,9 +488,6 @@ return *m_rareData.get(); } - // PaintInvalidationCapableScrollableArea - LayoutBox& boxForScrollControlPaintInvalidation() const { return box(); } - PaintLayer& m_layer; PaintLayer* m_nextTopmostScrollChild;
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp index d0860a4..07abff8 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp
@@ -21,19 +21,17 @@ void PaintPropertyTreeBuilder::buildTreeRootNodes(FrameView& rootFrame, PaintPropertyTreeBuilderContext& context) { - // Only create extra root clip and transform nodes when RLS is enabled, because the main frame - // unconditionally create frame translation / clip nodes otherwise. - if (rootFrame.frame().settings() && rootFrame.frame().settings()->rootLayerScrolls()) { - transformRoot = TransformPaintPropertyNode::create(TransformationMatrix(), FloatPoint3D(), nullptr); - context.currentTransform = context.transformForAbsolutePosition = context.transformForFixedPosition = transformRoot.get(); + RefPtr<TransformPaintPropertyNode> transformRoot = TransformPaintPropertyNode::create(TransformationMatrix(), FloatPoint3D(), nullptr); + context.currentTransform = context.transformForAbsolutePosition = context.transformForFixedPosition = transformRoot.get(); + rootFrame.setRootTransform(std::move(transformRoot)); - clipRoot = ClipPaintPropertyNode::create(transformRoot, FloatRoundedRect(LayoutRect::infiniteIntRect()), nullptr); - context.currentClip = context.clipForAbsolutePosition = context.clipForFixedPosition = clipRoot.get(); - } + RefPtr<ClipPaintPropertyNode> clipRoot = ClipPaintPropertyNode::create(transformRoot, FloatRoundedRect(LayoutRect::infiniteIntRect()), nullptr); + context.currentClip = context.clipForAbsolutePosition = context.clipForFixedPosition = clipRoot.get(); + rootFrame.setRootClip(std::move(clipRoot)); - // The root frame never creates effect node so we unconditionally create a root node here. - effectRoot = EffectPaintPropertyNode::create(1.0, nullptr); + RefPtr<EffectPaintPropertyNode> effectRoot = EffectPaintPropertyNode::create(1.0, nullptr); context.currentEffect = effectRoot.get(); + rootFrame.setRootEffect(std::move(effectRoot)); } void PaintPropertyTreeBuilder::buildTreeNodes(FrameView& frameView, PaintPropertyTreeBuilderContext& context)
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h index 0234bbe..118763f 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.h
@@ -86,11 +86,6 @@ static void updateSvgLocalToBorderBoxTransform(const LayoutObject&, PaintPropertyTreeBuilderContext&); static void updateScrollTranslation(const LayoutObject&, PaintPropertyTreeBuilderContext&); static void updateOutOfFlowContext(const LayoutObject&, PaintPropertyTreeBuilderContext&); - - // Holds references to root property nodes to keep them alive during tree walk. - RefPtr<TransformPaintPropertyNode> transformRoot; - RefPtr<ClipPaintPropertyNode> clipRoot; - RefPtr<EffectPaintPropertyNode> effectRoot; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp index 466906e..0bd39b2 100644 --- a/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilderTest.cpp
@@ -145,12 +145,14 @@ FrameView* frameView = document().view(); frameView->updateAllLifecyclePhases(); EXPECT_EQ(TransformationMatrix(), frameView->preTranslation()->matrix()); - EXPECT_EQ(nullptr, frameView->preTranslation()->parent()); + EXPECT_EQ(frameView->rootTransform(), frameView->preTranslation()->parent()); + EXPECT_EQ(nullptr, frameView->rootTransform()->parent()); EXPECT_EQ(TransformationMatrix().translate(0, -100), frameView->scrollTranslation()->matrix()); EXPECT_EQ(frameView->preTranslation(), frameView->scrollTranslation()->parent()); EXPECT_EQ(frameView->preTranslation(), frameView->contentClip()->localTransformSpace()); EXPECT_EQ(FloatRoundedRect(0, 0, 800, 600), frameView->contentClip()->clipRect()); - EXPECT_EQ(nullptr, frameView->contentClip()->parent()); + EXPECT_EQ(frameView->rootClip(), frameView->contentClip()->parent()); + EXPECT_EQ(nullptr, frameView->rootClip()->parent()); LayoutViewItem layoutViewItem = document().layoutViewItem(); ObjectPaintProperties* layoutViewProperties = layoutViewItem.objectPaintProperties();
diff --git a/third_party/WebKit/Source/core/paint/PaintTiming.cpp b/third_party/WebKit/Source/core/paint/PaintTiming.cpp index 7ff505a..87fc0e0 100644 --- a/third_party/WebKit/Source/core/paint/PaintTiming.cpp +++ b/third_party/WebKit/Source/core/paint/PaintTiming.cpp
@@ -68,6 +68,7 @@ DEFINE_TRACE(PaintTiming) { visitor->trace(m_document); + Supplement<Document>::trace(visitor); } PaintTiming::PaintTiming(Document& document)
diff --git a/third_party/WebKit/Source/core/paint/README.md b/third_party/WebKit/Source/core/paint/README.md index 1972dea..c391268 100644 --- a/third_party/WebKit/Source/core/paint/README.md +++ b/third_party/WebKit/Source/core/paint/README.md
@@ -215,9 +215,8 @@ ### Display item caching -We'll create a `CachedDisplayItem` when a painter would create a `DrawingDisplayItem` exactly -the same as the display item created in the previous painting. After painting, `PaintController` -will replace `CachedDisplayItem` with the corresponding display item from the cache. +When a painter would create a `DrawingDisplayItem` exactly the same as the display item +created in the previous painting, we'll reuse the previous one instead of repainting it. ### Subsequence caching @@ -225,10 +224,8 @@ (including display items generated by sublayers) in a pair of `BeginSubsequence/EndSubsequence` display items. -In a subsequence paint, if the layer would generate exactly the same display items, we'll simply -output a `CachedSubsequence` display item in place of the display items, and skip all paintings -of the layer and its descendants in painting order. After painting, `PaintController` will -replace `CacheSubsequence` with cached display items created in previous paintings. +In a subsequence paint, if the layer would generate exactly the same display items, we'll get +the whole subsequence from the cache instead of repainting them. There are many conditions affecting * whether we need to generate subsequence for a PaintLayer;
diff --git a/third_party/WebKit/Source/core/paint/VideoPainter.cpp b/third_party/WebKit/Source/core/paint/VideoPainter.cpp index 49ea54a..07b42bd 100644 --- a/third_party/WebKit/Source/core/paint/VideoPainter.cpp +++ b/third_party/WebKit/Source/core/paint/VideoPainter.cpp
@@ -12,7 +12,6 @@ #include "core/paint/LayoutObjectDrawingRecorder.h" #include "core/paint/PaintInfo.h" #include "platform/geometry/LayoutPoint.h" -#include "platform/graphics/paint/ClipRecorder.h" #include "platform/graphics/paint/ForeignLayerDisplayItem.h" namespace blink { @@ -29,18 +28,13 @@ return; rect.moveBy(paintOffset); + if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(paintInfo.context, m_layoutVideo, paintInfo.phase)) + return; + GraphicsContext& context = paintInfo.context; LayoutRect contentRect = m_layoutVideo.contentBoxRect(); contentRect.moveBy(paintOffset); - Optional<ClipRecorder> clipRecorder; - if (!contentRect.contains(rect)) - clipRecorder.emplace(context, m_layoutVideo, paintInfo.displayItemTypeForClipping(), pixelSnappedIntRect(contentRect)); - - if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, m_layoutVideo, paintInfo.phase)) - return; - - // Video frames are only painted in software for printing or capturing node images via web APIs. bool forceSoftwareVideoPaint = paintInfo.getGlobalPaintFlags() & GlobalPaintFlattenCompositingLayers; @@ -61,7 +55,7 @@ if (displayingPoster || !forceSoftwareVideoPaint) { // This will display the poster image, if one is present, and otherwise paint nothing. - ImagePainter(m_layoutVideo).paintIntoRect(context, rect); + ImagePainter(m_layoutVideo).paintIntoRect(context, rect, contentRect); } else { SkPaint videoPaint = context.fillPaint(); videoPaint.setColor(SK_ColorBLACK);
diff --git a/third_party/WebKit/Source/core/style/BorderData.h b/third_party/WebKit/Source/core/style/BorderData.h index eedc12a8..7bdb4d3 100644 --- a/third_party/WebKit/Source/core/style/BorderData.h +++ b/third_party/WebKit/Source/core/style/BorderData.h
@@ -124,6 +124,14 @@ return !(*this == o); } + bool sizeEquals(const BorderData& o) const + { + return borderLeftWidth() != o.borderLeftWidth() + || borderTopWidth() != o.borderTopWidth() + || borderRightWidth() != o.borderRightWidth() + || borderBottomWidth() != o.borderBottomWidth(); + } + const BorderValue& left() const { return m_left; } const BorderValue& right() const { return m_right; } const BorderValue& top() const { return m_top; }
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp index b0b2204d..8f5d6fb3 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp +++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -294,6 +294,7 @@ // See comments for each skipped flag below. m_nonInheritedData.m_effectiveDisplay = other.m_nonInheritedData.m_effectiveDisplay; m_nonInheritedData.m_originalDisplay = other.m_nonInheritedData.m_originalDisplay; + m_nonInheritedData.m_overflowAnchor = other.m_nonInheritedData.m_overflowAnchor; m_nonInheritedData.m_overflowX = other.m_nonInheritedData.m_overflowX; m_nonInheritedData.m_overflowY = other.m_nonInheritedData.m_overflowY; m_nonInheritedData.m_verticalAlign = other.m_nonInheritedData.m_verticalAlign;
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h index 24caa78..aec7897 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyle.h +++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -218,6 +218,7 @@ { return m_effectiveDisplay == other.m_effectiveDisplay && m_originalDisplay == other.m_originalDisplay + && m_overflowAnchor == other.m_overflowAnchor && m_overflowX == other.m_overflowX && m_overflowY == other.m_overflowY && m_verticalAlign == other.m_verticalAlign @@ -246,6 +247,7 @@ unsigned m_effectiveDisplay : 5; // EDisplay unsigned m_originalDisplay : 5; // EDisplay + unsigned m_overflowAnchor : 2; // EOverflowAnchor unsigned m_overflowX : 3; // EOverflow unsigned m_overflowY : 3; // EOverflow unsigned m_verticalAlign : 4; // EVerticalAlign @@ -312,6 +314,7 @@ m_inheritedData.m_writingMode = initialWritingMode(); m_nonInheritedData.m_effectiveDisplay = m_nonInheritedData.m_originalDisplay = initialDisplay(); + m_nonInheritedData.m_overflowAnchor = initialOverflowAnchor(); m_nonInheritedData.m_overflowX = initialOverflowX(); m_nonInheritedData.m_overflowY = initialOverflowY(); m_nonInheritedData.m_verticalAlign = initialVerticalAlign(); @@ -576,6 +579,7 @@ OutlineIsAuto outlineStyleIsAuto() const { return static_cast<OutlineIsAuto>(m_background->outline().isAuto()); } int outlineOutsetExtent() const; + EOverflowAnchor overflowAnchor() const { return static_cast<EOverflowAnchor>(m_nonInheritedData.m_overflowAnchor); } EOverflow overflowX() const { return static_cast<EOverflow>(m_nonInheritedData.m_overflowX); } EOverflow overflowY() const { return static_cast<EOverflow>(m_nonInheritedData.m_overflowY); } // It's sufficient to just check one direction, since it's illegal to have visible on only one overflow value. @@ -1174,6 +1178,7 @@ m_background.access()->m_outline = o.m_background->m_outline; } + void setOverflowAnchor(EOverflowAnchor v) { m_nonInheritedData.m_overflowAnchor = v; } void setOverflowX(EOverflow v) { m_nonInheritedData.m_overflowX = v; } void setOverflowY(EOverflow v) { m_nonInheritedData.m_overflowY = v; } void setVisibility(EVisibility v) { m_inheritedData.m_visibility = v; } @@ -1703,6 +1708,7 @@ static EFloat initialFloating() { return NoFloat; } static EListStylePosition initialListStylePosition() { return ListStylePositionOutside; } static EListStyleType initialListStyleType() { return Disc; } + static EOverflowAnchor initialOverflowAnchor() { return AnchorAuto; } static EOverflow initialOverflowX() { return OverflowVisible; } static EOverflow initialOverflowY() { return OverflowVisible; } static EBreak initialBreakAfter() { return BreakAuto; }
diff --git a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h index d3c42a7..f9b57ee 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h +++ b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
@@ -133,6 +133,10 @@ // Random visual rendering model attributes. Not inherited. +enum EOverflowAnchor { + AnchorVisible, AnchorNone, AnchorAuto +}; + enum EOverflow { OverflowVisible, OverflowHidden, OverflowScroll, OverflowAuto, OverflowOverlay, OverflowPagedX, OverflowPagedY };
diff --git a/third_party/WebKit/Source/core/style/StyleGeneratedImage.cpp b/third_party/WebKit/Source/core/style/StyleGeneratedImage.cpp index 1e63714f..e03e8ec 100644 --- a/third_party/WebKit/Source/core/style/StyleGeneratedImage.cpp +++ b/third_party/WebKit/Source/core/style/StyleGeneratedImage.cpp
@@ -68,9 +68,9 @@ m_imageGeneratorValue->removeClient(layoutObject); } -PassRefPtr<Image> StyleGeneratedImage::image(const LayoutObject& layoutObject, const IntSize& size, float) const +PassRefPtr<Image> StyleGeneratedImage::image(const LayoutObject& layoutObject, const IntSize& size, float zoom) const { - return m_imageGeneratorValue->image(layoutObject, size); + return m_imageGeneratorValue->image(layoutObject, size, zoom); } bool StyleGeneratedImage::knownToBeOpaque(const LayoutObject& layoutObject) const
diff --git a/third_party/WebKit/Source/core/svg/SVGAttributeNames.in b/third_party/WebKit/Source/core/svg/SVGAttributeNames.in index 8b2d5e1b..0d63f39 100644 --- a/third_party/WebKit/Source/core/svg/SVGAttributeNames.in +++ b/third_party/WebKit/Source/core/svg/SVGAttributeNames.in
@@ -127,7 +127,6 @@ onfocusin onfocusout onrepeat -onzoom opacity operator order
diff --git a/third_party/WebKit/Source/core/svg/SVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGElement.cpp index 28f432c..9f3bfab 100644 --- a/third_party/WebKit/Source/core/svg/SVGElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGElement.cpp
@@ -999,105 +999,99 @@ { // This static is atomically initialized to dodge a warning about // a race when dumping debug data for a layer. - DEFINE_THREAD_SAFE_STATIC_LOCAL(HashSet<QualifiedName>, animatableAttributes, new HashSet<QualifiedName>()); - - if (animatableAttributes.isEmpty()) { - const QualifiedName* const animatableAttrs[] = { - &SVGNames::amplitudeAttr, - &SVGNames::azimuthAttr, - &SVGNames::baseFrequencyAttr, - &SVGNames::biasAttr, - &SVGNames::clipPathUnitsAttr, - &SVGNames::cxAttr, - &SVGNames::cyAttr, - &SVGNames::diffuseConstantAttr, - &SVGNames::divisorAttr, - &SVGNames::dxAttr, - &SVGNames::dyAttr, - &SVGNames::edgeModeAttr, - &SVGNames::elevationAttr, - &SVGNames::exponentAttr, - &SVGNames::filterUnitsAttr, - &SVGNames::fxAttr, - &SVGNames::fyAttr, - &SVGNames::gradientTransformAttr, - &SVGNames::gradientUnitsAttr, - &SVGNames::heightAttr, - &SVGNames::hrefAttr, - &SVGNames::in2Attr, - &SVGNames::inAttr, - &SVGNames::interceptAttr, - &SVGNames::k1Attr, - &SVGNames::k2Attr, - &SVGNames::k3Attr, - &SVGNames::k4Attr, - &SVGNames::kernelMatrixAttr, - &SVGNames::kernelUnitLengthAttr, - &SVGNames::lengthAdjustAttr, - &SVGNames::limitingConeAngleAttr, - &SVGNames::markerHeightAttr, - &SVGNames::markerUnitsAttr, - &SVGNames::markerWidthAttr, - &SVGNames::maskContentUnitsAttr, - &SVGNames::maskUnitsAttr, - &SVGNames::methodAttr, - &SVGNames::modeAttr, - &SVGNames::numOctavesAttr, - &SVGNames::offsetAttr, - &SVGNames::operatorAttr, - &SVGNames::orderAttr, - &SVGNames::orientAttr, - &SVGNames::pathLengthAttr, - &SVGNames::patternContentUnitsAttr, - &SVGNames::patternTransformAttr, - &SVGNames::patternUnitsAttr, - &SVGNames::pointsAtXAttr, - &SVGNames::pointsAtYAttr, - &SVGNames::pointsAtZAttr, - &SVGNames::preserveAlphaAttr, - &SVGNames::preserveAspectRatioAttr, - &SVGNames::primitiveUnitsAttr, - &SVGNames::radiusAttr, - &SVGNames::rAttr, - &SVGNames::refXAttr, - &SVGNames::refYAttr, - &SVGNames::resultAttr, - &SVGNames::rotateAttr, - &SVGNames::rxAttr, - &SVGNames::ryAttr, - &SVGNames::scaleAttr, - &SVGNames::seedAttr, - &SVGNames::slopeAttr, - &SVGNames::spacingAttr, - &SVGNames::specularConstantAttr, - &SVGNames::specularExponentAttr, - &SVGNames::spreadMethodAttr, - &SVGNames::startOffsetAttr, - &SVGNames::stdDeviationAttr, - &SVGNames::stitchTilesAttr, - &SVGNames::surfaceScaleAttr, - &SVGNames::tableValuesAttr, - &SVGNames::targetAttr, - &SVGNames::targetXAttr, - &SVGNames::targetYAttr, - &SVGNames::transformAttr, - &SVGNames::typeAttr, - &SVGNames::valuesAttr, - &SVGNames::viewBoxAttr, - &SVGNames::widthAttr, - &SVGNames::x1Attr, - &SVGNames::x2Attr, - &SVGNames::xAttr, - &SVGNames::xChannelSelectorAttr, - &SVGNames::y1Attr, - &SVGNames::y2Attr, - &SVGNames::yAttr, - &SVGNames::yChannelSelectorAttr, - &SVGNames::zAttr, - }; - for (size_t i = 0; i < WTF_ARRAY_LENGTH(animatableAttrs); i++) - animatableAttributes.add(*animatableAttrs[i]); - } + DEFINE_THREAD_SAFE_STATIC_LOCAL(HashSet<QualifiedName>, animatableAttributes, new HashSet<QualifiedName>({ + SVGNames::amplitudeAttr, + SVGNames::azimuthAttr, + SVGNames::baseFrequencyAttr, + SVGNames::biasAttr, + SVGNames::clipPathUnitsAttr, + SVGNames::cxAttr, + SVGNames::cyAttr, + SVGNames::diffuseConstantAttr, + SVGNames::divisorAttr, + SVGNames::dxAttr, + SVGNames::dyAttr, + SVGNames::edgeModeAttr, + SVGNames::elevationAttr, + SVGNames::exponentAttr, + SVGNames::filterUnitsAttr, + SVGNames::fxAttr, + SVGNames::fyAttr, + SVGNames::gradientTransformAttr, + SVGNames::gradientUnitsAttr, + SVGNames::heightAttr, + SVGNames::hrefAttr, + SVGNames::in2Attr, + SVGNames::inAttr, + SVGNames::interceptAttr, + SVGNames::k1Attr, + SVGNames::k2Attr, + SVGNames::k3Attr, + SVGNames::k4Attr, + SVGNames::kernelMatrixAttr, + SVGNames::kernelUnitLengthAttr, + SVGNames::lengthAdjustAttr, + SVGNames::limitingConeAngleAttr, + SVGNames::markerHeightAttr, + SVGNames::markerUnitsAttr, + SVGNames::markerWidthAttr, + SVGNames::maskContentUnitsAttr, + SVGNames::maskUnitsAttr, + SVGNames::methodAttr, + SVGNames::modeAttr, + SVGNames::numOctavesAttr, + SVGNames::offsetAttr, + SVGNames::operatorAttr, + SVGNames::orderAttr, + SVGNames::orientAttr, + SVGNames::pathLengthAttr, + SVGNames::patternContentUnitsAttr, + SVGNames::patternTransformAttr, + SVGNames::patternUnitsAttr, + SVGNames::pointsAtXAttr, + SVGNames::pointsAtYAttr, + SVGNames::pointsAtZAttr, + SVGNames::preserveAlphaAttr, + SVGNames::preserveAspectRatioAttr, + SVGNames::primitiveUnitsAttr, + SVGNames::radiusAttr, + SVGNames::rAttr, + SVGNames::refXAttr, + SVGNames::refYAttr, + SVGNames::resultAttr, + SVGNames::rotateAttr, + SVGNames::rxAttr, + SVGNames::ryAttr, + SVGNames::scaleAttr, + SVGNames::seedAttr, + SVGNames::slopeAttr, + SVGNames::spacingAttr, + SVGNames::specularConstantAttr, + SVGNames::specularExponentAttr, + SVGNames::spreadMethodAttr, + SVGNames::startOffsetAttr, + SVGNames::stdDeviationAttr, + SVGNames::stitchTilesAttr, + SVGNames::surfaceScaleAttr, + SVGNames::tableValuesAttr, + SVGNames::targetAttr, + SVGNames::targetXAttr, + SVGNames::targetYAttr, + SVGNames::transformAttr, + SVGNames::typeAttr, + SVGNames::valuesAttr, + SVGNames::viewBoxAttr, + SVGNames::widthAttr, + SVGNames::x1Attr, + SVGNames::x2Attr, + SVGNames::xAttr, + SVGNames::xChannelSelectorAttr, + SVGNames::y1Attr, + SVGNames::y2Attr, + SVGNames::yAttr, + SVGNames::yChannelSelectorAttr, + SVGNames::zAttr, + })); if (name == classAttr) return true;
diff --git a/third_party/WebKit/Source/core/svg/SVGLength.cpp b/third_party/WebKit/Source/core/svg/SVGLength.cpp index c5fe9da..eb915de 100644 --- a/third_party/WebKit/Source/core/svg/SVGLength.cpp +++ b/third_party/WebKit/Source/core/svg/SVGLength.cpp
@@ -77,11 +77,6 @@ m_value->getFloatValue(), unitMode(), m_value->typeWithCalcResolved()); } -void SVGLength::setValueAsNumber(float value) -{ - m_value = CSSPrimitiveValue::create(value, CSSPrimitiveValue::UnitType::UserUnits); -} - void SVGLength::setValue(float value, const SVGLengthContext& context) { m_value = CSSPrimitiveValue::create( @@ -212,21 +207,18 @@ bool SVGLength::negativeValuesForbiddenForAnimatedLengthAttribute(const QualifiedName& attrName) { - DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, s_noNegativeValuesSet, ()); - - if (s_noNegativeValuesSet.isEmpty()) { - s_noNegativeValuesSet.add(SVGNames::frAttr); - s_noNegativeValuesSet.add(SVGNames::rAttr); - s_noNegativeValuesSet.add(SVGNames::rxAttr); - s_noNegativeValuesSet.add(SVGNames::ryAttr); - s_noNegativeValuesSet.add(SVGNames::widthAttr); - s_noNegativeValuesSet.add(SVGNames::heightAttr); - s_noNegativeValuesSet.add(SVGNames::markerWidthAttr); - s_noNegativeValuesSet.add(SVGNames::markerHeightAttr); - s_noNegativeValuesSet.add(SVGNames::textLengthAttr); - } - - return s_noNegativeValuesSet.contains(attrName); + DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, noNegativeValuesSet, ({ + SVGNames::frAttr, + SVGNames::rAttr, + SVGNames::rxAttr, + SVGNames::ryAttr, + SVGNames::widthAttr, + SVGNames::heightAttr, + SVGNames::markerWidthAttr, + SVGNames::markerHeightAttr, + SVGNames::textLengthAttr, + })); + return noNegativeValuesSet.contains(attrName); } void SVGLength::add(SVGPropertyBase* other, SVGElement* contextElement)
diff --git a/third_party/WebKit/Source/core/svg/SVGLength.h b/third_party/WebKit/Source/core/svg/SVGLength.h index 077aa33a..089e8f8 100644 --- a/third_party/WebKit/Source/core/svg/SVGLength.h +++ b/third_party/WebKit/Source/core/svg/SVGLength.h
@@ -56,7 +56,6 @@ float value(const SVGLengthContext&) const; void setValue(float, const SVGLengthContext&); - void setValueAsNumber(float); float valueInSpecifiedUnits() const { return m_value->getFloatValue(); } void setValueInSpecifiedUnits(float value) @@ -64,7 +63,7 @@ m_value = CSSPrimitiveValue::create(value, m_value->typeWithCalcResolved()); } - CSSPrimitiveValue* asCSSPrimitiveValue() const { return m_value.get(); } + const CSSPrimitiveValue* asCSSPrimitiveValue() const { return m_value.get(); } // Resolves LengthTypePercentage into a normalized floating point number (full value is 1.0). float valueAsPercentage() const; @@ -103,7 +102,7 @@ SVGLength(SVGLengthMode); SVGLength(const SVGLength&); - Member<CSSPrimitiveValue> m_value; + Member<const CSSPrimitiveValue> m_value; unsigned m_unitMode : 2; };
diff --git a/third_party/WebKit/Source/core/svg/SVGLengthTearOff.cpp b/third_party/WebKit/Source/core/svg/SVGLengthTearOff.cpp index 178046be..ebff1f65 100644 --- a/third_party/WebKit/Source/core/svg/SVGLengthTearOff.cpp +++ b/third_party/WebKit/Source/core/svg/SVGLengthTearOff.cpp
@@ -138,7 +138,13 @@ return; } - target()->setValueAsNumber(value); + if (target()->isRelative() && !canResolveRelativeUnits(contextElement())) { + exceptionState.throwDOMException(NotSupportedError, "Could not resolve relative length."); + return; + } + + SVGLengthContext lengthContext(contextElement()); + target()->setValue(value, lengthContext); commitChange(); }
diff --git a/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp b/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp index eb3e57ad7..73bddfc0 100644 --- a/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGSVGElement.cpp
@@ -177,9 +177,6 @@ document().setWindowAttributeEventListener(EventTypeNames::resize, createAttributeEventListener(document().frame(), name, value, eventParameterName())); } else if (name == HTMLNames::onscrollAttr) { document().setWindowAttributeEventListener(EventTypeNames::scroll, createAttributeEventListener(document().frame(), name, value, eventParameterName())); - } else if (name == SVGNames::onzoomAttr) { - Deprecation::countDeprecation(document(), UseCounter::SVGZoomEvent); - document().setWindowAttributeEventListener(EventTypeNames::zoom, createAttributeEventListener(document().frame(), name, value, eventParameterName())); } else { setListener = false; }
diff --git a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp index e6d6b6eb..d2249021f 100644 --- a/third_party/WebKit/Source/core/svg/SVGUseElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGUseElement.cpp
@@ -249,29 +249,28 @@ if (!element.isSVGElement()) return true; - DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, allowedElementTags, ()); - if (allowedElementTags.isEmpty()) { - allowedElementTags.add(SVGNames::aTag); - allowedElementTags.add(SVGNames::circleTag); - allowedElementTags.add(SVGNames::descTag); - allowedElementTags.add(SVGNames::ellipseTag); - allowedElementTags.add(SVGNames::gTag); - allowedElementTags.add(SVGNames::imageTag); - allowedElementTags.add(SVGNames::lineTag); - allowedElementTags.add(SVGNames::metadataTag); - allowedElementTags.add(SVGNames::pathTag); - allowedElementTags.add(SVGNames::polygonTag); - allowedElementTags.add(SVGNames::polylineTag); - allowedElementTags.add(SVGNames::rectTag); - allowedElementTags.add(SVGNames::svgTag); - allowedElementTags.add(SVGNames::switchTag); - allowedElementTags.add(SVGNames::symbolTag); - allowedElementTags.add(SVGNames::textTag); - allowedElementTags.add(SVGNames::textPathTag); - allowedElementTags.add(SVGNames::titleTag); - allowedElementTags.add(SVGNames::tspanTag); - allowedElementTags.add(SVGNames::useTag); - } + DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, allowedElementTags, ({ + SVGNames::aTag, + SVGNames::circleTag, + SVGNames::descTag, + SVGNames::ellipseTag, + SVGNames::gTag, + SVGNames::imageTag, + SVGNames::lineTag, + SVGNames::metadataTag, + SVGNames::pathTag, + SVGNames::polygonTag, + SVGNames::polylineTag, + SVGNames::rectTag, + SVGNames::svgTag, + SVGNames::switchTag, + SVGNames::symbolTag, + SVGNames::textTag, + SVGNames::textPathTag, + SVGNames::titleTag, + SVGNames::tspanTag, + SVGNames::useTag, + })); return !allowedElementTags.contains<SVGAttributeHashTranslator>(element.tagQName()); }
diff --git a/third_party/WebKit/Source/core/svg/SVGZoomEvent.cpp b/third_party/WebKit/Source/core/svg/SVGZoomEvent.cpp deleted file mode 100644 index f9f7d1c3..0000000 --- a/third_party/WebKit/Source/core/svg/SVGZoomEvent.cpp +++ /dev/null
@@ -1,77 +0,0 @@ -/* - * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org> - * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> - * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "core/svg/SVGZoomEvent.h" - -#include "core/svg/SVGElement.h" -#include "core/svg/SVGPointTearOff.h" -#include "core/svg/SVGRectTearOff.h" - -namespace blink { - -SVGZoomEvent::SVGZoomEvent() - : m_newScale(0.0f) - , m_previousScale(0.0f) -{ -} - -SVGRectTearOff* SVGZoomEvent::zoomRectScreen() const -{ - SVGRectTearOff* rectTearOff = SVGRectTearOff::create(SVGRect::create(), 0, PropertyIsNotAnimVal); - rectTearOff->setIsReadOnlyProperty(); - return rectTearOff; -} - -float SVGZoomEvent::previousScale() const -{ - return m_previousScale; -} - -SVGPointTearOff* SVGZoomEvent::previousTranslate() const -{ - SVGPointTearOff* pointTearOff = SVGPointTearOff::create(SVGPoint::create(m_previousTranslate), 0, PropertyIsNotAnimVal); - pointTearOff->setIsReadOnlyProperty(); - return pointTearOff; -} - -float SVGZoomEvent::newScale() const -{ - return m_newScale; -} - -SVGPointTearOff* SVGZoomEvent::newTranslate() const -{ - SVGPointTearOff* pointTearOff = SVGPointTearOff::create(SVGPoint::create(m_newTranslate), 0, PropertyIsNotAnimVal); - pointTearOff->setIsReadOnlyProperty(); - return pointTearOff; -} - -const AtomicString& SVGZoomEvent::interfaceName() const -{ - return EventNames::SVGZoomEvent; -} - -DEFINE_TRACE(SVGZoomEvent) -{ - UIEvent::trace(visitor); -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/core/svg/SVGZoomEvent.h b/third_party/WebKit/Source/core/svg/SVGZoomEvent.h deleted file mode 100644 index 0cbdc12..0000000 --- a/third_party/WebKit/Source/core/svg/SVGZoomEvent.h +++ /dev/null
@@ -1,67 +0,0 @@ -/* - * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org> - * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> - * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef SVGZoomEvent_h -#define SVGZoomEvent_h - -#include "core/events/UIEvent.h" -#include "core/svg/SVGPoint.h" -#include "core/svg/SVGRect.h" -#include "platform/heap/Handle.h" - -namespace blink { - -class SVGZoomEvent final : public UIEvent { - DEFINE_WRAPPERTYPEINFO(); -public: - static SVGZoomEvent* create() - { - return new SVGZoomEvent; - } - - // 'SVGZoomEvent' functions - SVGRectTearOff* zoomRectScreen() const; - - float previousScale() const; - - SVGPointTearOff* previousTranslate() const; - - float newScale() const; - - SVGPointTearOff* newTranslate() const; - - const AtomicString& interfaceName() const override; - - DECLARE_VIRTUAL_TRACE(); - -private: - SVGZoomEvent(); - - float m_newScale; - float m_previousScale; - - FloatPoint m_newTranslate; - FloatPoint m_previousTranslate; -}; - -} // namespace blink - -#endif // SVGZoomEvent_h
diff --git a/third_party/WebKit/Source/core/svg/SVGZoomEvent.idl b/third_party/WebKit/Source/core/svg/SVGZoomEvent.idl deleted file mode 100644 index 85fa751e..0000000 --- a/third_party/WebKit/Source/core/svg/SVGZoomEvent.idl +++ /dev/null
@@ -1,37 +0,0 @@ -/* - * Copyright (C) 2006 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// http://www.w3.org/TR/SVG2/script.html#InterfaceSVGZoomEvent - -[ - DependentLifetime, -] interface SVGZoomEvent : UIEvent { - // TODO(foolip): SVGRect/SVGPoint should be DOMRectReadOnly/DOMPointReadOnly. - readonly attribute SVGRect zoomRectScreen; - readonly attribute float previousScale; - readonly attribute SVGPoint previousTranslate; - readonly attribute float newScale; - readonly attribute SVGPoint newTranslate; -};
diff --git a/third_party/WebKit/Source/core/testing/DictionaryTest.cpp b/third_party/WebKit/Source/core/testing/DictionaryTest.cpp index e862f1f..4d99353 100644 --- a/third_party/WebKit/Source/core/testing/DictionaryTest.cpp +++ b/third_party/WebKit/Source/core/testing/DictionaryTest.cpp
@@ -163,7 +163,7 @@ if (firstLoop) firstLoop = false; else - result.append(","); + result.append(','); v8::Local<v8::Value> value; if (v8Call(iterator.value(), value))
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp index 33b5df0..b8d2e2d 100644 --- a/third_party/WebKit/Source/core/testing/Internals.cpp +++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -1557,6 +1557,11 @@ contextDocument()->frame()->spellChecker().toggleContinuousSpellChecking(); } +bool Internals::canHyphenate(const AtomicString& locale) +{ + return Hyphenation::get(locale); +} + void Internals::setMockHyphenation(const AtomicString& locale) { Hyphenation::setForTesting(locale, adoptRef(new MockHyphenation));
diff --git a/third_party/WebKit/Source/core/testing/Internals.h b/third_party/WebKit/Source/core/testing/Internals.h index 6f0d1d8..f7777ba2 100644 --- a/third_party/WebKit/Source/core/testing/Internals.h +++ b/third_party/WebKit/Source/core/testing/Internals.h
@@ -212,6 +212,7 @@ bool hasGrammarMarker(Document*, int from, int length); void setContinuousSpellCheckingEnabled(bool); + bool canHyphenate(const AtomicString& locale); void setMockHyphenation(const AtomicString& locale); bool isOverwriteModeEnabled(Document*);
diff --git a/third_party/WebKit/Source/core/testing/Internals.idl b/third_party/WebKit/Source/core/testing/Internals.idl index 9a594be3..b0108d6 100644 --- a/third_party/WebKit/Source/core/testing/Internals.idl +++ b/third_party/WebKit/Source/core/testing/Internals.idl
@@ -163,6 +163,7 @@ boolean hasGrammarMarker(Document document, long from, long length); void setContinuousSpellCheckingEnabled(boolean enabled); + bool canHyphenate(DOMString locale); void setMockHyphenation(DOMString locale); boolean isOverwriteModeEnabled(Document document);
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.cpp b/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.cpp index 1b1074d..3b191957 100644 --- a/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.cpp +++ b/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.cpp
@@ -268,13 +268,6 @@ m_workerInspectorProxy->dispatchMessageFromWorker(message); } -void InProcessWorkerMessagingProxy::postWorkerConsoleAgentEnabled() -{ - DCHECK(isParentContextThread()); - if (m_workerInspectorProxy) - m_workerInspectorProxy->workerConsoleAgentEnabled(); -} - void InProcessWorkerMessagingProxy::confirmMessageFromWorkerObject(bool hasPendingActivity) { DCHECK(isParentContextThread());
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.h b/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.h index 27722da..42c1eeb 100644 --- a/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.h +++ b/third_party/WebKit/Source/core/workers/InProcessWorkerMessagingProxy.h
@@ -70,7 +70,6 @@ void reportException(const String& errorMessage, std::unique_ptr<SourceLocation>); void reportConsoleMessage(MessageSource, MessageLevel, const String& message, std::unique_ptr<SourceLocation>); void postMessageToPageInspector(const String&); - void postWorkerConsoleAgentEnabled(); void confirmMessageFromWorkerObject(bool hasPendingActivity); void reportPendingActivity(bool hasPendingActivity); void workerThreadTerminated();
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.cpp b/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.cpp index b68dc72..402ca48 100644 --- a/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.cpp +++ b/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.cpp
@@ -85,13 +85,6 @@ toDocument(context)->postInspectorTask(BLINK_FROM_HERE, createCrossThreadTask(&InProcessWorkerMessagingProxy::postMessageToPageInspector, crossThreadUnretained(m_messagingProxy), message)); } -void InProcessWorkerObjectProxy::postWorkerConsoleAgentEnabled() -{ - ExecutionContext* context = getExecutionContext(); - if (context->isDocument()) - toDocument(context)->postInspectorTask(BLINK_FROM_HERE, createCrossThreadTask(&InProcessWorkerMessagingProxy::postWorkerConsoleAgentEnabled, crossThreadUnretained(m_messagingProxy))); -} - void InProcessWorkerObjectProxy::workerGlobalScopeClosed() { getExecutionContext()->postTask(BLINK_FROM_HERE, createCrossThreadTask(&InProcessWorkerMessagingProxy::terminateWorkerGlobalScope, crossThreadUnretained(m_messagingProxy)));
diff --git a/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.h b/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.h index 1bfe52a..ed8386c 100644 --- a/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.h +++ b/third_party/WebKit/Source/core/workers/InProcessWorkerObjectProxy.h
@@ -67,7 +67,6 @@ void reportException(const String& errorMessage, std::unique_ptr<SourceLocation>) override; void reportConsoleMessage(ConsoleMessage*) override; void postMessageToPageInspector(const String&) override; - void postWorkerConsoleAgentEnabled() override; void didEvaluateWorkerScript(bool success) override { } void workerGlobalScopeStarted(WorkerGlobalScope*) override { } void workerGlobalScopeClosed() override;
diff --git a/third_party/WebKit/Source/core/workers/WorkerClients.cpp b/third_party/WebKit/Source/core/workers/WorkerClients.cpp new file mode 100644 index 0000000..d3dc043 --- /dev/null +++ b/third_party/WebKit/Source/core/workers/WorkerClients.cpp
@@ -0,0 +1,11 @@ +// 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 "core/workers/WorkerClients.h" + +namespace blink { + +template class CORE_TEMPLATE_EXPORT Supplement<WorkerClients>; + +} // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/WorkerClients.h b/third_party/WebKit/Source/core/workers/WorkerClients.h index 70d5661e..f46c455 100644 --- a/third_party/WebKit/Source/core/workers/WorkerClients.h +++ b/third_party/WebKit/Source/core/workers/WorkerClients.h
@@ -31,11 +31,14 @@ #ifndef WorkerClients_h #define WorkerClients_h +#include "core/CoreExport.h" #include "platform/Supplementable.h" #include "wtf/Forward.h" namespace blink { +class WorkerClients; + // This is created on the main thread, passed to the worker thread and // attached to WorkerGlobalScope when it is created. // This class can be used to provide "client" implementations to Workers. @@ -57,6 +60,8 @@ WorkerClients() { } }; +extern template class CORE_EXTERN_TEMPLATE_EXPORT Supplement<WorkerClients>; + } // namespace blink #endif // WorkerClients_h
diff --git a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp index 0770e90d..d3fb816 100644 --- a/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerGlobalScope.cpp
@@ -48,7 +48,6 @@ #include "core/frame/Deprecation.h" #include "core/frame/LocalDOMWindow.h" #include "core/inspector/ConsoleMessage.h" -#include "core/inspector/IdentifiersFactory.h" #include "core/inspector/InspectorInstrumentation.h" #include "core/inspector/WorkerInspectorController.h" #include "core/inspector/WorkerThreadDebugger.h" @@ -282,20 +281,8 @@ void WorkerGlobalScope::addMessageToWorkerConsole(ConsoleMessage* consoleMessage) { DCHECK(isContextThread()); - WorkerThreadDebugger* debugger = WorkerThreadDebugger::from(thread()->isolate()); - if (!debugger) - return; - debugger->debugger()->addConsoleMessage( - debugger->contextGroupId(), - consoleMessage->source(), - consoleMessage->level(), - consoleMessage->message(), - consoleMessage->location()->url(), - consoleMessage->location()->lineNumber(), - consoleMessage->location()->columnNumber(), - consoleMessage->location()->cloneStackTrace(), - consoleMessage->location()->scriptId(), - IdentifiersFactory::requestId(consoleMessage->requestIdentifier())); + if (WorkerThreadDebugger* debugger = WorkerThreadDebugger::from(thread()->isolate())) + debugger->addConsoleMessage(consoleMessage); } bool WorkerGlobalScope::isContextThread() const
diff --git a/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.cpp b/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.cpp index d21c83a..2cc2908 100644 --- a/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.cpp
@@ -20,8 +20,6 @@ namespace { -static const unsigned maxConsoleMessageCount = 1000; - static WorkerInspectorProxy::WorkerInspectorProxySet& inspectorProxies() { DEFINE_STATIC_LOCAL(WorkerInspectorProxy::WorkerInspectorProxySet, proxies, ()); @@ -39,7 +37,6 @@ : m_workerThread(nullptr) , m_document(nullptr) , m_pageInspector(nullptr) - , m_ignoreConsoleMessages(false) { } @@ -85,13 +82,6 @@ InspectorInstrumentation::workerTerminated(m_document, this); } - LocalFrame* frame = m_document ? m_document->frame() : nullptr; - if (frame) { - for (ConsoleMessage* message : m_consoleMessages) - frame->console().adoptWorkerMessage(message); - m_consoleMessages.clear(); - } - m_workerThread = nullptr; m_pageInspector = nullptr; m_document = nullptr; @@ -103,22 +93,10 @@ m_pageInspector->dispatchMessageFromWorker(this, message); } -void WorkerInspectorProxy::workerConsoleAgentEnabled() -{ - m_ignoreConsoleMessages = true; - m_consoleMessages.clear(); -} - void WorkerInspectorProxy::addConsoleMessageFromWorker(ConsoleMessage* consoleMessage) { - if (!m_ignoreConsoleMessages) { - DCHECK(m_consoleMessages.size() <= maxConsoleMessageCount); - if (m_consoleMessages.size() == maxConsoleMessageCount) - m_consoleMessages.removeFirst(); - m_consoleMessages.append(consoleMessage); - } if (LocalFrame* frame = m_document->frame()) - frame->console().reportWorkerMessage(consoleMessage); + frame->console().addMessageFromWorker(consoleMessage, m_inspectorId); } static void connectToWorkerGlobalScopeInspectorTask(WorkerThread* workerThread) @@ -172,7 +150,6 @@ DEFINE_TRACE(WorkerInspectorProxy) { visitor->trace(m_document); - visitor->trace(m_consoleMessages); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.h b/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.h index 7ce7e37..af5e7a44 100644 --- a/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.h +++ b/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.h
@@ -37,7 +37,6 @@ void workerThreadCreated(Document*, WorkerThread*, const KURL&); void workerThreadTerminated(); void dispatchMessageFromWorker(const String&); - void workerConsoleAgentEnabled(); void addConsoleMessageFromWorker(ConsoleMessage*); void connectToInspector(PageInspector*); @@ -60,8 +59,6 @@ PageInspector* m_pageInspector; String m_url; String m_inspectorId; - HeapDeque<Member<ConsoleMessage>> m_consoleMessages; - bool m_ignoreConsoleMessages; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/WorkerReportingProxy.h b/third_party/WebKit/Source/core/workers/WorkerReportingProxy.h index 7e9d343..5d1f77a 100644 --- a/third_party/WebKit/Source/core/workers/WorkerReportingProxy.h +++ b/third_party/WebKit/Source/core/workers/WorkerReportingProxy.h
@@ -50,7 +50,6 @@ virtual void reportException(const String& errorMessage, std::unique_ptr<SourceLocation>) = 0; virtual void reportConsoleMessage(ConsoleMessage*) = 0; virtual void postMessageToPageInspector(const String&) = 0; - virtual void postWorkerConsoleAgentEnabled() = 0; // Invoked when the worker script is evaluated. |success| is true if the // evaluation completed with no uncaught exception.
diff --git a/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h b/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h index 5ceb933..3b48da6 100644 --- a/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h +++ b/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h
@@ -61,7 +61,6 @@ } MOCK_METHOD1(reportConsoleMessage, void(ConsoleMessage*)); MOCK_METHOD1(postMessageToPageInspector, void(const String&)); - MOCK_METHOD0(postWorkerConsoleAgentEnabled, void()); MOCK_METHOD1(didEvaluateWorkerScript, void(bool success)); MOCK_METHOD1(workerGlobalScopeStarted, void(WorkerGlobalScope*)); MOCK_METHOD0(workerGlobalScopeClosed, void());
diff --git a/third_party/WebKit/Source/core/xml/XPathParser.cpp b/third_party/WebKit/Source/core/xml/XPathParser.cpp index 3d2a055c..c44cbba1 100644 --- a/third_party/WebKit/Source/core/xml/XPathParser.cpp +++ b/third_party/WebKit/Source/core/xml/XPathParser.cpp
@@ -106,13 +106,12 @@ static bool isNodeTypeName(const String& name) { - DEFINE_STATIC_LOCAL(HashSet<String>, nodeTypeNames, ()); - if (nodeTypeNames.isEmpty()) { - nodeTypeNames.add("comment"); - nodeTypeNames.add("text"); - nodeTypeNames.add("processing-instruction"); - nodeTypeNames.add("node"); - } + DEFINE_STATIC_LOCAL(HashSet<String>, nodeTypeNames, ({ + "comment", + "text", + "processing-instruction", + "node", + })); return nodeTypeNames.contains(name); }
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp index 941a9f3..5868ce54 100644 --- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp +++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.cpp
@@ -837,7 +837,7 @@ String message = "Failed to load '" + m_url.elidedString() + "'"; if (reason.isNull()) { - message.append("."); + message.append('.'); } else { message.append(": "); message.append(reason); @@ -1716,4 +1716,12 @@ ActiveDOMObject::trace(visitor); } +DEFINE_TRACE_WRAPPERS(XMLHttpRequest) +{ + visitor->traceWrappers(m_responseBlob); + visitor->traceWrappers(m_responseLegacyStream); + visitor->traceWrappers(m_responseDocument); + visitor->traceWrappers(m_responseArrayBuffer); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h index 453404e..ea79344 100644 --- a/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h +++ b/third_party/WebKit/Source/core/xmlhttprequest/XMLHttpRequest.h
@@ -147,6 +147,7 @@ // progress event throttle. EAGERLY_FINALIZE(); DECLARE_VIRTUAL_TRACE(); + DECLARE_TRACE_WRAPPERS(); private: class BlobLoader;
diff --git a/third_party/WebKit/Source/devtools/devtools.gypi b/third_party/WebKit/Source/devtools/devtools.gypi index f4a0c08..9a2b2e9 100644 --- a/third_party/WebKit/Source/devtools/devtools.gypi +++ b/third_party/WebKit/Source/devtools/devtools.gypi
@@ -98,6 +98,7 @@ 'front_end/components/networkConditionsSettingsTab.css', 'front_end/components/objectPropertiesSection.css', 'front_end/components/objectValue.css', + 'front_end/components/spectrum.css', 'front_end/components/CustomPreviewSection.js', 'front_end/components/DataSaverInfobar.js', 'front_end/components/DockController.js', @@ -113,6 +114,7 @@ 'front_end/components/RemoteObjectPreviewFormatter.js', 'front_end/components/RequestAppBannerActionDelegate.js', 'front_end/components/ShortcutsScreen.js', + 'front_end/components/Spectrum.js', 'front_end/components/EventListenersUtils.js', 'front_end/components/EventListenersView.js', 'front_end/components/Reload.js', @@ -445,10 +447,10 @@ 'front_end/elements/elementsPanel.css', 'front_end/elements/elementsTreeOutline.css', 'front_end/elements/platformFontsWidget.css', - 'front_end/elements/spectrum.css', 'front_end/elements/BezierEditor.js', 'front_end/elements/BezierUI.js', 'front_end/elements/ClassesPaneWidget.js', + 'front_end/elements/ComputedStyleModel.js', 'front_end/elements/ElementsBreadcrumbs.js', 'front_end/elements/ElementsPanel.js', 'front_end/elements/ElementsSidebarPane.js', @@ -457,14 +459,12 @@ 'front_end/elements/ElementsTreeElementHighlighter.js', 'front_end/elements/ElementsTreeOutline.js', 'front_end/elements/ElementStatePaneWidget.js', - 'front_end/elements/SharedSidebarModel.js', 'front_end/elements/EventListenersWidget.js', 'front_end/elements/InspectElementModeController.js', 'front_end/elements/MetricsSidebarPane.js', 'front_end/elements/PlatformFontsWidget.js', 'front_end/elements/PropertiesWidget.js', 'front_end/elements/PropertyChangeHighlighter.js', - 'front_end/elements/Spectrum.js', 'front_end/elements/StylesPopoverHelper.js', 'front_end/elements/StylesSidebarPane.js', 'front_end/elements/ComputedStyleWidget.js',
diff --git a/third_party/WebKit/Source/devtools/front_end/Tests.js b/third_party/WebKit/Source/devtools/front_end/Tests.js index 268f62c..d78c776e 100644 --- a/third_party/WebKit/Source/devtools/front_end/Tests.js +++ b/third_party/WebKit/Source/devtools/front_end/Tests.js
@@ -608,7 +608,7 @@ function callback() { - var target = WebInspector.targetManager.targetsWithJSContext()[0]; + var target = WebInspector.targetManager.targets(WebInspector.Target.Capability.JS)[0]; target._connection.deprecatedRunAfterPendingDispatches(this.releaseControl.bind(this)); } }; @@ -620,7 +620,7 @@ function callback() { - var target = WebInspector.targetManager.targetsWithJSContext()[0]; + var target = WebInspector.targetManager.targets(WebInspector.Target.Capability.JS)[0]; var debuggerModel = WebInspector.DebuggerModel.fromTarget(target); if (debuggerModel.isPaused()) { this.releaseControl(); @@ -717,6 +717,20 @@ step1(); }; +TestSuite.prototype.testDispatchKeyEventDoesNotCrash = function() +{ + WebInspector.targetManager.mainTarget().inputAgent().invoke_dispatchKeyEvent({ + type: "rawKeyDown", + windowsVirtualKeyCode: 0x23, + key: "End" + }); + WebInspector.targetManager.mainTarget().inputAgent().invoke_dispatchKeyEvent({ + type: "keyUp", + windowsVirtualKeyCode: 0x23, + key: "End" + }); +}; + TestSuite.prototype.testEmulateNetworkConditions = function() { var test = this; @@ -899,6 +913,15 @@ } } +TestSuite.prototype.testWindowInitializedOnNavigateBack = function() +{ + var messages = WebInspector.multitargetConsoleModel.messages(); + this.assertEquals(1, messages.length); + var text = messages[0].messageText; + if (text.indexOf("Uncaught") !== -1) + this.fail(text); +}; + TestSuite.prototype.waitForTestResultsInConsole = function() { var messages = WebInspector.multitargetConsoleModel.messages();
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js b/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js index 4d4dcca0..33b75da78 100644 --- a/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js +++ b/third_party/WebKit/Source/devtools/front_end/animation/AnimationModel.js
@@ -202,10 +202,12 @@ /** * @param {!WebInspector.Target} target - * @return {!WebInspector.AnimationModel} + * @return {?WebInspector.AnimationModel} */ WebInspector.AnimationModel.fromTarget = function(target) { + if (!target.hasBrowserCapability()) + return null; if (!target[WebInspector.AnimationModel._symbol]) target[WebInspector.AnimationModel._symbol] = new WebInspector.AnimationModel(target);
diff --git a/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js b/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js index 6db738a..507c470 100644 --- a/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js +++ b/third_party/WebKit/Source/devtools/front_end/animation/AnimationTimeline.js
@@ -35,7 +35,7 @@ /** @type {!Map.<string, !WebInspector.AnimationModel.Animation>} */ this._animationsMap = new Map(); WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspector.DOMModel.Events.NodeRemoved, this._nodeRemoved, this); - WebInspector.targetManager.observeTargets(this, WebInspector.Target.Type.Page); + WebInspector.targetManager.observeTargets(this, WebInspector.Target.Capability.Browser); WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._nodeChanged, this); } @@ -51,13 +51,13 @@ WebInspector.AnimationTimeline.prototype = { wasShown: function() { - for (var target of WebInspector.targetManager.targets(WebInspector.Target.Type.Page)) + for (var target of WebInspector.targetManager.targets(WebInspector.Target.Capability.Browser)) this._addEventListeners(target); }, willHide: function() { - for (var target of WebInspector.targetManager.targets(WebInspector.Target.Type.Page)) + for (var target of WebInspector.targetManager.targets(WebInspector.Target.Capability.Browser)) this._removeEventListeners(target); this._popoverHelper.hidePopover(); },
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/PresentationConsoleMessageHelper.js b/third_party/WebKit/Source/devtools/front_end/bindings/PresentationConsoleMessageHelper.js index 77f57d9..4be67638 100644 --- a/third_party/WebKit/Source/devtools/front_end/bindings/PresentationConsoleMessageHelper.js +++ b/third_party/WebKit/Source/devtools/front_end/bindings/PresentationConsoleMessageHelper.js
@@ -88,10 +88,10 @@ return null; var callFrame = message.stackTrace && message.stackTrace.callFrames ? message.stackTrace.callFrames[0] : null; // FIXME(62725): stack trace line/column numbers are one-based. - var lineNumber = callFrame ? callFrame.lineNumber - 1 : message.line - 1; + var lineNumber = callFrame ? callFrame.lineNumber : message.line - 1; var columnNumber = message.column ? message.column - 1 : 0; - if (callFrame && callFrame.columnNumber) - columnNumber = callFrame.columnNumber - 1; + if (callFrame) + columnNumber = callFrame.columnNumber; if (message.scriptId) return debuggerModel.createRawLocationByScriptId(message.scriptId, lineNumber, columnNumber); return debuggerModel.createRawLocationByURL(message.url || "", lineNumber, columnNumber);
diff --git a/third_party/WebKit/Source/devtools/front_end/components/EventListenersUtils.js b/third_party/WebKit/Source/devtools/front_end/components/EventListenersUtils.js index 8942f42..b2b0389 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/EventListenersUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/components/EventListenersUtils.js
@@ -14,7 +14,7 @@ */ WebInspector.EventListener.frameworkEventListeners = function(object) { - if (!object.target().isPage()) { + if (!object.target().hasBrowserCapability()) { // TODO(kozyatinskiy): figure out how this should work for |window|. return Promise.resolve(/** @type {!WebInspector.FrameworkEventListenersObject} */ ({eventListeners: [], internalHandlers: null})); } @@ -137,7 +137,7 @@ function storeFunctionWithDetails(functionObject) { handler = functionObject; - return /** @type {!Promise<undefined>} */(functionObject.functionDetailsPromise().then(storeFunctionDetails)); + return /** @type {!Promise<undefined>} */(functionObject.debuggerModel().functionDetailsPromise(functionObject).then(storeFunctionDetails)); } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/components/ExecutionContextSelector.js b/third_party/WebKit/Source/devtools/front_end/components/ExecutionContextSelector.js index 4423213..0573f25 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/ExecutionContextSelector.js +++ b/third_party/WebKit/Source/devtools/front_end/components/ExecutionContextSelector.js
@@ -10,7 +10,7 @@ */ WebInspector.ExecutionContextSelector = function(targetManager, context) { - targetManager.observeTargets(this); + targetManager.observeTargets(this, WebInspector.Target.Capability.JS); context.addFlavorChangeListener(WebInspector.ExecutionContext, this._executionContextChanged, this); context.addFlavorChangeListener(WebInspector.Target, this._targetChanged, this); @@ -28,8 +28,6 @@ */ targetAdded: function(target) { - if (!target.hasJSContext()) - return; // Defer selecting default target since we need all clients to get their // targetAdded notifications first. setImmediate(deferred.bind(this)); @@ -51,13 +49,11 @@ */ targetRemoved: function(target) { - if (!target.hasJSContext()) - return; var currentExecutionContext = this._context.flavor(WebInspector.ExecutionContext); if (currentExecutionContext && currentExecutionContext.target() === target) this._currentExecutionContextGone(); - var targets = this._targetManager.targetsWithJSContext(); + var targets = this._targetManager.targets(WebInspector.Target.Capability.JS); if (this._context.flavor(WebInspector.Target) === target && targets.length) this._context.setFlavor(WebInspector.Target, targets[0]); }, @@ -165,11 +161,9 @@ _currentExecutionContextGone: function() { - var targets = this._targetManager.targetsWithJSContext(); + var targets = this._targetManager.targets(WebInspector.Target.Capability.JS); var newContext = null; for (var i = 0; i < targets.length && !newContext; ++i) { - if (targets[i].isServiceWorker()) - continue; var executionContexts = targets[i].runtimeModel.executionContexts(); for (var executionContext of executionContexts) { if (this._isMainFrameContext(executionContext)) {
diff --git a/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js b/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js index fc3b6b1c..07b04cf3 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js +++ b/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js
@@ -204,7 +204,19 @@ */ linkifyConsoleCallFrame: function(target, callFrame, classes) { - return this.linkifyScriptLocation(target, callFrame.scriptId, callFrame.url, WebInspector.DebuggerModel.fromOneBased(callFrame.lineNumber), WebInspector.DebuggerModel.fromOneBased(callFrame.columnNumber), classes); + return this.linkifyScriptLocation(target, callFrame.scriptId, callFrame.url, callFrame.lineNumber, callFrame.columnNumber, classes); + }, + + /** + * @param {?WebInspector.Target} target + * @param {!RuntimeAgent.CallFrame} callFrame + * @param {string=} classes + * @return {!Element} + */ + linkifyConsoleCallFrameForTimeline: function(target, callFrame, classes) + { + // TODO(kozyatinskiy): remove this when Profilers will migrate to 0-based lineNumber and columnNumber. + return this.linkifyScriptLocation(target, callFrame.scriptId, callFrame.url, callFrame.lineNumber - 1, callFrame.columnNumber - 1, classes); }, /** @@ -218,7 +230,7 @@ console.assert(stackTrace.callFrames && stackTrace.callFrames.length); var topFrame = stackTrace.callFrames[0]; - var fallbackAnchor = WebInspector.linkifyResourceAsNode(topFrame.url, WebInspector.DebuggerModel.fromOneBased(topFrame.lineNumber), WebInspector.DebuggerModel.fromOneBased(topFrame.columnNumber), classes); + var fallbackAnchor = WebInspector.linkifyResourceAsNode(topFrame.url, topFrame.lineNumber, topFrame.columnNumber, classes); if (target.isDetached()) return fallbackAnchor;
diff --git a/third_party/WebKit/Source/devtools/front_end/components/ObjectPopoverHelper.js b/third_party/WebKit/Source/devtools/front_end/components/ObjectPopoverHelper.js index 4b9b2fe..5d8ee50 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/ObjectPopoverHelper.js +++ b/third_party/WebKit/Source/devtools/front_end/components/ObjectPopoverHelper.js
@@ -75,7 +75,7 @@ } } WebInspector.ObjectPropertiesSection.formatObjectAsFunction(funcObject, popoverValueElement, true); - funcObject.functionDetails(didGetFunctionDetails.bind(this, popoverContentElement, anchorElement)); + funcObject.debuggerModel().functionDetailsPromise(funcObject).then(didGetFunctionDetails.bind(this, popoverContentElement, anchorElement)); } /** @@ -95,7 +95,6 @@ functionName.textContent = WebInspector.beautifyFunctionName(response.functionName); var rawLocation = response.location; - var sourceURL = response.sourceURL; var linkContainer = title.createChild("div", "function-title-link-container"); if (rawLocation && Runtime.experiments.isEnabled("continueToFirstInvocation")) { var sectionToolbar = new WebInspector.Toolbar("function-location-step-into", linkContainer); @@ -103,6 +102,7 @@ stepInto.addEventListener("click", () => rawLocation.continueToLocation()); sectionToolbar.appendToolbarItem(stepInto); } + var sourceURL = rawLocation && rawLocation.script() ? rawLocation.script().sourceURL : null; if (rawLocation && sourceURL) { var link = this._lazyLinkifier().linkifyRawLocation(rawLocation, sourceURL); linkContainer.appendChild(link);
diff --git a/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js b/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js index 8a90167..6a5813db 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js +++ b/third_party/WebKit/Source/devtools/front_end/components/ObjectPropertiesSection.js
@@ -591,23 +591,6 @@ treeNode.appendChild(treeElement); } } - if (value && value.type === "function") { - // Whether function has TargetFunction internal property. - // This is a simple way to tell that the function is actually a bound function (we are not told). - // Bound function never has inner scope and doesn't need corresponding UI node. - var hasTargetFunction = false; - - if (internalProperties) { - for (var i = 0; i < internalProperties.length; i++) { - if (internalProperties[i].name === "[[TargetFunction]]") { - hasTargetFunction = true; - break; - } - } - } - if (!hasTargetFunction) - treeNode.appendChild(new WebInspector.FunctionScopeMainTreeElement(value, linkifier)); - } WebInspector.ObjectPropertyTreeElement._appendEmptyPlaceholderIfNeeded(treeNode, emptyPlaceholder); } @@ -654,117 +637,6 @@ /** * @constructor * @extends {TreeElement} - * @param {!WebInspector.RemoteObject} remoteObject - * @param {!WebInspector.Linkifier=} linkifier - */ -WebInspector.FunctionScopeMainTreeElement = function(remoteObject, linkifier) -{ - TreeElement.call(this, "<function scope>", true); - this.toggleOnClick = true; - this.selectable = false; - this._remoteObject = remoteObject; - this._linkifier = linkifier; -} - -WebInspector.FunctionScopeMainTreeElement.prototype = { - onpopulate: function() - { - /** - * @param {?WebInspector.DebuggerModel.FunctionDetails} response - * @this {WebInspector.FunctionScopeMainTreeElement} - */ - function didGetDetails(response) - { - if (!response) - return; - this.removeChildren(); - - var scopeChain = response.scopeChain || []; - for (var i = 0; i < scopeChain.length; ++i) { - var scope = scopeChain[i]; - var title = null; - var isTrueObject = false; - - switch (scope.type) { - case DebuggerAgent.ScopeType.Local: - // Not really expecting this scope type here. - title = WebInspector.UIString("Local"); - break; - case DebuggerAgent.ScopeType.Closure: - title = WebInspector.UIString("Closure"); - break; - case DebuggerAgent.ScopeType.Catch: - title = WebInspector.UIString("Catch"); - break; - case DebuggerAgent.ScopeType.Block: - title = WebInspector.UIString("Block"); - break; - case DebuggerAgent.ScopeType.Script: - title = WebInspector.UIString("Script"); - break; - case DebuggerAgent.ScopeType.With: - title = WebInspector.UIString("With Block"); - isTrueObject = true; - break; - case DebuggerAgent.ScopeType.Global: - title = WebInspector.UIString("Global"); - isTrueObject = true; - break; - default: - console.error("Unknown scope type: " + scope.type); - continue; - } - - var runtimeModel = this._remoteObject.target().runtimeModel; - if (isTrueObject) { - var remoteObject = runtimeModel.createRemoteObject(scope.object); - var property = new WebInspector.RemoteObjectProperty(title, remoteObject); - property.writable = false; - property.parentObject = null; - this.appendChild(new WebInspector.ObjectPropertyTreeElement(property, this._linkifier)); - } else { - var scopeRef = new WebInspector.ScopeRef(i, undefined); - var remoteObject = runtimeModel.createScopeRemoteObject(scope.object, scopeRef); - var scopeTreeElement = new WebInspector.ScopeTreeElement(title, remoteObject); - this.appendChild(scopeTreeElement); - } - } - - WebInspector.ObjectPropertyTreeElement._appendEmptyPlaceholderIfNeeded(this, WebInspector.UIString("No Scopes")); - } - - this._remoteObject.functionDetails(didGetDetails.bind(this)); - }, - - __proto__: TreeElement.prototype -} - -/** - * @constructor - * @extends {TreeElement} - * @param {string} title - * @param {!WebInspector.RemoteObject} remoteObject - */ -WebInspector.ScopeTreeElement = function(title, remoteObject) -{ - TreeElement.call(this, title, true); - this.toggleOnClick = true; - this.selectable = false; - this._remoteObject = remoteObject; -} - -WebInspector.ScopeTreeElement.prototype = { - onpopulate: function() - { - WebInspector.ObjectPropertyTreeElement._populate(this, this._remoteObject, false); - }, - - __proto__: TreeElement.prototype -} - -/** - * @constructor - * @extends {TreeElement} * @param {!WebInspector.RemoteObject} object * @param {number} fromIndex * @param {number} toIndex @@ -1192,8 +1064,13 @@ valueElement.title = description || ""; } - if (type === "object" && subtype === "internal#location" && linkifier) - return linkifier.linkifyScriptLocation(value.target(), value.value.scriptId, "", value.value.lineNumber, value.value.columnNumber); + if (type === "object" && subtype === "internal#location") { + var rawLocation = value.debuggerModel().createRawLocationByScriptId(value.value.scriptId, value.value.lineNumber, value.value.columnNumber); + if (rawLocation && linkifier) + return linkifier.linkifyRawLocation(rawLocation, ""); + else + valueElement.textContent = "<unknown>"; + } function mouseMove() { @@ -1225,7 +1102,7 @@ */ WebInspector.ObjectPropertiesSection.formatObjectAsFunction = function(func, element, linkify, includePreview) { - func.functionDetails(didGetDetails); + func.debuggerModel().functionDetailsPromise(func).then(didGetDetails); /** * @param {?WebInspector.DebuggerModel.FunctionDetails} response
diff --git a/third_party/WebKit/Source/devtools/front_end/components/RequestAppBannerActionDelegate.js b/third_party/WebKit/Source/devtools/front_end/components/RequestAppBannerActionDelegate.js index 21f09f6e..a128fe8 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/RequestAppBannerActionDelegate.js +++ b/third_party/WebKit/Source/devtools/front_end/components/RequestAppBannerActionDelegate.js
@@ -20,7 +20,7 @@ handleAction: function(context, actionId) { var target = WebInspector.targetManager.mainTarget(); - if (target && target.isPage()) { + if (target && target.hasBrowserCapability()) { target.pageAgent().requestAppBanner(); WebInspector.console.show(); }
diff --git a/third_party/WebKit/Source/devtools/front_end/components/Spectrum.js b/third_party/WebKit/Source/devtools/front_end/components/Spectrum.js new file mode 100644 index 0000000..16d1f6f2 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/components/Spectrum.js
@@ -0,0 +1,1044 @@ +/* + * Copyright (C) 2011 Brian Grinstead All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @constructor + * @extends {WebInspector.VBox} + */ +WebInspector.Spectrum = function() +{ + /** + * @param {!Element} parentElement + */ + function appendSwitcherIcon(parentElement) + { + var icon = parentElement.createSVGChild("svg"); + icon.setAttribute("height", 16); + icon.setAttribute("width", 16); + var path = icon.createSVGChild("path"); + path.setAttribute("d", "M5,6 L11,6 L8,2 Z M5,10 L11,10 L8,14 Z"); + return icon; + } + + WebInspector.VBox.call(this, true); + this.registerRequiredCSS("components/spectrum.css"); + this.contentElement.tabIndex = 0; + + this._colorElement = this.contentElement.createChild("div", "spectrum-color"); + this._colorDragElement = this._colorElement.createChild("div", "spectrum-sat fill").createChild("div", "spectrum-val fill").createChild("div", "spectrum-dragger"); + var contrastRatioSVG = this._colorElement.createSVGChild("svg", "spectrum-contrast-container fill"); + this._contrastRatioLine = contrastRatioSVG.createSVGChild("path", "spectrum-contrast-line"); + + var toolbar = new WebInspector.Toolbar("spectrum-eye-dropper", this.contentElement); + this._colorPickerButton = new WebInspector.ToolbarToggle(WebInspector.UIString("Toggle color picker"), "eyedropper-toolbar-item"); + this._colorPickerButton.setToggled(true); + this._colorPickerButton.addEventListener("click", this._toggleColorPicker.bind(this, undefined)); + toolbar.appendToolbarItem(this._colorPickerButton); + + var swatchElement = this.contentElement.createChild("span", "swatch"); + this._swatchInnerElement = swatchElement.createChild("span", "swatch-inner"); + + this._hueElement = this.contentElement.createChild("div", "spectrum-hue"); + this._hueSlider = this._hueElement.createChild("div", "spectrum-slider"); + this._alphaElement = this.contentElement.createChild("div", "spectrum-alpha"); + this._alphaElementBackground = this._alphaElement.createChild("div", "spectrum-alpha-background"); + this._alphaSlider = this._alphaElement.createChild("div", "spectrum-slider"); + + var displaySwitcher = this.contentElement.createChild("div", "spectrum-display-switcher spectrum-switcher"); + appendSwitcherIcon(displaySwitcher); + displaySwitcher.addEventListener("click", this._formatViewSwitch.bind(this)); + + // RGBA/HSLA display. + this._displayContainer = this.contentElement.createChild("div", "spectrum-text source-code"); + this._textValues = []; + for (var i = 0; i < 4; ++i) { + var inputValue = this._displayContainer.createChild("input", "spectrum-text-value"); + inputValue.maxLength = 4; + this._textValues.push(inputValue); + inputValue.addEventListener("keydown", this._inputChanged.bind(this), false); + inputValue.addEventListener("input", this._inputChanged.bind(this), false); + inputValue.addEventListener("mousewheel", this._inputChanged.bind(this), false); + } + + this._textLabels = this._displayContainer.createChild("div", "spectrum-text-label"); + + // HEX display. + this._hexContainer = this.contentElement.createChild("div", "spectrum-text spectrum-text-hex source-code"); + this._hexValue = this._hexContainer.createChild("input", "spectrum-text-value"); + this._hexValue.maxLength = 9; + this._hexValue.addEventListener("keydown", this._inputChanged.bind(this), false); + this._hexValue.addEventListener("input", this._inputChanged.bind(this), false); + this._hexValue.addEventListener("mousewheel", this._inputChanged.bind(this), false); + + var label = this._hexContainer.createChild("div", "spectrum-text-label"); + label.textContent = "HEX"; + + WebInspector.installDragHandle(this._hueElement, dragStart.bind(this, positionHue.bind(this)), positionHue.bind(this), null, "default"); + WebInspector.installDragHandle(this._alphaElement, dragStart.bind(this, positionAlpha.bind(this)), positionAlpha.bind(this), null, "default"); + WebInspector.installDragHandle(this._colorElement, dragStart.bind(this, positionColor.bind(this)), positionColor.bind(this), null, "default"); + + this.element.classList.add("palettes-enabled"); + /** @type {!Map.<string, !WebInspector.Spectrum.Palette>} */ + this._palettes = new Map(); + this._palettePanel = this.contentElement.createChild("div", "palette-panel"); + this._palettePanelShowing = false; + this._paletteContainer = this.contentElement.createChild("div", "spectrum-palette"); + this._paletteContainer.addEventListener("contextmenu", this._showPaletteColorContextMenu.bind(this, -1)); + this._shadesContainer = this.contentElement.createChild("div", "palette-color-shades hidden"); + WebInspector.installDragHandle(this._paletteContainer, this._paletteDragStart.bind(this), this._paletteDrag.bind(this), this._paletteDragEnd.bind(this), "default"); + var paletteSwitcher = this.contentElement.createChild("div", "spectrum-palette-switcher spectrum-switcher"); + appendSwitcherIcon(paletteSwitcher); + paletteSwitcher.addEventListener("click", this._togglePalettePanel.bind(this, true)); + + this._deleteIconToolbar = new WebInspector.Toolbar("delete-color-toolbar"); + this._deleteButton = new WebInspector.ToolbarButton("", "garbage-collect-toolbar-item"); + this._deleteIconToolbar.appendToolbarItem(this._deleteButton); + + var overlay = this.contentElement.createChild("div", "spectrum-overlay fill"); + overlay.addEventListener("click", this._togglePalettePanel.bind(this, false)); + + this._addColorToolbar = new WebInspector.Toolbar("add-color-toolbar"); + var addColorButton = new WebInspector.ToolbarButton(WebInspector.UIString("Add to palette"), "add-toolbar-item"); + addColorButton.addEventListener("click", this._addColorToCustomPalette.bind(this)); + this._addColorToolbar.appendToolbarItem(addColorButton); + + this._loadPalettes(); + new WebInspector.Spectrum.PaletteGenerator(this._generatedPaletteLoaded.bind(this)); + + /** + * @param {function(!Event)} callback + * @param {!Event} event + * @return {boolean} + * @this {WebInspector.Spectrum} + */ + function dragStart(callback, event) + { + this._hueAlphaLeft = this._hueElement.totalOffsetLeft(); + this._colorOffset = this._colorElement.totalOffset(); + callback(event); + return true; + } + + /** + * @param {!Event} event + * @this {WebInspector.Spectrum} + */ + function positionHue(event) + { + var hsva = this._hsv.slice(); + hsva[0] = Number.constrain(1 - (event.x - this._hueAlphaLeft) / this._hueAlphaWidth, 0, 1); + this._innerSetColor(hsva, "", undefined, WebInspector.Spectrum._ChangeSource.Other); + } + + /** + * @param {!Event} event + * @this {WebInspector.Spectrum} + */ + function positionAlpha(event) + { + var newAlpha = Math.round((event.x - this._hueAlphaLeft) / this._hueAlphaWidth * 100) / 100; + var hsva = this._hsv.slice(); + hsva[3] = Number.constrain(newAlpha, 0, 1); + var colorFormat = undefined; + if (hsva[3] !== 1 && this._colorFormat === WebInspector.Color.Format.Nickname) + colorFormat = WebInspector.Color.Format.HEX; + this._innerSetColor(hsva, "", colorFormat, WebInspector.Spectrum._ChangeSource.Other); + } + + /** + * @param {!Event} event + * @this {WebInspector.Spectrum} + */ + function positionColor(event) + { + var hsva = this._hsv.slice(); + hsva[1] = Number.constrain((event.x - this._colorOffset.left) / this.dragWidth, 0, 1); + hsva[2] = Number.constrain(1 - (event.y - this._colorOffset.top) / this.dragHeight, 0, 1); + this._innerSetColor(hsva, "", undefined, WebInspector.Spectrum._ChangeSource.Other); + } +} + +WebInspector.Spectrum._ChangeSource = { + Input: "Input", + Model: "Model", + Other: "Other" +} + +WebInspector.Spectrum.Events = { + ColorChanged: "ColorChanged", + SizeChanged: "SizeChanged" +}; + +WebInspector.Spectrum._colorChipSize = 24; +WebInspector.Spectrum._itemsPerPaletteRow = 8; + +WebInspector.Spectrum.prototype = { + _updatePalettePanel: function() + { + this._palettePanel.removeChildren(); + var title = this._palettePanel.createChild("div", "palette-title"); + title.textContent = WebInspector.UIString("Color Palettes"); + var toolbar = new WebInspector.Toolbar("", this._palettePanel); + var closeButton = new WebInspector.ToolbarButton("Return to color picker", "delete-toolbar-item"); + closeButton.addEventListener("click", this._togglePalettePanel.bind(this, false)); + toolbar.appendToolbarItem(closeButton); + for (var palette of this._palettes.values()) + this._palettePanel.appendChild(this._createPreviewPaletteElement(palette)); + }, + + /** + * @param {boolean} show + */ + _togglePalettePanel: function(show) + { + if (this._palettePanelShowing === show) + return; + if (show) + this._updatePalettePanel(); + this._focus(); + this._palettePanelShowing = show; + this.contentElement.classList.toggle("palette-panel-showing", show); + }, + + _focus: function() + { + if (this.isShowing() && WebInspector.currentFocusElement() !== this.contentElement) + WebInspector.setCurrentFocusElement(this.contentElement); + }, + + /** + * @param {string} colorText + * @param {number=} animationDelay + * @return {!Element} + */ + _createPaletteColor: function(colorText, animationDelay) + { + var element = createElementWithClass("div", "spectrum-palette-color"); + element.style.background = String.sprintf("linear-gradient(%s, %s), url(Images/checker.png)", colorText, colorText); + if (animationDelay) + element.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 100, delay: animationDelay, fill: "backwards" }); + element.title = colorText; + return element; + }, + + /** + * @param {!WebInspector.Spectrum.Palette} palette + * @param {boolean} animate + * @param {!Event=} event + */ + _showPalette: function(palette, animate, event) + { + this._resizeForSelectedPalette(); + this._paletteContainer.removeChildren(); + for (var i = 0; i < palette.colors.length; i++) { + var animationDelay = animate ? i * 100 / palette.colors.length : 0; + var colorElement = this._createPaletteColor(palette.colors[i], animationDelay); + colorElement.addEventListener("mousedown", this._paletteColorSelected.bind(this, palette.colors[i], palette.matchUserFormat)); + if (palette.mutable) { + colorElement.__mutable = true; + colorElement.__color = palette.colors[i]; + colorElement.addEventListener("contextmenu", this._showPaletteColorContextMenu.bind(this, i)); + } else if (palette === WebInspector.Spectrum.MaterialPalette) { + colorElement.classList.add("has-material-shades"); + var shadow = colorElement.createChild("div", "spectrum-palette-color spectrum-palette-color-shadow"); + shadow.style.background = palette.colors[i]; + shadow = colorElement.createChild("div", "spectrum-palette-color spectrum-palette-color-shadow"); + shadow.style.background = palette.colors[i]; + colorElement.title = WebInspector.UIString(palette.colors[i] + ". Long-click to show alternate shades."); + new WebInspector.LongClickController(colorElement, this._showLightnessShades.bind(this, colorElement, palette.colors[i])); + } + this._paletteContainer.appendChild(colorElement); + } + this._paletteContainerMutable = palette.mutable; + + var numItems = palette.colors.length; + if (palette.mutable) + numItems++; + if (palette.mutable) { + this._paletteContainer.appendChild(this._addColorToolbar.element); + this._paletteContainer.appendChild(this._deleteIconToolbar.element); + } else { + this._addColorToolbar.element.remove(); + this._deleteIconToolbar.element.remove(); + } + + this._togglePalettePanel(false); + this._focus(); + }, + + /** + * @param {!Element} colorElement + * @param {string} colorText + * @param {!Event} event + */ + _showLightnessShades: function(colorElement, colorText, event) + { + /** + * @param {!Element} element + * @this {!WebInspector.Spectrum} + */ + function closeLightnessShades(element) + { + this._shadesContainer.classList.add("hidden"); + element.classList.remove("spectrum-shades-shown"); + this._shadesContainer.ownerDocument.removeEventListener("mousedown", this._shadesCloseHandler, true); + delete this._shadesCloseHandler; + } + + if (this._shadesCloseHandler) + this._shadesCloseHandler(); + + this._shadesContainer.classList.remove("hidden"); + this._shadesContainer.removeChildren(); + this._shadesContainer.animate([{ transform: "scaleY(0)", opacity: "0" }, { transform: "scaleY(1)", opacity: "1" }], { duration: 200, easing: "cubic-bezier(0.4, 0, 0.2, 1)" }); + this._shadesContainer.style.top = colorElement.offsetTop + colorElement.parentElement.offsetTop + "px"; + this._shadesContainer.style.left = colorElement.offsetLeft + "px"; + colorElement.classList.add("spectrum-shades-shown"); + + var shades = WebInspector.Spectrum.MaterialPaletteShades[colorText]; + for (var i = shades.length - 1; i >= 0; i--) { + var shadeElement = this._createPaletteColor(shades[i], i * 200 / shades.length + 100); + shadeElement.addEventListener("mousedown", this._paletteColorSelected.bind(this, shades[i], false)); + this._shadesContainer.appendChild(shadeElement); + } + + WebInspector.setCurrentFocusElement(this._shadesContainer); + this._shadesCloseHandler = closeLightnessShades.bind(this, colorElement); + this._shadesContainer.ownerDocument.addEventListener("mousedown", this._shadesCloseHandler, true); + }, + + /** + * @param {!Event} e + * @return {number} + */ + _slotIndexForEvent: function(e) + { + var localX = e.pageX - this._paletteContainer.totalOffsetLeft(); + var localY = e.pageY - this._paletteContainer.totalOffsetTop(); + var col = Math.min(localX / WebInspector.Spectrum._colorChipSize | 0, WebInspector.Spectrum._itemsPerPaletteRow - 1); + var row = (localY / WebInspector.Spectrum._colorChipSize) | 0; + return Math.min(row * WebInspector.Spectrum._itemsPerPaletteRow + col, this._customPaletteSetting.get().colors.length - 1); + }, + + /** + * @param {!Event} e + * @return {boolean} + */ + _isDraggingToBin: function(e) + { + return e.pageX > this._deleteIconToolbar.element.totalOffsetLeft(); + }, + + /** + * @param {!Event} e + * @return {boolean} + */ + _paletteDragStart: function(e) + { + var element = e.deepElementFromPoint(); + if (!element || !element.__mutable) + return false; + + var index = this._slotIndexForEvent(e); + this._dragElement = element; + this._dragHotSpotX = e.pageX - (index % WebInspector.Spectrum._itemsPerPaletteRow) * WebInspector.Spectrum._colorChipSize; + this._dragHotSpotY = e.pageY - (index / WebInspector.Spectrum._itemsPerPaletteRow | 0) * WebInspector.Spectrum._colorChipSize; + return true; + }, + + /** + * @param {!Event} e + */ + _paletteDrag: function(e) + { + if (e.pageX < this._paletteContainer.totalOffsetLeft() || e.pageY < this._paletteContainer.totalOffsetTop()) + return; + var newIndex = this._slotIndexForEvent(e); + var offsetX = e.pageX - (newIndex % WebInspector.Spectrum._itemsPerPaletteRow) * WebInspector.Spectrum._colorChipSize; + var offsetY = e.pageY - (newIndex / WebInspector.Spectrum._itemsPerPaletteRow | 0) * WebInspector.Spectrum._colorChipSize; + + var isDeleting = this._isDraggingToBin(e); + this._deleteIconToolbar.element.classList.add("dragging"); + this._deleteIconToolbar.element.classList.toggle("delete-color-toolbar-active", isDeleting); + var dragElementTransform = "translateX(" + (offsetX - this._dragHotSpotX) + "px) translateY(" + (offsetY - this._dragHotSpotY) + "px)"; + this._dragElement.style.transform = isDeleting ? dragElementTransform + " scale(0.8)" : dragElementTransform; + var children = Array.prototype.slice.call(this._paletteContainer.children); + var index = children.indexOf(this._dragElement); + /** @type {!Map.<!Element, {left: number, top: number}>} */ + var swatchOffsets = new Map(); + for (var swatch of children) + swatchOffsets.set(swatch, swatch.totalOffset()); + + if (index !== newIndex) + this._paletteContainer.insertBefore(this._dragElement, children[newIndex > index ? newIndex + 1 : newIndex]); + + for (var swatch of children) { + if (swatch === this._dragElement) + continue; + var before = swatchOffsets.get(swatch); + var after = swatch.totalOffset(); + if (before.left !== after.left || before.top !== after.top) { + swatch.animate([ + { transform: "translateX(" + (before.left - after.left) + "px) translateY(" + (before.top - after.top) + "px)" }, + { transform: "none" }], { duration: 100, easing: "cubic-bezier(0, 0, 0.2, 1)" }); + } + } + }, + + /** + * @param {!Event} e + */ + _paletteDragEnd: function(e) + { + if (this._isDraggingToBin(e)) + this._dragElement.remove(); + this._dragElement.style.removeProperty("transform"); + var children = this._paletteContainer.children; + var colors = []; + for (var i = 0; i < children.length; ++i) { + if (children[i].__color) + colors.push(children[i].__color); + } + var palette = this._customPaletteSetting.get(); + palette.colors = colors; + this._customPaletteSetting.set(palette); + this._showPalette(this._customPaletteSetting.get(), false); + + this._deleteIconToolbar.element.classList.remove("dragging"); + this._deleteIconToolbar.element.classList.remove("delete-color-toolbar-active"); + }, + + _loadPalettes: function() + { + this._palettes.set(WebInspector.Spectrum.MaterialPalette.title, WebInspector.Spectrum.MaterialPalette); + /** @type {!WebInspector.Spectrum.Palette} */ + var defaultCustomPalette = { title: "Custom", colors: [], mutable: true }; + this._customPaletteSetting = WebInspector.settings.createSetting("customColorPalette", defaultCustomPalette); + this._palettes.set(this._customPaletteSetting.get().title, this._customPaletteSetting.get()); + + this._selectedColorPalette = WebInspector.settings.createSetting("selectedColorPalette", WebInspector.Spectrum.GeneratedPaletteTitle); + var palette = this._palettes.get(this._selectedColorPalette.get()); + if (palette) + this._showPalette(palette, true); + }, + + /** + * @param {!WebInspector.Spectrum.Palette} generatedPalette + */ + _generatedPaletteLoaded: function(generatedPalette) + { + if (generatedPalette.colors.length) + this._palettes.set(generatedPalette.title, generatedPalette); + if (this._selectedColorPalette.get() !== generatedPalette.title) { + return; + } else if (!generatedPalette.colors.length) { + this._paletteSelected(WebInspector.Spectrum.MaterialPalette); + return; + } + this._showPalette(generatedPalette, true); + }, + + /** + * @param {!WebInspector.Spectrum.Palette} palette + * @return {!Element} + */ + _createPreviewPaletteElement: function(palette) + { + var colorsPerPreviewRow = 5; + var previewElement = createElementWithClass("div", "palette-preview"); + var titleElement = previewElement.createChild("div", "palette-preview-title"); + titleElement.textContent = palette.title; + for (var i = 0; i < colorsPerPreviewRow && i < palette.colors.length; i++) + previewElement.appendChild(this._createPaletteColor(palette.colors[i])); + for (; i < colorsPerPreviewRow; i++) + previewElement.createChild("div", "spectrum-palette-color empty-color"); + previewElement.addEventListener("click", this._paletteSelected.bind(this, palette)); + return previewElement; + }, + + /** + * @param {!WebInspector.Spectrum.Palette} palette + */ + _paletteSelected: function(palette) + { + this._selectedColorPalette.set(palette.title); + this._showPalette(palette, true); + }, + + _resizeForSelectedPalette: function() + { + var palette = this._palettes.get(this._selectedColorPalette.get()); + if (!palette) + return; + var numColors = palette.colors.length; + if (palette === this._customPaletteSetting.get()) + numColors++; + var rowsNeeded = Math.max(1, Math.ceil(numColors / WebInspector.Spectrum._itemsPerPaletteRow)); + if (this._numPaletteRowsShown === rowsNeeded) + return; + this._numPaletteRowsShown = rowsNeeded; + var paletteColorHeight = 12; + var paletteMargin = 12; + var paletteTop = 235; + this.element.style.height = (paletteTop + paletteMargin + (paletteColorHeight + paletteMargin) * rowsNeeded) + "px"; + this.dispatchEventToListeners(WebInspector.Spectrum.Events.SizeChanged); + }, + + /** + * @param {string} colorText + * @param {boolean} matchUserFormat + */ + _paletteColorSelected: function(colorText, matchUserFormat) + { + var color = WebInspector.Color.parse(colorText); + if (!color) + return; + this._innerSetColor(color.hsva(), colorText, matchUserFormat ? this._colorFormat : color.format(), WebInspector.Spectrum._ChangeSource.Other); + }, + + _addColorToCustomPalette: function() + { + var palette = this._customPaletteSetting.get(); + palette.colors.push(this.colorString()); + this._customPaletteSetting.set(palette); + this._showPalette(this._customPaletteSetting.get(), false); + }, + + /** + * @param {number} colorIndex + * @param {!Event} event + */ + _showPaletteColorContextMenu: function(colorIndex, event) + { + if (!this._paletteContainerMutable) + return; + var contextMenu = new WebInspector.ContextMenu(event); + if (colorIndex !== -1) { + contextMenu.appendItem(WebInspector.UIString("Remove color"), this._deletePaletteColors.bind(this, colorIndex, false)); + contextMenu.appendItem(WebInspector.UIString("Remove all to the right"), this._deletePaletteColors.bind(this, colorIndex, true)); + } + contextMenu.appendItem(WebInspector.UIString("Clear palette"), this._deletePaletteColors.bind(this, -1, true)); + contextMenu.show(); + }, + + /** + * @param {number} colorIndex + * @param {boolean} toRight + */ + _deletePaletteColors: function(colorIndex, toRight) + { + var palette = this._customPaletteSetting.get(); + if (toRight) + palette.colors.splice(colorIndex + 1, palette.colors.length - colorIndex - 1); + else + palette.colors.splice(colorIndex, 1); + this._customPaletteSetting.set(palette); + this._showPalette(this._customPaletteSetting.get(), false); + }, + + /** + * @param {!WebInspector.Color} color + * @param {string} colorFormat + */ + setColor: function(color, colorFormat) + { + this._originalFormat = colorFormat; + this._innerSetColor(color.hsva(), "", colorFormat, WebInspector.Spectrum._ChangeSource.Model); + }, + + /** + * @param {!Array<number>|undefined} hsva + * @param {string|undefined} colorString + * @param {string|undefined} colorFormat + * @param {string} changeSource + */ + _innerSetColor: function(hsva, colorString, colorFormat, changeSource) + { + if (hsva !== undefined) + this._hsv = hsva; + if (colorString !== undefined) + this._colorString = colorString; + if (colorFormat !== undefined) { + var cf = WebInspector.Color.Format; + console.assert(colorFormat !== cf.Original, "Spectrum's color format cannot be Original"); + if (colorFormat === cf.RGBA) + colorFormat = cf.RGB; + else if (colorFormat === cf.HSLA) + colorFormat = cf.HSL; + else if (colorFormat === cf.HEXA) + colorFormat = cf.HEX; + else if (colorFormat === cf.ShortHEXA) + colorFormat = cf.ShortHEX; + this._colorFormat = colorFormat; + } + + this._updateHelperLocations(); + this._updateUI(); + + if (changeSource !== WebInspector.Spectrum._ChangeSource.Input) + this._updateInput(); + if (changeSource !== WebInspector.Spectrum._ChangeSource.Model) + this.dispatchEventToListeners(WebInspector.Spectrum.Events.ColorChanged, this.colorString()); + }, + + /** + * @param {!WebInspector.Color} color + */ + setContrastColor: function(color) + { + this._contrastColor = color; + this._updateUI(); + }, + + /** + * @return {!WebInspector.Color} + */ + _color: function() + { + return WebInspector.Color.fromHSVA(this._hsv); + }, + + /** + * @return {string} + */ + colorString: function() + { + if (this._colorString) + return this._colorString; + var cf = WebInspector.Color.Format; + var color = this._color(); + var colorString = color.asString(this._colorFormat); + if (colorString) + return colorString; + + if (this._colorFormat === cf.Nickname) { + colorString = color.asString(cf.HEX); + if (colorString) + return colorString; + } + + if (this._colorFormat === cf.ShortHEX) + colorString = color.asString(color.detectHEXFormat()); + else if (this._colorFormat === cf.HEX) + colorString = color.asString(color.hasAlpha() ? cf.HEXA : cf.HEX); + else if (this._colorFormat === cf.HSL) + colorString = color.asString(cf.HSLA); + else + colorString = color.asString(cf.RGBA); + + console.assert(colorString); + return colorString || ""; + }, + + _updateHelperLocations: function() + { + var h = this._hsv[0]; + var s = this._hsv[1]; + var v = this._hsv[2]; + var alpha = this._hsv[3]; + + // Where to show the little circle that displays your current selected color. + var dragX = s * this.dragWidth; + var dragY = this.dragHeight - (v * this.dragHeight); + + dragX = Math.max(-this._colorDragElementHeight, + Math.min(this.dragWidth - this._colorDragElementHeight, dragX - this._colorDragElementHeight)); + dragY = Math.max(-this._colorDragElementHeight, + Math.min(this.dragHeight - this._colorDragElementHeight, dragY - this._colorDragElementHeight)); + + this._colorDragElement.positionAt(dragX, dragY); + + // Where to show the bar that displays your current selected hue. + var hueSlideX = (1 - h) * this._hueAlphaWidth - this.slideHelperWidth; + this._hueSlider.style.left = hueSlideX + "px"; + var alphaSlideX = alpha * this._hueAlphaWidth - this.slideHelperWidth; + this._alphaSlider.style.left = alphaSlideX + "px"; + }, + + _updateInput: function() + { + var cf = WebInspector.Color.Format; + if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX || this._colorFormat === cf.Nickname) { + this._hexContainer.hidden = false; + this._displayContainer.hidden = true; + if (this._colorFormat === cf.ShortHEX) + this._hexValue.value = this._color().asString(this._color().detectHEXFormat()); + else + // Don't use short HEX if original was not in that format. + this._hexValue.value = this._color().asString(this._color().hasAlpha() ? cf.HEXA : cf.HEX); + } else { + // RGBA, HSLA display. + this._hexContainer.hidden = true; + this._displayContainer.hidden = false; + var isRgb = this._colorFormat === cf.RGB; + this._textLabels.textContent = isRgb ? "RGBA" : "HSLA"; + var colorValues = isRgb ? this._color().canonicalRGBA() : this._color().canonicalHSLA(); + for (var i = 0; i < 3; ++i) { + this._textValues[i].value = colorValues[i]; + if (!isRgb && (i === 1 || i === 2)) + this._textValues[i].value += "%"; + } + this._textValues[3].value = Math.round(colorValues[3] * 100) / 100; + } + }, + + /** + * @param {number} requiredContrast + */ + _drawContrastRatioLine: function(requiredContrast) + { + if (!this._contrastColor || !this.dragWidth || !this.dragHeight) + return; + + /** const */ var width = this.dragWidth; + /** const */ var height = this.dragHeight; + /** const */ var dS = 0.02; + /** const */ var epsilon = 0.002; + /** const */ var H = 0; + /** const */ var S = 1; + /** const */ var V = 2; + /** const */ var A = 3; + + var fgRGBA = []; + WebInspector.Color.hsva2rgba(this._hsv, fgRGBA); + var fgLuminance = WebInspector.Color.luminance(fgRGBA); + var bgRGBA = this._contrastColor.rgba(); + var bgLuminance = WebInspector.Color.luminance(bgRGBA); + var fgIsLighter = fgLuminance > bgLuminance; + var desiredLuminance = WebInspector.Color.desiredLuminance(bgLuminance, requiredContrast, fgIsLighter); + + var lastV = this._hsv[V]; + var currentSlope = 0; + var candidateHSVA = [this._hsv[H], 0, 0, this._hsv[A]]; + var pathBuilder = []; + var candidateRGBA = []; + WebInspector.Color.hsva2rgba(candidateHSVA, candidateRGBA); + var blendedRGBA = []; + WebInspector.Color.blendColors(candidateRGBA, bgRGBA, blendedRGBA); + + /** + * Approach the desired contrast ratio by modifying the given component + * from the given starting value. + * @param {number} index + * @param {number} x + * @param {boolean} onAxis + * @return {?number} + */ + function approach(index, x, onAxis) + { + while (0 <= x && x <= 1) { + candidateHSVA[index] = x; + WebInspector.Color.hsva2rgba(candidateHSVA, candidateRGBA); + WebInspector.Color.blendColors(candidateRGBA, bgRGBA, blendedRGBA); + var fgLuminance = WebInspector.Color.luminance(blendedRGBA); + var dLuminance = fgLuminance - desiredLuminance; + + if (Math.abs(dLuminance) < (onAxis ? epsilon / 10 : epsilon)) + return x; + else + x += (index === V ? -dLuminance : dLuminance); + } + return null; + } + + for (var s = 0; s < 1 + dS; s += dS) { + s = Math.min(1, s); + candidateHSVA[S] = s; + + var v = lastV; + v = lastV + currentSlope * dS; + + v = approach(V, v, s === 0); + if (v === null) + break; + + currentSlope = (v - lastV) / dS; + + pathBuilder.push(pathBuilder.length ? "L" : "M"); + pathBuilder.push(s * width); + pathBuilder.push((1 - v) * height); + } + + if (s < 1 + dS) { + s -= dS; + candidateHSVA[V] = 1; + s = approach(S, s, true); + if (s !== null) + pathBuilder = pathBuilder.concat(["L", s * width, -1]) + } + + this._contrastRatioLine.setAttribute("d", pathBuilder.join(" ")); + }, + + _updateUI: function() + { + var h = WebInspector.Color.fromHSVA([this._hsv[0], 1, 1, 1]); + this._colorElement.style.backgroundColor = /** @type {string} */ (h.asString(WebInspector.Color.Format.RGB)); + if (Runtime.experiments.isEnabled("colorContrastRatio")) { + // TODO(samli): Determine size of text and switch between AA/AAA ratings. + this._drawContrastRatioLine(4.5); + } + this._swatchInnerElement.style.backgroundColor = /** @type {string} */ (this._color().asString(WebInspector.Color.Format.RGBA)); + // Show border if the swatch is white. + this._swatchInnerElement.classList.toggle("swatch-inner-white", this._color().hsla()[2] > 0.9); + this._colorDragElement.style.backgroundColor = /** @type {string} */ (this._color().asString(WebInspector.Color.Format.RGBA)); + var noAlpha = WebInspector.Color.fromHSVA(this._hsv.slice(0,3).concat(1)); + this._alphaElementBackground.style.backgroundImage = String.sprintf("linear-gradient(to right, rgba(0,0,0,0), %s)", noAlpha.asString(WebInspector.Color.Format.RGB)); + }, + + _formatViewSwitch: function() + { + var cf = WebInspector.Color.Format; + var format = cf.RGB; + if (this._colorFormat === cf.RGB) + format = cf.HSL; + else if (this._colorFormat === cf.HSL) + format = this._originalFormat === cf.ShortHEX ? cf.ShortHEX : cf.HEX; + this._innerSetColor(undefined, "", format, WebInspector.Spectrum._ChangeSource.Other); + }, + + /** + * @param {!Event} event + */ + _inputChanged: function(event) + { + /** + * @param {!Element} element + * @return {string} + */ + function elementValue(element) + { + return element.value; + } + + var inputElement = /** @type {!Element} */(event.currentTarget); + var arrowKeyOrMouseWheelEvent = (event.key === "ArrowUp" || event.key === "ArrowDown" || event.type === "mousewheel"); + var pageKeyPressed = (event.key === "PageUp" || event.key === "PageDown"); + if (arrowKeyOrMouseWheelEvent || pageKeyPressed) { + var newValue = WebInspector.createReplacementString(inputElement.value, event); + if (newValue) { + inputElement.value = newValue; + inputElement.selectionStart = 0; + inputElement.selectionEnd = newValue.length; + } + event.consume(true); + } + + const cf = WebInspector.Color.Format; + var colorString; + if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX) { + colorString = this._hexValue.value; + } else { + var format = this._colorFormat === cf.RGB ? "rgba" : "hsla"; + var values = this._textValues.map(elementValue).join(","); + colorString = String.sprintf("%s(%s)", format, values); + } + + var color = WebInspector.Color.parse(colorString); + if (!color) + return; + var hsv = color.hsva(); + if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX) + this._colorFormat = color.detectHEXFormat(); + this._innerSetColor(hsv, colorString, undefined, WebInspector.Spectrum._ChangeSource.Input); + }, + + wasShown: function() + { + this._hueAlphaWidth = this._hueElement.offsetWidth; + this.slideHelperWidth = this._hueSlider.offsetWidth / 2; + this.dragWidth = this._colorElement.offsetWidth; + this.dragHeight = this._colorElement.offsetHeight; + this._colorDragElementHeight = this._colorDragElement.offsetHeight / 2; + this._innerSetColor(undefined, undefined, undefined, WebInspector.Spectrum._ChangeSource.Model); + this._toggleColorPicker(true); + WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.EventTypes.ColorPicked, this._colorPicked, this); + }, + + willHide: function() + { + this._toggleColorPicker(false); + WebInspector.targetManager.removeModelListener(WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.EventTypes.ColorPicked, this._colorPicked, this); + }, + + /** + * @param {boolean=} enabled + * @param {!WebInspector.Event=} event + */ + _toggleColorPicker: function(enabled, event) + { + if (enabled === undefined) + enabled = !this._colorPickerButton.toggled(); + this._colorPickerButton.setToggled(enabled); + for (var target of WebInspector.targetManager.targets()) + target.pageAgent().setColorPickerEnabled(enabled); + }, + + /** + * @param {!WebInspector.Event} event + */ + _colorPicked: function(event) + { + var rgbColor = /** @type {!DOMAgent.RGBA} */ (event.data); + var rgba = [rgbColor.r, rgbColor.g, rgbColor.b, (rgbColor.a / 2.55 | 0) / 100]; + var color = WebInspector.Color.fromRGBA(rgba); + this._innerSetColor(color.hsva(), "", undefined, WebInspector.Spectrum._ChangeSource.Other); + InspectorFrontendHost.bringToFront(); + }, + + + __proto__: WebInspector.VBox.prototype +} + +/** @typedef {{ title: string, colors: !Array.<string>, mutable: boolean }} */ +WebInspector.Spectrum.Palette; +WebInspector.Spectrum.GeneratedPaletteTitle = "Page colors"; + +/** + * @constructor + * @param {function(!WebInspector.Spectrum.Palette)} callback + */ +WebInspector.Spectrum.PaletteGenerator = function(callback) +{ + this._callback = callback; + /** @type {!Map.<string, number>} */ + this._frequencyMap = new Map(); + var stylesheetPromises = []; + for (var target of WebInspector.targetManager.targets(WebInspector.Target.Capability.Browser)) { + var cssModel = WebInspector.CSSModel.fromTarget(target); + for (var stylesheet of cssModel.allStyleSheets()) + stylesheetPromises.push(new Promise(this._processStylesheet.bind(this, stylesheet))); + } + Promise.all(stylesheetPromises) + .catchException(null) + .then(this._finish.bind(this)); +} + +WebInspector.Spectrum.PaletteGenerator.prototype = { + /** + * @param {string} a + * @param {string} b + * @return {number} + */ + _frequencyComparator: function(a, b) + { + return this._frequencyMap.get(b) - this._frequencyMap.get(a); + }, + + _finish: function() + { + /** + * @param {string} a + * @param {string} b + * @return {number} + */ + function hueComparator(a, b) + { + var hsva = paletteColors.get(a).hsva(); + var hsvb = paletteColors.get(b).hsva(); + + // First trim the shades of gray + if (hsvb[1] < 0.12 && hsva[1] < 0.12) + return hsvb[2] * hsvb[3] - hsva[2] * hsva[3]; + if (hsvb[1] < 0.12) + return -1; + if (hsva[1] < 0.12) + return 1; + + // Equal hue -> sort by sat + if (hsvb[0] === hsva[0]) + return hsvb[1] * hsvb[3] - hsva[1] * hsva[3]; + + return (hsvb[0] + 0.94) % 1 - (hsva[0] + 0.94) % 1; + } + + var colors = this._frequencyMap.keysArray(); + colors = colors.sort(this._frequencyComparator.bind(this)); + /** @type {!Map.<string, !WebInspector.Color>} */ + var paletteColors = new Map(); + var colorsPerRow = 24; + while (paletteColors.size < colorsPerRow && colors.length) { + var colorText = colors.shift(); + var color = WebInspector.Color.parse(colorText); + if (!color || color.nickname() === "white" || color.nickname() === "black") + continue; + paletteColors.set(colorText, color); + } + + this._callback({ title: WebInspector.Spectrum.GeneratedPaletteTitle, colors: paletteColors.keysArray().sort(hueComparator), mutable: false }); + }, + + /** + * @param {!WebInspector.CSSStyleSheetHeader} stylesheet + * @param {function(?)} resolve + * @this {WebInspector.Spectrum.PaletteGenerator} + */ + _processStylesheet: function(stylesheet, resolve) + { + /** + * @param {?string} text + * @this {WebInspector.Spectrum.PaletteGenerator} + */ + function parseContent(text) + { + text = text.toLowerCase(); + var regexResult = text.match(/((?:rgb|hsl)a?\([^)]+\)|#[0-9a-f]{6}|#[0-9a-f]{3})/g) || []; + for (var c of regexResult) { + var frequency = this._frequencyMap.get(c) || 0; + this._frequencyMap.set(c, ++frequency); + } + resolve(null); + } + + stylesheet.requestContent().then(parseContent.bind(this)); + } +} + +WebInspector.Spectrum.MaterialPaletteShades = { + "#F44336": ["#FFEBEE", "#FFCDD2", "#EF9A9A", "#E57373", "#EF5350", "#F44336", "#E53935", "#D32F2F", "#C62828", "#B71C1C"], + "#E91E63": ["#FCE4EC", "#F8BBD0", "#F48FB1", "#F06292", "#EC407A", "#E91E63", "#D81B60", "#C2185B", "#AD1457", "#880E4F"], + "#9C27B0": ["#F3E5F5", "#E1BEE7", "#CE93D8", "#BA68C8", "#AB47BC", "#9C27B0", "#8E24AA", "#7B1FA2", "#6A1B9A", "#4A148C"], + "#673AB7": ["#EDE7F6", "#D1C4E9", "#B39DDB", "#9575CD", "#7E57C2", "#673AB7", "#5E35B1", "#512DA8", "#4527A0", "#311B92"], + "#3F51B5": ["#E8EAF6", "#C5CAE9", "#9FA8DA", "#7986CB", "#5C6BC0", "#3F51B5", "#3949AB", "#303F9F", "#283593", "#1A237E"], + "#2196F3": ["#E3F2FD", "#BBDEFB", "#90CAF9", "#64B5F6", "#42A5F5", "#2196F3", "#1E88E5", "#1976D2", "#1565C0", "#0D47A1"], + "#03A9F4": ["#E1F5FE", "#B3E5FC", "#81D4FA", "#4FC3F7", "#29B6F6", "#03A9F4", "#039BE5", "#0288D1", "#0277BD", "#01579B"], + "#00BCD4": ["#E0F7FA", "#B2EBF2", "#80DEEA", "#4DD0E1", "#26C6DA", "#00BCD4", "#00ACC1", "#0097A7", "#00838F", "#006064"], + "#009688": ["#E0F2F1", "#B2DFDB", "#80CBC4", "#4DB6AC", "#26A69A", "#009688", "#00897B", "#00796B", "#00695C", "#004D40"], + "#4CAF50": ["#E8F5E9", "#C8E6C9", "#A5D6A7", "#81C784", "#66BB6A", "#4CAF50", "#43A047", "#388E3C", "#2E7D32", "#1B5E20"], + "#8BC34A": ["#F1F8E9", "#DCEDC8", "#C5E1A5", "#AED581", "#9CCC65", "#8BC34A", "#7CB342", "#689F38", "#558B2F", "#33691E"], + "#CDDC39": ["#F9FBE7", "#F0F4C3", "#E6EE9C", "#DCE775", "#D4E157", "#CDDC39", "#C0CA33", "#AFB42B", "#9E9D24", "#827717"], + "#FFEB3B": ["#FFFDE7", "#FFF9C4", "#FFF59D", "#FFF176", "#FFEE58", "#FFEB3B", "#FDD835", "#FBC02D", "#F9A825", "#F57F17"], + "#FFC107": ["#FFF8E1", "#FFECB3", "#FFE082", "#FFD54F", "#FFCA28", "#FFC107", "#FFB300", "#FFA000", "#FF8F00", "#FF6F00"], + "#FF9800": ["#FFF3E0", "#FFE0B2", "#FFCC80", "#FFB74D", "#FFA726", "#FF9800", "#FB8C00", "#F57C00", "#EF6C00", "#E65100"], + "#FF5722": ["#FBE9E7", "#FFCCBC", "#FFAB91", "#FF8A65", "#FF7043", "#FF5722", "#F4511E", "#E64A19", "#D84315", "#BF360C"], + "#795548": ["#EFEBE9", "#D7CCC8", "#BCAAA4", "#A1887F", "#8D6E63", "#795548", "#6D4C41", "#5D4037", "#4E342E", "#3E2723"], + "#9E9E9E": ["#FAFAFA", "#F5F5F5", "#EEEEEE", "#E0E0E0", "#BDBDBD", "#9E9E9E", "#757575", "#616161", "#424242", "#212121"], + "#607D8B": ["#ECEFF1", "#CFD8DC", "#B0BEC5", "#90A4AE", "#78909C", "#607D8B", "#546E7A", "#455A64", "#37474F", "#263238"] +}; + +WebInspector.Spectrum.MaterialPalette = { title: "Material", mutable: false, matchUserFormat: true, colors: Object.keys(WebInspector.Spectrum.MaterialPaletteShades) };
diff --git a/third_party/WebKit/Source/devtools/front_end/components/module.json b/third_party/WebKit/Source/devtools/front_end/components/module.json index d8c350e..89f90cd3 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/module.json +++ b/third_party/WebKit/Source/devtools/front_end/components/module.json
@@ -76,6 +76,7 @@ "RemoteObjectPreviewFormatter.js", "RequestAppBannerActionDelegate.js", "ShortcutsScreen.js", + "Spectrum.js", "EventListenersUtils.js", "EventListenersView.js", "Reload.js" @@ -87,6 +88,7 @@ "domUtils.css", "networkConditionsSettingsTab.css", "objectPropertiesSection.css", - "objectValue.css" + "objectValue.css", + "spectrum.css" ] }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/spectrum.css b/third_party/WebKit/Source/devtools/front_end/components/spectrum.css similarity index 100% rename from third_party/WebKit/Source/devtools/front_end/elements/spectrum.css rename to third_party/WebKit/Source/devtools/front_end/components/spectrum.css
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleContextSelector.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleContextSelector.js index e9fc42f..de1ceda9 100644 --- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleContextSelector.js +++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleContextSelector.js
@@ -54,7 +54,7 @@ { // FIXME(413886): We never want to show execution context for the main thread of shadow page in service/shared worker frontend. // This check could be removed once we do not send this context to frontend. - if (executionContext.target().isServiceWorker()) + if (!executionContext.target().hasJSCapability()) return; var newOption = createElement("option"); @@ -63,7 +63,7 @@ this._optionByExecutionContext.set(executionContext, newOption); var options = this._selectElement.options; var contexts = Array.prototype.map.call(options, mapping); - var index = contexts.lowerBound(executionContext, WebInspector.ExecutionContext.comparator) + var index = contexts.lowerBound(executionContext, executionContext.runtimeModel.executionContextComparator()) this._selectElement.insertBefore(newOption, options[index]); if (executionContext === WebInspector.context.flavor(WebInspector.ExecutionContext))
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 0d134561..49694b8 100644 --- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js +++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
@@ -266,8 +266,8 @@ targetAdded: function(target) { this._viewport.invalidate(); - if (WebInspector.targetManager.targets().length > 1 && WebInspector.targetManager.mainTarget().isPage()) - this._showAllMessagesCheckbox.element.classList.toggle("hidden", false); + var hasMultipleCotexts = WebInspector.targetManager.targets(WebInspector.Target.Capability.JS).length > 1; + this._showAllMessagesCheckbox.element.classList.toggle("hidden", !hasMultipleCotexts); }, /**
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js index b187427d..b0bada0 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/ClassesPaneWidget.js
@@ -100,6 +100,7 @@ for (var i = 0; i < keys.length; ++i) { var className = keys[i]; var label = createCheckboxLabel(className, classes.get(className)); + label.visualizeFocus = true; label.classList.add("monospace"); label.checkboxElement.addEventListener("click", this._onClick.bind(this, className), false); this._classesContainer.appendChild(label);
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ComputedStyleModel.js b/third_party/WebKit/Source/devtools/front_end/elements/ComputedStyleModel.js new file mode 100644 index 0000000..6c67b5ba1 --- /dev/null +++ b/third_party/WebKit/Source/devtools/front_end/elements/ComputedStyleModel.js
@@ -0,0 +1,131 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @extends {WebInspector.Object} + * @constructor + */ +WebInspector.ComputedStyleModel = function() +{ + WebInspector.Object.call(this); + this._node = WebInspector.context.flavor(WebInspector.DOMNode); + WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._onNodeChanged, this); +} + +WebInspector.ComputedStyleModel.Events = { + ComputedStyleChanged: "ComputedStyleChanged" +} + +WebInspector.ComputedStyleModel.prototype = { + /** + * @return {?WebInspector.DOMNode} + */ + node: function() + { + return this._node; + }, + + /** + * @return {?WebInspector.CSSModel} + */ + cssModel: function() + { + return this._cssModel; + }, + + /** + * @param {!WebInspector.Event} event + */ + _onNodeChanged: function(event) + { + this._node = /** @type {?WebInspector.DOMNode} */(event.data); + this._updateTarget(this._node ? this._node.target() : null); + this._onComputedStyleChanged(); + }, + + /** + * @param {?WebInspector.Target} target + */ + _updateTarget: function(target) + { + if (this._target === target) + return; + if (this._targetEvents) { + WebInspector.EventTarget.removeEventListeners(this._targetEvents); + this._targetEvents = null; + } + this._target = target; + var domModel = null; + if (target) { + this._cssModel = WebInspector.CSSModel.fromTarget(target); + domModel = WebInspector.DOMModel.fromTarget(target); + } + + if (domModel && this._cssModel) { + this._targetEvents = [ + this._cssModel.addEventListener(WebInspector.CSSModel.Events.StyleSheetAdded, this._onComputedStyleChanged, this), + this._cssModel.addEventListener(WebInspector.CSSModel.Events.StyleSheetRemoved, this._onComputedStyleChanged, this), + this._cssModel.addEventListener(WebInspector.CSSModel.Events.StyleSheetChanged, this._onComputedStyleChanged, this), + this._cssModel.addEventListener(WebInspector.CSSModel.Events.MediaQueryResultChanged, this._onComputedStyleChanged, this), + this._cssModel.addEventListener(WebInspector.CSSModel.Events.PseudoStateForced, this._onComputedStyleChanged, this), + this._cssModel.addEventListener(WebInspector.CSSModel.Events.ModelWasEnabled, this._onComputedStyleChanged, this), + domModel.addEventListener(WebInspector.DOMModel.Events.DOMMutated, this._onComputedStyleChanged, this) + ]; + } + }, + + /** + * @return {?WebInspector.DOMNode} + */ + _elementNode: function() + { + return this.node() ? this.node().enclosingElementOrSelf() : null; + }, + + /** + * @return {!Promise.<?WebInspector.ComputedStyleModel.ComputedStyle>} + */ + fetchComputedStyle: function() + { + var elementNode = this._elementNode(); + var cssModel = this.cssModel(); + if (!elementNode || !cssModel) + return Promise.resolve(/** @type {?WebInspector.ComputedStyleModel.ComputedStyle} */(null)); + + if (!this._computedStylePromise) + this._computedStylePromise = cssModel.computedStylePromise(elementNode.id).then(verifyOutdated.bind(this, elementNode)); + + return this._computedStylePromise; + + /** + * @param {!WebInspector.DOMNode} elementNode + * @param {?Map.<string, string>} style + * @return {?WebInspector.ComputedStyleModel.ComputedStyle} + * @this {WebInspector.ComputedStyleModel} + */ + function verifyOutdated(elementNode, style) + { + return elementNode === this._elementNode() && style ? new WebInspector.ComputedStyleModel.ComputedStyle(elementNode, style) : /** @type {?WebInspector.ComputedStyleModel.ComputedStyle} */(null); + } + }, + + _onComputedStyleChanged: function() + { + delete this._computedStylePromise; + this.dispatchEventToListeners(WebInspector.ComputedStyleModel.Events.ComputedStyleChanged); + }, + + __proto__: WebInspector.Object.prototype +} + +/** + * @constructor + * @param {!WebInspector.DOMNode} node + * @param {!Map.<string, string>} computedStyle + */ +WebInspector.ComputedStyleModel.ComputedStyle = function(node, computedStyle) +{ + this.node = node; + this.computedStyle = computedStyle; +}
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ComputedStyleWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/ComputedStyleWidget.js index 31a20f8..15e246a 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/ComputedStyleWidget.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/ComputedStyleWidget.js
@@ -30,11 +30,8 @@ /** * @constructor * @extends {WebInspector.ThrottledWidget} - * @param {!WebInspector.StylesSidebarPane} stylesSidebarPane - * @param {!WebInspector.SharedSidebarModel} sharedModel - * @param {function(!WebInspector.CSSProperty)} revealCallback */ -WebInspector.ComputedStyleWidget = function(stylesSidebarPane, sharedModel, revealCallback) +WebInspector.ComputedStyleWidget = function() { WebInspector.ThrottledWidget.call(this); this.element.classList.add("computed-style-sidebar-pane"); @@ -42,8 +39,8 @@ this.registerRequiredCSS("elements/computedStyleSidebarPane.css"); this._alwaysShowComputedProperties = { "display": true, "height": true, "width": true }; - this._sharedModel = sharedModel; - this._sharedModel.addEventListener(WebInspector.SharedSidebarModel.Events.ComputedStyleChanged, this.update, this); + this._computedStyleModel = new WebInspector.ComputedStyleModel(); + this._computedStyleModel.addEventListener(WebInspector.ComputedStyleModel.Events.ComputedStyleChanged, this.update, this); this._showInheritedComputedStylePropertiesSetting = WebInspector.settings.createSetting("showInheritedComputedStyleProperties", false); this._showInheritedComputedStylePropertiesSetting.addChangeListener(this._showInheritedComputedStyleChanged.bind(this)); @@ -62,9 +59,7 @@ this._propertiesOutline.element.classList.add("monospace", "computed-properties"); this.element.appendChild(this._propertiesOutline.element); - this._stylesSidebarPane = stylesSidebarPane; this._linkifier = new WebInspector.Linkifier(new WebInspector.Linkifier.DefaultCSSFormatter()); - this._revealCallback = revealCallback; /** * @param {?RegExp} regex @@ -75,17 +70,17 @@ this._filterRegex = regex; this._updateFilter(regex); } + + var fontsWidget = new WebInspector.PlatformFontsWidget(this._computedStyleModel); + fontsWidget.show(this.element); } /** - * @param {!WebInspector.StylesSidebarPane} stylesSidebarPane - * @param {!WebInspector.SharedSidebarModel} sharedModel - * @param {function(!WebInspector.CSSProperty)} revealCallback * @return {!WebInspector.ElementsSidebarViewWrapperPane} */ -WebInspector.ComputedStyleWidget.createSidebarWrapper = function(stylesSidebarPane, sharedModel, revealCallback) +WebInspector.ComputedStyleWidget.createSidebarWrapper = function() { - var widget = new WebInspector.ComputedStyleWidget(stylesSidebarPane, sharedModel, revealCallback); + var widget = new WebInspector.ComputedStyleWidget(); return new WebInspector.ElementsSidebarViewWrapperPane(WebInspector.UIString("Computed Style"), widget) } @@ -104,14 +99,36 @@ doUpdate: function() { var promises = [ - this._sharedModel.fetchComputedStyle(), - this._stylesSidebarPane.fetchMatchedCascade() + this._computedStyleModel.fetchComputedStyle(), + this._fetchMatchedCascade() ]; return Promise.all(promises) .spread(this._innerRebuildUpdate.bind(this)); }, /** + * @return {!Promise.<?WebInspector.CSSMatchedStyles>} + */ + _fetchMatchedCascade: function() + { + var node = this._computedStyleModel.node(); + if (!node || !this._computedStyleModel.cssModel()) + return Promise.resolve(/** @type {?WebInspector.CSSMatchedStyles} */(null)); + + return this._computedStyleModel.cssModel().cachedMatchedCascadeForNode(node).then(validateStyles.bind(this)); + + /** + * @param {?WebInspector.CSSMatchedStyles} matchedStyles + * @return {?WebInspector.CSSMatchedStyles} + * @this {WebInspector.ComputedStyleWidget} + */ + function validateStyles(matchedStyles) + { + return matchedStyles && matchedStyles.node() === this._computedStyleModel.node() ? matchedStyles : null; + } + }, + + /** * @param {string} text * @return {!Node} */ @@ -127,14 +144,14 @@ }, /** - * @param {?WebInspector.SharedSidebarModel.ComputedStyle} nodeStyle + * @param {?WebInspector.ComputedStyleModel.ComputedStyle} nodeStyle * @param {?WebInspector.CSSMatchedStyles} matchedStyles */ _innerRebuildUpdate: function(nodeStyle, matchedStyles) { this._propertiesOutline.removeChildren(); this._linkifier.reset(); - var cssModel = this._sharedModel.cssModel(); + var cssModel = this._computedStyleModel.cssModel(); if (!nodeStyle || !matchedStyles || !cssModel) return; @@ -234,8 +251,7 @@ */ _navigateToSource: function(cssProperty, event) { - if (this._revealCallback) - this._revealCallback.call(null, cssProperty); + WebInspector.Revealer.reveal(cssProperty); event.consume(true); },
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js index bc5f4de..d4ca4cc4 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
@@ -71,11 +71,8 @@ this._elementsSidebarViewWrappers = []; this._currentToolbarPane = null; - var sharedSidebarModel = new WebInspector.SharedSidebarModel(); - this.sidebarPanes.platformFonts = WebInspector.PlatformFontsWidget.createSidebarWrapper(sharedSidebarModel); this.sidebarPanes.styles = new WebInspector.StylesSidebarPane(); - this.sidebarPanes.computedStyle = WebInspector.ComputedStyleWidget.createSidebarWrapper(this.sidebarPanes.styles, sharedSidebarModel, this._revealProperty.bind(this)); - + this.sidebarPanes.computedStyle = WebInspector.ComputedStyleWidget.createSidebarWrapper(); this.sidebarPanes.metrics = new WebInspector.MetricsSidebarPane(); this.sidebarPanes.properties = WebInspector.PropertiesWidget.createSidebarWrapper(); this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane.createProxy(this); @@ -89,8 +86,6 @@ /** @type {!Array.<!WebInspector.ElementsTreeOutline>} */ this._treeOutlines = []; - /** @type {!Map.<!WebInspector.DOMModel, !WebInspector.ElementsTreeOutline>} */ - this._modelToTreeOutline = new Map(); WebInspector.targetManager.observeTargets(this); WebInspector.moduleSetting("showUAShadowDOM").addChangeListener(this._showUAShadowDOMChanged.bind(this)); WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspector.DOMModel.Events.DocumentUpdated, this._documentUpdatedEvent, this); @@ -123,7 +118,6 @@ var filterInput = WebInspector.StylesSidebarPane.createPropertyFilterElement(WebInspector.UIString("Filter"), hbox, ssp.onFilterChanged.bind(ssp)); filterContainerElement.appendChild(filterInput); var toolbar = new WebInspector.ExtensibleToolbar("styles-sidebarpane-toolbar", hbox); - toolbar.onLoad().then(() => toolbar.appendToolbarItem(WebInspector.StylesSidebarPane.createAddNewRuleButton(ssp))); toolbar.element.classList.add("styles-pane-toolbar"); toolbar.makeToggledGray(); var toolbarPaneContainer = container.createChild("div", "styles-sidebar-toolbar-pane-container"); @@ -203,24 +197,6 @@ } }, - _toggleHideElement: function() - { - var node = this.selectedDOMNode(); - var treeOutline = this._treeOutlineForNode(node); - if (!node || !treeOutline) - return; - treeOutline.toggleHideElement(node); - }, - - _toggleEditAsHTML: function() - { - var node = this.selectedDOMNode(); - var treeOutline = this._treeOutlineForNode(node); - if (!node || !treeOutline) - return; - treeOutline.toggleEditAsHTML(node); - }, - _loadSidebarViews: function() { var extensions = self.runtime.extensions("@WebInspector.Widget"); @@ -266,7 +242,6 @@ treeOutline.addEventListener(WebInspector.ElementsTreeOutline.Events.ElementsTreeUpdated, this._updateBreadcrumbIfNeeded, this); new WebInspector.ElementsTreeElementHighlighter(treeOutline); this._treeOutlines.push(treeOutline); - this._modelToTreeOutline.set(domModel, treeOutline); // Perform attach if necessary. if (this.isShowing()) @@ -283,7 +258,7 @@ var domModel = WebInspector.DOMModel.fromTarget(target); if (!domModel) return; - var treeOutline = this._modelToTreeOutline.remove(domModel); + var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(domModel); treeOutline.unwireFromDOMModel(); this._treeOutlines.remove(treeOutline); treeOutline.element.remove(); @@ -429,7 +404,7 @@ this._reset(); this.searchCanceled(); - var treeOutline = this._modelToTreeOutline.get(domModel); + var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(domModel); treeOutline.rootDOMNode = inspectedRootDocument; if (!inspectedRootDocument) { @@ -694,7 +669,7 @@ var searchResult = this._searchResults[this._currentSearchResultIndex]; if (!searchResult.node) return; - var treeOutline = this._modelToTreeOutline.get(searchResult.node.domModel()); + var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(searchResult.node.domModel()); var treeElement = treeOutline.findTreeElement(searchResult.node); if (treeElement) treeElement.hideSearchHighlights(); @@ -805,19 +780,7 @@ { if (!node) return null; - return this._modelToTreeOutline.get(node.domModel()) || null; - }, - - /** - * @return {?WebInspector.ElementsTreeOutline} - */ - _focusedTreeOutline: function() - { - for (var i = 0; i < this._treeOutlines.length; ++i) { - if (this._treeOutlines[i].hasFocus()) - return this._treeOutlines[i]; - } - return null; + return WebInspector.ElementsTreeOutline.forDOMModel(node.domModel()); }, /** @@ -831,36 +794,6 @@ }, /** - * @param {!Event} event - */ - handleCopyEvent: function(event) - { - var treeOutline = this._focusedTreeOutline(); - if (treeOutline) - treeOutline.handleCopyOrCutKeyboardEvent(false, event); - }, - - /** - * @param {!Event} event - */ - handleCutEvent: function(event) - { - var treeOutline = this._focusedTreeOutline(); - if (treeOutline) - treeOutline.handleCopyOrCutKeyboardEvent(true, event); - }, - - /** - * @param {!Event} event - */ - handlePasteEvent: function(event) - { - var treeOutline = this._focusedTreeOutline(); - if (treeOutline) - treeOutline.handlePasteKeyboardEvent(event); - }, - - /** * @param {!WebInspector.DOMNode} node * @return {!WebInspector.DOMNode} */ @@ -896,33 +829,6 @@ this._notFirstInspectElement = true; }, - /** - * @param {!Event} event - * @param {!WebInspector.ContextMenu} contextMenu - * @param {!Object} object - */ - appendApplicableItems: function(event, contextMenu, object) - { - if (!(object instanceof WebInspector.RemoteObject && (/** @type {!WebInspector.RemoteObject} */ (object)).isNode()) - && !(object instanceof WebInspector.DOMNode) - && !(object instanceof WebInspector.DeferredDOMNode)) { - return; - } - - // Add debbuging-related actions - if (object instanceof WebInspector.DOMNode) { - contextMenu.appendSeparator(); - WebInspector.domBreakpointsSidebarPane.populateNodeContextMenu(object, contextMenu, true); - } - - // Skip adding "Reveal..." menu item for our own tree outline. - if (this.element.isAncestor(/** @type {!Node} */ (event.target))) - return; - var commandCallback = WebInspector.Revealer.reveal.bind(WebInspector.Revealer, object); - - contextMenu.appendItem(WebInspector.UIString.capitalize("Reveal in Elements ^panel"), commandCallback); - }, - _sidebarContextMenuEventFired: function(event) { var contextMenu = new WebInspector.ContextMenu(event); @@ -1039,7 +945,6 @@ this.sidebarPanes.styles.show(matchedStylePanesWrapper.element); this.sidebarPanes.computedStyle.show(computedStylePanesWrapper.element); showMetrics.call(this, horizontally); - this.sidebarPanes.platformFonts.show(computedStylePanesWrapper.element); this.sidebarPaneView.addPane(this.sidebarPanes.eventListeners); this.sidebarPaneView.addPane(this.sidebarPanes.domBreakpoints); @@ -1094,11 +999,27 @@ * @override * @param {!Event} event * @param {!WebInspector.ContextMenu} contextMenu - * @param {!Object} target + * @param {!Object} object */ - appendApplicableItems: function(event, contextMenu, target) + appendApplicableItems: function(event, contextMenu, object) { - WebInspector.ElementsPanel.instance().appendApplicableItems(event, contextMenu, target); + if (!(object instanceof WebInspector.RemoteObject && (/** @type {!WebInspector.RemoteObject} */ (object)).isNode()) + && !(object instanceof WebInspector.DOMNode) + && !(object instanceof WebInspector.DeferredDOMNode)) { + return; + } + + // Add debbuging-related actions + if (object instanceof WebInspector.DOMNode) { + contextMenu.appendSeparator(); + WebInspector.domBreakpointsSidebarPane.populateNodeContextMenu(object, contextMenu, true); + } + + // Skip adding "Reveal..." menu item for our own tree outline. + if (WebInspector.ElementsPanel.instance().element.isAncestor(/** @type {!Node} */ (event.target))) + return; + var commandCallback = WebInspector.Revealer.reveal.bind(WebInspector.Revealer, object); + contextMenu.appendItem(WebInspector.UIString.capitalize("Reveal in Elements ^panel"), commandCallback); } } @@ -1106,9 +1027,7 @@ * @constructor * @implements {WebInspector.Revealer} */ -WebInspector.ElementsPanel.DOMNodeRevealer = function() -{ -} +WebInspector.ElementsPanel.DOMNodeRevealer = function() { } WebInspector.ElementsPanel.DOMNodeRevealer.prototype = { /** @@ -1162,6 +1081,25 @@ } } +/** + * @constructor + * @implements {WebInspector.Revealer} + */ +WebInspector.ElementsPanel.CSSPropertyRevealer = function() { } + +WebInspector.ElementsPanel.CSSPropertyRevealer.prototype = { + /** + * @override + * @param {!Object} property + * @return {!Promise} + */ + reveal: function(property) + { + var panel = WebInspector.ElementsPanel.instance(); + return panel._revealProperty(/** @type {!WebInspector.CSSProperty} */ (property)); + } +} + WebInspector.ElementsPanel.show = function() { WebInspector.inspectorView.setCurrentPanel(WebInspector.ElementsPanel.instance()); @@ -1211,12 +1149,19 @@ */ handleAction: function(context, actionId) { + var node = WebInspector.context.flavor(WebInspector.DOMNode); + if (!node) + return true; + var treeOutline = WebInspector.ElementsTreeOutline.forDOMModel(node.domModel()); + if (!treeOutline) + return true; + switch (actionId) { case "elements.hide-element": - WebInspector.ElementsPanel.instance()._toggleHideElement(); + treeOutline.toggleHideElement(node); return true; case "elements.edit-as-html": - WebInspector.ElementsPanel.instance()._toggleEditAsHTML(); + treeOutline.toggleEditAsHTML(node); return true; } return false;
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js index 4b56b65..396f912 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsTreeOutline.js
@@ -57,6 +57,10 @@ this._element.addEventListener("drop", this._ondrop.bind(this), false); this._element.addEventListener("dragend", this._ondragend.bind(this), false); this._element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), false); + this._element.addEventListener("clipboard-beforecopy", this._onBeforeCopy.bind(this), false); + this._element.addEventListener("clipboard-copy", this._onCopyOrCut.bind(this, false), false); + this._element.addEventListener("clipboard-cut", this._onCopyOrCut.bind(this, true), false); + this._element.addEventListener("clipboard-paste", this._onPaste.bind(this), false); outlineDisclosureElement.appendChild(this._element); this.element = element; @@ -81,6 +85,17 @@ this._domModel.addEventListener(WebInspector.DOMModel.Events.MarkersChanged, this._markersChanged, this); } +WebInspector.ElementsTreeOutline._treeOutlineSymbol = Symbol("treeOutline"); + +/** + * @param {!WebInspector.DOMModel} domModel + * @return {?WebInspector.ElementsTreeOutline} + */ +WebInspector.ElementsTreeOutline.forDOMModel = function(domModel) +{ + return domModel[WebInspector.ElementsTreeOutline._treeOutlineSymbol] || null; +} + /** @typedef {{node: !WebInspector.DOMNode, isCut: boolean}} */ WebInspector.ElementsTreeOutline.ClipboardData; @@ -211,15 +226,24 @@ }, /** + * @param {!Event} event + */ + _onBeforeCopy: function(event) + { + event.handled = true; + }, + + /** * @param {boolean} isCut * @param {!Event} event */ - handleCopyOrCutKeyboardEvent: function(isCut, event) + _onCopyOrCut: function(isCut, event) { this._setClipboardData(null); + var originalEvent = event["original"]; // Don't prevent the normal copy if the user has a selection. - if (!event.target.isComponentSelectionCollapsed()) + if (!originalEvent.target.isComponentSelectionCollapsed()) return; // Do not interfere with text editing. @@ -230,8 +254,8 @@ if (!targetNode) return; - event.clipboardData.clearData(); - event.preventDefault(); + originalEvent.clipboardData.clearData(); + event.handled = true; this.performCopyOrCut(isCut, targetNode); }, @@ -282,7 +306,7 @@ /** * @param {!Event} event */ - handlePasteKeyboardEvent: function(event) + _onPaste: function(event) { // Do not interfere with text editing. if (WebInspector.isEditing()) @@ -292,7 +316,7 @@ if (!targetNode || !this.canPaste(targetNode)) return; - event.preventDefault(); + event.handled = true; this._performPaste(targetNode); }, @@ -1056,6 +1080,7 @@ wireToDOMModel: function() { + this._domModel[WebInspector.ElementsTreeOutline._treeOutlineSymbol] = this; this._domModel.addEventListener(WebInspector.DOMModel.Events.NodeInserted, this._nodeInserted, this); this._domModel.addEventListener(WebInspector.DOMModel.Events.NodeRemoved, this._nodeRemoved, this); this._domModel.addEventListener(WebInspector.DOMModel.Events.AttrModified, this._attributeModified, this); @@ -1076,6 +1101,7 @@ this._domModel.removeEventListener(WebInspector.DOMModel.Events.DocumentUpdated, this._documentUpdated, this); this._domModel.removeEventListener(WebInspector.DOMModel.Events.ChildNodeCountUpdated, this._childNodeCountUpdated, this); this._domModel.removeEventListener(WebInspector.DOMModel.Events.DistributedNodesChanged, this._distributedNodesChanged, this); + delete this._domModel[WebInspector.ElementsTreeOutline._treeOutlineSymbol]; }, /**
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/InspectElementModeController.js b/third_party/WebKit/Source/devtools/front_end/elements/InspectElementModeController.js index e0c4478f..3903fe3b 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/InspectElementModeController.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/InspectElementModeController.js
@@ -40,7 +40,7 @@ this._mode = DOMAgent.InspectMode.None; WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Events.SuspendStateChanged, this._suspendStateChanged, this); - WebInspector.targetManager.observeTargets(this, WebInspector.Target.Type.Page); + WebInspector.targetManager.observeTargets(this, WebInspector.Target.Capability.Browser); } WebInspector.InspectElementModeController.prototype = {
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/PlatformFontsWidget.js b/third_party/WebKit/Source/devtools/front_end/elements/PlatformFontsWidget.js index f4067cf..ed0edd6 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/PlatformFontsWidget.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/PlatformFontsWidget.js
@@ -31,7 +31,7 @@ /** * @constructor * @extends {WebInspector.ThrottledWidget} - * @param {!WebInspector.SharedSidebarModel} sharedModel + * @param {!WebInspector.ComputedStyleModel} sharedModel */ WebInspector.PlatformFontsWidget = function(sharedModel) { @@ -39,7 +39,7 @@ this.registerRequiredCSS("elements/platformFontsWidget.css"); this._sharedModel = sharedModel; - this._sharedModel.addEventListener(WebInspector.SharedSidebarModel.Events.ComputedStyleChanged, this.update, this); + this._sharedModel.addEventListener(WebInspector.ComputedStyleModel.Events.ComputedStyleChanged, this.update, this); this._sectionTitle = createElementWithClass("div", "title"); this.contentElement.appendChild(this._sectionTitle); @@ -48,7 +48,7 @@ } /** - * @param {!WebInspector.SharedSidebarModel} sharedModel + * @param {!WebInspector.ComputedStyleModel} sharedModel * @return {!WebInspector.ElementsSidebarViewWrapperPane} */ WebInspector.PlatformFontsWidget.createSidebarWrapper = function(sharedModel)
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/SharedSidebarModel.js b/third_party/WebKit/Source/devtools/front_end/elements/SharedSidebarModel.js deleted file mode 100644 index 1eb7e82..0000000 --- a/third_party/WebKit/Source/devtools/front_end/elements/SharedSidebarModel.js +++ /dev/null
@@ -1,131 +0,0 @@ -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @extends {WebInspector.Object} - * @constructor - */ -WebInspector.SharedSidebarModel = function() -{ - WebInspector.Object.call(this); - this._node = WebInspector.context.flavor(WebInspector.DOMNode); - WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, this._onNodeChanged, this); -} - -WebInspector.SharedSidebarModel.Events = { - ComputedStyleChanged: "ComputedStyleChanged" -} - -WebInspector.SharedSidebarModel.prototype = { - /** - * @return {?WebInspector.DOMNode} - */ - node: function() - { - return this._node; - }, - - /** - * @return {?WebInspector.CSSModel} - */ - cssModel: function() - { - return this._cssModel; - }, - - /** - * @param {!WebInspector.Event} event - */ - _onNodeChanged: function(event) - { - this._node = /** @type {?WebInspector.DOMNode} */(event.data); - this._updateTarget(this._node ? this._node.target() : null); - this._onComputedStyleChanged(); - }, - - /** - * @param {?WebInspector.Target} target - */ - _updateTarget: function(target) - { - if (this._target === target) - return; - if (this._targetEvents) { - WebInspector.EventTarget.removeEventListeners(this._targetEvents); - this._targetEvents = null; - } - this._target = target; - var domModel = null; - if (target) { - this._cssModel = WebInspector.CSSModel.fromTarget(target); - domModel = WebInspector.DOMModel.fromTarget(target); - } - - if (domModel && this._cssModel) { - this._targetEvents = [ - this._cssModel.addEventListener(WebInspector.CSSModel.Events.StyleSheetAdded, this._onComputedStyleChanged, this), - this._cssModel.addEventListener(WebInspector.CSSModel.Events.StyleSheetRemoved, this._onComputedStyleChanged, this), - this._cssModel.addEventListener(WebInspector.CSSModel.Events.StyleSheetChanged, this._onComputedStyleChanged, this), - this._cssModel.addEventListener(WebInspector.CSSModel.Events.MediaQueryResultChanged, this._onComputedStyleChanged, this), - this._cssModel.addEventListener(WebInspector.CSSModel.Events.PseudoStateForced, this._onComputedStyleChanged, this), - this._cssModel.addEventListener(WebInspector.CSSModel.Events.ModelWasEnabled, this._onComputedStyleChanged, this), - domModel.addEventListener(WebInspector.DOMModel.Events.DOMMutated, this._onComputedStyleChanged, this) - ]; - } - }, - - /** - * @return {?WebInspector.DOMNode} - */ - _elementNode: function() - { - return this.node() ? this.node().enclosingElementOrSelf() : null; - }, - - /** - * @return {!Promise.<?WebInspector.SharedSidebarModel.ComputedStyle>} - */ - fetchComputedStyle: function() - { - var elementNode = this._elementNode(); - var cssModel = this.cssModel(); - if (!elementNode || !cssModel) - return Promise.resolve(/** @type {?WebInspector.SharedSidebarModel.ComputedStyle} */(null)); - - if (!this._computedStylePromise) - this._computedStylePromise = cssModel.computedStylePromise(elementNode.id).then(verifyOutdated.bind(this, elementNode)); - - return this._computedStylePromise; - - /** - * @param {!WebInspector.DOMNode} elementNode - * @param {?Map.<string, string>} style - * @return {?WebInspector.SharedSidebarModel.ComputedStyle} - * @this {WebInspector.SharedSidebarModel} - */ - function verifyOutdated(elementNode, style) - { - return elementNode === this._elementNode() && style ? new WebInspector.SharedSidebarModel.ComputedStyle(elementNode, style) : /** @type {?WebInspector.SharedSidebarModel.ComputedStyle} */(null); - } - }, - - _onComputedStyleChanged: function() - { - delete this._computedStylePromise; - this.dispatchEventToListeners(WebInspector.SharedSidebarModel.Events.ComputedStyleChanged); - }, - - __proto__: WebInspector.Object.prototype -} - -/** - * @constructor - * @param {!WebInspector.DOMNode} node - * @param {!Map.<string, string>} computedStyle - */ -WebInspector.SharedSidebarModel.ComputedStyle = function(node, computedStyle) -{ - this.node = node; - this.computedStyle = computedStyle; -}
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/Spectrum.js b/third_party/WebKit/Source/devtools/front_end/elements/Spectrum.js deleted file mode 100644 index a91e6be..0000000 --- a/third_party/WebKit/Source/devtools/front_end/elements/Spectrum.js +++ /dev/null
@@ -1,1044 +0,0 @@ -/* - * Copyright (C) 2011 Brian Grinstead All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @constructor - * @extends {WebInspector.VBox} - */ -WebInspector.Spectrum = function() -{ - /** - * @param {!Element} parentElement - */ - function appendSwitcherIcon(parentElement) - { - var icon = parentElement.createSVGChild("svg"); - icon.setAttribute("height", 16); - icon.setAttribute("width", 16); - var path = icon.createSVGChild("path"); - path.setAttribute("d", "M5,6 L11,6 L8,2 Z M5,10 L11,10 L8,14 Z"); - return icon; - } - - WebInspector.VBox.call(this, true); - this.registerRequiredCSS("elements/spectrum.css"); - this.contentElement.tabIndex = 0; - - this._colorElement = this.contentElement.createChild("div", "spectrum-color"); - this._colorDragElement = this._colorElement.createChild("div", "spectrum-sat fill").createChild("div", "spectrum-val fill").createChild("div", "spectrum-dragger"); - var contrastRatioSVG = this._colorElement.createSVGChild("svg", "spectrum-contrast-container fill"); - this._contrastRatioLine = contrastRatioSVG.createSVGChild("path", "spectrum-contrast-line"); - - var toolbar = new WebInspector.Toolbar("spectrum-eye-dropper", this.contentElement); - this._colorPickerButton = new WebInspector.ToolbarToggle(WebInspector.UIString("Toggle color picker"), "eyedropper-toolbar-item"); - this._colorPickerButton.setToggled(true); - this._colorPickerButton.addEventListener("click", this._toggleColorPicker.bind(this, undefined)); - toolbar.appendToolbarItem(this._colorPickerButton); - - var swatchElement = this.contentElement.createChild("span", "swatch"); - this._swatchInnerElement = swatchElement.createChild("span", "swatch-inner"); - - this._hueElement = this.contentElement.createChild("div", "spectrum-hue"); - this._hueSlider = this._hueElement.createChild("div", "spectrum-slider"); - this._alphaElement = this.contentElement.createChild("div", "spectrum-alpha"); - this._alphaElementBackground = this._alphaElement.createChild("div", "spectrum-alpha-background"); - this._alphaSlider = this._alphaElement.createChild("div", "spectrum-slider"); - - var displaySwitcher = this.contentElement.createChild("div", "spectrum-display-switcher spectrum-switcher"); - appendSwitcherIcon(displaySwitcher); - displaySwitcher.addEventListener("click", this._formatViewSwitch.bind(this)); - - // RGBA/HSLA display. - this._displayContainer = this.contentElement.createChild("div", "spectrum-text source-code"); - this._textValues = []; - for (var i = 0; i < 4; ++i) { - var inputValue = this._displayContainer.createChild("input", "spectrum-text-value"); - inputValue.maxLength = 4; - this._textValues.push(inputValue); - inputValue.addEventListener("keydown", this._inputChanged.bind(this), false); - inputValue.addEventListener("input", this._inputChanged.bind(this), false); - inputValue.addEventListener("mousewheel", this._inputChanged.bind(this), false); - } - - this._textLabels = this._displayContainer.createChild("div", "spectrum-text-label"); - - // HEX display. - this._hexContainer = this.contentElement.createChild("div", "spectrum-text spectrum-text-hex source-code"); - this._hexValue = this._hexContainer.createChild("input", "spectrum-text-value"); - this._hexValue.maxLength = 9; - this._hexValue.addEventListener("keydown", this._inputChanged.bind(this), false); - this._hexValue.addEventListener("input", this._inputChanged.bind(this), false); - this._hexValue.addEventListener("mousewheel", this._inputChanged.bind(this), false); - - var label = this._hexContainer.createChild("div", "spectrum-text-label"); - label.textContent = "HEX"; - - WebInspector.installDragHandle(this._hueElement, dragStart.bind(this, positionHue.bind(this)), positionHue.bind(this), null, "default"); - WebInspector.installDragHandle(this._alphaElement, dragStart.bind(this, positionAlpha.bind(this)), positionAlpha.bind(this), null, "default"); - WebInspector.installDragHandle(this._colorElement, dragStart.bind(this, positionColor.bind(this)), positionColor.bind(this), null, "default"); - - this.element.classList.add("palettes-enabled"); - /** @type {!Map.<string, !WebInspector.Spectrum.Palette>} */ - this._palettes = new Map(); - this._palettePanel = this.contentElement.createChild("div", "palette-panel"); - this._palettePanelShowing = false; - this._paletteContainer = this.contentElement.createChild("div", "spectrum-palette"); - this._paletteContainer.addEventListener("contextmenu", this._showPaletteColorContextMenu.bind(this, -1)); - this._shadesContainer = this.contentElement.createChild("div", "palette-color-shades hidden"); - WebInspector.installDragHandle(this._paletteContainer, this._paletteDragStart.bind(this), this._paletteDrag.bind(this), this._paletteDragEnd.bind(this), "default"); - var paletteSwitcher = this.contentElement.createChild("div", "spectrum-palette-switcher spectrum-switcher"); - appendSwitcherIcon(paletteSwitcher); - paletteSwitcher.addEventListener("click", this._togglePalettePanel.bind(this, true)); - - this._deleteIconToolbar = new WebInspector.Toolbar("delete-color-toolbar"); - this._deleteButton = new WebInspector.ToolbarButton("", "garbage-collect-toolbar-item"); - this._deleteIconToolbar.appendToolbarItem(this._deleteButton); - - var overlay = this.contentElement.createChild("div", "spectrum-overlay fill"); - overlay.addEventListener("click", this._togglePalettePanel.bind(this, false)); - - this._addColorToolbar = new WebInspector.Toolbar("add-color-toolbar"); - var addColorButton = new WebInspector.ToolbarButton(WebInspector.UIString("Add to palette"), "add-toolbar-item"); - addColorButton.addEventListener("click", this._addColorToCustomPalette.bind(this)); - this._addColorToolbar.appendToolbarItem(addColorButton); - - this._loadPalettes(); - new WebInspector.Spectrum.PaletteGenerator(this._generatedPaletteLoaded.bind(this)); - - /** - * @param {function(!Event)} callback - * @param {!Event} event - * @return {boolean} - * @this {WebInspector.Spectrum} - */ - function dragStart(callback, event) - { - this._hueAlphaLeft = this._hueElement.totalOffsetLeft(); - this._colorOffset = this._colorElement.totalOffset(); - callback(event); - return true; - } - - /** - * @param {!Event} event - * @this {WebInspector.Spectrum} - */ - function positionHue(event) - { - var hsva = this._hsv.slice(); - hsva[0] = Number.constrain(1 - (event.x - this._hueAlphaLeft) / this._hueAlphaWidth, 0, 1); - this._innerSetColor(hsva, "", undefined, WebInspector.Spectrum._ChangeSource.Other); - } - - /** - * @param {!Event} event - * @this {WebInspector.Spectrum} - */ - function positionAlpha(event) - { - var newAlpha = Math.round((event.x - this._hueAlphaLeft) / this._hueAlphaWidth * 100) / 100; - var hsva = this._hsv.slice(); - hsva[3] = Number.constrain(newAlpha, 0, 1); - var colorFormat = undefined; - if (hsva[3] !== 1 && this._colorFormat === WebInspector.Color.Format.Nickname) - colorFormat = WebInspector.Color.Format.HEX; - this._innerSetColor(hsva, "", colorFormat, WebInspector.Spectrum._ChangeSource.Other); - } - - /** - * @param {!Event} event - * @this {WebInspector.Spectrum} - */ - function positionColor(event) - { - var hsva = this._hsv.slice(); - hsva[1] = Number.constrain((event.x - this._colorOffset.left) / this.dragWidth, 0, 1); - hsva[2] = Number.constrain(1 - (event.y - this._colorOffset.top) / this.dragHeight, 0, 1); - this._innerSetColor(hsva, "", undefined, WebInspector.Spectrum._ChangeSource.Other); - } -} - -WebInspector.Spectrum._ChangeSource = { - Input: "Input", - Model: "Model", - Other: "Other" -} - -WebInspector.Spectrum.Events = { - ColorChanged: "ColorChanged", - SizeChanged: "SizeChanged" -}; - -WebInspector.Spectrum._colorChipSize = 24; -WebInspector.Spectrum._itemsPerPaletteRow = 8; - -WebInspector.Spectrum.prototype = { - _updatePalettePanel: function() - { - this._palettePanel.removeChildren(); - var title = this._palettePanel.createChild("div", "palette-title"); - title.textContent = WebInspector.UIString("Color Palettes"); - var toolbar = new WebInspector.Toolbar("", this._palettePanel); - var closeButton = new WebInspector.ToolbarButton("Return to color picker", "delete-toolbar-item"); - closeButton.addEventListener("click", this._togglePalettePanel.bind(this, false)); - toolbar.appendToolbarItem(closeButton); - for (var palette of this._palettes.values()) - this._palettePanel.appendChild(this._createPreviewPaletteElement(palette)); - }, - - /** - * @param {boolean} show - */ - _togglePalettePanel: function(show) - { - if (this._palettePanelShowing === show) - return; - if (show) - this._updatePalettePanel(); - this._focus(); - this._palettePanelShowing = show; - this.contentElement.classList.toggle("palette-panel-showing", show); - }, - - _focus: function() - { - if (this.isShowing() && WebInspector.currentFocusElement() !== this.contentElement) - WebInspector.setCurrentFocusElement(this.contentElement); - }, - - /** - * @param {string} colorText - * @param {number=} animationDelay - * @return {!Element} - */ - _createPaletteColor: function(colorText, animationDelay) - { - var element = createElementWithClass("div", "spectrum-palette-color"); - element.style.background = String.sprintf("linear-gradient(%s, %s), url(Images/checker.png)", colorText, colorText); - if (animationDelay) - element.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 100, delay: animationDelay, fill: "backwards" }); - element.title = colorText; - return element; - }, - - /** - * @param {!WebInspector.Spectrum.Palette} palette - * @param {boolean} animate - * @param {!Event=} event - */ - _showPalette: function(palette, animate, event) - { - this._resizeForSelectedPalette(); - this._paletteContainer.removeChildren(); - for (var i = 0; i < palette.colors.length; i++) { - var animationDelay = animate ? i * 100 / palette.colors.length : 0; - var colorElement = this._createPaletteColor(palette.colors[i], animationDelay); - colorElement.addEventListener("mousedown", this._paletteColorSelected.bind(this, palette.colors[i], palette.matchUserFormat)); - if (palette.mutable) { - colorElement.__mutable = true; - colorElement.__color = palette.colors[i]; - colorElement.addEventListener("contextmenu", this._showPaletteColorContextMenu.bind(this, i)); - } else if (palette === WebInspector.Spectrum.MaterialPalette) { - colorElement.classList.add("has-material-shades"); - var shadow = colorElement.createChild("div", "spectrum-palette-color spectrum-palette-color-shadow"); - shadow.style.background = palette.colors[i]; - shadow = colorElement.createChild("div", "spectrum-palette-color spectrum-palette-color-shadow"); - shadow.style.background = palette.colors[i]; - colorElement.title = WebInspector.UIString(palette.colors[i] + ". Long-click to show alternate shades."); - new WebInspector.LongClickController(colorElement, this._showLightnessShades.bind(this, colorElement, palette.colors[i])); - } - this._paletteContainer.appendChild(colorElement); - } - this._paletteContainerMutable = palette.mutable; - - var numItems = palette.colors.length; - if (palette.mutable) - numItems++; - if (palette.mutable) { - this._paletteContainer.appendChild(this._addColorToolbar.element); - this._paletteContainer.appendChild(this._deleteIconToolbar.element); - } else { - this._addColorToolbar.element.remove(); - this._deleteIconToolbar.element.remove(); - } - - this._togglePalettePanel(false); - this._focus(); - }, - - /** - * @param {!Element} colorElement - * @param {string} colorText - * @param {!Event} event - */ - _showLightnessShades: function(colorElement, colorText, event) - { - /** - * @param {!Element} element - * @this {!WebInspector.Spectrum} - */ - function closeLightnessShades(element) - { - this._shadesContainer.classList.add("hidden"); - element.classList.remove("spectrum-shades-shown"); - this._shadesContainer.ownerDocument.removeEventListener("mousedown", this._shadesCloseHandler, true); - delete this._shadesCloseHandler; - } - - if (this._shadesCloseHandler) - this._shadesCloseHandler(); - - this._shadesContainer.classList.remove("hidden"); - this._shadesContainer.removeChildren(); - this._shadesContainer.animate([{ transform: "scaleY(0)", opacity: "0" }, { transform: "scaleY(1)", opacity: "1" }], { duration: 200, easing: "cubic-bezier(0.4, 0, 0.2, 1)" }); - this._shadesContainer.style.top = colorElement.offsetTop + colorElement.parentElement.offsetTop + "px"; - this._shadesContainer.style.left = colorElement.offsetLeft + "px"; - colorElement.classList.add("spectrum-shades-shown"); - - var shades = WebInspector.Spectrum.MaterialPaletteShades[colorText]; - for (var i = shades.length - 1; i >= 0; i--) { - var shadeElement = this._createPaletteColor(shades[i], i * 200 / shades.length + 100); - shadeElement.addEventListener("mousedown", this._paletteColorSelected.bind(this, shades[i], false)); - this._shadesContainer.appendChild(shadeElement); - } - - WebInspector.setCurrentFocusElement(this._shadesContainer); - this._shadesCloseHandler = closeLightnessShades.bind(this, colorElement); - this._shadesContainer.ownerDocument.addEventListener("mousedown", this._shadesCloseHandler, true); - }, - - /** - * @param {!Event} e - * @return {number} - */ - _slotIndexForEvent: function(e) - { - var localX = e.pageX - this._paletteContainer.totalOffsetLeft(); - var localY = e.pageY - this._paletteContainer.totalOffsetTop(); - var col = Math.min(localX / WebInspector.Spectrum._colorChipSize | 0, WebInspector.Spectrum._itemsPerPaletteRow - 1); - var row = (localY / WebInspector.Spectrum._colorChipSize) | 0; - return Math.min(row * WebInspector.Spectrum._itemsPerPaletteRow + col, this._customPaletteSetting.get().colors.length - 1); - }, - - /** - * @param {!Event} e - * @return {boolean} - */ - _isDraggingToBin: function(e) - { - return e.pageX > this._deleteIconToolbar.element.totalOffsetLeft(); - }, - - /** - * @param {!Event} e - * @return {boolean} - */ - _paletteDragStart: function(e) - { - var element = e.deepElementFromPoint(); - if (!element || !element.__mutable) - return false; - - var index = this._slotIndexForEvent(e); - this._dragElement = element; - this._dragHotSpotX = e.pageX - (index % WebInspector.Spectrum._itemsPerPaletteRow) * WebInspector.Spectrum._colorChipSize; - this._dragHotSpotY = e.pageY - (index / WebInspector.Spectrum._itemsPerPaletteRow | 0) * WebInspector.Spectrum._colorChipSize; - return true; - }, - - /** - * @param {!Event} e - */ - _paletteDrag: function(e) - { - if (e.pageX < this._paletteContainer.totalOffsetLeft() || e.pageY < this._paletteContainer.totalOffsetTop()) - return; - var newIndex = this._slotIndexForEvent(e); - var offsetX = e.pageX - (newIndex % WebInspector.Spectrum._itemsPerPaletteRow) * WebInspector.Spectrum._colorChipSize; - var offsetY = e.pageY - (newIndex / WebInspector.Spectrum._itemsPerPaletteRow | 0) * WebInspector.Spectrum._colorChipSize; - - var isDeleting = this._isDraggingToBin(e); - this._deleteIconToolbar.element.classList.add("dragging"); - this._deleteIconToolbar.element.classList.toggle("delete-color-toolbar-active", isDeleting); - var dragElementTransform = "translateX(" + (offsetX - this._dragHotSpotX) + "px) translateY(" + (offsetY - this._dragHotSpotY) + "px)"; - this._dragElement.style.transform = isDeleting ? dragElementTransform + " scale(0.8)" : dragElementTransform; - var children = Array.prototype.slice.call(this._paletteContainer.children); - var index = children.indexOf(this._dragElement); - /** @type {!Map.<!Element, {left: number, top: number}>} */ - var swatchOffsets = new Map(); - for (var swatch of children) - swatchOffsets.set(swatch, swatch.totalOffset()); - - if (index !== newIndex) - this._paletteContainer.insertBefore(this._dragElement, children[newIndex > index ? newIndex + 1 : newIndex]); - - for (var swatch of children) { - if (swatch === this._dragElement) - continue; - var before = swatchOffsets.get(swatch); - var after = swatch.totalOffset(); - if (before.left !== after.left || before.top !== after.top) { - swatch.animate([ - { transform: "translateX(" + (before.left - after.left) + "px) translateY(" + (before.top - after.top) + "px)" }, - { transform: "none" }], { duration: 100, easing: "cubic-bezier(0, 0, 0.2, 1)" }); - } - } - }, - - /** - * @param {!Event} e - */ - _paletteDragEnd: function(e) - { - if (this._isDraggingToBin(e)) - this._dragElement.remove(); - this._dragElement.style.removeProperty("transform"); - var children = this._paletteContainer.children; - var colors = []; - for (var i = 0; i < children.length; ++i) { - if (children[i].__color) - colors.push(children[i].__color); - } - var palette = this._customPaletteSetting.get(); - palette.colors = colors; - this._customPaletteSetting.set(palette); - this._showPalette(this._customPaletteSetting.get(), false); - - this._deleteIconToolbar.element.classList.remove("dragging"); - this._deleteIconToolbar.element.classList.remove("delete-color-toolbar-active"); - }, - - _loadPalettes: function() - { - this._palettes.set(WebInspector.Spectrum.MaterialPalette.title, WebInspector.Spectrum.MaterialPalette); - /** @type {!WebInspector.Spectrum.Palette} */ - var defaultCustomPalette = { title: "Custom", colors: [], mutable: true }; - this._customPaletteSetting = WebInspector.settings.createSetting("customColorPalette", defaultCustomPalette); - this._palettes.set(this._customPaletteSetting.get().title, this._customPaletteSetting.get()); - - this._selectedColorPalette = WebInspector.settings.createSetting("selectedColorPalette", WebInspector.Spectrum.GeneratedPaletteTitle); - var palette = this._palettes.get(this._selectedColorPalette.get()); - if (palette) - this._showPalette(palette, true); - }, - - /** - * @param {!WebInspector.Spectrum.Palette} generatedPalette - */ - _generatedPaletteLoaded: function(generatedPalette) - { - if (generatedPalette.colors.length) - this._palettes.set(generatedPalette.title, generatedPalette); - if (this._selectedColorPalette.get() !== generatedPalette.title) { - return; - } else if (!generatedPalette.colors.length) { - this._paletteSelected(WebInspector.Spectrum.MaterialPalette); - return; - } - this._showPalette(generatedPalette, true); - }, - - /** - * @param {!WebInspector.Spectrum.Palette} palette - * @return {!Element} - */ - _createPreviewPaletteElement: function(palette) - { - var colorsPerPreviewRow = 5; - var previewElement = createElementWithClass("div", "palette-preview"); - var titleElement = previewElement.createChild("div", "palette-preview-title"); - titleElement.textContent = palette.title; - for (var i = 0; i < colorsPerPreviewRow && i < palette.colors.length; i++) - previewElement.appendChild(this._createPaletteColor(palette.colors[i])); - for (; i < colorsPerPreviewRow; i++) - previewElement.createChild("div", "spectrum-palette-color empty-color"); - previewElement.addEventListener("click", this._paletteSelected.bind(this, palette)); - return previewElement; - }, - - /** - * @param {!WebInspector.Spectrum.Palette} palette - */ - _paletteSelected: function(palette) - { - this._selectedColorPalette.set(palette.title); - this._showPalette(palette, true); - }, - - _resizeForSelectedPalette: function() - { - var palette = this._palettes.get(this._selectedColorPalette.get()); - if (!palette) - return; - var numColors = palette.colors.length; - if (palette === this._customPaletteSetting.get()) - numColors++; - var rowsNeeded = Math.max(1, Math.ceil(numColors / WebInspector.Spectrum._itemsPerPaletteRow)); - if (this._numPaletteRowsShown === rowsNeeded) - return; - this._numPaletteRowsShown = rowsNeeded; - var paletteColorHeight = 12; - var paletteMargin = 12; - var paletteTop = 235; - this.element.style.height = (paletteTop + paletteMargin + (paletteColorHeight + paletteMargin) * rowsNeeded) + "px"; - this.dispatchEventToListeners(WebInspector.Spectrum.Events.SizeChanged); - }, - - /** - * @param {string} colorText - * @param {boolean} matchUserFormat - */ - _paletteColorSelected: function(colorText, matchUserFormat) - { - var color = WebInspector.Color.parse(colorText); - if (!color) - return; - this._innerSetColor(color.hsva(), colorText, matchUserFormat ? this._colorFormat : color.format(), WebInspector.Spectrum._ChangeSource.Other); - }, - - _addColorToCustomPalette: function() - { - var palette = this._customPaletteSetting.get(); - palette.colors.push(this.colorString()); - this._customPaletteSetting.set(palette); - this._showPalette(this._customPaletteSetting.get(), false); - }, - - /** - * @param {number} colorIndex - * @param {!Event} event - */ - _showPaletteColorContextMenu: function(colorIndex, event) - { - if (!this._paletteContainerMutable) - return; - var contextMenu = new WebInspector.ContextMenu(event); - if (colorIndex !== -1) { - contextMenu.appendItem(WebInspector.UIString("Remove color"), this._deletePaletteColors.bind(this, colorIndex, false)); - contextMenu.appendItem(WebInspector.UIString("Remove all to the right"), this._deletePaletteColors.bind(this, colorIndex, true)); - } - contextMenu.appendItem(WebInspector.UIString("Clear palette"), this._deletePaletteColors.bind(this, -1, true)); - contextMenu.show(); - }, - - /** - * @param {number} colorIndex - * @param {boolean} toRight - */ - _deletePaletteColors: function(colorIndex, toRight) - { - var palette = this._customPaletteSetting.get(); - if (toRight) - palette.colors.splice(colorIndex + 1, palette.colors.length - colorIndex - 1); - else - palette.colors.splice(colorIndex, 1); - this._customPaletteSetting.set(palette); - this._showPalette(this._customPaletteSetting.get(), false); - }, - - /** - * @param {!WebInspector.Color} color - * @param {string} colorFormat - */ - setColor: function(color, colorFormat) - { - this._originalFormat = colorFormat; - this._innerSetColor(color.hsva(), "", colorFormat, WebInspector.Spectrum._ChangeSource.Model); - }, - - /** - * @param {!Array<number>|undefined} hsva - * @param {string|undefined} colorString - * @param {string|undefined} colorFormat - * @param {string} changeSource - */ - _innerSetColor: function(hsva, colorString, colorFormat, changeSource) - { - if (hsva !== undefined) - this._hsv = hsva; - if (colorString !== undefined) - this._colorString = colorString; - if (colorFormat !== undefined) { - var cf = WebInspector.Color.Format; - console.assert(colorFormat !== cf.Original, "Spectrum's color format cannot be Original"); - if (colorFormat === cf.RGBA) - colorFormat = cf.RGB; - else if (colorFormat === cf.HSLA) - colorFormat = cf.HSL; - else if (colorFormat === cf.HEXA) - colorFormat = cf.HEX; - else if (colorFormat === cf.ShortHEXA) - colorFormat = cf.ShortHEX; - this._colorFormat = colorFormat; - } - - this._updateHelperLocations(); - this._updateUI(); - - if (changeSource !== WebInspector.Spectrum._ChangeSource.Input) - this._updateInput(); - if (changeSource !== WebInspector.Spectrum._ChangeSource.Model) - this.dispatchEventToListeners(WebInspector.Spectrum.Events.ColorChanged, this.colorString()); - }, - - /** - * @param {!WebInspector.Color} color - */ - setContrastColor: function(color) - { - this._contrastColor = color; - this._updateUI(); - }, - - /** - * @return {!WebInspector.Color} - */ - _color: function() - { - return WebInspector.Color.fromHSVA(this._hsv); - }, - - /** - * @return {string} - */ - colorString: function() - { - if (this._colorString) - return this._colorString; - var cf = WebInspector.Color.Format; - var color = this._color(); - var colorString = color.asString(this._colorFormat); - if (colorString) - return colorString; - - if (this._colorFormat === cf.Nickname) { - colorString = color.asString(cf.HEX); - if (colorString) - return colorString; - } - - if (this._colorFormat === cf.ShortHEX) - colorString = color.asString(color.detectHEXFormat()); - else if (this._colorFormat === cf.HEX) - colorString = color.asString(color.hasAlpha() ? cf.HEXA : cf.HEX); - else if (this._colorFormat === cf.HSL) - colorString = color.asString(cf.HSLA); - else - colorString = color.asString(cf.RGBA); - - console.assert(colorString); - return colorString || ""; - }, - - _updateHelperLocations: function() - { - var h = this._hsv[0]; - var s = this._hsv[1]; - var v = this._hsv[2]; - var alpha = this._hsv[3]; - - // Where to show the little circle that displays your current selected color. - var dragX = s * this.dragWidth; - var dragY = this.dragHeight - (v * this.dragHeight); - - dragX = Math.max(-this._colorDragElementHeight, - Math.min(this.dragWidth - this._colorDragElementHeight, dragX - this._colorDragElementHeight)); - dragY = Math.max(-this._colorDragElementHeight, - Math.min(this.dragHeight - this._colorDragElementHeight, dragY - this._colorDragElementHeight)); - - this._colorDragElement.positionAt(dragX, dragY); - - // Where to show the bar that displays your current selected hue. - var hueSlideX = (1 - h) * this._hueAlphaWidth - this.slideHelperWidth; - this._hueSlider.style.left = hueSlideX + "px"; - var alphaSlideX = alpha * this._hueAlphaWidth - this.slideHelperWidth; - this._alphaSlider.style.left = alphaSlideX + "px"; - }, - - _updateInput: function() - { - var cf = WebInspector.Color.Format; - if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX || this._colorFormat === cf.Nickname) { - this._hexContainer.hidden = false; - this._displayContainer.hidden = true; - if (this._colorFormat === cf.ShortHEX) - this._hexValue.value = this._color().asString(this._color().detectHEXFormat()); - else - // Don't use short HEX if original was not in that format. - this._hexValue.value = this._color().asString(this._color().hasAlpha() ? cf.HEXA : cf.HEX); - } else { - // RGBA, HSLA display. - this._hexContainer.hidden = true; - this._displayContainer.hidden = false; - var isRgb = this._colorFormat === cf.RGB; - this._textLabels.textContent = isRgb ? "RGBA" : "HSLA"; - var colorValues = isRgb ? this._color().canonicalRGBA() : this._color().canonicalHSLA(); - for (var i = 0; i < 3; ++i) { - this._textValues[i].value = colorValues[i]; - if (!isRgb && (i === 1 || i === 2)) - this._textValues[i].value += "%"; - } - this._textValues[3].value = Math.round(colorValues[3] * 100) / 100; - } - }, - - /** - * @param {number} requiredContrast - */ - _drawContrastRatioLine: function(requiredContrast) - { - if (!this._contrastColor || !this.dragWidth || !this.dragHeight) - return; - - /** const */ var width = this.dragWidth; - /** const */ var height = this.dragHeight; - /** const */ var dS = 0.02; - /** const */ var epsilon = 0.002; - /** const */ var H = 0; - /** const */ var S = 1; - /** const */ var V = 2; - /** const */ var A = 3; - - var fgRGBA = []; - WebInspector.Color.hsva2rgba(this._hsv, fgRGBA); - var fgLuminance = WebInspector.Color.luminance(fgRGBA); - var bgRGBA = this._contrastColor.rgba(); - var bgLuminance = WebInspector.Color.luminance(bgRGBA); - var fgIsLighter = fgLuminance > bgLuminance; - var desiredLuminance = WebInspector.Color.desiredLuminance(bgLuminance, requiredContrast, fgIsLighter); - - var lastV = this._hsv[V]; - var currentSlope = 0; - var candidateHSVA = [this._hsv[H], 0, 0, this._hsv[A]]; - var pathBuilder = []; - var candidateRGBA = []; - WebInspector.Color.hsva2rgba(candidateHSVA, candidateRGBA); - var blendedRGBA = []; - WebInspector.Color.blendColors(candidateRGBA, bgRGBA, blendedRGBA); - - /** - * Approach the desired contrast ratio by modifying the given component - * from the given starting value. - * @param {number} index - * @param {number} x - * @param {boolean} onAxis - * @return {?number} - */ - function approach(index, x, onAxis) - { - while (0 <= x && x <= 1) { - candidateHSVA[index] = x; - WebInspector.Color.hsva2rgba(candidateHSVA, candidateRGBA); - WebInspector.Color.blendColors(candidateRGBA, bgRGBA, blendedRGBA); - var fgLuminance = WebInspector.Color.luminance(blendedRGBA); - var dLuminance = fgLuminance - desiredLuminance; - - if (Math.abs(dLuminance) < (onAxis ? epsilon / 10 : epsilon)) - return x; - else - x += (index === V ? -dLuminance : dLuminance); - } - return null; - } - - for (var s = 0; s < 1 + dS; s += dS) { - s = Math.min(1, s); - candidateHSVA[S] = s; - - var v = lastV; - v = lastV + currentSlope * dS; - - v = approach(V, v, s === 0); - if (v === null) - break; - - currentSlope = (v - lastV) / dS; - - pathBuilder.push(pathBuilder.length ? "L" : "M"); - pathBuilder.push(s * width); - pathBuilder.push((1 - v) * height); - } - - if (s < 1 + dS) { - s -= dS; - candidateHSVA[V] = 1; - s = approach(S, s, true); - if (s !== null) - pathBuilder = pathBuilder.concat(["L", s * width, -1]) - } - - this._contrastRatioLine.setAttribute("d", pathBuilder.join(" ")); - }, - - _updateUI: function() - { - var h = WebInspector.Color.fromHSVA([this._hsv[0], 1, 1, 1]); - this._colorElement.style.backgroundColor = /** @type {string} */ (h.asString(WebInspector.Color.Format.RGB)); - if (Runtime.experiments.isEnabled("colorContrastRatio")) { - // TODO(samli): Determine size of text and switch between AA/AAA ratings. - this._drawContrastRatioLine(4.5); - } - this._swatchInnerElement.style.backgroundColor = /** @type {string} */ (this._color().asString(WebInspector.Color.Format.RGBA)); - // Show border if the swatch is white. - this._swatchInnerElement.classList.toggle("swatch-inner-white", this._color().hsla()[2] > 0.9); - this._colorDragElement.style.backgroundColor = /** @type {string} */ (this._color().asString(WebInspector.Color.Format.RGBA)); - var noAlpha = WebInspector.Color.fromHSVA(this._hsv.slice(0,3).concat(1)); - this._alphaElementBackground.style.backgroundImage = String.sprintf("linear-gradient(to right, rgba(0,0,0,0), %s)", noAlpha.asString(WebInspector.Color.Format.RGB)); - }, - - _formatViewSwitch: function() - { - var cf = WebInspector.Color.Format; - var format = cf.RGB; - if (this._colorFormat === cf.RGB) - format = cf.HSL; - else if (this._colorFormat === cf.HSL) - format = this._originalFormat === cf.ShortHEX ? cf.ShortHEX : cf.HEX; - this._innerSetColor(undefined, "", format, WebInspector.Spectrum._ChangeSource.Other); - }, - - /** - * @param {!Event} event - */ - _inputChanged: function(event) - { - /** - * @param {!Element} element - * @return {string} - */ - function elementValue(element) - { - return element.value; - } - - var inputElement = /** @type {!Element} */(event.currentTarget); - var arrowKeyOrMouseWheelEvent = (event.key === "ArrowUp" || event.key === "ArrowDown" || event.type === "mousewheel"); - var pageKeyPressed = (event.key === "PageUp" || event.key === "PageDown"); - if (arrowKeyOrMouseWheelEvent || pageKeyPressed) { - var newValue = WebInspector.createReplacementString(inputElement.value, event); - if (newValue) { - inputElement.value = newValue; - inputElement.selectionStart = 0; - inputElement.selectionEnd = newValue.length; - } - event.consume(true); - } - - const cf = WebInspector.Color.Format; - var colorString; - if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX) { - colorString = this._hexValue.value; - } else { - var format = this._colorFormat === cf.RGB ? "rgba" : "hsla"; - var values = this._textValues.map(elementValue).join(","); - colorString = String.sprintf("%s(%s)", format, values); - } - - var color = WebInspector.Color.parse(colorString); - if (!color) - return; - var hsv = color.hsva(); - if (this._colorFormat === cf.HEX || this._colorFormat === cf.ShortHEX) - this._colorFormat = color.detectHEXFormat(); - this._innerSetColor(hsv, colorString, undefined, WebInspector.Spectrum._ChangeSource.Input); - }, - - wasShown: function() - { - this._hueAlphaWidth = this._hueElement.offsetWidth; - this.slideHelperWidth = this._hueSlider.offsetWidth / 2; - this.dragWidth = this._colorElement.offsetWidth; - this.dragHeight = this._colorElement.offsetHeight; - this._colorDragElementHeight = this._colorDragElement.offsetHeight / 2; - this._innerSetColor(undefined, undefined, undefined, WebInspector.Spectrum._ChangeSource.Model); - this._toggleColorPicker(true); - WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.EventTypes.ColorPicked, this._colorPicked, this); - }, - - willHide: function() - { - this._toggleColorPicker(false); - WebInspector.targetManager.removeModelListener(WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.EventTypes.ColorPicked, this._colorPicked, this); - }, - - /** - * @param {boolean=} enabled - * @param {!WebInspector.Event=} event - */ - _toggleColorPicker: function(enabled, event) - { - if (enabled === undefined) - enabled = !this._colorPickerButton.toggled(); - this._colorPickerButton.setToggled(enabled); - for (var target of WebInspector.targetManager.targets()) - target.pageAgent().setColorPickerEnabled(enabled); - }, - - /** - * @param {!WebInspector.Event} event - */ - _colorPicked: function(event) - { - var rgbColor = /** @type {!DOMAgent.RGBA} */ (event.data); - var rgba = [rgbColor.r, rgbColor.g, rgbColor.b, (rgbColor.a / 2.55 | 0) / 100]; - var color = WebInspector.Color.fromRGBA(rgba); - this._innerSetColor(color.hsva(), "", undefined, WebInspector.Spectrum._ChangeSource.Other); - InspectorFrontendHost.bringToFront(); - }, - - - __proto__: WebInspector.VBox.prototype -} - -/** @typedef {{ title: string, colors: !Array.<string>, mutable: boolean }} */ -WebInspector.Spectrum.Palette; -WebInspector.Spectrum.GeneratedPaletteTitle = "Page colors"; - -/** - * @constructor - * @param {function(!WebInspector.Spectrum.Palette)} callback - */ -WebInspector.Spectrum.PaletteGenerator = function(callback) -{ - this._callback = callback; - /** @type {!Map.<string, number>} */ - this._frequencyMap = new Map(); - var stylesheetPromises = []; - for (var target of WebInspector.targetManager.targets(WebInspector.Target.Type.Page)) { - var cssModel = WebInspector.CSSModel.fromTarget(target); - for (var stylesheet of cssModel.allStyleSheets()) - stylesheetPromises.push(new Promise(this._processStylesheet.bind(this, stylesheet))); - } - Promise.all(stylesheetPromises) - .catchException(null) - .then(this._finish.bind(this)); -} - -WebInspector.Spectrum.PaletteGenerator.prototype = { - /** - * @param {string} a - * @param {string} b - * @return {number} - */ - _frequencyComparator: function(a, b) - { - return this._frequencyMap.get(b) - this._frequencyMap.get(a); - }, - - _finish: function() - { - /** - * @param {string} a - * @param {string} b - * @return {number} - */ - function hueComparator(a, b) - { - var hsva = paletteColors.get(a).hsva(); - var hsvb = paletteColors.get(b).hsva(); - - // First trim the shades of gray - if (hsvb[1] < 0.12 && hsva[1] < 0.12) - return hsvb[2] * hsvb[3] - hsva[2] * hsva[3]; - if (hsvb[1] < 0.12) - return -1; - if (hsva[1] < 0.12) - return 1; - - // Equal hue -> sort by sat - if (hsvb[0] === hsva[0]) - return hsvb[1] * hsvb[3] - hsva[1] * hsva[3]; - - return (hsvb[0] + 0.94) % 1 - (hsva[0] + 0.94) % 1; - } - - var colors = this._frequencyMap.keysArray(); - colors = colors.sort(this._frequencyComparator.bind(this)); - /** @type {!Map.<string, !WebInspector.Color>} */ - var paletteColors = new Map(); - var colorsPerRow = 24; - while (paletteColors.size < colorsPerRow && colors.length) { - var colorText = colors.shift(); - var color = WebInspector.Color.parse(colorText); - if (!color || color.nickname() === "white" || color.nickname() === "black") - continue; - paletteColors.set(colorText, color); - } - - this._callback({ title: WebInspector.Spectrum.GeneratedPaletteTitle, colors: paletteColors.keysArray().sort(hueComparator), mutable: false }); - }, - - /** - * @param {!WebInspector.CSSStyleSheetHeader} stylesheet - * @param {function(?)} resolve - * @this {WebInspector.Spectrum.PaletteGenerator} - */ - _processStylesheet: function(stylesheet, resolve) - { - /** - * @param {?string} text - * @this {WebInspector.Spectrum.PaletteGenerator} - */ - function parseContent(text) - { - text = text.toLowerCase(); - var regexResult = text.match(/((?:rgb|hsl)a?\([^)]+\)|#[0-9a-f]{6}|#[0-9a-f]{3})/g) || []; - for (var c of regexResult) { - var frequency = this._frequencyMap.get(c) || 0; - this._frequencyMap.set(c, ++frequency); - } - resolve(null); - } - - stylesheet.requestContent().then(parseContent.bind(this)); - } -} - -WebInspector.Spectrum.MaterialPaletteShades = { - "#F44336": ["#FFEBEE", "#FFCDD2", "#EF9A9A", "#E57373", "#EF5350", "#F44336", "#E53935", "#D32F2F", "#C62828", "#B71C1C"], - "#E91E63": ["#FCE4EC", "#F8BBD0", "#F48FB1", "#F06292", "#EC407A", "#E91E63", "#D81B60", "#C2185B", "#AD1457", "#880E4F"], - "#9C27B0": ["#F3E5F5", "#E1BEE7", "#CE93D8", "#BA68C8", "#AB47BC", "#9C27B0", "#8E24AA", "#7B1FA2", "#6A1B9A", "#4A148C"], - "#673AB7": ["#EDE7F6", "#D1C4E9", "#B39DDB", "#9575CD", "#7E57C2", "#673AB7", "#5E35B1", "#512DA8", "#4527A0", "#311B92"], - "#3F51B5": ["#E8EAF6", "#C5CAE9", "#9FA8DA", "#7986CB", "#5C6BC0", "#3F51B5", "#3949AB", "#303F9F", "#283593", "#1A237E"], - "#2196F3": ["#E3F2FD", "#BBDEFB", "#90CAF9", "#64B5F6", "#42A5F5", "#2196F3", "#1E88E5", "#1976D2", "#1565C0", "#0D47A1"], - "#03A9F4": ["#E1F5FE", "#B3E5FC", "#81D4FA", "#4FC3F7", "#29B6F6", "#03A9F4", "#039BE5", "#0288D1", "#0277BD", "#01579B"], - "#00BCD4": ["#E0F7FA", "#B2EBF2", "#80DEEA", "#4DD0E1", "#26C6DA", "#00BCD4", "#00ACC1", "#0097A7", "#00838F", "#006064"], - "#009688": ["#E0F2F1", "#B2DFDB", "#80CBC4", "#4DB6AC", "#26A69A", "#009688", "#00897B", "#00796B", "#00695C", "#004D40"], - "#4CAF50": ["#E8F5E9", "#C8E6C9", "#A5D6A7", "#81C784", "#66BB6A", "#4CAF50", "#43A047", "#388E3C", "#2E7D32", "#1B5E20"], - "#8BC34A": ["#F1F8E9", "#DCEDC8", "#C5E1A5", "#AED581", "#9CCC65", "#8BC34A", "#7CB342", "#689F38", "#558B2F", "#33691E"], - "#CDDC39": ["#F9FBE7", "#F0F4C3", "#E6EE9C", "#DCE775", "#D4E157", "#CDDC39", "#C0CA33", "#AFB42B", "#9E9D24", "#827717"], - "#FFEB3B": ["#FFFDE7", "#FFF9C4", "#FFF59D", "#FFF176", "#FFEE58", "#FFEB3B", "#FDD835", "#FBC02D", "#F9A825", "#F57F17"], - "#FFC107": ["#FFF8E1", "#FFECB3", "#FFE082", "#FFD54F", "#FFCA28", "#FFC107", "#FFB300", "#FFA000", "#FF8F00", "#FF6F00"], - "#FF9800": ["#FFF3E0", "#FFE0B2", "#FFCC80", "#FFB74D", "#FFA726", "#FF9800", "#FB8C00", "#F57C00", "#EF6C00", "#E65100"], - "#FF5722": ["#FBE9E7", "#FFCCBC", "#FFAB91", "#FF8A65", "#FF7043", "#FF5722", "#F4511E", "#E64A19", "#D84315", "#BF360C"], - "#795548": ["#EFEBE9", "#D7CCC8", "#BCAAA4", "#A1887F", "#8D6E63", "#795548", "#6D4C41", "#5D4037", "#4E342E", "#3E2723"], - "#9E9E9E": ["#FAFAFA", "#F5F5F5", "#EEEEEE", "#E0E0E0", "#BDBDBD", "#9E9E9E", "#757575", "#616161", "#424242", "#212121"], - "#607D8B": ["#ECEFF1", "#CFD8DC", "#B0BEC5", "#90A4AE", "#78909C", "#607D8B", "#546E7A", "#455A64", "#37474F", "#263238"] -}; - -WebInspector.Spectrum.MaterialPalette = { title: "Material", mutable: false, matchUserFormat: true, colors: Object.keys(WebInspector.Spectrum.MaterialPaletteShades) };
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js index 4304ea08..3b98d61 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSidebarPane.js
@@ -50,6 +50,7 @@ /** @type {!Array<!WebInspector.SectionBlock>} */ this._sectionBlocks = []; + WebInspector.StylesSidebarPane._instance = this; WebInspector.targetManager.addModelListener(WebInspector.CSSModel, WebInspector.CSSModel.Events.LayoutEditorChange, this._onLayoutEditorChange, this); } @@ -241,26 +242,26 @@ { this._discardElementUnderMouse(); - return this.fetchMatchedCascade() + return this._fetchMatchedCascade() .then(this._innerRebuildUpdate.bind(this)); }, _resetCache: function() { - delete this._matchedCascadePromise; + if (this.cssModel()) + this.cssModel().discardCachedMatchedCascade(); }, /** * @return {!Promise.<?WebInspector.CSSMatchedStyles>} */ - fetchMatchedCascade: function() + _fetchMatchedCascade: function() { var node = this.node(); - if (!node) + if (!node || !this.cssModel()) return Promise.resolve(/** @type {?WebInspector.CSSMatchedStyles} */(null)); - if (!this._matchedCascadePromise) - this._matchedCascadePromise = this._matchedStylesForNode(node).then(validateStyles.bind(this)); - return this._matchedCascadePromise; + + return this.cssModel().cachedMatchedCascadeForNode(node).then(validateStyles.bind(this)); /** * @param {?WebInspector.CSSMatchedStyles} matchedStyles @@ -274,18 +275,6 @@ }, /** - * @param {!WebInspector.DOMNode} node - * @return {!Promise.<?WebInspector.CSSMatchedStyles>} - */ - _matchedStylesForNode: function(node) - { - var cssModel = this.cssModel(); - if (!cssModel) - return Promise.resolve(/** @type {?WebInspector.CSSMatchedStyles} */(null)); - return cssModel.matchedStylesPromise(node.id) - }, - - /** * @param {boolean} editing */ setEditingStyle: function(editing) @@ -3124,23 +3113,50 @@ } } - /** - * @return {!WebInspector.ToolbarItem} + * @constructor + * @implements {WebInspector.ToolbarItem.Provider} */ -WebInspector.StylesSidebarPane.createAddNewRuleButton = function(stylesSidebarPane) +WebInspector.StylesSidebarPane.ButtonProvider = function() { - var button = new WebInspector.ToolbarButton(WebInspector.UIString("New Style Rule"), "add-toolbar-item"); - button.addEventListener("click", stylesSidebarPane._createNewRuleInViaInspectorStyleSheet, stylesSidebarPane); - button.element.createChild("div", "long-click-glyph toolbar-button-theme"); - new WebInspector.LongClickController(button.element, stylesSidebarPane._onAddButtonLongClick.bind(stylesSidebarPane)); - WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, onNodeChanged); - onNodeChanged(); - return button; + this._button = new WebInspector.ToolbarButton(WebInspector.UIString("New Style Rule"), "add-toolbar-item"); + this._button.addEventListener("click", this._clicked, this); + this._button.element.createChild("div", "long-click-glyph toolbar-button-theme"); + new WebInspector.LongClickController(this._button.element, this._longClicked.bind(this)); + WebInspector.context.addFlavorChangeListener(WebInspector.DOMNode, onNodeChanged.bind(this)); + onNodeChanged.call(this); + /** + * @this {WebInspector.StylesSidebarPane.ButtonProvider} + */ function onNodeChanged() { var node = WebInspector.context.flavor(WebInspector.DOMNode); - button.setEnabled(!!node); + node = node ? node.enclosingElementOrSelf() : null; + this._button.setEnabled(!!node); + } +} + +WebInspector.StylesSidebarPane.ButtonProvider.prototype = { + _clicked: function() + { + WebInspector.StylesSidebarPane._instance._createNewRuleInViaInspectorStyleSheet(); + }, + + /** + * @param {!Event} e + */ + _longClicked: function(e) + { + WebInspector.StylesSidebarPane._instance._onAddButtonLongClick(e); + }, + + /** + * @override + * @return {!WebInspector.ToolbarItem} + */ + item: function() + { + return this._button; } }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/module.json b/third_party/WebKit/Source/devtools/front_end/elements/module.json index f0cb659..63fd0cb3 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/module.json +++ b/third_party/WebKit/Source/devtools/front_end/elements/module.json
@@ -21,6 +21,11 @@ "type": "@WebInspector.Revealer", "contextTypes": ["WebInspector.DOMNode", "WebInspector.DeferredDOMNode", "WebInspector.RemoteObject" ], "className": "WebInspector.ElementsPanel.DOMNodeRevealer" + }, + { + "type": "@WebInspector.Revealer", + "contextTypes": ["WebInspector.CSSProperty" ], + "className": "WebInspector.ElementsPanel.CSSPropertyRevealer" }, { "type": "setting", @@ -81,6 +86,12 @@ "location": "styles-sidebarpane-toolbar" }, { + "type": "@WebInspector.ToolbarItem.Provider", + "className": "WebInspector.StylesSidebarPane.ButtonProvider", + "order": 100, + "location": "styles-sidebarpane-toolbar" + }, + { "type": "@WebInspector.ActionDelegate", "actionId": "elements.hide-element", "contextTypes": ["WebInspector.ElementsPanel"], @@ -154,13 +165,12 @@ "BezierUI.js", "StylesPopoverHelper.js", "BezierEditor.js", - "Spectrum.js", + "ComputedStyleModel.js", "ElementsBreadcrumbs.js", "ElementsSidebarPane.js", "ElementsSidebarView.js", "ElementsTreeElement.js", "ElementsTreeOutline.js", - "SharedSidebarModel.js", "EventListenersWidget.js", "MetricsSidebarPane.js", "PlatformFontsWidget.js", @@ -179,7 +189,6 @@ "computedStyleSidebarPane.css", "elementsPanel.css", "elementsTreeOutline.css", - "spectrum.css", "platformFontsWidget.css" ] }
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js index 2e5c1b5..ca3bb5c 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js +++ b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceModeModel.js
@@ -61,7 +61,7 @@ this._target = null; /** @type {?function()} */ this._onTargetAvailable = null; - WebInspector.targetManager.observeTargets(this, WebInspector.Target.Type.Page); + WebInspector.targetManager.observeTargets(this, WebInspector.Target.Capability.Browser); } /** @enum {string} */
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceOrientation.js b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceOrientation.js index 94a6b65..32ae781 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/DeviceOrientation.js +++ b/third_party/WebKit/Source/devtools/front_end/emulation/DeviceOrientation.js
@@ -26,13 +26,13 @@ apply: function() { - for (var target of WebInspector.targetManager.targets(WebInspector.Target.Type.Page)) + for (var target of WebInspector.targetManager.targets(WebInspector.Target.Capability.Browser)) target.deviceOrientationAgent().setDeviceOrientationOverride(this.alpha, this.beta, this.gamma); }, clear: function() { - for (var target of WebInspector.targetManager.targets(WebInspector.Target.Type.Page)) + for (var target of WebInspector.targetManager.targets(WebInspector.Target.Capability.Browser)) target.deviceOrientationAgent().clearDeviceOrientationOverride(); } }
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/Geolocation.js b/third_party/WebKit/Source/devtools/front_end/emulation/Geolocation.js index 08ee5fa62..7ede716c 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/Geolocation.js +++ b/third_party/WebKit/Source/devtools/front_end/emulation/Geolocation.js
@@ -26,7 +26,7 @@ apply: function() { - for (var target of WebInspector.targetManager.targets(WebInspector.Target.Type.Page)) { + for (var target of WebInspector.targetManager.targets(WebInspector.Target.Capability.Browser)) { if (this.error) target.emulationAgent().setGeolocationOverride(); else @@ -36,7 +36,7 @@ clear: function() { - for (var target of WebInspector.targetManager.targets(WebInspector.Target.Type.Page)) + for (var target of WebInspector.targetManager.targets(WebInspector.Target.Capability.Browser)) target.emulationAgent().clearGeolocationOverride(); } }
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/TouchModel.js b/third_party/WebKit/Source/devtools/front_end/emulation/TouchModel.js index d0a39d7..b39ce97 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/TouchModel.js +++ b/third_party/WebKit/Source/devtools/front_end/emulation/TouchModel.js
@@ -12,7 +12,7 @@ this._touchMobile = false; this._customTouchEnabled = false; - WebInspector.targetManager.observeTargets(this, WebInspector.Target.Type.Page); + WebInspector.targetManager.observeTargets(this, WebInspector.Target.Capability.Browser); } WebInspector.MultitargetTouchModel._symbol = Symbol("MultitargetTouchModel.symbol"); @@ -40,7 +40,7 @@ _updateAllTargets: function() { - for (var target of WebInspector.targetManager.targets(WebInspector.Target.Type.Page)) + for (var target of WebInspector.targetManager.targets(WebInspector.Target.Capability.Browser)) this._applyToTarget(target); },
diff --git a/third_party/WebKit/Source/devtools/front_end/externs.js b/third_party/WebKit/Source/devtools/front_end/externs.js index 870da2b..3efe70a 100644 --- a/third_party/WebKit/Source/devtools/front_end/externs.js +++ b/third_party/WebKit/Source/devtools/front_end/externs.js
@@ -585,6 +585,12 @@ sol: function() { } } +/** @constructor */ +CodeMirror.TextMarker = function(doc, type) { } +CodeMirror.TextMarker.prototype = { + clear: function() { } +} + /** @type {Object.<string, !Object.<string, string>>} */ CodeMirror.keyMap;
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 1e7cf982..2804d1b 100644 --- a/third_party/WebKit/Source/devtools/front_end/main/Main.js +++ b/third_party/WebKit/Source/devtools/front_end/main/Main.js
@@ -119,6 +119,7 @@ Runtime.experiments.register("resolveVariableNames", "Resolve variable names"); Runtime.experiments.register("timelineShowAllEvents", "Show all events on Timeline", true); Runtime.experiments.register("securityPanel", "Security panel"); + Runtime.experiments.register("sourceColorPicker", "Source color picker"); Runtime.experiments.register("sourceDiff", "Source diff"); Runtime.experiments.register("timelineFlowEvents", "Timeline flow events", true); Runtime.experiments.register("timelineInvalidationTracking", "Timeline invalidation tracking", true); @@ -309,13 +310,13 @@ WebInspector.RemoteDebuggingTerminatedScreen.show(event.data.reason); } - var targetType = WebInspector.Target.Type.Page; + var capabilities = WebInspector.Target.Capability.Browser | WebInspector.Target.Capability.JS | WebInspector.Target.Capability.Network | WebInspector.Target.Capability.Worker; if (Runtime.queryParam("isSharedWorker")) - targetType = WebInspector.Target.Type.ServiceWorker; + capabilities = WebInspector.Target.Capability.Network | WebInspector.Target.Capability.Worker; else if (Runtime.queryParam("v8only")) - targetType = WebInspector.Target.Type.JSInspector; + capabilities = WebInspector.Target.Capability.JS; - this._mainTarget = WebInspector.targetManager.createTarget(WebInspector.UIString("Main"), targetType, connection, null); + this._mainTarget = WebInspector.targetManager.createTarget(WebInspector.UIString("Main"), capabilities, connection, null); console.timeStamp("Main._mainTargetCreated"); this._registerShortcuts(); @@ -323,8 +324,7 @@ InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.ReloadInspectedPage, this._reloadInspectedPage, this); InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.EvaluateForTestInFrontend, this._evaluateForTestInFrontend, this); - if (this._mainTarget.isServiceWorker() || this._mainTarget.isPage() || this._mainTarget.isJSInspector()) - this._mainTarget.runtimeAgent().run(); + this._mainTarget.runtimeAgent().run(); this._mainTarget.inspectorAgent().enable(); InspectorFrontendHost.readyForTest(); @@ -493,34 +493,18 @@ WebInspector.shortcutRegistry.handleShortcut(event); }, - _documentCanCopy: function(event) + /** + * @param {!Event} event + */ + _redispatchClipboardEvent: function(event) { - var panel = WebInspector.inspectorView.currentPanel(); - if (panel && panel["handleCopyEvent"]) + var eventCopy = new CustomEvent("clipboard-" + event.type); + eventCopy["original"] = event; + event.deepActiveElement().dispatchEvent(eventCopy); + if (eventCopy.handled) event.preventDefault(); }, - _documentCopy: function(event) - { - var panel = WebInspector.inspectorView.currentPanel(); - if (panel && panel["handleCopyEvent"]) - panel["handleCopyEvent"](event); - }, - - _documentCut: function(event) - { - var panel = WebInspector.inspectorView.currentPanel(); - if (panel && panel["handleCutEvent"]) - panel["handleCutEvent"](event); - }, - - _documentPaste: function(event) - { - var panel = WebInspector.inspectorView.currentPanel(); - if (panel && panel["handlePasteEvent"]) - panel["handlePasteEvent"](event); - }, - _contextMenuEventFired: function(event) { if (event.handled || event.target.classList.contains("popup-glasspane")) @@ -533,10 +517,10 @@ _addMainEventListeners: function(document) { document.addEventListener("keydown", this._postDocumentKeyDown.bind(this), false); - document.addEventListener("beforecopy", this._documentCanCopy.bind(this), true); - document.addEventListener("copy", this._documentCopy.bind(this), false); - document.addEventListener("cut", this._documentCut.bind(this), false); - document.addEventListener("paste", this._documentPaste.bind(this), false); + document.addEventListener("beforecopy", this._redispatchClipboardEvent.bind(this), true); + document.addEventListener("copy", this._redispatchClipboardEvent.bind(this), false); + document.addEventListener("cut", this._redispatchClipboardEvent.bind(this), false); + document.addEventListener("paste", this._redispatchClipboardEvent.bind(this), false); document.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true); document.addEventListener("click", this._documentClick.bind(this), false); }, @@ -710,26 +694,9 @@ */ WebInspector.Main._reloadPage = function(hard) { - if (!WebInspector.targetManager.hasTargets()) - return; - if (WebInspector.targetManager.mainTarget().isServiceWorker()) - return; - WebInspector.targetManager.reloadPage(hard); -} - -/** - * @param {string} ws - */ -WebInspector.Main._addWebSocketTarget = function(ws) -{ - /** - * @param {!InspectorBackendClass.Connection} connection - */ - function callback(connection) - { - WebInspector.targetManager.createTarget(ws, WebInspector.Target.Type.Page, connection, null); - } - new WebInspector.WebSocketConnection(ws, callback); + var mainTarget = WebInspector.targetManager.mainTarget(); + if (mainTarget && mainTarget.hasBrowserCapability()) + WebInspector.targetManager.reloadPage(hard); } /** @@ -1072,7 +1039,7 @@ this._disableJavascriptSetting.addChangeListener(this._update, this); this._blockedEventsWarningSetting = WebInspector.settings.moduleSetting("blockedEventsWarningEnabled"); this._blockedEventsWarningSetting.addChangeListener(this._update, this); - WebInspector.targetManager.observeTargets(this, WebInspector.Target.Type.Page); + WebInspector.targetManager.observeTargets(this, WebInspector.Target.Capability.Browser); } WebInspector.BackendSettingsSync.prototype = { @@ -1089,7 +1056,7 @@ _update: function() { - WebInspector.targetManager.targets(WebInspector.Target.Type.Page).forEach(this._updateTarget, this); + WebInspector.targetManager.targets(WebInspector.Target.Capability.Browser).forEach(this._updateTarget, this); }, /**
diff --git a/third_party/WebKit/Source/devtools/front_end/main/RenderingOptions.js b/third_party/WebKit/Source/devtools/front_end/main/RenderingOptions.js index 05914662..35d99109b 100644 --- a/third_party/WebKit/Source/devtools/front_end/main/RenderingOptions.js +++ b/third_party/WebKit/Source/devtools/front_end/main/RenderingOptions.js
@@ -82,7 +82,7 @@ this._mediaSelect.addEventListener("change", this._mediaToggled.bind(this), false); this._mediaSelect.disabled = true; - WebInspector.targetManager.observeTargets(this, WebInspector.Target.Type.Page); + WebInspector.targetManager.observeTargets(this, WebInspector.Target.Capability.Browser); } WebInspector.RenderingOptionsView.prototype = { @@ -108,9 +108,8 @@ _settingToggled: function(setterName) { var enabled = this._settings.get(setterName).checked; - var targets = WebInspector.targetManager.targets(WebInspector.Target.Type.Page); - for (var i = 0; i < targets.length; ++i) - targets[i].renderingAgent()[setterName](enabled); + for (var target of WebInspector.targetManager.targets(WebInspector.Target.Capability.Browser)) + target.renderingAgent()[setterName](enabled); }, /** @@ -130,7 +129,7 @@ _mediaToggled: function() { this._mediaSelect.disabled = !this._mediaCheckbox.checked; - var targets = WebInspector.targetManager.targets(WebInspector.Target.Type.Page); + var targets = WebInspector.targetManager.targets(WebInspector.Target.Capability.Browser); for (var target of targets) this._applyPrintMediaOverride(target); },
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js b/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js index 4fd2517b..8f42a3b 100644 --- a/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js +++ b/third_party/WebKit/Source/devtools/front_end/profiler/CPUProfileView.js
@@ -349,8 +349,7 @@ */ linkifyNode: function(node) { - var callFrame = node.profileNode.frame; - return this._profileView.linkifier().linkifyConsoleCallFrame(this._profileView.target(), callFrame, "profile-node-file"); + return this._profileView.linkifier().linkifyConsoleCallFrameForTimeline(this._profileView.target(), node.profileNode.frame, "profile-node-file"); } } @@ -478,9 +477,8 @@ var totalTime = millisecondsToString(timelineData.entryTotalTimes[entryIndex]); pushEntryInfoRow(WebInspector.UIString("Self time"), selfTime); pushEntryInfoRow(WebInspector.UIString("Total time"), totalTime); - var callFrame = /** @type {!RuntimeAgent.CallFrame} */ (node); var linkifier = new WebInspector.Linkifier(); - var text = linkifier.linkifyConsoleCallFrame(this._target, callFrame).textContent; + var text = linkifier.linkifyConsoleCallFrameForTimeline(this._target, node).textContent; linkifier.dispose(); pushEntryInfoRow(WebInspector.UIString("URL"), text); pushEntryInfoRow(WebInspector.UIString("Aggregated self time"), Number.secondsToString(node.selfTime / 1000, true));
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfileView.js b/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfileView.js index ef44c98..24404a6 100644 --- a/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfileView.js +++ b/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfileView.js
@@ -302,8 +302,7 @@ */ linkifyNode: function(node) { - var callFrame = node.profileNode.frame; - return this._profileView.linkifier().linkifyConsoleCallFrame(this._profileView.target(), callFrame, "profile-node-file"); + return this._profileView.linkifier().linkifyConsoleCallFrameForTimeline(this._profileView.target(), node.profileNode.frame, "profile-node-file"); } } @@ -423,7 +422,7 @@ pushEntryInfoRow(WebInspector.UIString("Self size"), Number.bytesToString(node.self)); pushEntryInfoRow(WebInspector.UIString("Total size"), Number.bytesToString(node.total)); var linkifier = new WebInspector.Linkifier(); - var text = (new WebInspector.Linkifier()).linkifyConsoleCallFrame(this._target, node.frame).textContent; + var text = (new WebInspector.Linkifier()).linkifyConsoleCallFrameForTimeline(this._target, node.frame).textContent; linkifier.dispose(); pushEntryInfoRow(WebInspector.UIString("URL"), text); return entryInfo;
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/ProfileLauncherView.js b/third_party/WebKit/Source/devtools/front_end/profiler/ProfileLauncherView.js index 0cec690..69e9d9a 100644 --- a/third_party/WebKit/Source/devtools/front_end/profiler/ProfileLauncherView.js +++ b/third_party/WebKit/Source/devtools/front_end/profiler/ProfileLauncherView.js
@@ -87,7 +87,7 @@ _updateLoadButtonLayout: function() { - this._loadButton.classList.toggle("multi-target", WebInspector.targetManager.targetsWithJSContext().length > 1); + this._loadButton.classList.toggle("multi-target", WebInspector.targetManager.targets(WebInspector.Target.Capability.JS).length > 1); }, /**
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/TargetsComboBoxController.js b/third_party/WebKit/Source/devtools/front_end/profiler/TargetsComboBoxController.js index 1942cbd..c703eac 100644 --- a/third_party/WebKit/Source/devtools/front_end/profiler/TargetsComboBoxController.js +++ b/third_party/WebKit/Source/devtools/front_end/profiler/TargetsComboBoxController.js
@@ -18,7 +18,7 @@ this._targetToOption = new Map(); WebInspector.context.addFlavorChangeListener(WebInspector.Target, this._targetChangedExternally, this); - WebInspector.targetManager.observeTargets(this); + WebInspector.targetManager.observeTargets(this, WebInspector.Target.Capability.JS); } WebInspector.TargetsComboBoxController.prototype = { @@ -29,8 +29,6 @@ */ targetAdded: function(target) { - if (!target.hasJSContext()) - return; var option = this._selectElement.createChild("option"); option.text = target.name(); option.__target = target; @@ -47,8 +45,6 @@ */ targetRemoved: function(target) { - if (!target.hasJSContext()) - return; var option = this._targetToOption.remove(target); this._selectElement.removeChild(option); this._updateVisibility();
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/AppManifestView.js b/third_party/WebKit/Source/devtools/front_end/resources/AppManifestView.js index 97ecc01..a458ab19f 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/AppManifestView.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/AppManifestView.js
@@ -132,7 +132,7 @@ _addToHomescreen: function() { var target = WebInspector.targetManager.mainTarget(); - if (target && target.isPage()) { + if (target && target.hasBrowserCapability()) { target.pageAgent().requestAppBanner(); WebInspector.console.show(); }
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ResourcesPanel.js b/third_party/WebKit/Source/devtools/front_end/resources/ResourcesPanel.js index d1f6f83..3b3b82d 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/ResourcesPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/ResourcesPanel.js
@@ -167,7 +167,7 @@ if (cacheStorageModel) cacheStorageModel.enable(); - if (this._target.isPage()) + if (this._target.hasBrowserCapability()) this._populateResourceTree(); this._populateDOMStorageTree(); this._populateApplicationCacheTree();
diff --git a/third_party/WebKit/Source/devtools/front_end/sass/SASSSupport.js b/third_party/WebKit/Source/devtools/front_end/sass/SASSSupport.js index 0a81a04..8c5b285 100644 --- a/third_party/WebKit/Source/devtools/front_end/sass/SASSSupport.js +++ b/third_party/WebKit/Source/devtools/front_end/sass/SASSSupport.js
@@ -250,7 +250,10 @@ } var oldRange1 = new WebInspector.TextRange(this.range.startLine, this.range.startColumn, this.range.startLine, this.name.range.startColumn); var edit1 = new WebInspector.SourceEdit(this.document.url, oldRange1, ""); - var oldRange2 = new WebInspector.TextRange(this.range.endLine, this.range.endColumn - 2, this.range.endLine, this.range.endColumn); + + var propertyText = this.document.text.extract(this.range); + var endsWithSemicolon = propertyText.slice(0, -2).trim().endsWith(";"); + var oldRange2 = new WebInspector.TextRange(this.range.endLine, this.value.range.endColumn + (endsWithSemicolon ? 1 : 0), this.range.endLine, this.range.endColumn); var edit2 = new WebInspector.SourceEdit(this.document.url, oldRange2, ""); this.document.edits.push(edit1, edit2); },
diff --git a/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastApp.js b/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastApp.js index 8eb9804..a4ba497 100644 --- a/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastApp.js +++ b/third_party/WebKit/Source/devtools/front_end/screencast/ScreencastApp.js
@@ -46,7 +46,7 @@ return; this._target = target; - if (target.isPage()) { + if (target.hasBrowserCapability()) { this._screencastView = new WebInspector.ScreencastView(target); this._rootSplitWidget.setMainWidget(this._screencastView); this._screencastView.initialize();
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js index 5ee2239f..4a2f1021 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/CSSModel.js
@@ -996,6 +996,26 @@ this._agent.setEffectivePropertyValueForNode(nodeId, name, value); }, + /** + * @param {!WebInspector.DOMNode} node + * @return {!Promise.<?WebInspector.CSSMatchedStyles>} + */ + cachedMatchedCascadeForNode: function(node) + { + if (this._cachedMatchedCascadeNode !== node) + this.discardCachedMatchedCascade(); + this._cachedMatchedCascadeNode = node; + if (!this._cachedMatchedCascadePromise) + this._cachedMatchedCascadePromise = this.matchedStylesPromise(node.id); + return this._cachedMatchedCascadePromise; + }, + + discardCachedMatchedCascade: function() + { + delete this._cachedMatchedCascadeNode; + delete this._cachedMatchedCascadePromise; + }, + __proto__: WebInspector.SDKModel.prototype } @@ -1173,8 +1193,6 @@ */ WebInspector.CSSModel.fromTarget = function(target) { - if (!target.isPage()) - return null; return /** @type {?WebInspector.CSSModel} */ (target.model(WebInspector.CSSModel)); }
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js index 03e46ff..485b8889 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/ConsoleModel.js
@@ -79,6 +79,9 @@ if (this._isBlacklisted(msg)) return; + if (msg.source === WebInspector.ConsoleMessage.MessageSource.Worker && msg.target().workerManager && msg.target().workerManager.targetByWorkerId(msg.workerId)) + return; + if (msg.level === WebInspector.ConsoleMessage.MessageLevel.RevokedError && msg._revokedExceptionId) { var exceptionMessage = this._messageByExceptionId.get(msg._revokedExceptionId); if (!exceptionMessage) @@ -269,8 +272,9 @@ * @param {number=} timestamp * @param {!RuntimeAgent.ExecutionContextId=} executionContextId * @param {?string=} scriptId + * @param {?string=} workerId */ -WebInspector.ConsoleMessage = function(target, source, level, messageText, type, url, line, column, requestId, parameters, stackTrace, timestamp, executionContextId, scriptId) +WebInspector.ConsoleMessage = function(target, source, level, messageText, type, url, line, column, requestId, parameters, stackTrace, timestamp, executionContextId, scriptId, workerId) { this._target = target; this.source = source; @@ -289,6 +293,7 @@ this.timestamp = timestamp || Date.now(); this.executionContextId = executionContextId || 0; this.scriptId = scriptId || null; + this.workerId = workerId || null; var networkLog = target && WebInspector.NetworkLog.fromTarget(target); this.request = (requestId && networkLog) ? networkLog.requestForId(requestId) : null; @@ -463,7 +468,8 @@ CSS: "css", Security: "security", Other: "other", - Deprecation: "deprecation" + Deprecation: "deprecation", + Worker: "worker" } /** @@ -539,7 +545,8 @@ payload.stack, payload.timestamp * 1000, // Convert to ms. payload.executionContextId, - payload.scriptId); + payload.scriptId, + payload.workerId); this._console.addMessage(consoleMessage); },
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/CookieParser.js b/third_party/WebKit/Source/devtools/front_end/sdk/CookieParser.js index f33cd97..ac604a77 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/CookieParser.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/CookieParser.js
@@ -406,7 +406,7 @@ } var barrier = new CallbackBarrier(); - for (var target of WebInspector.targetManager.targets(WebInspector.Target.Type.Page)) + for (var target of WebInspector.targetManager.targets(WebInspector.Target.Capability.Network)) target.networkAgent().getCookies(barrier.createCallback(mycallback.bind(null, target))); barrier.callWhenDone(callback.bind(null, allCookies)); }
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js index 67fe2cd..2c913c8 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
@@ -58,7 +58,7 @@ this.enableDebugger(); } -/** @typedef {{location: ?WebInspector.DebuggerModel.Location, sourceURL: ?string, functionName: string, scopeChain: (Array.<!DebuggerAgent.Scope>|null)}} */ +/** @typedef {{location: ?WebInspector.DebuggerModel.Location, functionName: string}} */ WebInspector.DebuggerModel.FunctionDetails; /** @@ -98,16 +98,6 @@ Other: "other" } -/** - * @param {number=} value - * @return {number} - */ -WebInspector.DebuggerModel.fromOneBased = function(value) -{ - // FIXME(webkit:62725): console stack trace line/column numbers are one-based. - return value ? value - 1 : 0; -} - WebInspector.DebuggerModel.prototype = { /** * @return {boolean} @@ -581,7 +571,7 @@ var rawLocations = []; for (var frame of frames) { - var rawLocation = this.createRawLocationByScriptId(frame.scriptId, WebInspector.DebuggerModel.fromOneBased(frame.lineNumber), WebInspector.DebuggerModel.fromOneBased(frame.columnNumber)); + var rawLocation = this.createRawLocationByScriptId(frame.scriptId, frame.lineNumber, frame.columnNumber); if (rawLocation) rawLocations.push(rawLocation); } @@ -659,28 +649,43 @@ /** * @param {!WebInspector.RemoteObject} remoteObject - * @param {function(?WebInspector.DebuggerModel.FunctionDetails)} callback + * @return {!Promise<?WebInspector.DebuggerModel.FunctionDetails>} */ - functionDetails: function(remoteObject, callback) + functionDetailsPromise: function(remoteObject) { - this._agent.getFunctionDetails(remoteObject.objectId, didGetDetails.bind(this)); + return remoteObject.getAllPropertiesPromise(/* accessorPropertiesOnly */false).then(buildDetails.bind(this)); /** - * @param {?Protocol.Error} error - * @param {!DebuggerAgent.FunctionDetails} response - * @this {WebInspector.DebuggerModel} + * @param {!{properties: ?Array.<!WebInspector.RemoteObjectProperty>, internalProperties: ?Array.<!WebInspector.RemoteObjectProperty>}} response + * @return {?WebInspector.DebuggerModel.FunctionDetails} + * @this {!WebInspector.DebuggerModel} */ - function didGetDetails(error, response) + function buildDetails(response) { - if (error) { - callback(null); - return; + if (!response) + return null; + var location = null; + if (response.internalProperties) { + for (var prop of response.internalProperties) { + if (prop.name === "[[FunctionLocation]]") + location = prop.value; + } } - var location = response.location; - var script = this.scriptForId(location.scriptId); - var rawLocation = script ? this.createRawLocation(script, location.lineNumber, location.columnNumber || 0) : null; - var sourceURL = script ? script.contentURL() : null; - callback({location: rawLocation, sourceURL: sourceURL, functionName: response.functionName, scopeChain: response.scopeChain || null}); + var functionName = null; + if (response.properties) { + for (var prop of response.properties) { + if (prop.name === "name" && prop.value && prop.value.type === "string") + functionName = prop.value; + if (prop.name === "displayName" && prop.value && prop.value.type === "string") { + functionName = prop.value; + break; + } + } + } + var debuggerLocation = null; + if (location) + debuggerLocation = this.createRawLocationByScriptId(location.value.scriptId, location.value.lineNumber, location.value.columnNumber); + return { location: debuggerLocation, functionName: functionName ? functionName.value : "" }; } }, @@ -1286,7 +1291,7 @@ */ WebInspector.DebuggerModel.fromTarget = function(target) { - if (!target || !target.hasJSContext()) + if (!target || !target.hasJSCapability()) return null; return /** @type {?WebInspector.DebuggerModel} */ (target.model(WebInspector.DebuggerModel)); }
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js index f59a6b0d..b8f422c 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/RemoteObject.js
@@ -281,31 +281,6 @@ isNode: function() { return false; - }, - - /** - * @param {function(?WebInspector.DebuggerModel.FunctionDetails)} callback - */ - functionDetails: function(callback) - { - callback(null); - }, - - /** - * @return {!Promise<?WebInspector.DebuggerModel.FunctionDetails>} - */ - functionDetailsPromise: function() - { - return new Promise(promiseConstructor.bind(this)); - - /** - * @param {function(?WebInspector.DebuggerModel.FunctionDetails)} success - * @this {WebInspector.RemoteObject} - */ - function promiseConstructor(success) - { - this.functionDetails(success); - } } } @@ -532,7 +507,7 @@ */ function eventListeners(fulfill, reject) { - if (!this.target().isPage()) { + if (!this.target().hasBrowserCapability()) { // TODO(kozyatinskiy): figure out how this should work for |window| when there is no DOMDebugger. fulfill([]); return; @@ -860,15 +835,6 @@ return !!this._objectId && this.type === "object" && this.subtype === "node"; }, - /** - * @override - * @param {function(?WebInspector.DebuggerModel.FunctionDetails)} callback - */ - functionDetails: function(callback) - { - this._debuggerModel.functionDetails(this, callback); - }, - __proto__: WebInspector.RemoteObject.prototype }; @@ -1526,7 +1492,7 @@ function functionDetails(targetFunction) { var boundReleaseFunctionDetails = releaseTargetFunction.bind(null, this._object !== targetFunction ? targetFunction : null); - return targetFunction.functionDetailsPromise().then(boundReleaseFunctionDetails); + return targetFunction.debuggerModel().functionDetailsPromise(targetFunction).then(boundReleaseFunctionDetails); } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js index 8f5b5c55..ee17408 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/ResourceTreeModel.js
@@ -55,6 +55,8 @@ this._inspectedPageURL = ""; this._pendingReloadOptions = null; this._reloadSuspensionCount = 0; + + target.runtimeModel.setExecutionContextComparator(this._executionContextComparator.bind(this)); } WebInspector.ResourceTreeModel.EventTypes = { @@ -127,7 +129,7 @@ this._inspectedPageURL = mainFramePayload.frame.url; // Do not process SW resources. - if (this.target().isPage()) + if (this.target().hasBrowserCapability()) this._addFramesRecursively(null, mainFramePayload); else this._addSecurityOrigin(mainFramePayload.frame.securityOrigin); @@ -486,6 +488,49 @@ callback(url, data || null, errors); } }, + /** + * @param {!WebInspector.ExecutionContext} a + * @param {!WebInspector.ExecutionContext} b + * @return {number} + */ + _executionContextComparator: function(a,b) + { + /** + * @param {!WebInspector.ResourceTreeFrame} frame + */ + function framePath(frame) + { + var currentFrame = frame; + var parents = []; + while (currentFrame) { + parents.push(currentFrame); + currentFrame = currentFrame.parentFrame; + } + return parents.reverse(); + } + + var framesA = a.frameId ? framePath(this.frameForId(a.frameId)) : []; + var framesB = b.frameId ? framePath(this.frameForId(b.frameId)) : []; + var frameA; + var frameB; + for (var i = 0; ; i++) { + if (!framesA[i] || !framesB[i] || (framesA[i] !== framesB[i])) { + frameA = framesA[i]; + frameB = framesB[i]; + break; + } + } + if (!frameA && frameB) + return -1; + + if (!frameB && frameA) + return 1; + + if (frameA && frameB) { + return frameA.id.localeCompare(frameB.id); + } + return WebInspector.ExecutionContext.comparator(a,b); + }, __proto__: WebInspector.SDKModel.prototype }
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js index 4013efa2..bf764a5 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/RuntimeModel.js
@@ -39,12 +39,13 @@ this._agent = target.runtimeAgent(); this.target().registerRuntimeDispatcher(new WebInspector.RuntimeDispatcher(this)); - if (target.hasJSContext()) + if (target.hasJSCapability()) this._agent.enable(); /** * @type {!Object.<number, !WebInspector.ExecutionContext>} */ this._executionContextById = {}; + this._executionContextComparator = WebInspector.ExecutionContext.comparator; if (WebInspector.moduleSetting("customFormatters").get()) this._agent.setCustomObjectFormatterEnabled(true); @@ -67,7 +68,23 @@ */ executionContexts: function() { - return Object.values(this._executionContextById); + return Object.values(this._executionContextById).sort(this.executionContextComparator()); + }, + + /** + * @param {function(!WebInspector.ExecutionContext,!WebInspector.ExecutionContext)} comparator + */ + setExecutionContextComparator: function(comparator) + { + this._executionContextComparator = comparator; + }, + + /** + * @return {function(!WebInspector.ExecutionContext,!WebInspector.ExecutionContext)} comparator + */ + executionContextComparator: function() + { + return this._executionContextComparator; }, /** @@ -442,9 +459,9 @@ */ function targetWeight(target) { - if (target.isPage()) + if (target.hasBrowserCapability()) return 3; - if (target.isDedicatedWorker()) + if (target.hasJSCapability()) return 2; return 1; } @@ -453,10 +470,6 @@ if (weightDiff) return -weightDiff; - var frameIdDiff = String.hashCode(a.frameId) - String.hashCode(b.frameId); - if (frameIdDiff) - return frameIdDiff; - // Main world context should always go first. if (a.isDefault) return -1; @@ -869,11 +882,11 @@ if (!this._removeFunction) return Promise.resolve(); return this._removeFunction.callFunctionPromise(callCustomRemove, [ - WebInspector.RemoteObject.toCallArgument(this._type), - WebInspector.RemoteObject.toCallArgument(this._originalHandler), - WebInspector.RemoteObject.toCallArgument(this._useCapture), - WebInspector.RemoteObject.toCallArgument(this._passive), - ]).then(() => undefined); + WebInspector.RemoteObject.toCallArgument(this._type), + WebInspector.RemoteObject.toCallArgument(this._originalHandler), + WebInspector.RemoteObject.toCallArgument(this._useCapture), + WebInspector.RemoteObject.toCallArgument(this._passive), + ]).then(() => undefined); /** * @param {string} type
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerManager.js index ab0e7d5..f24c6b3 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerManager.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/ServiceWorkerManager.js
@@ -435,7 +435,8 @@ this._scope = parsedURL.host + parsedURL.folderPathComponents; this._manager._workers.set(workerId, this); - this._target = WebInspector.targetManager.createTarget(this._name, WebInspector.Target.Type.ServiceWorker, this._connection, manager.target()); + var capabilities = WebInspector.Target.Capability.Network | WebInspector.Target.Capability.Worker; + this._target = WebInspector.targetManager.createTarget(this._name, capabilities, this._connection, manager.target()); this._target[WebInspector.ServiceWorker.Symbol] = this; this._manager.dispatchEventToListeners(WebInspector.ServiceWorkerManager.Events.WorkersUpdated); this._target.runtimeAgent().run();
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/Target.js b/third_party/WebKit/Source/devtools/front_end/sdk/Target.js index ebaf360..0ba8715d 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/Target.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/Target.js
@@ -9,16 +9,16 @@ * @extends {Protocol.Agents} * @param {!WebInspector.TargetManager} targetManager * @param {string} name - * @param {number} type + * @param {number} capabilitiesMask * @param {!InspectorBackendClass.Connection} connection * @param {?WebInspector.Target} parentTarget */ -WebInspector.Target = function(targetManager, name, type, connection, parentTarget) +WebInspector.Target = function(targetManager, name, capabilitiesMask, connection, parentTarget) { Protocol.Agents.call(this, connection.agentsMap()); this._targetManager = targetManager; this._name = name; - this._type = type; + this._capabilitiesMask = capabilitiesMask; this._connection = connection; this._parentTarget = parentTarget; connection.addEventListener(InspectorBackendClass.Connection.Events.Disconnected, this._onDisconnect, this); @@ -31,11 +31,11 @@ /** * @enum {number} */ -WebInspector.Target.Type = { - Page: 1, - DedicatedWorker: 2, - ServiceWorker: 4, - JSInspector: 8 +WebInspector.Target.Capability = { + Browser: 1, + JS: 2, + Network: 4, + Worker: 8, } WebInspector.Target._nextId = 1; @@ -58,16 +58,6 @@ }, /** - * - * @return {number} - */ - type: function() - { - return this._type; - }, - - /** - * * @return {!WebInspector.TargetManager} */ targetManager: function() @@ -76,12 +66,21 @@ }, /** + * @param {number} capabilitiesMask + * @return {boolean} + */ + hasAllCapabilities: function(capabilitiesMask) + { + return (this._capabilitiesMask & capabilitiesMask) === capabilitiesMask; + }, + + /** * @param {string} label * @return {string} */ decorateLabel: function(label) { - return this.isWorker() ? "\u2699 " + label : label; + return !this.hasBrowserCapability() ? "\u2699 " + label : label; }, /** @@ -97,57 +96,33 @@ /** * @return {boolean} */ - isPage: function() + hasBrowserCapability: function() { - return this._type === WebInspector.Target.Type.Page; + return this.hasAllCapabilities(WebInspector.Target.Capability.Browser); }, /** * @return {boolean} */ - isWorker: function() + hasJSCapability: function() { - return this.isDedicatedWorker() || this.isServiceWorker() || this.isJSInspector(); + return this.hasAllCapabilities(WebInspector.Target.Capability.JS); }, /** * @return {boolean} */ - isDedicatedWorker: function() + hasNetworkCapability: function() { - return this._type === WebInspector.Target.Type.DedicatedWorker; + return this.hasAllCapabilities(WebInspector.Target.Capability.Network); }, /** * @return {boolean} */ - isServiceWorker: function() + hasWorkerCapability: function() { - return this._type === WebInspector.Target.Type.ServiceWorker; - }, - - /** - * @return {boolean} - */ - isJSInspector: function() - { - return this._type === WebInspector.Target.Type.JSInspector; - }, - - /** - * @return {boolean} - */ - hasJSContext: function() - { - return !this.isServiceWorker(); - }, - - /** - * @return {boolean} - */ - supportsWorkers: function() - { - return this.isPage() || this.isServiceWorker(); + return this.hasAllCapabilities(WebInspector.Target.Capability.Worker); }, /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js index 7e09dff..c7a4de86 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/TargetManager.js
@@ -15,7 +15,7 @@ this._targets = []; /** @type {!Array.<!WebInspector.TargetManager.Observer>} */ this._observers = []; - this._observerTypeSymbol = Symbol("observerType"); + this._observerCapabiliesMaskSymbol = Symbol("observerCapabilitiesMask"); /** @type {!Object.<string, !Array.<{modelClass: !Function, thisObject: (!Object|undefined), listener: function(!WebInspector.Event)}>>} */ this._modelListeners = {}; this._isSuspended = false; @@ -163,14 +163,14 @@ /** * @param {!WebInspector.TargetManager.Observer} targetObserver - * @param {number=} type + * @param {number=} capabilitiesMask */ - observeTargets: function(targetObserver, type) + observeTargets: function(targetObserver, capabilitiesMask) { - if (this._observerTypeSymbol in targetObserver) + if (this._observerCapabiliesMaskSymbol in targetObserver) throw new Error("Observer can only be registered once"); - targetObserver[this._observerTypeSymbol] = type || 0x7fff; - this.targets(type).forEach(targetObserver.targetAdded.bind(targetObserver)); + targetObserver[this._observerCapabiliesMaskSymbol] = capabilitiesMask || 0; + this.targets(capabilitiesMask).forEach(targetObserver.targetAdded.bind(targetObserver)); this._observers.push(targetObserver); }, @@ -179,26 +179,28 @@ */ unobserveTargets: function(targetObserver) { - delete targetObserver[this._observerTypeSymbol]; + delete targetObserver[this._observerCapabiliesMaskSymbol]; this._observers.remove(targetObserver); }, /** * @param {string} name - * @param {number} type + * @param {number} capabilitiesMask * @param {!InspectorBackendClass.Connection} connection * @param {?WebInspector.Target} parentTarget * @return {!WebInspector.Target} */ - createTarget: function(name, type, connection, parentTarget) + createTarget: function(name, capabilitiesMask, connection, parentTarget) { - var target = new WebInspector.Target(this, name, type, connection, parentTarget); + var target = new WebInspector.Target(this, name, capabilitiesMask, connection, parentTarget); /** @type {!WebInspector.ConsoleModel} */ target.consoleModel = new WebInspector.ConsoleModel(target); + /** @type {!WebInspector.RuntimeModel} */ + target.runtimeModel = new WebInspector.RuntimeModel(target); var networkManager = null; - if (!target.isJSInspector()) + if (target.hasNetworkCapability()) networkManager = new WebInspector.NetworkManager(target); /** @type {!WebInspector.ResourceTreeModel} */ @@ -207,18 +209,16 @@ if (networkManager) new WebInspector.NetworkLog(target, networkManager); - /** @type {!WebInspector.RuntimeModel} */ - target.runtimeModel = new WebInspector.RuntimeModel(target); - if (target.hasJSContext()) + if (target.hasJSCapability()) new WebInspector.DebuggerModel(target); - if (target.type() === WebInspector.Target.Type.Page) { + if (target.hasBrowserCapability()) { new WebInspector.DOMModel(target); new WebInspector.CSSModel(target); } /** @type {?WebInspector.WorkerManager} */ - target.workerManager = target.supportsWorkers() ? new WebInspector.WorkerManager(target) : null; + target.workerManager = target.hasWorkerCapability() ? new WebInspector.WorkerManager(target) : null; /** @type {!WebInspector.CPUProfilerModel} */ target.cpuProfilerModel = new WebInspector.CPUProfilerModel(target); /** @type {!WebInspector.HeapProfilerModel} */ @@ -226,7 +226,7 @@ target.tracingManager = new WebInspector.TracingManager(target); - if (target.isPage()) + if (target.hasBrowserCapability()) target.serviceWorkerManager = new WebInspector.ServiceWorkerManager(target); this.addTarget(target); @@ -234,17 +234,12 @@ }, /** - * @param {number} type + * @param {!WebInspector.Target} target * @return {!Array<!WebInspector.TargetManager.Observer>} */ - _observersByType: function(type) + _observersForTarget: function(target) { - var result = []; - for (var observer of this._observers) { - if (observer[this._observerTypeSymbol] & type) - result.push(observer); - } - return result; + return this._observers.filter((observer) => target.hasAllCapabilities(observer[this._observerCapabiliesMaskSymbol] || 0)); }, /** @@ -260,7 +255,7 @@ target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.PageReloadRequested, this._redispatchEvent, this); target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.WillReloadPage, this._redispatchEvent, this); } - var copy = this._observersByType(target.type()); + var copy = this._observersForTarget(target); for (var i = 0; i < copy.length; ++i) copy[i].targetAdded(target); @@ -286,7 +281,7 @@ target.resourceTreeModel.removeEventListener(WebInspector.ResourceTreeModel.EventTypes.Load, this._redispatchEvent, this); target.resourceTreeModel.removeEventListener(WebInspector.ResourceTreeModel.EventTypes.WillReloadPage, this._redispatchEvent, this); } - var copy = this._observersByType(target.type()); + var copy = this._observersForTarget(target); for (var i = 0; i < copy.length; ++i) copy[i].targetRemoved(target); @@ -301,42 +296,15 @@ }, /** - * @param {number=} type - * @return {boolean} - */ - hasTargets: function(type) - { - return !!this.targets(type).length; - }, - - /** - * @param {number=} type + * @param {number=} capabilitiesMask * @return {!Array.<!WebInspector.Target>} */ - targets: function(type) + targets: function(capabilitiesMask) { - if (!type) + if (!capabilitiesMask) return this._targets.slice(); - - var result = []; - for (var target of this._targets) { - if (target.type() & type) - result.push(target); - } - return result; - }, - - /** - * @return {!Array.<!WebInspector.Target>} - */ - targetsWithJSContext: function() - { - var result = []; - for (var target of this._targets) { - if (target.hasJSContext()) - result.push(target); - } - return result; + else + return this._targets.filter((target) => target.hasAllCapabilities(capabilitiesMask || 0)); }, /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/WorkerManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/WorkerManager.js index 2313c2ec..3bde930 100644 --- a/third_party/WebKit/Source/devtools/front_end/sdk/WorkerManager.js +++ b/third_party/WebKit/Source/devtools/front_end/sdk/WorkerManager.js
@@ -101,12 +101,12 @@ var parsedURL = url.asParsedURL(); var workerName = parsedURL ? parsedURL.lastPathComponentWithFragment() : "#" + (++this._lastAnonymousTargetId); - var target = WebInspector.targetManager.createTarget(workerName, WebInspector.Target.Type.DedicatedWorker, connection, this.target()); + var target = WebInspector.targetManager.createTarget(workerName, WebInspector.Target.Capability.JS, connection, this.target()); this._targetsByWorkerId.set(workerId, target); // Only pause new worker if debugging SW - we are going through the // pause on start checkbox. - var mainIsServiceWorker = WebInspector.targetManager.mainTarget().isServiceWorker(); + var mainIsServiceWorker = WebInspector.targetManager.mainTarget().hasWorkerCapability() && !WebInspector.targetManager.mainTarget().hasBrowserCapability(); if (mainIsServiceWorker && waitingForDebugger) target.debuggerAgent().pause(); target.runtimeAgent().run();
diff --git a/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js b/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js index a2bf52c..8205e9d 100644 --- a/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/security/SecurityPanel.js
@@ -27,7 +27,7 @@ /** @type {!Map<!WebInspector.NetworkLogView.MixedContentFilterValues, number>} */ this._filterRequestCounts = new Map(); - WebInspector.targetManager.observeTargets(this, WebInspector.Target.Type.Page); + WebInspector.targetManager.observeTargets(this, WebInspector.Target.Capability.Network); } /** @typedef {string} */ @@ -248,12 +248,12 @@ this._target = target; - target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._onMainFrameNavigated, this); + if (target.hasBrowserCapability()) + target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._onMainFrameNavigated, this); + var networkManager = WebInspector.NetworkManager.fromTarget(target); - if (networkManager) { - networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResponseReceived, this._onResponseReceived, this); - networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestFinished, this._onRequestFinished, this); - } + networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResponseReceived, this._onResponseReceived, this); + networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestFinished, this._onRequestFinished, this); var securityModel = WebInspector.SecurityModel.fromTarget(target); securityModel.addEventListener(WebInspector.SecurityModel.EventTypes.SecurityStateChanged, this._onSecurityStateChanged, this);
diff --git a/third_party/WebKit/Source/devtools/front_end/source_frame/CodeMirrorTextEditor.js b/third_party/WebKit/Source/devtools/front_end/source_frame/CodeMirrorTextEditor.js index 51bc556..229c825 100644 --- a/third_party/WebKit/Source/devtools/front_end/source_frame/CodeMirrorTextEditor.js +++ b/third_party/WebKit/Source/devtools/front_end/source_frame/CodeMirrorTextEditor.js
@@ -1006,6 +1006,19 @@ }, /** + * @param {number} lineNumber + * @param {number} columnNumber + * @param {!Element} element + * @return {!CodeMirror.TextMarker} + */ + addBookmark: function(lineNumber, columnNumber, element) + { + return this._codeMirror.setBookmark(new CodeMirror.Pos(lineNumber, columnNumber), { + widget: element + }); + }, + + /** * @override * @return {!Element} */
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/CSSSourceFrame.js b/third_party/WebKit/Source/devtools/front_end/sources/CSSSourceFrame.js index 1a90859..47a4c21 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/CSSSourceFrame.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/CSSSourceFrame.js
@@ -38,8 +38,12 @@ WebInspector.UISourceCodeFrame.call(this, uiSourceCode); this.textEditor.setAutocompleteDelegate(new WebInspector.CSSSourceFrame.AutocompleteDelegate()); this._registerShortcuts(); + this._colorBookmarks = []; } +/** @type {number} */ +WebInspector.CSSSourceFrame.UpdateTimeout = 200; + WebInspector.CSSSourceFrame.prototype = { _registerShortcuts: function() { @@ -97,11 +101,117 @@ return true; }, + _updateColorSwatches: function() + { + if (this._updateTimeout) + clearTimeout(this._updateTimeout); + this._updateTimeout = null; + + var colorPositions = this._extractColorPositions(this.textEditor.text()); + this.textEditor.operation(this._putColorSwatchesInline.bind(this, colorPositions)); + }, + + /** + * @param {string} content + * @return {?Array<!WebInspector.CSSSourceFrame.ColorPosition>} + */ + _extractColorPositions: function(content) + { + if (!content) + return null; + + var colorPositions = []; + var text = new WebInspector.Text(content); + var numberOfLines = text.lineCount(); + var colorRegex = /[\s:;,(){}]((?:rgb|hsl)a?\([^)]+\)|#[0-9a-f]{8}|#[0-9a-f]{6}|#[0-9a-f]{3,4}|[a-z]+)(?=[\s;,(){}])/gi; + for (var lineNumber = 0; lineNumber < numberOfLines; lineNumber++) { + var line = text.lineAt(lineNumber) + "\n"; + var match; + while ((match = colorRegex.exec(line)) !== null) { + if (match.length < 2) + continue; + + var colorText = match[1]; + var color = WebInspector.Color.parse(colorText); + if (color) + colorPositions.push(new WebInspector.CSSSourceFrame.ColorPosition(color, lineNumber, match.index + 1, colorText.length)); + } + } + + return colorPositions; + }, + + /** + * @param {?Array<!WebInspector.CSSSourceFrame.ColorPosition>} colorPositions + */ + _putColorSwatchesInline: function(colorPositions) + { + this._clearColorBookmarks(); + if (!colorPositions) + return; + + for (var i = 0; i < colorPositions.length; i++) { + var colorPosition = colorPositions[i]; + + var swatch = WebInspector.ColorSwatch.create(); + swatch.setColorText(colorPosition.color.asString(WebInspector.Color.Format.Original)); + swatch.hideText(true); + + var bookmark = this.textEditor.addBookmark(colorPosition.textRange.startLine, colorPosition.textRange.startColumn, swatch); + this._colorBookmarks.push(bookmark); + } + }, + + _clearColorBookmarks: function() + { + for (var i = 0; i < this._colorBookmarks.length; i++) + this._colorBookmarks[i].clear(); + this._colorBookmarks = []; + }, + + /** + * @override + */ + onTextEditorContentLoaded: function() + { + WebInspector.UISourceCodeFrame.prototype.onTextEditorContentLoaded.call(this); + if (Runtime.experiments.isEnabled("sourceColorPicker")) + this._updateColorSwatches(); + }, + + /** + * @override + * @param {!WebInspector.TextRange} oldRange + * @param {!WebInspector.TextRange} newRange + */ + onTextChanged: function(oldRange, newRange) + { + WebInspector.UISourceCodeFrame.prototype.onTextChanged.call(this, oldRange, newRange); + if (Runtime.experiments.isEnabled("sourceColorPicker")) { + if (this._updateTimeout) + clearTimeout(this._updateTimeout); + this._updateTimeout = setTimeout(this._updateColorSwatches.bind(this), WebInspector.CSSSourceFrame.UpdateTimeout); + } + }, + __proto__: WebInspector.UISourceCodeFrame.prototype } /** * @constructor + * @param {!WebInspector.Color} color + * @param {number} lineNumber + * @param {number} startColumn + * @param {number} textLength + */ +WebInspector.CSSSourceFrame.ColorPosition = function(color, lineNumber, startColumn, textLength) +{ + this.color = color; + this.textRange = new WebInspector.TextRange(lineNumber, startColumn, lineNumber, startColumn + textLength); +} + +/** + * @constructor * @implements {WebInspector.TextEditorAutocompleteDelegate} */ WebInspector.CSSSourceFrame.AutocompleteDelegate = function()
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/EventListenerBreakpointsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/EventListenerBreakpointsSidebarPane.js index 3cfa98e..3b5e208 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/EventListenerBreakpointsSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/EventListenerBreakpointsSidebarPane.js
@@ -42,7 +42,7 @@ this._createCategory(WebInspector.UIString("Window"), ["close"], true); this._createCategory(WebInspector.UIString("XHR"), ["readystatechange", "load", "loadstart", "loadend", "abort", "error", "progress", "timeout"], false, ["XMLHttpRequest", "XMLHttpRequestUpload"]); - WebInspector.targetManager.observeTargets(this, WebInspector.Target.Type.Page); + WebInspector.targetManager.observeTargets(this, WebInspector.Target.Capability.Browser); } WebInspector.EventListenerBreakpointsSidebarPane.categoryListener = "listener:"; @@ -234,20 +234,20 @@ */ _updateBreakpointOnTarget: function(eventName, eventTargetName, enable, target) { - var targets = target ? [target] : WebInspector.targetManager.targets(WebInspector.Target.Type.Page); - for (var i = 0; i < targets.length; ++i) { + var targets = target ? [target] : WebInspector.targetManager.targets(WebInspector.Target.Capability.Browser); + for (target of targets) { if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categoryListener)) { var protocolEventName = eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categoryListener.length); if (enable) - targets[i].domdebuggerAgent().setEventListenerBreakpoint(protocolEventName, eventTargetName); + target.domdebuggerAgent().setEventListenerBreakpoint(protocolEventName, eventTargetName); else - targets[i].domdebuggerAgent().removeEventListenerBreakpoint(protocolEventName, eventTargetName); + target.domdebuggerAgent().removeEventListenerBreakpoint(protocolEventName, eventTargetName); } else if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categoryInstrumentation)) { var protocolEventName = eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categoryInstrumentation.length); if (enable) - targets[i].domdebuggerAgent().setInstrumentationBreakpoint(protocolEventName); + target.domdebuggerAgent().setInstrumentationBreakpoint(protocolEventName); else - targets[i].domdebuggerAgent().removeInstrumentationBreakpoint(protocolEventName); + target.domdebuggerAgent().removeInstrumentationBreakpoint(protocolEventName); } } },
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js b/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js index f742218..95b6464 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js
@@ -399,7 +399,7 @@ var targetNode = this._rootNode.child("target:" + target.id()); if (!targetNode) { - targetNode = new WebInspector.NavigatorGroupTreeNode(this, project, "target:" + target.id(), target.isWorker() ? WebInspector.NavigatorView.Types.Worker : WebInspector.NavigatorView.Types.NetworkFolder, target.name()); + targetNode = new WebInspector.NavigatorGroupTreeNode(this, project, "target:" + target.id(), !target.hasBrowserCapability() ? WebInspector.NavigatorView.Types.Worker : WebInspector.NavigatorView.Types.NetworkFolder, target.name()); this._rootNode.appendChild(targetNode); } return targetNode;
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js b/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js index 955d19d3..4816c9f 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/SourceMapNamesResolver.js
@@ -573,15 +573,6 @@ return this._object.isNode(); }, - /** - * @override - * @param {function(?WebInspector.DebuggerModel.FunctionDetails)} callback - */ - functionDetails: function(callback) - { - this._object.functionDetails(callback); - }, - __proto__: WebInspector.RemoteObject.prototype }
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js index 80306fd..1105848 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
@@ -1038,7 +1038,7 @@ */ _showFunctionDefinition: function(remoteObject) { - remoteObject.debuggerModel().functionDetails(remoteObject, this._didGetFunctionDetails.bind(this)); + remoteObject.debuggerModel().functionDetailsPromise(remoteObject).then(this._didGetFunctionDetails.bind(this)); }, /**
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/XHRBreakpointsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/XHRBreakpointsSidebarPane.js index 8243eae..26038c1 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/XHRBreakpointsSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/XHRBreakpointsSidebarPane.js
@@ -21,7 +21,7 @@ this.emptyElement.addEventListener("contextmenu", this._emptyElementContextMenu.bind(this), true); - WebInspector.targetManager.observeTargets(this, WebInspector.Target.Type.Page); + WebInspector.targetManager.observeTargets(this, WebInspector.Target.Capability.Browser); } WebInspector.XHRBreakpointsSidebarPane.prototype = { @@ -139,12 +139,12 @@ */ _updateBreakpointOnTarget: function(url, enable, target) { - var targets = target ? [target] : WebInspector.targetManager.targets(WebInspector.Target.Type.Page); - for (var i = 0; i < targets.length; ++i) { + var targets = target ? [target] : WebInspector.targetManager.targets(WebInspector.Target.Capability.Browser); + for (target of targets) { if (enable) - targets[i].domdebuggerAgent().setXHRBreakpoint(url); + target.domdebuggerAgent().setXHRBreakpoint(url); else - targets[i].domdebuggerAgent().removeXHRBreakpoint(url); + target.domdebuggerAgent().removeXHRBreakpoint(url); } },
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js index 63a911ee..d567d30b 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelinePanel.js
@@ -2002,7 +2002,7 @@ { this._targets = []; this._throttlingRate = 1.; // No throttling - WebInspector.targetManager.observeTargets(this, WebInspector.Target.Type.Page); + WebInspector.targetManager.observeTargets(this, WebInspector.Target.Capability.Browser); } WebInspector.CPUThrottlingManager.prototype = {
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js index 025a36c..21471d7 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js
@@ -86,7 +86,7 @@ */ linkifyLocation: function(frame) { - return this._linkifier.linkifyConsoleCallFrame(this._model.target(), frame); + return this._linkifier.linkifyConsoleCallFrameForTimeline(this._model.target(), frame); }, /** @@ -618,10 +618,10 @@ */ _createAggregator: function() { - return new WebInspector.TimelineAggregator( - event => WebInspector.TimelineUIUtils.eventStyle(event).title, - event => WebInspector.TimelineUIUtils.eventStyle(event).category.name - ); + return new WebInspector.TimelineAggregator( + event => WebInspector.TimelineUIUtils.eventStyle(event).title, + event => WebInspector.TimelineUIUtils.eventStyle(event).category.name + ); }, __proto__: WebInspector.TimelineTreeView.prototype,
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js index d374d3c..ead36900 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline/TimelineUIUtils.js
@@ -619,7 +619,7 @@ function linkifyTopCallFrame() { var frame = WebInspector.TimelineUIUtils.topStackFrame(event); - return frame ? linkifier.linkifyConsoleCallFrame(target, frame, "timeline-details") : null; + return frame ? linkifier.linkifyConsoleCallFrameForTimeline(target, frame, "timeline-details") : null; } } @@ -803,7 +803,7 @@ break; case recordTypes.Layout: var beginData = event.args["beginData"]; - contentHelper.appendTextRow(WebInspector.UIString("Nodes That Need Layout"), beginData["dirtyObjects"]); + contentHelper.appendTextRow(WebInspector.UIString("Nodes That Need Layout"), WebInspector.UIString("%s of %s", beginData["dirtyObjects"], beginData["totalObjects"])); relatedNodeLabel = WebInspector.UIString("Layout root"); break; case recordTypes.ConsoleTime: @@ -996,7 +996,7 @@ var sendRequest = request.children[0]; var topFrame = WebInspector.TimelineUIUtils.topStackFrame(sendRequest); if (topFrame) { - contentHelper.appendElementRow(title, linkifier.linkifyConsoleCallFrame(target, topFrame)); + contentHelper.appendElementRow(title, linkifier.linkifyConsoleCallFrameForTimeline(target, topFrame)); } else if (sendRequest.initiator) { var initiatorURL = WebInspector.TimelineUIUtils.eventURL(sendRequest.initiator); if (initiatorURL) @@ -1241,7 +1241,7 @@ var stack = title.createChild("span", "monospace"); stack.createChild("span").textContent = WebInspector.beautifyFunctionName(topFrame.functionName); stack.createChild("span").textContent = " @ "; - stack.createChild("span").appendChild(this._contentHelper.linkifier().linkifyConsoleCallFrame(target, topFrame)); + stack.createChild("span").appendChild(this._contentHelper.linkifier().linkifyConsoleCallFrameForTimeline(target, topFrame)); } return title;
diff --git a/third_party/WebKit/Source/devtools/front_end/timeline_model/LayerTreeModel.js b/third_party/WebKit/Source/devtools/front_end/timeline_model/LayerTreeModel.js index 001735f..f78e14db 100644 --- a/third_party/WebKit/Source/devtools/front_end/timeline_model/LayerTreeModel.js +++ b/third_party/WebKit/Source/devtools/front_end/timeline_model/LayerTreeModel.js
@@ -1299,7 +1299,7 @@ */ WebInspector.LayerTreeModel.fromTarget = function(target) { - if (!target.isPage()) + if (!target.hasBrowserCapability()) return null; var model = /** @type {?WebInspector.LayerTreeModel} */ (target.model(WebInspector.LayerTreeModel));
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/ColorSwatch.js b/third_party/WebKit/Source/devtools/front_end/ui/ColorSwatch.js index 2262add..7fe3f20 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/ColorSwatch.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/ColorSwatch.js
@@ -43,6 +43,14 @@ }, /** + * @param {boolean} hide + */ + hideText: function(hide) + { + this._colorValueElement.hidden = hide; + }, + + /** * @return {!WebInspector.Color.Format} */ format: function()
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js b/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js index 711d4837..6a000d9 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/Toolbar.js
@@ -945,7 +945,7 @@ if (extensions[i].descriptor()["location"] === location) promises.push(resolveItem(extensions[i])); } - this._promise = Promise.all(promises).then(appendItemsInOrder.bind(this)); + Promise.all(promises).then(appendItemsInOrder.bind(this)); /** * @param {!Runtime.Extension} extension @@ -985,13 +985,5 @@ } }, - /** - * @return {!Promise} - */ - onLoad: function() - { - return this._promise; - }, - __proto__: WebInspector.Toolbar.prototype }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js index 48a123b..695643f0 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js
@@ -1504,6 +1504,15 @@ this.checkboxElement.style.borderColor = color; }, + /** + * @param {boolean} focus + * @this {Element} + */ + set visualizeFocus(focus) + { + this.checkboxElement.classList.toggle("dt-checkbox-visualize-focus", focus); + }, + __proto__: HTMLLabelElement.prototype });
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/checkboxTextLabel.css b/third_party/WebKit/Source/devtools/front_end/ui/checkboxTextLabel.css index 5d876fe..4f3cd80d 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/checkboxTextLabel.css +++ b/third_party/WebKit/Source/devtools/front_end/ui/checkboxTextLabel.css
@@ -18,6 +18,10 @@ flex-shrink: 0; } +input.dt-checkbox-visualize-focus:focus { + outline: auto 5px -webkit-focus-ring-color; +} + input.dt-checkbox-themed { -webkit-appearance: none; margin: 0 5px auto 2px;
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/filter.css b/third_party/WebKit/Source/devtools/front_end/ui/filter.css index 7987f02..d741dfe 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/filter.css +++ b/third_party/WebKit/Source/devtools/front_end/ui/filter.css
@@ -30,7 +30,7 @@ .filter-bar { background-color: #f3f3f3; - padding: 4px 0 4px 0; + padding: 2px 0; flex: none; flex-wrap: wrap; align-items: center; @@ -63,10 +63,10 @@ display: inline-block; flex: none; margin: auto 2px; - padding: 3px 6px 3px 3px; + padding: 3px; background: transparent; text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0; - border-radius: 8px; + border-radius: 6px; overflow: hidden; }
diff --git a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp index cf28e55..109ce6a 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXLayoutObject.cpp
@@ -2029,6 +2029,11 @@ if (!frame) return; + // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited. + // see http://crbug.com/590369 for more details. + // This callsite should probably move up the stack. + frame->document()->updateStyleAndLayoutIgnorePendingStylesheets(); + // Set the selection based on visible positions, because the offsets in accessibility nodes // are based on visible indexes, which often skips redundant whitespace, for example. VisiblePosition anchorVisiblePosition = anchorNode->isTextNode()
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp index 93d5da6..cbb0e6d 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp
@@ -865,7 +865,7 @@ localRelatedObjects.append(new NameSourceRelatedObject(axElement, result)); if (!result.isEmpty()) { if (!accumulatedText.isEmpty()) - accumulatedText.append(" "); + accumulatedText.append(' '); accumulatedText.append(result); } }
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.cpp b/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.cpp index 0aff29dd..b10b14c 100644 --- a/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.cpp +++ b/third_party/WebKit/Source/modules/accessibility/AXObjectCacheImpl.cpp
@@ -1075,7 +1075,7 @@ const Element* AXObjectCacheImpl::rootAXEditableElement(const Node* node) { - const Element* result = node->rootEditableElement(); + const Element* result = rootEditableElement(*node); const Element* element = node->isElementNode() ? toElement(node) : node->parentElement(); for (; element; element = element->parentElement()) {
diff --git a/third_party/WebKit/Source/modules/audio_output_devices/AudioOutputDeviceClient.cpp b/third_party/WebKit/Source/modules/audio_output_devices/AudioOutputDeviceClient.cpp index 2bda77e..31fa813 100644 --- a/third_party/WebKit/Source/modules/audio_output_devices/AudioOutputDeviceClient.cpp +++ b/third_party/WebKit/Source/modules/audio_output_devices/AudioOutputDeviceClient.cpp
@@ -32,4 +32,9 @@ frame.provideSupplement(AudioOutputDeviceClient::supplementName(), client); } +DEFINE_TRACE(AudioOutputDeviceClient) +{ + Supplement<LocalFrame>::trace(visitor); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/modules/audio_output_devices/AudioOutputDeviceClient.h b/third_party/WebKit/Source/modules/audio_output_devices/AudioOutputDeviceClient.h index 7d824bd..363c4ae 100644 --- a/third_party/WebKit/Source/modules/audio_output_devices/AudioOutputDeviceClient.h +++ b/third_party/WebKit/Source/modules/audio_output_devices/AudioOutputDeviceClient.h
@@ -5,6 +5,7 @@ #ifndef AudioOutputDeviceClient_h #define AudioOutputDeviceClient_h +#include "core/frame/LocalFrame.h" #include "modules/ModulesExport.h" #include "platform/Supplementable.h" #include "public/platform/WebSetSinkIdCallbacks.h" @@ -13,17 +14,18 @@ namespace blink { class ExecutionContext; -class LocalFrame; class WebString; class ScriptState; -class AudioOutputDeviceClient : public Supplement<LocalFrame> { +class MODULES_EXPORT AudioOutputDeviceClient : public Supplement<LocalFrame> { public: virtual ~AudioOutputDeviceClient() {} // Checks that a given sink exists and has permissions to be used from the origin of the current frame. virtual void checkIfAudioSinkExistsAndIsAuthorized(ExecutionContext*, const WebString& sinkId, std::unique_ptr<WebSetSinkIdCallbacks>) = 0; + DECLARE_VIRTUAL_TRACE(); + // Supplement requirements. static AudioOutputDeviceClient* from(ExecutionContext*); static const char* supplementName();
diff --git a/third_party/WebKit/Source/modules/cachestorage/Cache.cpp b/third_party/WebKit/Source/modules/cachestorage/Cache.cpp index 3a3787ef..1ec1096 100644 --- a/third_party/WebKit/Source/modules/cachestorage/Cache.cpp +++ b/third_party/WebKit/Source/modules/cachestorage/Cache.cpp
@@ -50,6 +50,7 @@ { if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContext()->activeDOMObjectsAreStopped()) return; + ScriptState::Scope scope(m_resolver->getScriptState()); m_resolver->resolve(Response::create(m_resolver->getScriptState(), webResponse)); m_resolver.clear(); } @@ -80,6 +81,7 @@ { if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContext()->activeDOMObjectsAreStopped()) return; + ScriptState::Scope scope(m_resolver->getScriptState()); HeapVector<Member<Response>> responses; for (size_t i = 0; i < webResponses.size(); ++i) responses.append(Response::create(m_resolver->getScriptState(), webResponses[i])); @@ -140,6 +142,7 @@ { if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContext()->activeDOMObjectsAreStopped()) return; + ScriptState::Scope scope(m_resolver->getScriptState()); HeapVector<Member<Request>> requests; for (size_t i = 0; i < webRequests.size(); ++i) requests.append(Request::create(m_resolver->getScriptState(), webRequests[i]));
diff --git a/third_party/WebKit/Source/modules/cachestorage/CacheStorage.cpp b/third_party/WebKit/Source/modules/cachestorage/CacheStorage.cpp index 057bd46cc..2abd491b 100644 --- a/third_party/WebKit/Source/modules/cachestorage/CacheStorage.cpp +++ b/third_party/WebKit/Source/modules/cachestorage/CacheStorage.cpp
@@ -131,6 +131,7 @@ { if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContext()->activeDOMObjectsAreStopped()) return; + ScriptState::Scope scope(m_resolver->getScriptState()); m_resolver->resolve(Response::create(m_resolver->getScriptState(), webResponse)); m_resolver.clear(); }
diff --git a/third_party/WebKit/Source/modules/cachestorage/InspectorCacheStorageAgent.cpp b/third_party/WebKit/Source/modules/cachestorage/InspectorCacheStorageAgent.cpp index a509375..232b7e3 100644 --- a/third_party/WebKit/Source/modules/cachestorage/InspectorCacheStorageAgent.cpp +++ b/third_party/WebKit/Source/modules/cachestorage/InspectorCacheStorageAgent.cpp
@@ -46,7 +46,7 @@ String buildCacheId(const String& securityOrigin, const String& cacheName) { String id(securityOrigin); - id.append("|"); + id.append('|'); id.append(cacheName); return id; }
diff --git a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp index 1a0c7ffd..1b0724c3 100644 --- a/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp +++ b/third_party/WebKit/Source/modules/canvas2d/CanvasRenderingContext2DTest.cpp
@@ -469,8 +469,9 @@ sourceCanvas->createImageBufferUsingSurfaceForTesting(std::move(sourceSurface)); const ImageBitmapOptions defaultOptions; + Optional<IntRect> cropRect = IntRect(IntPoint(0, 0), sourceSize); // Go through an ImageBitmap to avoid triggering a display list fallback - ImageBitmap* sourceImageBitmap = ImageBitmap::create(sourceCanvas, IntRect(IntPoint(0, 0), sourceSize), defaultOptions); + ImageBitmap* sourceImageBitmap = ImageBitmap::create(sourceCanvas, cropRect, defaultOptions); context2d()->drawImage(canvasElement().getExecutionContext(), sourceImageBitmap, 0, 0, 1, 1, 0, 0, 1, 1, exceptionState); EXPECT_FALSE(exceptionState.hadException()); @@ -493,8 +494,9 @@ sourceCanvas->createImageBufferUsingSurfaceForTesting(std::move(sourceSurface)); const ImageBitmapOptions defaultOptions; + Optional<IntRect> cropRect = IntRect(IntPoint(0, 0), sourceSize); // Go through an ImageBitmap to avoid triggering a display list fallback - ImageBitmap* sourceImageBitmap = ImageBitmap::create(sourceCanvas, IntRect(IntPoint(0, 0), sourceSize), defaultOptions); + ImageBitmap* sourceImageBitmap = ImageBitmap::create(sourceCanvas, cropRect, defaultOptions); context2d()->drawImage(canvasElement().getExecutionContext(), sourceImageBitmap, 0, 0, 1, 1, 0, 0, 1, 1, exceptionState); EXPECT_FALSE(exceptionState.hadException()); @@ -683,8 +685,10 @@ ImageBitmap* imageBitmapDerived = nullptr; { const ImageBitmapOptions defaultOptions; - ImageBitmap* imageBitmapFromCanvas = ImageBitmap::create(canvas, IntRect(0, 0, canvas->width(), canvas->height()), defaultOptions); - imageBitmapDerived = ImageBitmap::create(imageBitmapFromCanvas, IntRect(0, 0, 20, 20), defaultOptions); + Optional<IntRect> cropRect = IntRect(0, 0, canvas->width(), canvas->height()); + ImageBitmap* imageBitmapFromCanvas = ImageBitmap::create(canvas, cropRect, defaultOptions); + cropRect = IntRect(0, 0, 20, 20); + imageBitmapDerived = ImageBitmap::create(imageBitmapFromCanvas, cropRect, defaultOptions); } CanvasContextCreationAttributes attributes; CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(canvas->getCanvasRenderingContext("2d", attributes)); @@ -783,9 +787,15 @@ context2d()->getImageData(0, 0, 1, 1, exceptionState); EXPECT_FALSE(exceptionState.hadException()); - EXPECT_FALSE(bridge->isAccelerated()); - EXPECT_EQ(0u, getGlobalAcceleratedImageBufferCount()); - EXPECT_EQ(0, getGlobalGPUMemoryUsage()); + if (ExpensiveCanvasHeuristicParameters::GetImageDataForcesNoAcceleration) { + EXPECT_FALSE(bridge->isAccelerated()); + EXPECT_EQ(0u, getGlobalAcceleratedImageBufferCount()); + EXPECT_EQ(0, getGlobalGPUMemoryUsage()); + } else { + EXPECT_TRUE(bridge->isAccelerated()); + EXPECT_EQ(1u, getGlobalAcceleratedImageBufferCount()); + EXPECT_EQ(720000, getGlobalGPUMemoryUsage()); + } // Restore global state to prevent side-effects on other tests RuntimeEnabledFeatures::setCanvas2dFixedRenderingModeEnabled(savedFixedRenderingMode);
diff --git a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp index bc13d96..43d24aa 100644 --- a/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp +++ b/third_party/WebKit/Source/modules/compositorworker/CompositorWorkerThreadTest.cpp
@@ -41,7 +41,6 @@ virtual void reportException(const String& errorMessage, std::unique_ptr<SourceLocation>) {} void reportConsoleMessage(ConsoleMessage*) override {} void postMessageToPageInspector(const String&) override {} - void postWorkerConsoleAgentEnabled() override {} void didEvaluateWorkerScript(bool success) override {} void workerGlobalScopeStarted(WorkerGlobalScope*) override {}
diff --git a/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.cpp b/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.cpp index ff04f11b..7db6844 100644 --- a/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.cpp +++ b/third_party/WebKit/Source/modules/crypto/CryptoResultImpl.cpp
@@ -192,7 +192,7 @@ ScriptState* scriptState = m_resolver->getScriptState(); ScriptState::Scope scope(scriptState); - v8::Local<v8::String> jsonString = v8AtomicString(scriptState->isolate(), utf8Data, length); + v8::Local<v8::String> jsonString = v8StringFromUtf8(scriptState->isolate(), utf8Data, length); v8::TryCatch exceptionCatcher(scriptState->isolate()); v8::Local<v8::Value> jsonDictionary;
diff --git a/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.cpp b/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.cpp index ba9e7486..963a504 100644 --- a/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.cpp +++ b/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.cpp
@@ -21,6 +21,19 @@ namespace blink { +namespace { + +IntSize getSpecifiedSize(const IntSize& size, float zoom) +{ + float unZoomFactor = 1 / zoom; + auto unZoomFn = [unZoomFactor](int a) -> int { + return round(a * unZoomFactor); + }; + return IntSize(unZoomFn(size.width()), unZoomFn(size.height())); +} + +} // namespace + CSSPaintDefinition* CSSPaintDefinition::create(ScriptState* scriptState, v8::Local<v8::Function> constructor, v8::Local<v8::Function> paint, Vector<CSSPropertyID>& nativeInvalidationProperties, Vector<AtomicString>& customInvalidationProperties, bool hasAlpha) { return new CSSPaintDefinition(scriptState, constructor, paint, nativeInvalidationProperties, customInvalidationProperties, hasAlpha); @@ -41,8 +54,10 @@ { } -PassRefPtr<Image> CSSPaintDefinition::paint(const LayoutObject& layoutObject, const IntSize& size) +PassRefPtr<Image> CSSPaintDefinition::paint(const LayoutObject& layoutObject, const IntSize& size, float zoom) { + const IntSize specifiedSize = getSpecifiedSize(size, zoom); + ScriptState::Scope scope(m_scriptState.get()); maybeCreatePaintInstance(); @@ -58,8 +73,8 @@ DCHECK(layoutObject.node()); PaintRenderingContext2D* renderingContext = PaintRenderingContext2D::create( - ImageBuffer::create(wrapUnique(new RecordingImageBufferSurface(size, nullptr /* fallbackFactory */, m_hasAlpha ? NonOpaque : Opaque))), m_hasAlpha); - PaintSize* paintSize = PaintSize::create(size); + ImageBuffer::create(wrapUnique(new RecordingImageBufferSurface(size, nullptr /* fallbackFactory */, m_hasAlpha ? NonOpaque : Opaque))), m_hasAlpha, zoom); + PaintSize* paintSize = PaintSize::create(specifiedSize); StylePropertyMap* styleMap = FilteredComputedStylePropertyMap::create( CSSComputedStyleDeclaration::create(layoutObject.node()), m_nativeInvalidationProperties, m_customInvalidationProperties); @@ -83,7 +98,7 @@ return nullptr; } - return PaintGeneratedImage::create(renderingContext->imageBuffer()->getPicture(), size); + return PaintGeneratedImage::create(renderingContext->imageBuffer()->getPicture(), specifiedSize); } void CSSPaintDefinition::maybeCreatePaintInstance()
diff --git a/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.h b/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.h index 7e0df358b..b4b720a 100644 --- a/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.h +++ b/third_party/WebKit/Source/modules/csspaint/CSSPaintDefinition.h
@@ -30,7 +30,7 @@ // // This may return a nullptr (representing an invalid image) if javascript // throws an error. - PassRefPtr<Image> paint(const LayoutObject&, const IntSize&); + PassRefPtr<Image> paint(const LayoutObject&, const IntSize&, float zoom); const Vector<CSSPropertyID>& nativeInvalidationProperties() const { return m_nativeInvalidationProperties; } const Vector<AtomicString>& customInvalidationProperties() const { return m_customInvalidationProperties; } bool hasAlpha() const { return m_hasAlpha; }
diff --git a/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.cpp b/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.cpp index 416c0a8..733767a4 100644 --- a/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.cpp +++ b/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.cpp
@@ -53,9 +53,9 @@ m_observer->paintImageGeneratorReady(); } -PassRefPtr<Image> CSSPaintImageGeneratorImpl::paint(const LayoutObject& layoutObject, const IntSize& size) +PassRefPtr<Image> CSSPaintImageGeneratorImpl::paint(const LayoutObject& layoutObject, const IntSize& size, float zoom) { - return m_definition ? m_definition->paint(layoutObject, size) : nullptr; + return m_definition ? m_definition->paint(layoutObject, size, zoom) : nullptr; } const Vector<CSSPropertyID>& CSSPaintImageGeneratorImpl::nativeInvalidationProperties() const
diff --git a/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.h b/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.h index a4c8f3e..561b2eb6 100644 --- a/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.h +++ b/third_party/WebKit/Source/modules/csspaint/CSSPaintImageGeneratorImpl.h
@@ -22,7 +22,7 @@ static CSSPaintImageGenerator* create(const String& name, Document&, Observer*); ~CSSPaintImageGeneratorImpl() override; - PassRefPtr<Image> paint(const LayoutObject&, const IntSize&) final; + PassRefPtr<Image> paint(const LayoutObject&, const IntSize&, float zoom) final; const Vector<CSSPropertyID>& nativeInvalidationProperties() const final; const Vector<AtomicString>& customInvalidationProperties() const final; bool hasAlpha() const final;
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.cpp b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.cpp index 19884e3..28f6a81 100644 --- a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.cpp +++ b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.cpp
@@ -9,17 +9,18 @@ namespace blink { -PaintRenderingContext2D::PaintRenderingContext2D(std::unique_ptr<ImageBuffer> imageBuffer, bool hasAlpha) +PaintRenderingContext2D::PaintRenderingContext2D(std::unique_ptr<ImageBuffer> imageBuffer, bool hasAlpha, float zoom) : m_imageBuffer(std::move(imageBuffer)), m_hasAlpha(hasAlpha) { m_clipAntialiasing = AntiAliased; modifiableState().setShouldAntialias(true); - // RecordingImageBufferSurface doesn't call ImageBufferSurface::clear explicitly. DCHECK(m_imageBuffer); m_imageBuffer->canvas()->clear(hasAlpha ? SK_ColorTRANSPARENT : SK_ColorBLACK); m_imageBuffer->didDraw(FloatRect(0, 0, width(), height())); + + m_imageBuffer->canvas()->scale(zoom, zoom); } int PaintRenderingContext2D::width() const
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.h b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.h index 9ce602f..9c98aea4 100644 --- a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.h +++ b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.h
@@ -23,9 +23,9 @@ USING_GARBAGE_COLLECTED_MIXIN(PaintRenderingContext2D); WTF_MAKE_NONCOPYABLE(PaintRenderingContext2D); public: - static PaintRenderingContext2D* create(std::unique_ptr<ImageBuffer> imageBuffer, bool hasAlpha) + static PaintRenderingContext2D* create(std::unique_ptr<ImageBuffer> imageBuffer, bool hasAlpha, float zoom) { - return new PaintRenderingContext2D(std::move(imageBuffer), hasAlpha); + return new PaintRenderingContext2D(std::move(imageBuffer), hasAlpha, zoom); } // BaseRenderingContext2D @@ -68,7 +68,7 @@ bool isContextLost() const final { return false; } private: - PaintRenderingContext2D(std::unique_ptr<ImageBuffer>, bool hasAlpha); + PaintRenderingContext2D(std::unique_ptr<ImageBuffer>, bool hasAlpha, float zoom); std::unique_ptr<ImageBuffer> m_imageBuffer; bool m_hasAlpha;
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2DTest.cpp b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2DTest.cpp index acf37dd..891ef2f 100644 --- a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2DTest.cpp +++ b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2DTest.cpp
@@ -12,6 +12,7 @@ static const int s_width = 50; static const int s_height = 75; +static const float s_zoom = 1.0; class PaintRenderingContext2DTest : public ::testing::Test { protected: @@ -22,7 +23,7 @@ void PaintRenderingContext2DTest::SetUp() { - m_ctx = PaintRenderingContext2D::create(ImageBuffer::create(IntSize(s_width, s_height)), false /* hasAlpha */); + m_ctx = PaintRenderingContext2D::create(ImageBuffer::create(IntSize(s_width, s_height)), false /* hasAlpha */, s_zoom); } void trySettingStrokeStyle(PaintRenderingContext2D* ctx, const String& expected, const String& value)
diff --git a/third_party/WebKit/Source/modules/fetch/Body.idl b/third_party/WebKit/Source/modules/fetch/Body.idl index 0908a63..c00f5c5 100644 --- a/third_party/WebKit/Source/modules/fetch/Body.idl +++ b/third_party/WebKit/Source/modules/fetch/Body.idl
@@ -3,7 +3,7 @@ // found in the LICENSE file. // http://fetch.spec.whatwg.org/#body -typedef object JSON; + [ ActiveScriptWrappable, DependentLifetime,
diff --git a/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.cpp b/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.cpp index a339b1e..b21ff4f 100644 --- a/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.cpp +++ b/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.cpp
@@ -106,7 +106,6 @@ , m_madeFromReadableStream(false) { if (RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()) { - ScriptState::Scope scope(scriptState); if (isTerminating(scriptState)) { m_reader = nullptr; m_handle = nullptr; @@ -141,7 +140,6 @@ , m_scriptState(scriptState) , m_madeFromReadableStream(true) { - ScriptState::Scope scope(scriptState); DCHECK(RuntimeEnabledFeatures::responseBodyWithV8ExtraStreamEnabled()); DCHECK(ReadableStreamOperations::isReadableStream(scriptState, stream)); if (isTerminating(scriptState)) @@ -228,7 +226,6 @@ *branch2 = nullptr; if (m_madeFromReadableStream) { - ScriptState::Scope scope(m_scriptState.get()); ScriptValue stream1, stream2; ReadableStreamOperations::tee(m_scriptState.get(), stream(), &stream1, &stream2); *branch1 = new BodyStreamBuffer(m_scriptState.get(), stream1);
diff --git a/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.h b/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.h index ba0226b..403b0b1 100644 --- a/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.h +++ b/third_party/WebKit/Source/modules/fetch/BodyStreamBuffer.h
@@ -31,8 +31,10 @@ // Needed because we have to release |m_reader| promptly. EAGERLY_FINALIZE(); // |handle| cannot be null and cannot be locked. + // This function must be called with entering an appropriate V8 context. BodyStreamBuffer(ScriptState*, std::unique_ptr<FetchDataConsumerHandle> /* handle */); // |ReadableStreamOperations::isReadableStream(stream)| must hold. + // This function must be called with entering an appropriate V8 context. BodyStreamBuffer(ScriptState*, ScriptValue stream); ScriptValue stream();
diff --git a/third_party/WebKit/Source/modules/fetch/BodyStreamBufferTest.cpp b/third_party/WebKit/Source/modules/fetch/BodyStreamBufferTest.cpp index defd829..a547d78 100644 --- a/third_party/WebKit/Source/modules/fetch/BodyStreamBufferTest.cpp +++ b/third_party/WebKit/Source/modules/fetch/BodyStreamBufferTest.cpp
@@ -4,8 +4,8 @@ #include "modules/fetch/BodyStreamBuffer.h" +#include "bindings/core/v8/V8BindingForTesting.h" #include "core/html/FormData.h" -#include "core/testing/DummyPageHolder.h" #include "modules/fetch/DataConsumerHandleTestUtil.h" #include "modules/fetch/FetchBlobDataConsumerHandle.h" #include "modules/fetch/FetchFormDataConsumerHandle.h" @@ -40,40 +40,28 @@ }; class BodyStreamBufferTest : public ::testing::Test { -public: - BodyStreamBufferTest() - { - m_page = DummyPageHolder::create(IntSize(1, 1)); - } - ~BodyStreamBufferTest() override {} - protected: - ScriptState* getScriptState() { return ScriptState::forMainWorld(m_page->document().frame()); } - ExecutionContext* getExecutionContext() { return &m_page->document(); } - - std::unique_ptr<DummyPageHolder> m_page; - - ScriptValue eval(const char* s) + ScriptValue eval(ScriptState* scriptState, const char* s) { v8::Local<v8::String> source; v8::Local<v8::Script> script; - v8::MicrotasksScope microtasks(getScriptState()->isolate(), v8::MicrotasksScope::kDoNotRunMicrotasks); - if (!v8Call(v8::String::NewFromUtf8(getScriptState()->isolate(), s, v8::NewStringType::kNormal), source)) { + v8::MicrotasksScope microtasks(scriptState->isolate(), v8::MicrotasksScope::kDoNotRunMicrotasks); + if (!v8Call(v8::String::NewFromUtf8(scriptState->isolate(), s, v8::NewStringType::kNormal), source)) { ADD_FAILURE(); return ScriptValue(); } - if (!v8Call(v8::Script::Compile(getScriptState()->context(), source), script)) { + if (!v8Call(v8::Script::Compile(scriptState->context(), source), script)) { ADD_FAILURE() << "Compilation fails"; return ScriptValue(); } - return ScriptValue(getScriptState(), script->Run(getScriptState()->context())); + return ScriptValue(scriptState, script->Run(scriptState->context())); } - ScriptValue evalWithPrintingError(const char* s) + ScriptValue evalWithPrintingError(ScriptState* scriptState, const char* s) { - v8::TryCatch block(getScriptState()->isolate()); - ScriptValue r = eval(s); + v8::TryCatch block(scriptState->isolate()); + ScriptValue r = eval(scriptState, s); if (block.HasCaught()) { - ADD_FAILURE() << toCoreString(block.Exception()->ToString(getScriptState()->isolate())).utf8().data(); + ADD_FAILURE() << toCoreString(block.Exception()->ToString(scriptState->isolate())).utf8().data(); block.ReThrow(); } return r; @@ -82,6 +70,7 @@ TEST_F(BodyStreamBufferTest, Tee) { + V8TestingScope scope; Checkpoint checkpoint; MockFetchDataLoaderClient* client1 = MockFetchDataLoaderClient::create(); MockFetchDataLoaderClient* client2 = MockFetchDataLoaderClient::create(); @@ -98,7 +87,7 @@ handle->add(DataConsumerHandleTestUtil::Command(DataConsumerHandleTestUtil::Command::Data, "hello, ")); handle->add(DataConsumerHandleTestUtil::Command(DataConsumerHandleTestUtil::Command::Data, "world")); handle->add(DataConsumerHandleTestUtil::Command(DataConsumerHandleTestUtil::Command::Done)); - BodyStreamBuffer* buffer = new BodyStreamBuffer(getScriptState(), createFetchDataConsumerHandleFromWebHandle(std::move(handle))); + BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), createFetchDataConsumerHandleFromWebHandle(std::move(handle))); BodyStreamBuffer* new1; BodyStreamBuffer* new2; @@ -121,8 +110,9 @@ TEST_F(BodyStreamBufferTest, TeeFromHandleMadeFromStream) { - ScriptState::Scope scope(getScriptState()); + V8TestingScope scope; ScriptValue stream = evalWithPrintingError( + scope.getScriptState(), "stream = new ReadableStream({start: c => controller = c});" "controller.enqueue(new Uint8Array([0x41, 0x42]));" "controller.enqueue(new Uint8Array([0x55, 0x58]));" @@ -140,7 +130,7 @@ EXPECT_CALL(*client2, didFetchDataLoadedString(String("ABUX"))); EXPECT_CALL(checkpoint, Call(4)); - BodyStreamBuffer* buffer = new BodyStreamBuffer(getScriptState(), stream); + BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), stream); BodyStreamBuffer* new1; BodyStreamBuffer* new2; @@ -155,7 +145,7 @@ EXPECT_FALSE(buffer->isStreamDisturbed()); EXPECT_FALSE(buffer->hasPendingActivity()); - v8::MicrotasksScope::PerformCheckpoint(getScriptState()->isolate()); + v8::MicrotasksScope::PerformCheckpoint(scope.getScriptState()->isolate()); EXPECT_TRUE(buffer->isStreamLocked()); EXPECT_TRUE(buffer->isStreamDisturbed()); @@ -174,11 +164,12 @@ TEST_F(BodyStreamBufferTest, DrainAsBlobDataHandle) { + V8TestingScope scope; std::unique_ptr<BlobData> data = BlobData::create(); data->appendText("hello", false); auto size = data->length(); RefPtr<BlobDataHandle> blobDataHandle = BlobDataHandle::create(std::move(data), size); - BodyStreamBuffer* buffer = new BodyStreamBuffer(getScriptState(), FetchBlobDataConsumerHandle::create(getExecutionContext(), blobDataHandle, new FakeLoaderFactory)); + BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), FetchBlobDataConsumerHandle::create(scope.getExecutionContext(), blobDataHandle, new FakeLoaderFactory)); EXPECT_FALSE(buffer->isStreamLocked()); EXPECT_FALSE(buffer->isStreamDisturbed()); @@ -193,9 +184,10 @@ TEST_F(BodyStreamBufferTest, DrainAsBlobDataHandleReturnsNull) { + V8TestingScope scope; // This handle is not drainable. std::unique_ptr<FetchDataConsumerHandle> handle = createFetchDataConsumerHandleFromWebHandle(createWaitingDataConsumerHandle()); - BodyStreamBuffer* buffer = new BodyStreamBuffer(getScriptState(), std::move(handle)); + BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), std::move(handle)); EXPECT_FALSE(buffer->isStreamLocked()); EXPECT_FALSE(buffer->isStreamDisturbed()); @@ -210,9 +202,9 @@ TEST_F(BodyStreamBufferTest, DrainAsBlobFromBufferMadeFromBufferMadeFromStream) { - ScriptState::Scope scope(getScriptState()); - ScriptValue stream = evalWithPrintingError("new ReadableStream()"); - BodyStreamBuffer* buffer = new BodyStreamBuffer(getScriptState(), stream); + V8TestingScope scope; + ScriptValue stream = evalWithPrintingError(scope.getScriptState(), "new ReadableStream()"); + BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), stream); EXPECT_FALSE(buffer->hasPendingActivity()); EXPECT_FALSE(buffer->isStreamLocked()); @@ -229,12 +221,13 @@ TEST_F(BodyStreamBufferTest, DrainAsFormData) { + V8TestingScope scope; FormData* data = FormData::create(UTF8Encoding()); data->append("name1", "value1"); data->append("name2", "value2"); RefPtr<EncodedFormData> inputFormData = data->encodeMultiPartFormData(); - BodyStreamBuffer* buffer = new BodyStreamBuffer(getScriptState(), FetchFormDataConsumerHandle::create(getExecutionContext(), inputFormData)); + BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), FetchFormDataConsumerHandle::create(scope.getExecutionContext(), inputFormData)); EXPECT_FALSE(buffer->isStreamLocked()); EXPECT_FALSE(buffer->isStreamDisturbed()); @@ -249,9 +242,10 @@ TEST_F(BodyStreamBufferTest, DrainAsFormDataReturnsNull) { + V8TestingScope scope; // This handle is not drainable. std::unique_ptr<FetchDataConsumerHandle> handle = createFetchDataConsumerHandleFromWebHandle(createWaitingDataConsumerHandle()); - BodyStreamBuffer* buffer = new BodyStreamBuffer(getScriptState(), std::move(handle)); + BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), std::move(handle)); EXPECT_FALSE(buffer->isStreamLocked()); EXPECT_FALSE(buffer->isStreamDisturbed()); @@ -266,9 +260,9 @@ TEST_F(BodyStreamBufferTest, DrainAsFormDataFromBufferMadeFromBufferMadeFromStream) { - ScriptState::Scope scope(getScriptState()); - ScriptValue stream = evalWithPrintingError("new ReadableStream()"); - BodyStreamBuffer* buffer = new BodyStreamBuffer(getScriptState(), stream); + V8TestingScope scope; + ScriptValue stream = evalWithPrintingError(scope.getScriptState(), "new ReadableStream()"); + BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), stream); EXPECT_FALSE(buffer->hasPendingActivity()); EXPECT_FALSE(buffer->isStreamLocked()); @@ -285,6 +279,7 @@ TEST_F(BodyStreamBufferTest, LoadBodyStreamBufferAsArrayBuffer) { + V8TestingScope scope; Checkpoint checkpoint; MockFetchDataLoaderClient* client = MockFetchDataLoaderClient::create(); DOMArrayBuffer* arrayBuffer = nullptr; @@ -297,7 +292,7 @@ std::unique_ptr<ReplayingHandle> handle = ReplayingHandle::create(); handle->add(Command(Command::Data, "hello")); handle->add(Command(Command::Done)); - BodyStreamBuffer* buffer = new BodyStreamBuffer(getScriptState(), createFetchDataConsumerHandleFromWebHandle(std::move(handle))); + BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), createFetchDataConsumerHandleFromWebHandle(std::move(handle))); buffer->startLoading(FetchDataLoader::createLoaderAsArrayBuffer(), client); EXPECT_TRUE(buffer->isStreamLocked()); @@ -317,6 +312,7 @@ TEST_F(BodyStreamBufferTest, LoadBodyStreamBufferAsBlob) { + V8TestingScope scope; Checkpoint checkpoint; MockFetchDataLoaderClient* client = MockFetchDataLoaderClient::create(); RefPtr<BlobDataHandle> blobDataHandle; @@ -329,7 +325,7 @@ std::unique_ptr<ReplayingHandle> handle = ReplayingHandle::create(); handle->add(Command(Command::Data, "hello")); handle->add(Command(Command::Done)); - BodyStreamBuffer* buffer = new BodyStreamBuffer(getScriptState(), createFetchDataConsumerHandleFromWebHandle(std::move(handle))); + BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), createFetchDataConsumerHandleFromWebHandle(std::move(handle))); buffer->startLoading(FetchDataLoader::createLoaderAsBlobHandle("text/plain"), client); EXPECT_TRUE(buffer->isStreamLocked()); @@ -348,6 +344,7 @@ TEST_F(BodyStreamBufferTest, LoadBodyStreamBufferAsString) { + V8TestingScope scope; Checkpoint checkpoint; MockFetchDataLoaderClient* client = MockFetchDataLoaderClient::create(); @@ -359,7 +356,7 @@ std::unique_ptr<ReplayingHandle> handle = ReplayingHandle::create(); handle->add(Command(Command::Data, "hello")); handle->add(Command(Command::Done)); - BodyStreamBuffer* buffer = new BodyStreamBuffer(getScriptState(), createFetchDataConsumerHandleFromWebHandle(std::move(handle))); + BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), createFetchDataConsumerHandleFromWebHandle(std::move(handle))); buffer->startLoading(FetchDataLoader::createLoaderAsString(), client); EXPECT_TRUE(buffer->isStreamLocked()); @@ -377,6 +374,7 @@ TEST_F(BodyStreamBufferTest, LoadClosedHandle) { + V8TestingScope scope; Checkpoint checkpoint; MockFetchDataLoaderClient* client = MockFetchDataLoaderClient::create(); @@ -385,7 +383,7 @@ EXPECT_CALL(*client, didFetchDataLoadedString(String(""))); EXPECT_CALL(checkpoint, Call(2)); - BodyStreamBuffer* buffer = new BodyStreamBuffer(getScriptState(), createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumerHandle())); + BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumerHandle())); EXPECT_TRUE(buffer->isStreamReadable()); testing::runPendingTasks(); @@ -411,6 +409,7 @@ TEST_F(BodyStreamBufferTest, LoadErroredHandle) { + V8TestingScope scope; Checkpoint checkpoint; MockFetchDataLoaderClient* client = MockFetchDataLoaderClient::create(); @@ -419,7 +418,7 @@ EXPECT_CALL(*client, didFetchDataLoadFailed()); EXPECT_CALL(checkpoint, Call(2)); - BodyStreamBuffer* buffer = new BodyStreamBuffer(getScriptState(), createFetchDataConsumerHandleFromWebHandle(createUnexpectedErrorDataConsumerHandle())); + BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), createFetchDataConsumerHandleFromWebHandle(createUnexpectedErrorDataConsumerHandle())); EXPECT_TRUE(buffer->isStreamReadable()); testing::runPendingTasks(); @@ -444,6 +443,7 @@ TEST_F(BodyStreamBufferTest, LoaderShouldBeKeptAliveByBodyStreamBuffer) { + V8TestingScope scope; Checkpoint checkpoint; MockFetchDataLoaderClient* client = MockFetchDataLoaderClient::create(); @@ -455,7 +455,7 @@ std::unique_ptr<ReplayingHandle> handle = ReplayingHandle::create(); handle->add(Command(Command::Data, "hello")); handle->add(Command(Command::Done)); - Persistent<BodyStreamBuffer> buffer = new BodyStreamBuffer(getScriptState(), createFetchDataConsumerHandleFromWebHandle(std::move(handle))); + Persistent<BodyStreamBuffer> buffer = new BodyStreamBuffer(scope.getScriptState(), createFetchDataConsumerHandleFromWebHandle(std::move(handle))); buffer->startLoading(FetchDataLoader::createLoaderAsString(), client); ThreadHeap::collectAllGarbage(); @@ -479,7 +479,7 @@ TEST_F(BodyStreamBufferTest, SourceHandleAndReaderShouldBeDestructedWhenCanceled) { - ScriptState::Scope scope(getScriptState()); + V8TestingScope scope; using MockHandle = MockFetchDataConsumerHandleWithMockDestructor; using MockReader = DataConsumerHandleTestUtil::MockFetchDataConsumerReader; std::unique_ptr<MockHandle> handle = MockHandle::create(); @@ -497,10 +497,10 @@ // |reader| is adopted by |obtainReader|. ASSERT_TRUE(reader.release()); - BodyStreamBuffer* buffer = new BodyStreamBuffer(getScriptState(), std::move(handle)); + BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), std::move(handle)); checkpoint.Call(1); - ScriptValue reason(getScriptState(), v8String(getScriptState()->isolate(), "reason")); - buffer->cancelSource(getScriptState(), reason); + ScriptValue reason(scope.getScriptState(), v8String(scope.getScriptState()->isolate(), "reason")); + buffer->cancelSource(scope.getScriptState(), reason); checkpoint.Call(2); }
diff --git a/third_party/WebKit/Source/modules/fetch/FetchManager.cpp b/third_party/WebKit/Source/modules/fetch/FetchManager.cpp index 0d53af6e..0acdab5 100644 --- a/third_party/WebKit/Source/modules/fetch/FetchManager.cpp +++ b/third_party/WebKit/Source/modules/fetch/FetchManager.cpp
@@ -143,6 +143,8 @@ private: std::unique_ptr<WebDataConsumerHandle> m_handle; Member<CompositeDataConsumerHandle::Updater> m_updater; + // We cannot store a Response because its JS wrapper can be collected. + // TODO(yhirano): Fix this. Member<Response> m_response; Member<FetchManager::Loader> m_loader; String m_integrityMetadata; @@ -209,6 +211,8 @@ void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceResponse& response, std::unique_ptr<WebDataConsumerHandle> handle) { ASSERT(handle); + ScriptState* scriptState = m_resolver->getScriptState(); + ScriptState::Scope scope(scriptState); if (response.url().protocolIs("blob") && response.httpStatusCode() == 404) { // "If |blob| is null, return a network error." @@ -290,7 +294,6 @@ } } - ScriptState* scriptState = m_resolver->getScriptState(); FetchResponseData* responseData = nullptr; CompositeDataConsumerHandle::Updater* updater = nullptr; if (m_request->integrity().isEmpty())
diff --git a/third_party/WebKit/Source/modules/fetch/Request.cpp b/third_party/WebKit/Source/modules/fetch/Request.cpp index d872c5d..08aff7d0 100644 --- a/third_party/WebKit/Source/modules/fetch/Request.cpp +++ b/third_party/WebKit/Source/modules/fetch/Request.cpp
@@ -678,7 +678,6 @@ void Request::refreshBody(ScriptState* scriptState) { - ScriptState::Scope scope(scriptState); v8::Local<v8::Value> bodyBuffer = toV8(this->bodyBuffer(), scriptState); v8::Local<v8::Value> request = toV8(this, scriptState); if (request.IsEmpty()) {
diff --git a/third_party/WebKit/Source/modules/fetch/Request.h b/third_party/WebKit/Source/modules/fetch/Request.h index 57a9f3b..569b84fa 100644 --- a/third_party/WebKit/Source/modules/fetch/Request.h +++ b/third_party/WebKit/Source/modules/fetch/Request.h
@@ -31,6 +31,8 @@ DEFINE_WRAPPERTYPEINFO(); WTF_MAKE_NONCOPYABLE(Request); public: + // These "create" function must be called with entering an appropriate + // V8 context. // From Request.idl: static Request* create(ScriptState*, const RequestInfo&, const Dictionary&, ExceptionState&); @@ -54,6 +56,7 @@ String integrity() const; // From Request.idl: + // This function must be called with entering an appropriate V8 context. Request* clone(ScriptState*, ExceptionState&); FetchRequestData* passRequestData(ScriptState*);
diff --git a/third_party/WebKit/Source/modules/fetch/RequestTest.cpp b/third_party/WebKit/Source/modules/fetch/RequestTest.cpp index a264e1e..90e8cd3 100644 --- a/third_party/WebKit/Source/modules/fetch/RequestTest.cpp +++ b/third_party/WebKit/Source/modules/fetch/RequestTest.cpp
@@ -6,9 +6,8 @@ #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/ScriptState.h" +#include "bindings/core/v8/V8BindingForTesting.h" #include "core/dom/Document.h" -#include "core/frame/Frame.h" -#include "core/testing/DummyPageHolder.h" #include "public/platform/WebURLRequest.h" #include "public/platform/modules/serviceworker/WebServiceWorkerRequest.h" #include "testing/gtest/include/gtest/gtest.h" @@ -19,45 +18,36 @@ namespace blink { namespace { -class ServiceWorkerRequestTest : public ::testing::Test { -public: - ServiceWorkerRequestTest() - : m_page(DummyPageHolder::create(IntSize(1, 1))) { } - - ScriptState* getScriptState() { return ScriptState::forMainWorld(m_page->document().frame()); } - ExecutionContext* getExecutionContext() { return getScriptState()->getExecutionContext(); } - -private: - std::unique_ptr<DummyPageHolder> m_page; -}; - -TEST_F(ServiceWorkerRequestTest, FromString) +TEST(ServiceWorkerRequestTest, FromString) { + V8TestingScope scope; TrackExceptionState exceptionState; KURL url(ParsedURLString, "http://www.example.com/"); - Request* request = Request::create(getScriptState(), url, exceptionState); + Request* request = Request::create(scope.getScriptState(), url, exceptionState); ASSERT_FALSE(exceptionState.hadException()); ASSERT(request); EXPECT_EQ(url, request->url()); } -TEST_F(ServiceWorkerRequestTest, FromRequest) +TEST(ServiceWorkerRequestTest, FromRequest) { + V8TestingScope scope; TrackExceptionState exceptionState; KURL url(ParsedURLString, "http://www.example.com/"); - Request* request1 = Request::create(getScriptState(), url, exceptionState); + Request* request1 = Request::create(scope.getScriptState(), url, exceptionState); ASSERT(request1); - Request* request2 = Request::create(getScriptState(), request1, exceptionState); + Request* request2 = Request::create(scope.getScriptState(), request1, exceptionState); ASSERT_FALSE(exceptionState.hadException()); ASSERT(request2); EXPECT_EQ(url, request2->url()); } -TEST_F(ServiceWorkerRequestTest, FromAndToWebRequest) +TEST(ServiceWorkerRequestTest, FromAndToWebRequest) { + V8TestingScope scope; WebServiceWorkerRequest webRequest; const KURL url(ParsedURLString, "http://www.example.com/"); @@ -79,7 +69,7 @@ webRequest.setHeader(WebString::fromUTF8(headers[i].key), WebString::fromUTF8(headers[i].value)); webRequest.setReferrer(referrer, referrerPolicy); - Request* request = Request::create(getScriptState(), webRequest); + Request* request = Request::create(scope.getScriptState(), webRequest); ASSERT(request); EXPECT_EQ(url, request->url()); EXPECT_EQ(method, request->method()); @@ -110,12 +100,13 @@ EXPECT_EQ(WebURLRequest::FetchRequestModeNoCORS, secondWebRequest.mode()); } -TEST_F(ServiceWorkerRequestTest, ToWebRequestStripsURLFragment) +TEST(ServiceWorkerRequestTest, ToWebRequestStripsURLFragment) { + V8TestingScope scope; TrackExceptionState exceptionState; String urlWithoutFragment = "http://www.example.com/"; String url = urlWithoutFragment + "#fragment"; - Request* request = Request::create(getScriptState(), url, exceptionState); + Request* request = Request::create(scope.getScriptState(), url, exceptionState); ASSERT(request); WebServiceWorkerRequest webRequest;
diff --git a/third_party/WebKit/Source/modules/fetch/Response.cpp b/third_party/WebKit/Source/modules/fetch/Response.cpp index d801f76..5ccedd4 100644 --- a/third_party/WebKit/Source/modules/fetch/Response.cpp +++ b/third_party/WebKit/Source/modules/fetch/Response.cpp
@@ -433,7 +433,6 @@ void Response::refreshBody(ScriptState* scriptState) { - ScriptState::Scope scope(scriptState); v8::Local<v8::Value> bodyBuffer = toV8(internalBodyBuffer(), scriptState); v8::Local<v8::Value> response = toV8(this, scriptState); if (response.IsEmpty()) {
diff --git a/third_party/WebKit/Source/modules/fetch/Response.h b/third_party/WebKit/Source/modules/fetch/Response.h index 4f91a0d..b05e275 100644 --- a/third_party/WebKit/Source/modules/fetch/Response.h +++ b/third_party/WebKit/Source/modules/fetch/Response.h
@@ -30,6 +30,8 @@ DEFINE_WRAPPERTYPEINFO(); WTF_MAKE_NONCOPYABLE(Response); public: + // These "create" function which takes a ScriptState* must be called with + // entering an appropriate V8 context. // From Response.idl: static Response* create(ScriptState*, ExceptionState&); static Response* create(ScriptState*, ScriptValue body, const Dictionary&, ExceptionState&); @@ -54,6 +56,7 @@ Headers* headers() const; // From Response.idl: + // This function must be called with entering an appropriate V8 context. Response* clone(ScriptState*, ExceptionState&); // ActiveScriptWrappable
diff --git a/third_party/WebKit/Source/modules/fetch/ResponseTest.cpp b/third_party/WebKit/Source/modules/fetch/ResponseTest.cpp index 0fee482..d9aa422 100644 --- a/third_party/WebKit/Source/modules/fetch/ResponseTest.cpp +++ b/third_party/WebKit/Source/modules/fetch/ResponseTest.cpp
@@ -6,6 +6,7 @@ #include "bindings/core/v8/ExceptionState.h" #include "bindings/core/v8/ScriptState.h" +#include "bindings/core/v8/V8BindingForTesting.h" #include "core/dom/Document.h" #include "core/frame/Frame.h" #include "core/testing/DummyPageHolder.h" @@ -43,35 +44,24 @@ return webResponse; } -class ServiceWorkerResponseTest : public ::testing::Test { -public: - ServiceWorkerResponseTest() - : m_page(DummyPageHolder::create(IntSize(1, 1))) { } - - ScriptState* getScriptState() { return ScriptState::forMainWorld(m_page->document().frame()); } - ExecutionContext* getExecutionContext() { return getScriptState()->getExecutionContext(); } - -private: - std::unique_ptr<DummyPageHolder> m_page; -}; - - -TEST_F(ServiceWorkerResponseTest, FromFetchResponseData) +TEST(ServiceWorkerResponseTest, FromFetchResponseData) { + std::unique_ptr<DummyPageHolder> page = DummyPageHolder::create(IntSize(1, 1)); const KURL url(ParsedURLString, "http://www.response.com"); FetchResponseData* fetchResponseData = FetchResponseData::create(); fetchResponseData->setURL(url); - Response* response = Response::create(getExecutionContext(), fetchResponseData); + Response* response = Response::create(&page->document(), fetchResponseData); ASSERT(response); EXPECT_EQ(url, response->url()); } -TEST_F(ServiceWorkerResponseTest, FromWebServiceWorkerResponse) +TEST(ServiceWorkerResponseTest, FromWebServiceWorkerResponse) { + V8TestingScope scope; std::unique_ptr<WebServiceWorkerResponse> webResponse = createTestWebServiceWorkerResponse(); - Response* response = Response::create(getScriptState(), *webResponse); + Response* response = Response::create(scope.getScriptState(), *webResponse); ASSERT(response); EXPECT_EQ(webResponse->url(), response->url()); EXPECT_EQ(webResponse->status(), response->status()); @@ -89,11 +79,12 @@ } } -TEST_F(ServiceWorkerResponseTest, FromWebServiceWorkerResponseDefault) +TEST(ServiceWorkerResponseTest, FromWebServiceWorkerResponseDefault) { + V8TestingScope scope; std::unique_ptr<WebServiceWorkerResponse> webResponse = createTestWebServiceWorkerResponse(); webResponse->setResponseType(WebServiceWorkerResponseTypeDefault); - Response* response = Response::create(getScriptState(), *webResponse); + Response* response = Response::create(scope.getScriptState(), *webResponse); Headers* responseHeaders = response->headers(); TrackExceptionState exceptionState; @@ -103,11 +94,12 @@ EXPECT_FALSE(exceptionState.hadException()); } -TEST_F(ServiceWorkerResponseTest, FromWebServiceWorkerResponseBasic) +TEST(ServiceWorkerResponseTest, FromWebServiceWorkerResponseBasic) { + V8TestingScope scope; std::unique_ptr<WebServiceWorkerResponse> webResponse = createTestWebServiceWorkerResponse(); webResponse->setResponseType(WebServiceWorkerResponseTypeBasic); - Response* response = Response::create(getScriptState(), *webResponse); + Response* response = Response::create(scope.getScriptState(), *webResponse); Headers* responseHeaders = response->headers(); TrackExceptionState exceptionState; @@ -117,11 +109,12 @@ EXPECT_FALSE(exceptionState.hadException()); } -TEST_F(ServiceWorkerResponseTest, FromWebServiceWorkerResponseCORS) +TEST(ServiceWorkerResponseTest, FromWebServiceWorkerResponseCORS) { + V8TestingScope scope; std::unique_ptr<WebServiceWorkerResponse> webResponse = createTestWebServiceWorkerResponse(); webResponse->setResponseType(WebServiceWorkerResponseTypeCORS); - Response* response = Response::create(getScriptState(), *webResponse); + Response* response = Response::create(scope.getScriptState(), *webResponse); Headers* responseHeaders = response->headers(); TrackExceptionState exceptionState; @@ -131,11 +124,12 @@ EXPECT_FALSE(exceptionState.hadException()); } -TEST_F(ServiceWorkerResponseTest, FromWebServiceWorkerResponseOpaque) +TEST(ServiceWorkerResponseTest, FromWebServiceWorkerResponseOpaque) { + V8TestingScope scope; std::unique_ptr<WebServiceWorkerResponse> webResponse = createTestWebServiceWorkerResponse(); webResponse->setResponseType(WebServiceWorkerResponseTypeOpaque); - Response* response = Response::create(getScriptState(), *webResponse); + Response* response = Response::create(scope.getScriptState(), *webResponse); Headers* responseHeaders = response->headers(); TrackExceptionState exceptionState; @@ -196,57 +190,62 @@ return new BodyStreamBuffer(scriptState, createFetchDataConsumerHandleFromWebHandle(std::move(src))); } -TEST_F(ServiceWorkerResponseTest, BodyStreamBufferCloneDefault) +TEST(ServiceWorkerResponseTest, BodyStreamBufferCloneDefault) { - BodyStreamBuffer* buffer = createHelloWorldBuffer(getScriptState()); + V8TestingScope scope; + BodyStreamBuffer* buffer = createHelloWorldBuffer(scope.getScriptState()); FetchResponseData* fetchResponseData = FetchResponseData::createWithBuffer(buffer); fetchResponseData->setURL(KURL(ParsedURLString, "http://www.response.com")); - Response* response = Response::create(getExecutionContext(), fetchResponseData); + Response* response = Response::create(scope.getExecutionContext(), fetchResponseData); EXPECT_EQ(response->internalBodyBuffer(), buffer); - checkResponseStream(getScriptState(), response, true); + checkResponseStream(scope.getScriptState(), response, true); } -TEST_F(ServiceWorkerResponseTest, BodyStreamBufferCloneBasic) +TEST(ServiceWorkerResponseTest, BodyStreamBufferCloneBasic) { - BodyStreamBuffer* buffer = createHelloWorldBuffer(getScriptState()); + V8TestingScope scope; + BodyStreamBuffer* buffer = createHelloWorldBuffer(scope.getScriptState()); FetchResponseData* fetchResponseData = FetchResponseData::createWithBuffer(buffer); fetchResponseData->setURL(KURL(ParsedURLString, "http://www.response.com")); fetchResponseData = fetchResponseData->createBasicFilteredResponse(); - Response* response = Response::create(getExecutionContext(), fetchResponseData); + Response* response = Response::create(scope.getExecutionContext(), fetchResponseData); EXPECT_EQ(response->internalBodyBuffer(), buffer); - checkResponseStream(getScriptState(), response, true); + checkResponseStream(scope.getScriptState(), response, true); } -TEST_F(ServiceWorkerResponseTest, BodyStreamBufferCloneCORS) +TEST(ServiceWorkerResponseTest, BodyStreamBufferCloneCORS) { - BodyStreamBuffer* buffer = createHelloWorldBuffer(getScriptState()); + V8TestingScope scope; + BodyStreamBuffer* buffer = createHelloWorldBuffer(scope.getScriptState()); FetchResponseData* fetchResponseData = FetchResponseData::createWithBuffer(buffer); fetchResponseData->setURL(KURL(ParsedURLString, "http://www.response.com")); fetchResponseData = fetchResponseData->createCORSFilteredResponse(); - Response* response = Response::create(getExecutionContext(), fetchResponseData); + Response* response = Response::create(scope.getExecutionContext(), fetchResponseData); EXPECT_EQ(response->internalBodyBuffer(), buffer); - checkResponseStream(getScriptState(), response, true); + checkResponseStream(scope.getScriptState(), response, true); } -TEST_F(ServiceWorkerResponseTest, BodyStreamBufferCloneOpaque) +TEST(ServiceWorkerResponseTest, BodyStreamBufferCloneOpaque) { - BodyStreamBuffer* buffer = createHelloWorldBuffer(getScriptState()); + V8TestingScope scope; + BodyStreamBuffer* buffer = createHelloWorldBuffer(scope.getScriptState()); FetchResponseData* fetchResponseData = FetchResponseData::createWithBuffer(buffer); fetchResponseData->setURL(KURL(ParsedURLString, "http://www.response.com")); fetchResponseData = fetchResponseData->createOpaqueFilteredResponse(); - Response* response = Response::create(getExecutionContext(), fetchResponseData); + Response* response = Response::create(scope.getExecutionContext(), fetchResponseData); EXPECT_EQ(response->internalBodyBuffer(), buffer); - checkResponseStream(getScriptState(), response, false); + checkResponseStream(scope.getScriptState(), response, false); } -TEST_F(ServiceWorkerResponseTest, BodyStreamBufferCloneError) +TEST(ServiceWorkerResponseTest, BodyStreamBufferCloneError) { - BodyStreamBuffer* buffer = new BodyStreamBuffer(getScriptState(), createFetchDataConsumerHandleFromWebHandle(createUnexpectedErrorDataConsumerHandle())); + V8TestingScope scope; + BodyStreamBuffer* buffer = new BodyStreamBuffer(scope.getScriptState(), createFetchDataConsumerHandleFromWebHandle(createUnexpectedErrorDataConsumerHandle())); FetchResponseData* fetchResponseData = FetchResponseData::createWithBuffer(buffer); fetchResponseData->setURL(KURL(ParsedURLString, "http://www.response.com")); - Response* response = Response::create(getExecutionContext(), fetchResponseData); + Response* response = Response::create(scope.getExecutionContext(), fetchResponseData); TrackExceptionState exceptionState; - Response* clonedResponse = response->clone(getScriptState(), exceptionState); + Response* clonedResponse = response->clone(scope.getScriptState(), exceptionState); EXPECT_FALSE(exceptionState.hadException()); DataConsumerHandleTestUtil::MockFetchDataLoaderClient* client1 = new DataConsumerHandleTestUtil::MockFetchDataLoaderClient();
diff --git a/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.cpp b/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.cpp index 8585373..0489559 100644 --- a/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.cpp +++ b/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.cpp
@@ -195,6 +195,12 @@ { } +DEFINE_TRACE(LocalFileSystem) +{ + Supplement<LocalFrame>::trace(visitor); + Supplement<WorkerClients>::trace(visitor); +} + const char* LocalFileSystem::supplementName() { return "LocalFileSystem";
diff --git a/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.h b/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.h index 75baffe..1c06b5a 100644 --- a/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.h +++ b/third_party/WebKit/Source/modules/filesystem/LocalFileSystem.h
@@ -31,6 +31,7 @@ #ifndef LocalFileSystem_h #define LocalFileSystem_h +#include "core/frame/LocalFrame.h" #include "core/workers/WorkerClients.h" #include "platform/FileSystemType.h" #include "platform/Supplementable.h" @@ -46,7 +47,6 @@ class FileSystemClient; class ExecutionContext; class KURL; -class LocalFrame; class WebFileSystem; class LocalFileSystem final : public GarbageCollectedFinalized<LocalFileSystem>, public Supplement<LocalFrame>, public Supplement<WorkerClients> { @@ -65,11 +65,7 @@ static const char* supplementName(); static LocalFileSystem* from(ExecutionContext&); - DEFINE_INLINE_VIRTUAL_TRACE() - { - Supplement<LocalFrame>::trace(visitor); - Supplement<WorkerClients>::trace(visitor); - } + DECLARE_VIRTUAL_TRACE(); private: explicit LocalFileSystem(std::unique_ptr<FileSystemClient>);
diff --git a/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp b/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp index a5b7404..5735dc4 100644 --- a/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp +++ b/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.cpp
@@ -106,14 +106,15 @@ visitor->trace(m_pendingEvents); visitor->trace(m_dispatchOneEventRunner); Supplement<Navigator>::trace(visitor); - DOMWindowProperty::trace(visitor); + ContextLifecycleObserver::trace(visitor); PlatformEventController::trace(visitor); } bool NavigatorGamepad::startUpdatingIfAttached() { + Document* document = static_cast<Document*>(getExecutionContext()); // The frame must be attached to start updating. - if (frame() && frame()->host()) { + if (document && document->frame()) { startUpdating(); return true; } @@ -123,14 +124,14 @@ void NavigatorGamepad::didUpdateData() { // We should stop listening once we detached. - ASSERT(frame()); - ASSERT(frame()->domWindow()); + Document* document = static_cast<Document*>(getExecutionContext()); + DCHECK(document->frame()); + DCHECK(document->frame()->domWindow()); // We register to the dispatcher before sampling gamepads so we need to check if we actually have an event listener. if (!m_hasEventListener) return; - Document* document = frame()->domWindow()->document(); if (document->activeDOMObjectsAreStopped() || document->activeDOMObjectsAreSuspended()) return; @@ -151,20 +152,21 @@ void NavigatorGamepad::dispatchOneEvent() { - ASSERT(frame()); - ASSERT(frame()->domWindow()); - ASSERT(!m_pendingEvents.isEmpty()); + Document* document = static_cast<Document*>(getExecutionContext()); + DCHECK(document->frame()); + DCHECK(document->frame()->domWindow()); + DCHECK(!m_pendingEvents.isEmpty()); Gamepad* gamepad = m_pendingEvents.takeFirst(); const AtomicString& eventName = gamepad->connected() ? EventTypeNames::gamepadconnected : EventTypeNames::gamepaddisconnected; - frame()->domWindow()->dispatchEvent(GamepadEvent::create(eventName, false, true, gamepad)); + document->frame()->domWindow()->dispatchEvent(GamepadEvent::create(eventName, false, true, gamepad)); if (!m_pendingEvents.isEmpty()) m_dispatchOneEventRunner->runAsync(); } NavigatorGamepad::NavigatorGamepad(LocalFrame* frame) - : DOMWindowProperty(frame) + : ContextLifecycleObserver(frame->document()) , PlatformEventController(frame ? frame->page() : 0) , m_dispatchOneEventRunner(AsyncMethodRunner<NavigatorGamepad>::create(this, &NavigatorGamepad::dispatchOneEvent)) { @@ -181,16 +183,9 @@ return "NavigatorGamepad"; } -void NavigatorGamepad::willDestroyGlobalObjectInFrame() +void NavigatorGamepad::contextDestroyed() { stopUpdating(); - DOMWindowProperty::willDestroyGlobalObjectInFrame(); -} - -void NavigatorGamepad::willDetachGlobalObjectFromFrame() -{ - stopUpdating(); - DOMWindowProperty::willDetachGlobalObjectFromFrame(); } void NavigatorGamepad::registerWithDispatcher() @@ -263,7 +258,7 @@ GamepadList* oldGamepads = m_gamepads.release(); gamepads(); GamepadList* newGamepads = m_gamepads.get(); - ASSERT(newGamepads); + DCHECK(newGamepads); for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) { Gamepad* oldGamepad = oldGamepads ? oldGamepads->item(i) : 0;
diff --git a/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h b/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h index a170945..a0febcc 100644 --- a/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h +++ b/third_party/WebKit/Source/modules/gamepad/NavigatorGamepad.h
@@ -26,7 +26,7 @@ #ifndef NavigatorGamepad_h #define NavigatorGamepad_h -#include "core/frame/DOMWindowProperty.h" +#include "core/dom/ContextLifecycleObserver.h" #include "core/frame/LocalDOMWindow.h" #include "core/frame/PlatformEventController.h" #include "modules/ModulesExport.h" @@ -42,7 +42,7 @@ class GamepadList; class Navigator; -class MODULES_EXPORT NavigatorGamepad final : public GarbageCollectedFinalized<NavigatorGamepad>, public Supplement<Navigator>, public DOMWindowProperty, public PlatformEventController, public LocalDOMWindow::EventListenerObserver { +class MODULES_EXPORT NavigatorGamepad final : public GarbageCollectedFinalized<NavigatorGamepad>, public Supplement<Navigator>, public ContextLifecycleObserver, public PlatformEventController, public LocalDOMWindow::EventListenerObserver { USING_GARBAGE_COLLECTED_MIXIN(NavigatorGamepad); public: static NavigatorGamepad* from(Document&); @@ -65,9 +65,8 @@ void didRemoveGamepadEventListeners(); bool startUpdatingIfAttached(); - // DOMWindowProperty - void willDestroyGlobalObjectInFrame() override; - void willDetachGlobalObjectFromFrame() override; + // ContextLifecycleObserver + void contextDestroyed() override; // PlatformEventController void registerWithDispatcher() override;
diff --git a/third_party/WebKit/Source/modules/imagecapture/ImageCapture.cpp b/third_party/WebKit/Source/modules/imagecapture/ImageCapture.cpp index 7601b5f..ff23736 100644 --- a/third_party/WebKit/Source/modules/imagecapture/ImageCapture.cpp +++ b/third_party/WebKit/Source/modules/imagecapture/ImageCapture.cpp
@@ -200,6 +200,7 @@ MediaSettingsRange* zoom = MediaSettingsRange::create(capabilities->zoom->max, capabilities->zoom->min, capabilities->zoom->current); PhotoCapabilities* caps = PhotoCapabilities::create(); caps->setZoom(zoom); + caps->setFocusMode(capabilities->focus_mode); resolver->resolve(caps); } m_serviceRequests.remove(resolver);
diff --git a/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.cpp b/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.cpp new file mode 100644 index 0000000..c1d7ffd --- /dev/null +++ b/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.cpp
@@ -0,0 +1,44 @@ +// 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 "modules/imagecapture/PhotoCapabilities.h" + +namespace blink { + +// static +PhotoCapabilities* PhotoCapabilities::create() +{ + return new PhotoCapabilities(); +} + +MediaSettingsRange* PhotoCapabilities::zoom() const { return m_zoom; } + +void PhotoCapabilities::setZoom(MediaSettingsRange* value) { m_zoom = value; } + +String PhotoCapabilities::focusMode() const +{ + switch (m_focusMode) { + case media::mojom::blink::FocusMode::UNAVAILABLE: + return "unavailable"; + case media::mojom::blink::FocusMode::AUTO: + return "auto"; + case media::mojom::blink::FocusMode::MANUAL: + return "manual"; + default: + NOTREACHED(); + } + return emptyString(); +} + +void PhotoCapabilities::setFocusMode(media::mojom::blink::FocusMode focusMode) +{ + m_focusMode = focusMode; +} + +DEFINE_TRACE(PhotoCapabilities) +{ + visitor->trace(m_zoom); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.h b/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.h index 0d5afdc..4d1e435 100644 --- a/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.h +++ b/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.h
@@ -6,6 +6,7 @@ #define PhotoCapabilities_h #include "bindings/core/v8/ScriptWrappable.h" +#include "media/mojo/interfaces/image_capture.mojom-blink.h" #include "modules/imagecapture/MediaSettingsRange.h" #include "wtf/text/WTFString.h" @@ -16,24 +17,22 @@ , public ScriptWrappable { DEFINE_WRAPPERTYPEINFO(); public: - static PhotoCapabilities* create() - { - return new PhotoCapabilities(); - } + static PhotoCapabilities* create(); virtual ~PhotoCapabilities() = default; - MediaSettingsRange* zoom() const { return m_zoom; } - void setZoom(MediaSettingsRange* value) { m_zoom = value; } + MediaSettingsRange* zoom() const; + void setZoom(MediaSettingsRange* value); - DEFINE_INLINE_TRACE() - { - visitor->trace(m_zoom); - } + String focusMode() const; + void setFocusMode(media::mojom::blink::FocusMode); + + DECLARE_VIRTUAL_TRACE(); private: PhotoCapabilities() = default; Member<MediaSettingsRange> m_zoom; + media::mojom::blink::FocusMode m_focusMode = media::mojom::blink::FocusMode::UNAVAILABLE; }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.idl b/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.idl index f977f5b..0b59ae3 100644 --- a/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.idl +++ b/third_party/WebKit/Source/modules/imagecapture/PhotoCapabilities.idl
@@ -3,10 +3,18 @@ // found in the LICENSE file. // https://w3c.github.io/mediacapture-image/index.html#idl-def-PhotoCapabilities + +enum FocusMode { + "unavailable", + "auto", + "manual" +}; + [ RuntimeEnabled=ImageCapture, ] interface PhotoCapabilities { - attribute MediaSettingsRange zoom; + readonly attribute MediaSettingsRange zoom; + readonly attribute FocusMode focusMode; // TODO(mcasas): Implement all other PhotoCapabilities fields // https://crbug.com/518807 };
diff --git a/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.cpp b/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.cpp index f8ddc1a..8c17873 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.cpp +++ b/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.cpp
@@ -31,6 +31,12 @@ return "IndexedDBClient"; } +DEFINE_TRACE(IndexedDBClient) +{ + Supplement<LocalFrame>::trace(visitor); + Supplement<WorkerClients>::trace(visitor); +} + void provideIndexedDBClientTo(LocalFrame& frame, IndexedDBClient* client) { frame.provideSupplement(IndexedDBClient::supplementName(), client);
diff --git a/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.h b/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.h index 3c65ee9..ac1a739 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.h +++ b/third_party/WebKit/Source/modules/indexeddb/IndexedDBClient.h
@@ -28,6 +28,8 @@ #ifndef IndexedDBClient_h #define IndexedDBClient_h +#include "core/frame/LocalFrame.h" +#include "core/workers/WorkerClients.h" #include "modules/ModulesExport.h" #include "platform/Supplementable.h" #include "platform/heap/Handle.h" @@ -46,7 +48,7 @@ IndexedDBClient(); virtual ~IndexedDBClient() {} - DEFINE_INLINE_VIRTUAL_TRACE() { } + DECLARE_VIRTUAL_TRACE(); virtual bool allowIndexedDB(ExecutionContext*, const String& name) = 0;
diff --git a/third_party/WebKit/Source/modules/installedapp/InstalledAppController.cpp b/third_party/WebKit/Source/modules/installedapp/InstalledAppController.cpp index 4f0c188..1b97479 100644 --- a/third_party/WebKit/Source/modules/installedapp/InstalledAppController.cpp +++ b/third_party/WebKit/Source/modules/installedapp/InstalledAppController.cpp
@@ -54,7 +54,7 @@ m_client->getInstalledRelatedApps(url, std::move(callback)); } -void InstalledAppController::willDetachFrameHost() +void InstalledAppController::contextDestroyed() { m_client = nullptr; }
diff --git a/third_party/WebKit/Source/modules/installedapp/InstalledAppController.h b/third_party/WebKit/Source/modules/installedapp/InstalledAppController.h index c1496a4..571071c9 100644 --- a/third_party/WebKit/Source/modules/installedapp/InstalledAppController.h +++ b/third_party/WebKit/Source/modules/installedapp/InstalledAppController.h
@@ -33,7 +33,7 @@ InstalledAppController(LocalFrame&, WebInstalledAppClient*); // Inherited from LocalFrameLifecycleObserver. - void willDetachFrameHost() override; + void contextDestroyed() override; WebInstalledAppClient* m_client; };
diff --git a/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp b/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp index ba29649..4b511498 100644 --- a/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp +++ b/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp
@@ -58,12 +58,21 @@ namespace blink { -static bool throwExceptionIfClosedOrUpdating(bool isOpen, bool isUpdating, ExceptionState& exceptionState) +static bool throwExceptionIfClosed(bool isOpen, ExceptionState& exceptionState) { if (!isOpen) { MediaSource::logAndThrowDOMException(exceptionState, InvalidStateError, "The MediaSource's readyState is not 'open'."); return true; } + + return false; +} + +static bool throwExceptionIfClosedOrUpdating(bool isOpen, bool isUpdating, ExceptionState& exceptionState) +{ + if (throwExceptionIfClosed(isOpen, exceptionState)) + return true; + if (isUpdating) { MediaSource::logAndThrowDOMException(exceptionState, InvalidStateError, "The 'updating' attribute is true on one or more of this MediaSource's SourceBuffers."); return true; @@ -530,7 +539,9 @@ // 2. If the updating attribute equals true on any SourceBuffer in // SourceBuffers, then throw an InvalidStateError exception and abort // these steps. - if (throwExceptionIfClosedOrUpdating(isOpen(), isUpdating(), exceptionState)) + // Note: https://github.com/w3c/media-source/issues/118, once fixed, will + // remove the updating check (step 2). We skip that check here already. + if (throwExceptionIfClosed(isOpen(), exceptionState)) return; // 3. If start is negative or greater than end, then throw a TypeError @@ -554,7 +565,9 @@ // 2. If the updating attribute equals true on any SourceBuffer in // SourceBuffers, then throw an InvalidStateError exception and abort // these steps. - if (throwExceptionIfClosedOrUpdating(isOpen(), isUpdating(), exceptionState)) + // Note: https://github.com/w3c/media-source/issues/118, once fixed, will + // remove the updating check (step 2). We skip that check here already. + if (throwExceptionIfClosed(isOpen(), exceptionState)) return; // 3. If live seekable range contains a range, then set live seekable range
diff --git a/third_party/WebKit/Source/modules/mediasource/SourceBuffer.cpp b/third_party/WebKit/Source/modules/mediasource/SourceBuffer.cpp index fe119e1d..573f455 100644 --- a/third_party/WebKit/Source/modules/mediasource/SourceBuffer.cpp +++ b/third_party/WebKit/Source/modules/mediasource/SourceBuffer.cpp
@@ -85,13 +85,13 @@ WTF::String webTimeRangesToString(const WebTimeRanges& ranges) { StringBuilder stringBuilder; - stringBuilder.append("{"); + stringBuilder.append('{'); for (auto& r : ranges) { stringBuilder.append(" ["); stringBuilder.appendNumber(r.start); - stringBuilder.append(";"); + stringBuilder.append(';'); stringBuilder.appendNumber(r.end); - stringBuilder.append("]"); + stringBuilder.append(']'); } stringBuilder.append(" }"); return stringBuilder.toString();
diff --git a/third_party/WebKit/Source/modules/modules.gypi b/third_party/WebKit/Source/modules/modules.gypi index 04da11c7..2ad10c7 100644 --- a/third_party/WebKit/Source/modules/modules.gypi +++ b/third_party/WebKit/Source/modules/modules.gypi
@@ -1168,6 +1168,7 @@ 'imagecapture/ImageCapture.cpp', 'imagecapture/ImageCapture.h', 'imagecapture/MediaSettingsRange.h', + 'imagecapture/PhotoCapabilities.cpp', 'imagecapture/PhotoCapabilities.h', 'indexeddb/GlobalIndexedDB.cpp', 'indexeddb/GlobalIndexedDB.h',
diff --git a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp index ccb2d8fc..3032706 100644 --- a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp +++ b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.cpp
@@ -226,6 +226,12 @@ NavigatorContentUtils::from(*navigator.frame())->client()->unregisterProtocolHandler(scheme, document->completeURL(url)); } +DEFINE_TRACE(NavigatorContentUtils) +{ + visitor->trace(m_client); + Supplement<LocalFrame>::trace(visitor); +} + const char* NavigatorContentUtils::supplementName() { return "NavigatorContentUtils";
diff --git a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.h b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.h index d510d47e..323b00c4 100644 --- a/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.h +++ b/third_party/WebKit/Source/modules/navigatorcontentutils/NavigatorContentUtils.h
@@ -27,6 +27,7 @@ #ifndef NavigatorContentUtils_h #define NavigatorContentUtils_h +#include "core/frame/LocalFrame.h" #include "modules/ModulesExport.h" #include "modules/navigatorcontentutils/NavigatorContentUtilsClient.h" #include "platform/Supplementable.h" @@ -53,11 +54,7 @@ static NavigatorContentUtils* create(NavigatorContentUtilsClient*); - DEFINE_INLINE_VIRTUAL_TRACE() - { - visitor->trace(m_client); - Supplement<LocalFrame>::trace(visitor); - } + DECLARE_VIRTUAL_TRACE(); void setClientForTest(NavigatorContentUtilsClient* client) { m_client = client; }
diff --git a/third_party/WebKit/Source/modules/payments/PaymentAddress.cpp b/third_party/WebKit/Source/modules/payments/PaymentAddress.cpp index 10fc779105..fea61124 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentAddress.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentAddress.cpp
@@ -4,6 +4,8 @@ #include "modules/payments/PaymentAddress.h" +#include "wtf/text/StringBuilder.h" + namespace blink { PaymentAddress::PaymentAddress(mojom::blink::PaymentAddressPtr address) @@ -21,8 +23,11 @@ , m_phone(address->phone) { if (!m_languageCode.isEmpty() && !address->script_code.isEmpty()) { - m_languageCode.append("-"); - m_languageCode.append(address->script_code); + StringBuilder builder; + builder.append(m_languageCode); + builder.append('-'); + builder.append(address->script_code); + m_languageCode = builder.toString(); } }
diff --git a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp index 386f6308..c24a730f 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentRequest.cpp
@@ -206,12 +206,19 @@ void validateShippingOptions(const HeapVector<PaymentShippingOption>& options, ExceptionState& exceptionState) { + HashSet<String> uniqueIds; for (const auto& option : options) { if (!option.hasId() || option.id().isEmpty()) { exceptionState.throwTypeError("ShippingOption id required"); return; } + if (uniqueIds.contains(option.id())) { + exceptionState.throwTypeError("Duplicate shipping option identifiers are not allowed"); + return; + } + uniqueIds.add(option.id()); + validateShippingOptionOrPaymentItem(option, exceptionState); if (exceptionState.hadException()) return; @@ -231,6 +238,7 @@ exceptionState.throwTypeError("Must specify at least one payment method identifier"); return; } + for (const auto& method : modifier.supportedMethods()) { if (uniqueMethods.contains(method)) { exceptionState.throwTypeError("Duplicate payment method identifiers are not allowed"); @@ -304,6 +312,7 @@ exceptionState.throwTypeError("Must specify at least one payment method identifier"); return; } + for (const auto& method : pmd.supportedMethods()) { if (uniqueMethods.contains(method)) { exceptionState.throwTypeError("Duplicate payment method identifiers are not allowed");
diff --git a/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp b/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp index 1d2293ef..5714c8c 100644 --- a/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp +++ b/third_party/WebKit/Source/modules/payments/PaymentTestHelper.cpp
@@ -13,6 +13,7 @@ namespace blink { namespace { +static int gUniqueId = 0; // PaymentItem and PaymentShippingOption have identical structure // except for the "id" field, which is present only in PaymentShippingOption. template <typename PaymentItemOrPaymentShippingOption> @@ -60,7 +61,7 @@ if (modificationType == PaymentTestOverwriteValue) shippingOption.setId(valueToUse); } else { - shippingOption.setId("id"); + shippingOption.setId("id" + String::number(gUniqueId++)); } setValues(shippingOption, data, modificationType, valueToUse); return shippingOption; @@ -116,7 +117,7 @@ PaymentDetails result; result.setTotal(total); result.setDisplayItems(HeapVector<PaymentItem>(1, item)); - result.setShippingOptions(HeapVector<PaymentShippingOption>(2, shippingOption)); + result.setShippingOptions(HeapVector<PaymentShippingOption>(1, shippingOption)); result.setModifiers(HeapVector<PaymentDetailsModifier>(1, modifier)); return result;
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescriptionRequestPromiseImpl.cpp b/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescriptionRequestPromiseImpl.cpp index febfb0f..b737df0 100644 --- a/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescriptionRequestPromiseImpl.cpp +++ b/third_party/WebKit/Source/modules/peerconnection/RTCSessionDescriptionRequestPromiseImpl.cpp
@@ -28,7 +28,6 @@ RTCSessionDescriptionRequestPromiseImpl::~RTCSessionDescriptionRequestPromiseImpl() { - DCHECK(!m_requester); } void RTCSessionDescriptionRequestPromiseImpl::requestSucceeded(const WebRTCSessionDescription& webSessionDescription)
diff --git a/third_party/WebKit/Source/modules/peerconnection/RTCVoidRequestPromiseImpl.cpp b/third_party/WebKit/Source/modules/peerconnection/RTCVoidRequestPromiseImpl.cpp index 068fb93..706d0c2 100644 --- a/third_party/WebKit/Source/modules/peerconnection/RTCVoidRequestPromiseImpl.cpp +++ b/third_party/WebKit/Source/modules/peerconnection/RTCVoidRequestPromiseImpl.cpp
@@ -26,7 +26,6 @@ RTCVoidRequestPromiseImpl::~RTCVoidRequestPromiseImpl() { - DCHECK(!m_requester); } void RTCVoidRequestPromiseImpl::requestSucceeded()
diff --git a/third_party/WebKit/Source/modules/permissions/PermissionController.cpp b/third_party/WebKit/Source/modules/permissions/PermissionController.cpp index 96e06c5..f1bfef0 100644 --- a/third_party/WebKit/Source/modules/permissions/PermissionController.cpp +++ b/third_party/WebKit/Source/modules/permissions/PermissionController.cpp
@@ -43,7 +43,7 @@ return m_client; } -void PermissionController::willDetachFrameHost() +void PermissionController::contextDestroyed() { m_client = nullptr; }
diff --git a/third_party/WebKit/Source/modules/permissions/PermissionController.h b/third_party/WebKit/Source/modules/permissions/PermissionController.h index 6c4f7c1..c59228c 100644 --- a/third_party/WebKit/Source/modules/permissions/PermissionController.h +++ b/third_party/WebKit/Source/modules/permissions/PermissionController.h
@@ -34,7 +34,7 @@ PermissionController(LocalFrame&, WebPermissionClient*); // Inherited from LocalFrameLifecycleObserver. - void willDetachFrameHost() override; + void contextDestroyed() override; WebPermissionClient* m_client; };
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationController.cpp b/third_party/WebKit/Source/modules/presentation/PresentationController.cpp index 2cc3b32..50c9ffe1 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationController.cpp +++ b/third_party/WebKit/Source/modules/presentation/PresentationController.cpp
@@ -131,7 +131,7 @@ m_connections.add(connection); } -void PresentationController::willDetachFrameHost() +void PresentationController::contextDestroyed() { if (m_client) { m_client->setController(nullptr);
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationController.h b/third_party/WebKit/Source/modules/presentation/PresentationController.h index ef45351..73cee31 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationController.h +++ b/third_party/WebKit/Source/modules/presentation/PresentationController.h
@@ -71,7 +71,7 @@ PresentationController(LocalFrame&, WebPresentationClient*); // Implementation of LocalFrameLifecycleObserver. - void willDetachFrameHost() override; + void contextDestroyed() override; // Return the connection associated with the given |connectionClient| or // null if it doesn't exist.
diff --git a/third_party/WebKit/Source/modules/push_messaging/PushMessageData.idl b/third_party/WebKit/Source/modules/push_messaging/PushMessageData.idl index d0cd7ee1..bfd0b24 100644 --- a/third_party/WebKit/Source/modules/push_messaging/PushMessageData.idl +++ b/third_party/WebKit/Source/modules/push_messaging/PushMessageData.idl
@@ -4,8 +4,6 @@ // http://w3c.github.io/push-api/#pushmessagedata-interface -typedef object JSON; - [ Exposed=ServiceWorker, ] interface PushMessageData {
diff --git a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.cpp b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.cpp index 87380a3..9dc9f52 100644 --- a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.cpp +++ b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.cpp
@@ -197,7 +197,7 @@ return true; } -void ScreenOrientationController::willDetachFrameHost() +void ScreenOrientationController::contextDestroyed() { m_client = nullptr; }
diff --git a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.h b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.h index 07e7ed6..d06c3c0a 100644 --- a/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.h +++ b/third_party/WebKit/Source/modules/screen_orientation/ScreenOrientationController.h
@@ -55,7 +55,7 @@ void pageVisibilityChanged() override; // Inherited from LocalFrameLifecycleObserver. - void willDetachFrameHost() override; + void contextDestroyed() override; void notifyDispatcher();
diff --git a/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.cpp b/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.cpp index a7ba1e19..4dd3c93 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.cpp +++ b/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.cpp
@@ -13,7 +13,7 @@ namespace blink { NavigatorServiceWorker::NavigatorServiceWorker(Navigator& navigator) - : DOMWindowProperty(navigator.frame()) + : ContextLifecycleObserver(navigator.frame() ? navigator.frame()->document() : nullptr) { } @@ -33,7 +33,7 @@ provideTo(navigator, supplementName(), supplement); if (navigator.frame() && navigator.frame()->securityContext()->getSecurityOrigin()->canAccessServiceWorkers()) { // Initialize ServiceWorkerContainer too. - supplement->serviceWorker(ASSERT_NO_EXCEPTION); + supplement->serviceWorker(navigator.frame(), ASSERT_NO_EXCEPTION); } } return *supplement; @@ -51,27 +51,27 @@ ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(ExecutionContext* executionContext, Navigator& navigator, ExceptionState& exceptionState) { - ASSERT(!navigator.frame() || executionContext->getSecurityOrigin()->canAccessCheckSuborigins(navigator.frame()->securityContext()->getSecurityOrigin())); - return NavigatorServiceWorker::from(navigator).serviceWorker(exceptionState); + DCHECK(!navigator.frame() || executionContext->getSecurityOrigin()->canAccessCheckSuborigins(navigator.frame()->securityContext()->getSecurityOrigin())); + return NavigatorServiceWorker::from(navigator).serviceWorker(navigator.frame(), exceptionState); } -ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(ExceptionState& exceptionState) +ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(LocalFrame* frame, ExceptionState& exceptionState) { - if (frame() && !frame()->securityContext()->getSecurityOrigin()->canAccessServiceWorkers()) { - if (frame()->securityContext()->isSandboxed(SandboxOrigin)) + if (frame && !frame->securityContext()->getSecurityOrigin()->canAccessServiceWorkers()) { + if (frame->securityContext()->isSandboxed(SandboxOrigin)) exceptionState.throwSecurityError("Service worker is disabled because the context is sandboxed and lacks the 'allow-same-origin' flag."); else exceptionState.throwSecurityError("Access to service workers is denied in this document origin."); return nullptr; } - if (!m_serviceWorker && frame()) { - ASSERT(frame()->domWindow()); - m_serviceWorker = ServiceWorkerContainer::create(frame()->domWindow()->getExecutionContext()); + if (!m_serviceWorker && frame) { + DCHECK(frame->domWindow()); + m_serviceWorker = ServiceWorkerContainer::create(frame->domWindow()->getExecutionContext()); } return m_serviceWorker.get(); } -void NavigatorServiceWorker::willDetachGlobalObjectFromFrame() +void NavigatorServiceWorker::contextDestroyed() { if (m_serviceWorker) { m_serviceWorker->willBeDetachedFromFrame(); @@ -83,7 +83,7 @@ { visitor->trace(m_serviceWorker); Supplement<Navigator>::trace(visitor); - DOMWindowProperty::trace(visitor); + ContextLifecycleObserver::trace(visitor); } } // namespace blink
diff --git a/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.h b/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.h index ebcb21b..9d8584e 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.h +++ b/third_party/WebKit/Source/modules/serviceworkers/NavigatorServiceWorker.h
@@ -5,6 +5,7 @@ #ifndef NavigatorServiceWorker_h #define NavigatorServiceWorker_h +#include "core/dom/ContextLifecycleObserver.h" #include "core/frame/Navigator.h" #include "modules/ModulesExport.h" #include "platform/Supplementable.h" @@ -17,7 +18,7 @@ class Navigator; class ServiceWorkerContainer; -class MODULES_EXPORT NavigatorServiceWorker final : public GarbageCollected<NavigatorServiceWorker>, public Supplement<Navigator>, public DOMWindowProperty { +class MODULES_EXPORT NavigatorServiceWorker final : public GarbageCollected<NavigatorServiceWorker>, public Supplement<Navigator>, public ContextLifecycleObserver { USING_GARBAGE_COLLECTED_MIXIN(NavigatorServiceWorker); public: static NavigatorServiceWorker* from(Document&); @@ -29,12 +30,12 @@ private: explicit NavigatorServiceWorker(Navigator&); - ServiceWorkerContainer* serviceWorker(ExceptionState&); + ServiceWorkerContainer* serviceWorker(LocalFrame*, ExceptionState&); static const char* supplementName(); - // DOMWindowProperty override. - void willDetachGlobalObjectFromFrame() override; + // ContextLifecycleObserver override. + void contextDestroyed() override; Member<ServiceWorkerContainer> m_serviceWorker; };
diff --git a/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp b/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp index 0a560cf..9ca5c36c 100644 --- a/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp +++ b/third_party/WebKit/Source/modules/vibration/NavigatorVibration.cpp
@@ -19,6 +19,7 @@ #include "modules/vibration/NavigatorVibration.h" +#include "core/dom/Document.h" #include "core/frame/LocalFrame.h" #include "core/frame/Navigator.h" #include "core/frame/UseCounter.h" @@ -30,7 +31,7 @@ namespace blink { NavigatorVibration::NavigatorVibration(Navigator& navigator) - : DOMWindowProperty(navigator.frame()) + : ContextLifecycleObserver(navigator.frame()->document()) { } @@ -80,7 +81,7 @@ if (!frame->page()->isPageVisible()) return false; - return NavigatorVibration::from(navigator).controller()->vibrate(pattern); + return NavigatorVibration::from(navigator).controller(*frame)->vibrate(pattern); } // static @@ -112,15 +113,15 @@ NavigatorVibrateHistogram.count(type); } -VibrationController* NavigatorVibration::controller() +VibrationController* NavigatorVibration::controller(const LocalFrame& frame) { - if (!m_controller && frame()) - m_controller = new VibrationController(*frame()->document()); + if (!m_controller) + m_controller = new VibrationController(*frame.document()); return m_controller.get(); } -void NavigatorVibration::willDetachGlobalObjectFromFrame() +void NavigatorVibration::contextDestroyed() { if (m_controller) { m_controller->cancel(); @@ -132,7 +133,7 @@ { visitor->trace(m_controller); Supplement<Navigator>::trace(visitor); - DOMWindowProperty::trace(visitor); + ContextLifecycleObserver::trace(visitor); } } // namespace blink
diff --git a/third_party/WebKit/Source/modules/vibration/NavigatorVibration.h b/third_party/WebKit/Source/modules/vibration/NavigatorVibration.h index ec978cff..723cf09 100644 --- a/third_party/WebKit/Source/modules/vibration/NavigatorVibration.h +++ b/third_party/WebKit/Source/modules/vibration/NavigatorVibration.h
@@ -20,7 +20,7 @@ #ifndef NavigatorVibration_h #define NavigatorVibration_h -#include "core/frame/DOMWindowProperty.h" +#include "core/dom/ContextLifecycleObserver.h" #include "modules/ModulesExport.h" #include "platform/Supplementable.h" #include "platform/heap/GarbageCollected.h" @@ -30,6 +30,7 @@ namespace blink { +class LocalFrame; class Navigator; class VibrationController; @@ -46,7 +47,7 @@ class MODULES_EXPORT NavigatorVibration final : public GarbageCollectedFinalized<NavigatorVibration> , public Supplement<Navigator> - , public DOMWindowProperty { + , public ContextLifecycleObserver { USING_GARBAGE_COLLECTED_MIXIN(NavigatorVibration); WTF_MAKE_NONCOPYABLE(NavigatorVibration); public: @@ -59,7 +60,7 @@ static bool vibrate(Navigator&, unsigned time); static bool vibrate(Navigator&, const VibrationPattern&); - VibrationController* controller(); + VibrationController* controller(const LocalFrame&); DECLARE_VIRTUAL_TRACE(); @@ -68,8 +69,8 @@ explicit NavigatorVibration(Navigator&); - // Inherited from DOMWindowProperty. - void willDetachGlobalObjectFromFrame() override; + // Inherited from ContextLifecycleObserver. + void contextDestroyed() override; static void collectHistogramMetrics(const LocalFrame&);
diff --git a/third_party/WebKit/Source/modules/vibration/testing/InternalsVibration.cpp b/third_party/WebKit/Source/modules/vibration/testing/InternalsVibration.cpp index 5c7c679..814c78e 100644 --- a/third_party/WebKit/Source/modules/vibration/testing/InternalsVibration.cpp +++ b/third_party/WebKit/Source/modules/vibration/testing/InternalsVibration.cpp
@@ -40,13 +40,13 @@ bool InternalsVibration::isVibrating(Internals&, Navigator* navigator) { DCHECK(navigator && navigator->frame()); - return NavigatorVibration::from(*navigator).controller()->isRunning(); + return NavigatorVibration::from(*navigator).controller(*navigator->frame())->isRunning(); } Vector<unsigned> InternalsVibration::pendingVibrationPattern(Internals&, Navigator* navigator) { DCHECK(navigator && navigator->frame()); - return NavigatorVibration::from(*navigator).controller()->pattern(); + return NavigatorVibration::from(*navigator).controller(*navigator->frame())->pattern(); } } // namespace blink
diff --git a/third_party/WebKit/Source/modules/vr/VRController.cpp b/third_party/WebKit/Source/modules/vr/VRController.cpp index 88a2128..455d700 100644 --- a/third_party/WebKit/Source/modules/vr/VRController.cpp +++ b/third_party/WebKit/Source/modules/vr/VRController.cpp
@@ -28,7 +28,6 @@ } VRController::VRController(LocalFrame& frame, ServiceRegistry* registry) - : LocalFrameLifecycleObserver(&frame) { ASSERT(!m_service.is_bound()); registry->connectToRemoteService(mojo::GetProxy(&m_service)); @@ -67,11 +66,6 @@ m_service->ResetPose(index); } -void VRController::willDetachFrameHost() -{ - // TODO(kphanee): Detach from the mojo service connection. -} - void VRController::onGetDisplays(mojo::WTFArray<device::blink::VRDisplayPtr> displays) { std::unique_ptr<VRGetDevicesCallback> callback = m_pendingGetDevicesCallbacks.takeFirst(); @@ -84,7 +78,6 @@ DEFINE_TRACE(VRController) { Supplement<LocalFrame>::trace(visitor); - LocalFrameLifecycleObserver::trace(visitor); } } // namespace blink
diff --git a/third_party/WebKit/Source/modules/vr/VRController.h b/third_party/WebKit/Source/modules/vr/VRController.h index 32c984cd..3e01a2f 100644 --- a/third_party/WebKit/Source/modules/vr/VRController.h +++ b/third_party/WebKit/Source/modules/vr/VRController.h
@@ -5,7 +5,7 @@ #ifndef VRController_h #define VRController_h -#include "core/frame/LocalFrameLifecycleObserver.h" +#include "core/frame/LocalFrame.h" #include "device/vr/vr_service.mojom-blink.h" #include "modules/ModulesExport.h" #include "platform/Supplementable.h" @@ -20,8 +20,7 @@ class MODULES_EXPORT VRController final : public GarbageCollectedFinalized<VRController> - , public Supplement<LocalFrame> - , public LocalFrameLifecycleObserver { + , public Supplement<LocalFrame> { USING_GARBAGE_COLLECTED_MIXIN(VRController); WTF_MAKE_NONCOPYABLE(VRController); public: @@ -42,9 +41,6 @@ private: VRController(LocalFrame&, ServiceRegistry*); - // Inherited from LocalFrameLifecycleObserver. - void willDetachFrameHost() override; - // Binding callbacks. void onGetDisplays(mojo::WTFArray<device::blink::VRDisplayPtr>);
diff --git a/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.cpp b/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.cpp index 345d5c6..353d3b02 100644 --- a/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.cpp +++ b/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.cpp
@@ -28,6 +28,10 @@ #include "modules/webdatabase/DatabaseAuthorizer.h" +#include "wtf/HashSet.h" +#include "wtf/StdLibExtras.h" +#include "wtf/text/StringHash.h" + namespace blink { DatabaseAuthorizer* DatabaseAuthorizer::create(const String& databaseInfoTableName) @@ -42,7 +46,6 @@ DCHECK(isMainThread()); reset(); - addWhitelistedFunctions(); } void DatabaseAuthorizer::reset() @@ -57,68 +60,70 @@ m_hadDeletes = false; } -void DatabaseAuthorizer::addWhitelistedFunctions() +namespace { +using FunctionNameList = HashSet<String, CaseFoldingHash>; + +const FunctionNameList& whitelistedFunctions() { - // SQLite functions used to help implement some operations - // ALTER TABLE helpers - m_whitelistedFunctions.add("sqlite_rename_table"); - m_whitelistedFunctions.add("sqlite_rename_trigger"); - // GLOB helpers - m_whitelistedFunctions.add("glob"); - - // SQLite core functions - m_whitelistedFunctions.add("abs"); - m_whitelistedFunctions.add("changes"); - m_whitelistedFunctions.add("coalesce"); - m_whitelistedFunctions.add("glob"); - m_whitelistedFunctions.add("ifnull"); - m_whitelistedFunctions.add("hex"); - m_whitelistedFunctions.add("last_insert_rowid"); - m_whitelistedFunctions.add("length"); - m_whitelistedFunctions.add("like"); - m_whitelistedFunctions.add("lower"); - m_whitelistedFunctions.add("ltrim"); - m_whitelistedFunctions.add("max"); - m_whitelistedFunctions.add("min"); - m_whitelistedFunctions.add("nullif"); - m_whitelistedFunctions.add("quote"); - m_whitelistedFunctions.add("replace"); - m_whitelistedFunctions.add("round"); - m_whitelistedFunctions.add("rtrim"); - m_whitelistedFunctions.add("soundex"); - m_whitelistedFunctions.add("sqlite_source_id"); - m_whitelistedFunctions.add("sqlite_version"); - m_whitelistedFunctions.add("substr"); - m_whitelistedFunctions.add("total_changes"); - m_whitelistedFunctions.add("trim"); - m_whitelistedFunctions.add("typeof"); - m_whitelistedFunctions.add("upper"); - m_whitelistedFunctions.add("zeroblob"); - - // SQLite date and time functions - m_whitelistedFunctions.add("date"); - m_whitelistedFunctions.add("time"); - m_whitelistedFunctions.add("datetime"); - m_whitelistedFunctions.add("julianday"); - m_whitelistedFunctions.add("strftime"); - - // SQLite aggregate functions - // max() and min() are already in the list - m_whitelistedFunctions.add("avg"); - m_whitelistedFunctions.add("count"); - m_whitelistedFunctions.add("group_concat"); - m_whitelistedFunctions.add("sum"); - m_whitelistedFunctions.add("total"); - - // SQLite FTS functions - m_whitelistedFunctions.add("match"); - m_whitelistedFunctions.add("snippet"); - m_whitelistedFunctions.add("offsets"); - m_whitelistedFunctions.add("optimize"); - - // SQLite ICU functions - // like(), lower() and upper() are already in the list - m_whitelistedFunctions.add("regexp"); + DEFINE_STATIC_LOCAL(FunctionNameList, list, ({ + // SQLite functions used to help implement some operations + // ALTER TABLE helpers + "sqlite_rename_table", + "sqlite_rename_trigger", + // GLOB helpers + "glob", + // SQLite core functions + "abs", + "changes", + "coalesce", + "glob", + "ifnull", + "hex", + "last_insert_rowid", + "length", + "like", + "lower", + "ltrim", + "max", + "min", + "nullif", + "quote", + "replace", + "round", + "rtrim", + "soundex", + "sqlite_source_id", + "sqlite_version", + "substr", + "total_changes", + "trim", + "typeof", + "upper", + "zeroblob", + // SQLite date and time functions + "date", + "time", + "datetime", + "julianday", + "strftime", + // SQLite aggregate functions + // max() and min() are already in the list + "avg", + "count", + "group_concat", + "sum", + "total", + // SQLite FTS functions + "match", + "snippet", + "offsets", + "optimize", + // SQLite ICU functions + // like(), lower() and upper() are already in the list + "regexp", + })); + return list; +} } int DatabaseAuthorizer::createTable(const String& tableName) @@ -373,7 +378,7 @@ int DatabaseAuthorizer::allowFunction(const String& functionName) { - if (m_securityEnabled && !m_whitelistedFunctions.contains(functionName)) + if (m_securityEnabled && !whitelistedFunctions().contains(functionName)) return SQLAuthDeny; return SQLAuthAllow;
diff --git a/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.h b/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.h index 81bfd4fe..c612528 100644 --- a/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.h +++ b/third_party/WebKit/Source/modules/webdatabase/DatabaseAuthorizer.h
@@ -30,8 +30,6 @@ #include "platform/heap/Handle.h" #include "wtf/Forward.h" -#include "wtf/HashSet.h" -#include "wtf/text/StringHash.h" #include "wtf/text/WTFString.h" namespace blink { @@ -116,8 +114,6 @@ bool m_hadDeletes : 1; const String m_databaseInfoTableName; - - HashSet<String, CaseFoldingHash> m_whitelistedFunctions; }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/webdatabase/DatabaseClient.cpp b/third_party/WebKit/Source/modules/webdatabase/DatabaseClient.cpp index 88c2fab3..3b36126 100644 --- a/third_party/WebKit/Source/modules/webdatabase/DatabaseClient.cpp +++ b/third_party/WebKit/Source/modules/webdatabase/DatabaseClient.cpp
@@ -44,6 +44,7 @@ DEFINE_TRACE(DatabaseClient) { visitor->trace(m_inspectorAgent); + Supplement<Page>::trace(visitor); } DatabaseClient* DatabaseClient::fromPage(Page* page)
diff --git a/third_party/WebKit/Source/modules/webgl/OESTextureHalfFloat.idl b/third_party/WebKit/Source/modules/webgl/OESTextureHalfFloat.idl index 37aabac..2769a76 100644 --- a/third_party/WebKit/Source/modules/webgl/OESTextureHalfFloat.idl +++ b/third_party/WebKit/Source/modules/webgl/OESTextureHalfFloat.idl
@@ -23,8 +23,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -typedef unsigned long GLenum; - [ NoInterfaceObject, DoNotCheckConstants,
diff --git a/third_party/WebKit/Source/modules/webgl/PRESUBMIT.py b/third_party/WebKit/Source/modules/webgl/PRESUBMIT.py index 923a26b3d4d..389fdeab 100644 --- a/third_party/WebKit/Source/modules/webgl/PRESUBMIT.py +++ b/third_party/WebKit/Source/modules/webgl/PRESUBMIT.py
@@ -25,8 +25,8 @@ return [] bots = [ - 'tryserver.chromium.win:win_optional_gpu_tests_rel', - 'tryserver.chromium.mac:mac_optional_gpu_tests_rel', + 'master.tryserver.chromium.win:win_optional_gpu_tests_rel', + 'master.tryserver.chromium.mac:mac_optional_gpu_tests_rel', ] results = []
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.idl b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.idl index 6bddcfb..ac9b986 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.idl +++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.idl
@@ -2,20 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -typedef unsigned long GLenum; -typedef boolean GLboolean; -typedef unsigned long GLbitfield; -typedef byte GLbyte; // 'byte' should be a signed 8 bit type. -typedef short GLshort; -typedef long GLint; -typedef long GLsizei; -typedef long long GLintptr; -typedef long long GLsizeiptr; -typedef octet GLubyte; // 'octet' should be an unsigned 8 bit type. -typedef unsigned short GLushort; -typedef unsigned long GLuint; -typedef unrestricted float GLfloat; -typedef unrestricted float GLclampf; typedef long long GLint64; [
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLDrawBuffers.idl b/third_party/WebKit/Source/modules/webgl/WebGLDrawBuffers.idl index cf76ce1c..5618b1f8 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLDrawBuffers.idl +++ b/third_party/WebKit/Source/modules/webgl/WebGLDrawBuffers.idl
@@ -23,8 +23,6 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -typedef unsigned long GLenum; - [ NoInterfaceObject, DoNotCheckConstants,
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp index 382461c7..671efb1 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -534,7 +534,7 @@ formatWebGLStatusString("Reset notification strategy", String::format("0x%04x", info.resetNotificationStrategy).utf8().data(), statusMessage); formatWebGLStatusString("GPU process crash count", String::number(info.processCrashCount).utf8().data(), statusMessage); formatWebGLStatusString("ErrorMessage", info.errorMessage.utf8().data(), statusMessage); - statusMessage.append("."); + statusMessage.append('.'); return statusMessage; } @@ -642,7 +642,15 @@ return nullptr; WebExternalTextureMailbox mailbox; drawingBuffer()->prepareMailbox(&mailbox, 0); - ImageBitmap* imageBitmap = ImageBitmap::create(mailbox); + ImageBitmap* imageBitmap; + // If the mailbox is invalid, return an transparent black ImageBitmap. + // The only situation this could happen is when two or more calls to transferToImageBitmap are made back-to-back. + if (mailbox.textureSize.width == 0 && mailbox.textureSize.height == 0) { + sk_sp<SkSurface>surface = SkSurface::MakeRasterN32Premul(drawingBuffer()->size().width(), drawingBuffer()->size().height()); + imageBitmap = ImageBitmap::create(StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot()))); + } else { + imageBitmap = ImageBitmap::create(mailbox); + } // TODO(xidachen): Create a small pool of recycled textures from ImageBitmapRenderingContext's // transferFromImageBitmap, and try to use them in DrawingBuffer. return imageBitmap;
diff --git a/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp b/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp index 7669a9c..53b7bc6 100644 --- a/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp +++ b/third_party/WebKit/Source/modules/websockets/DOMWebSocketTest.cpp
@@ -20,6 +20,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "wtf/Vector.h" #include "wtf/text/CString.h" +#include "wtf/text/StringBuilder.h" #include "wtf/text/WTFString.h" #include <memory> #include <v8.h> @@ -358,15 +359,15 @@ EXPECT_CALL(webSocketScope.channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); EXPECT_CALL(webSocketScope.channel(), failMock(_, _, _)); } - String reason; + StringBuilder reason; for (size_t i = 0; i < 123; ++i) - reason.append("a"); + reason.append('a'); webSocketScope.socket().connect("ws://example.com/", Vector<String>(), scope.getExceptionState()); EXPECT_FALSE(scope.getExceptionState().hadException()); EXPECT_EQ(DOMWebSocket::CONNECTING, webSocketScope.socket().readyState()); - webSocketScope.socket().close(1000, reason, scope.getExceptionState()); + webSocketScope.socket().close(1000, reason.toString(), scope.getExceptionState()); EXPECT_FALSE(scope.getExceptionState().hadException()); EXPECT_EQ(DOMWebSocket::CLOSING, webSocketScope.socket().readyState()); @@ -380,15 +381,15 @@ InSequence s; EXPECT_CALL(webSocketScope.channel(), connect(KURL(KURL(), "ws://example.com/"), String())).WillOnce(Return(true)); } - String reason; + StringBuilder reason; for (size_t i = 0; i < 124; ++i) - reason.append("a"); + reason.append('a'); webSocketScope.socket().connect("ws://example.com/", Vector<String>(), scope.getExceptionState()); EXPECT_FALSE(scope.getExceptionState().hadException()); EXPECT_EQ(DOMWebSocket::CONNECTING, webSocketScope.socket().readyState()); - webSocketScope.socket().close(1000, reason, scope.getExceptionState()); + webSocketScope.socket().close(1000, reason.toString(), scope.getExceptionState()); EXPECT_TRUE(scope.getExceptionState().hadException()); EXPECT_EQ(SyntaxError, scope.getExceptionState().code());
diff --git a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp index 8d4c7b9..456d2711 100644 --- a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp +++ b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannel.cpp
@@ -58,8 +58,6 @@ #include "wtf/PtrUtil.h" #include <memory> -using blink::WebSocketHandle; - namespace blink { class DocumentWebSocketChannel::BlobLoader final : public GarbageCollectedFinalized<DocumentWebSocketChannel::BlobLoader>, public FileReaderLoaderClient { @@ -184,7 +182,8 @@ if (document()->frame()) document()->frame()->loader().client()->dispatchWillOpenWebSocket(m_handle.get()); - m_handle->connect(url, webProtocols, WebSecurityOrigin(getExecutionContext()->getSecurityOrigin()), document()->userAgent(), this); + m_handle->connect(url, webProtocols, WebSecurityOrigin(getExecutionContext()->getSecurityOrigin()), document()->firstPartyForCookies(), document()->userAgent(), this); + flowControlIfNecessary(); TRACE_EVENT_INSTANT1("devtools.timeline", "WebSocketCreate", TRACE_EVENT_SCOPE_THREAD, "data", InspectorWebSocketCreateEvent::data(document(), m_identifier, url, protocol)); InspectorInstrumentation::didCreateWebSocket(document(), m_identifier, url, protocol);
diff --git a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp index 2b8ce537..56494e6 100644 --- a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp +++ b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp
@@ -30,7 +30,7 @@ using testing::InSequence; using testing::PrintToString; using testing::AnyNumber; - +using testing::SaveArg; namespace blink { @@ -80,7 +80,7 @@ ~MockWebSocketHandle() override { } - MOCK_METHOD5(connect, void(const WebURL&, const WebVector<WebString>&, const WebSecurityOrigin&, const WebString&, WebSocketHandleClient*)); + MOCK_METHOD6(connect, void(const WebURL&, const WebVector<WebString>&, const WebSecurityOrigin&, const WebURL&, const WebString&, WebSocketHandleClient*)); MOCK_METHOD4(send, void(bool, WebSocketHandle::MessageType, const char*, size_t)); MOCK_METHOD1(flowControl, void(int64_t)); MOCK_METHOD2(close, void(unsigned short, const WebString&)); @@ -132,7 +132,7 @@ { { InSequence s; - EXPECT_CALL(*handle(), connect(WebURL(KURL(KURL(), "ws://localhost/")), _, _, _, handleClient())); + EXPECT_CALL(*handle(), connect(WebURL(KURL(KURL(), "ws://localhost/")), _, _, _, _, handleClient())); EXPECT_CALL(*handle(), flowControl(65536)); EXPECT_CALL(*channelClient(), didConnect(String("a"), String("b"))); } @@ -158,18 +158,46 @@ return memcmp(arg, p, len) == 0; } +MATCHER_P(WebURLEq, urlString, + std::string(negation ? "doesn't equal" : "equals") + + " to \"" + urlString + "\"" +) +{ + WebURL url(KURL(KURL(), urlString)); + *result_listener << "where the url is \"" << arg.string().utf8() << "\""; + return arg == url; +} + TEST_F(DocumentWebSocketChannelTest, connectSuccess) { + WebVector<WebString> protocols; + WebSecurityOrigin origin; + Checkpoint checkpoint; { InSequence s; - EXPECT_CALL(*handle(), connect(WebURL(KURL(KURL(), "ws://localhost/")), _, _, _, handleClient())); + EXPECT_CALL(*handle(), connect(WebURLEq("ws://localhost/"), _, _, WebURLEq("http://example.com/"), _, handleClient())).WillOnce(DoAll( + SaveArg<1>(&protocols), + SaveArg<2>(&origin))); EXPECT_CALL(*handle(), flowControl(65536)); EXPECT_CALL(checkpoint, Call(1)); EXPECT_CALL(*channelClient(), didConnect(String("a"), String("b"))); } + KURL pageUrl(KURL(), "http://example.com/"); + m_pageHolder->frame().securityContext()->setSecurityOrigin(SecurityOrigin::create(pageUrl)); + Document& document = m_pageHolder->document(); + document.setURL(pageUrl); + // Make sure that firstPartyForCookies() is set to the given value. + EXPECT_STREQ("http://example.com/", document.firstPartyForCookies().getString().utf8().data()); + EXPECT_TRUE(channel()->connect(KURL(KURL(), "ws://localhost/"), "x")); + + EXPECT_EQ(1U, protocols.size()); + EXPECT_STREQ("x", protocols[0].utf8().data()); + + EXPECT_STREQ("http://example.com", origin.toString().utf8().data()); + checkpoint.Call(1); handleClient()->didConnect(handle(), WebString("a"), WebString("b")); }
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index 631aa544..cfffb11 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/features.gni") import("//build/config/ui.gni") import("//testing/test.gni") import("//third_party/WebKit/Source/build/scripts/scripts.gni") @@ -367,6 +368,7 @@ "//mojo/public/cpp/bindings:wtf_support", "//third_party/WebKit/Source/platform/heap", "//third_party/WebKit/public:mojo_bindings_blink", + "//third_party/ced", "//third_party/harfbuzz-ng", "//third_party/icu", "//ui/gfx", @@ -436,6 +438,10 @@ sources -= [ "scroll/ScrollbarThemeAndroid.cpp" ] } + if (use_minikin_hyphenation) { + sources += [ "text/hyphenation/HyphenationMinikin.cpp" ] + } + if (!use_default_render_theme) { sources -= [ "scroll/ScrollbarThemeAura.cpp",
diff --git a/third_party/WebKit/Source/platform/Crypto.cpp b/third_party/WebKit/Source/platform/Crypto.cpp index 79fa67b..90808a76 100644 --- a/third_party/WebKit/Source/platform/Crypto.cpp +++ b/third_party/WebKit/Source/platform/Crypto.cpp
@@ -7,7 +7,6 @@ #include "public/platform/Platform.h" #include "public/platform/WebCrypto.h" #include "public/platform/WebCryptoAlgorithm.h" -#include "wtf/PtrUtil.h" #include <memory> namespace blink { @@ -38,8 +37,9 @@ ASSERT(crypto); - std::unique_ptr<WebCryptoDigestor> digestor = wrapUnique(crypto->createDigestor(algorithmId)); - if (!digestor.get() || !digestor->consume(reinterpret_cast<const unsigned char*>(digestable), length) || !digestor->finish(result, resultSize)) + std::unique_ptr<WebCryptoDigestor> digestor = crypto->createDigestor(algorithmId); + DCHECK(digestor); + if (!digestor->consume(reinterpret_cast<const unsigned char*>(digestable), length) || !digestor->finish(result, resultSize)) return false; digestResult.append(static_cast<uint8_t*>(result), resultSize); @@ -48,7 +48,7 @@ std::unique_ptr<WebCryptoDigestor> createDigestor(HashAlgorithm algorithm) { - return wrapUnique(Platform::current()->crypto()->createDigestor(toWebCryptoAlgorithmId(algorithm))); + return Platform::current()->crypto()->createDigestor(toWebCryptoAlgorithmId(algorithm)); } void finishDigestor(WebCryptoDigestor* digestor, DigestValue& digestResult)
diff --git a/third_party/WebKit/Source/platform/Crypto.h b/third_party/WebKit/Source/platform/Crypto.h index 388462e..cbe597c 100644 --- a/third_party/WebKit/Source/platform/Crypto.h +++ b/third_party/WebKit/Source/platform/Crypto.h
@@ -33,6 +33,7 @@ }; PLATFORM_EXPORT bool computeDigest(HashAlgorithm, const char* digestable, size_t length, DigestValue& digestResult); +// Note: this will never return null. PLATFORM_EXPORT std::unique_ptr<WebCryptoDigestor> createDigestor(HashAlgorithm); PLATFORM_EXPORT void finishDigestor(WebCryptoDigestor*, DigestValue& digestResult);
diff --git a/third_party/WebKit/Source/platform/DEPS b/third_party/WebKit/Source/platform/DEPS index c572870..8b92e56 100644 --- a/third_party/WebKit/Source/platform/DEPS +++ b/third_party/WebKit/Source/platform/DEPS
@@ -18,14 +18,17 @@ "+base/test", "+base/threading/thread_task_runner_handle.h", "+base/time", + "+base/timer", "+base/trace_event", "+base/values.h", "+device", "+gpu/GLES2", + "+mojo/public", "+mozilla", "+platform", "+public/platform", "+skia/ext", + "+third_party/ced/src/compact_enc_det/compact_enc_det.h", "+third_party/khronos", "+third_party/skia", "+ui/gfx",
diff --git a/third_party/WebKit/Source/platform/Supplementable.h b/third_party/WebKit/Source/platform/Supplementable.h index f60bc75..4878737 100644 --- a/third_party/WebKit/Source/platform/Supplementable.h +++ b/third_party/WebKit/Source/platform/Supplementable.h
@@ -107,6 +107,8 @@ { return host ? host->requireSupplement(key) : 0; } + + DEFINE_INLINE_VIRTUAL_TRACE() { } }; // Supplementable<T> inherits from GarbageCollectedMixin virtually
diff --git a/third_party/WebKit/Source/platform/blink_platform.gyp b/third_party/WebKit/Source/platform/blink_platform.gyp index 56cd039..65825db 100644 --- a/third_party/WebKit/Source/platform/blink_platform.gyp +++ b/third_party/WebKit/Source/platform/blink_platform.gyp
@@ -150,6 +150,7 @@ '<(DEPTH)/mojo/mojo_public.gyp:mojo_cpp_bindings_wtf_support', '<(DEPTH)/net/net.gyp:net', '<(DEPTH)/skia/skia.gyp:skia', + '<(DEPTH)/third_party/ced/ced.gyp:ced', '<(DEPTH)/third_party/harfbuzz-ng/harfbuzz.gyp:harfbuzz-ng', '<(DEPTH)/third_party/iccjpeg/iccjpeg.gyp:iccjpeg', '<(DEPTH)/third_party/icu/icu.gyp:icui18n',
diff --git a/third_party/WebKit/Source/platform/blink_platform.gypi b/third_party/WebKit/Source/platform/blink_platform.gypi index 7e6763e..1ec0dff2 100644 --- a/third_party/WebKit/Source/platform/blink_platform.gypi +++ b/third_party/WebKit/Source/platform/blink_platform.gypi
@@ -376,7 +376,6 @@ 'exported/WebURLLoaderTestDelegate.cpp', 'exported/WebURLLoadTiming.cpp', 'exported/WebURLRequest.cpp', - 'exported/WebURLRequestPrivate.h', 'exported/WebURLResponse.cpp', 'exported/WrappedResourceRequest.h', 'exported/WrappedResourceResponse.h', @@ -743,7 +742,6 @@ 'graphics/gpu/Extensions3DUtil.h', 'graphics/gpu/WebGLImageConversion.cpp', 'graphics/gpu/WebGLImageConversion.h', - 'graphics/paint/CachedDisplayItem.h', 'graphics/paint/ClipDisplayItem.cpp', 'graphics/paint/ClipDisplayItem.h', 'graphics/paint/ClipPaintPropertyNode.h', @@ -1038,7 +1036,6 @@ 'text/UnicodeRange.h', 'text/UnicodeUtilities.cpp', 'text/UnicodeUtilities.h', - 'text/android/HyphenationAndroid.cpp', 'text/linux/HyphenationLinux.cpp', 'text/mac/HyphenationMac.cpp', 'text/win/HyphenationWin.cpp', @@ -1101,6 +1098,8 @@ 'v8_inspector/V8InjectedScriptHost.h', 'v8_inspector/V8InspectorSessionImpl.cpp', 'v8_inspector/V8InspectorSessionImpl.h', + 'v8_inspector/V8InternalValueType.cpp', + 'v8_inspector/V8InternalValueType.h', 'v8_inspector/V8ProfilerAgentImpl.cpp', 'v8_inspector/V8ProfilerAgentImpl.h', 'v8_inspector/V8Regex.cpp', @@ -1239,6 +1238,7 @@ 'network/LinkHeaderTest.cpp', 'network/NetworkUtilsTest.cpp', 'network/ResourceRequestTest.cpp', + 'network/ResourceResponseTest.cpp', 'scheduler/CancellableTaskFactoryTest.cpp', 'scroll/ScrollableAreaTest.cpp', 'testing/ArenaTestHelpers.h',
diff --git a/third_party/WebKit/Source/platform/exported/WebBlobData.cpp b/third_party/WebKit/Source/platform/exported/WebBlobData.cpp index 942d2aec..52aa5ca 100644 --- a/third_party/WebKit/Source/platform/exported/WebBlobData.cpp +++ b/third_party/WebKit/Source/platform/exported/WebBlobData.cpp
@@ -42,7 +42,6 @@ WebBlobData::~WebBlobData() { - m_private.reset(0); } size_t WebBlobData::itemCount() const @@ -101,13 +100,13 @@ WebBlobData& WebBlobData::operator=(std::unique_ptr<BlobData> data) { - m_private.reset(std::move(data)); + m_private = std::move(data); return *this; } WebBlobData::operator std::unique_ptr<BlobData>() { - return m_private.release(); + return std::move(m_private); } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/exported/WebFont.cpp b/third_party/WebKit/Source/platform/exported/WebFont.cpp index f2306489..be277e92 100644 --- a/third_party/WebKit/Source/platform/exported/WebFont.cpp +++ b/third_party/WebKit/Source/platform/exported/WebFont.cpp
@@ -45,7 +45,6 @@ WebFont::~WebFont() { - m_private.reset(0); } WebFontDescription WebFont::getFontDescription() const
diff --git a/third_party/WebKit/Source/platform/exported/WebSocketHandshakeResponseInfo.cpp b/third_party/WebKit/Source/platform/exported/WebSocketHandshakeResponseInfo.cpp index 82f6f05b..14ccc9c 100644 --- a/third_party/WebKit/Source/platform/exported/WebSocketHandshakeResponseInfo.cpp +++ b/third_party/WebKit/Source/platform/exported/WebSocketHandshakeResponseInfo.cpp
@@ -41,7 +41,6 @@ WebSocketHandshakeResponseInfo::~WebSocketHandshakeResponseInfo() { - m_private.reset(0); } void WebSocketHandshakeResponseInfo::setStatusCode(int statusCode)
diff --git a/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp b/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp index 008bb5f..6c5a96c62 100644 --- a/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp +++ b/third_party/WebKit/Source/platform/exported/WebURLRequest.cpp
@@ -30,7 +30,6 @@ #include "public/platform/WebURLRequest.h" -#include "platform/exported/WebURLRequestPrivate.h" #include "platform/network/ResourceRequest.h" #include "public/platform/WebCachePolicy.h" #include "public/platform/WebHTTPBody.h" @@ -65,120 +64,123 @@ } // namespace -// The standard implementation of WebURLRequestPrivate, which maintains -// ownership of a ResourceRequest instance. -class WebURLRequestPrivateImpl final : public WebURLRequestPrivate { - USING_FAST_MALLOC(WebURLRequestPrivate); -public: - WebURLRequestPrivateImpl() - { - m_resourceRequest = &m_resourceRequestAllocation; - } +// The purpose of this struct is to permit allocating a ResourceRequest on the +// heap, which is otherwise disallowed by DISALLOW_NEW_EXCEPT_PLACEMENT_NEW +// annotation on ResourceRequest. +struct WebURLRequest::ResourceRequestContainer { + ResourceRequestContainer() {} + explicit ResourceRequestContainer(const ResourceRequest& r) : resourceRequest(r) {} - WebURLRequestPrivateImpl(const WebURLRequestPrivate* p) - : m_resourceRequestAllocation(*p->m_resourceRequest) - { - m_resourceRequest = &m_resourceRequestAllocation; - } - - virtual void dispose() { delete this; } - -private: - virtual ~WebURLRequestPrivateImpl() { } - - ResourceRequest m_resourceRequestAllocation; + ResourceRequest resourceRequest; }; -void WebURLRequest::initialize() +WebURLRequest::~WebURLRequest() { - assign(new WebURLRequestPrivateImpl()); } -void WebURLRequest::reset() +WebURLRequest::WebURLRequest() + : m_ownedResourceRequest(new ResourceRequestContainer()) + , m_resourceRequest(&m_ownedResourceRequest->resourceRequest) { - assign(0); } -void WebURLRequest::assign(const WebURLRequest& r) +WebURLRequest::WebURLRequest(const WebURLRequest& r) + : m_ownedResourceRequest(new ResourceRequestContainer(*r.m_resourceRequest)) + , m_resourceRequest(&m_ownedResourceRequest->resourceRequest) { +} + +WebURLRequest::WebURLRequest(const WebURL& url) + : WebURLRequest() +{ + setURL(url); +} + +WebURLRequest& WebURLRequest::operator=(const WebURLRequest& r) +{ + // Copying subclasses that have different m_resourceRequest ownership + // semantics via this operator is just not supported. + DCHECK(m_ownedResourceRequest); + DCHECK(m_resourceRequest); if (&r != this) - assign(r.m_private ? new WebURLRequestPrivateImpl(r.m_private) : 0); + *m_resourceRequest = *r.m_resourceRequest; + return *this; } bool WebURLRequest::isNull() const { - return !m_private || m_private->m_resourceRequest->isNull(); + return m_resourceRequest->isNull(); } WebURL WebURLRequest::url() const { - return m_private->m_resourceRequest->url(); + return m_resourceRequest->url(); } void WebURLRequest::setURL(const WebURL& url) { - m_private->m_resourceRequest->setURL(url); + m_resourceRequest->setURL(url); } WebURL WebURLRequest::firstPartyForCookies() const { - return m_private->m_resourceRequest->firstPartyForCookies(); + return m_resourceRequest->firstPartyForCookies(); } void WebURLRequest::setFirstPartyForCookies(const WebURL& firstPartyForCookies) { - m_private->m_resourceRequest->setFirstPartyForCookies(firstPartyForCookies); + m_resourceRequest->setFirstPartyForCookies(firstPartyForCookies); } WebSecurityOrigin WebURLRequest::requestorOrigin() const { - return m_private->m_resourceRequest->requestorOrigin(); + return m_resourceRequest->requestorOrigin(); } void WebURLRequest::setRequestorOrigin(const WebSecurityOrigin& requestorOrigin) { - m_private->m_resourceRequest->setRequestorOrigin(requestorOrigin); + m_resourceRequest->setRequestorOrigin(requestorOrigin); } bool WebURLRequest::allowStoredCredentials() const { - return m_private->m_resourceRequest->allowStoredCredentials(); + return m_resourceRequest->allowStoredCredentials(); } void WebURLRequest::setAllowStoredCredentials(bool allowStoredCredentials) { - m_private->m_resourceRequest->setAllowStoredCredentials(allowStoredCredentials); + m_resourceRequest->setAllowStoredCredentials(allowStoredCredentials); } WebCachePolicy WebURLRequest::getCachePolicy() const { - return m_private->m_resourceRequest->getCachePolicy(); + return m_resourceRequest->getCachePolicy(); } void WebURLRequest::setCachePolicy(WebCachePolicy cachePolicy) { - m_private->m_resourceRequest->setCachePolicy(cachePolicy); + m_resourceRequest->setCachePolicy(cachePolicy); } WebString WebURLRequest::httpMethod() const { - return m_private->m_resourceRequest->httpMethod(); + return m_resourceRequest->httpMethod(); } void WebURLRequest::setHTTPMethod(const WebString& httpMethod) { - m_private->m_resourceRequest->setHTTPMethod(httpMethod); + m_resourceRequest->setHTTPMethod(httpMethod); } WebString WebURLRequest::httpHeaderField(const WebString& name) const { - return m_private->m_resourceRequest->httpHeaderField(name); + return m_resourceRequest->httpHeaderField(name); } void WebURLRequest::setHTTPHeaderField(const WebString& name, const WebString& value) { RELEASE_ASSERT(!equalIgnoringCase(name, "referer")); - m_private->m_resourceRequest->setHTTPHeaderField(name, value); + m_resourceRequest->setHTTPHeaderField(name, value); } void WebURLRequest::setHTTPReferrer(const WebString& webReferrer, WebReferrerPolicy referrerPolicy) @@ -187,22 +189,22 @@ // the null WTFString for referrer. ASSERT(Referrer::noReferrer() == String()); String referrer = webReferrer.isEmpty() ? Referrer::noReferrer() : String(webReferrer); - m_private->m_resourceRequest->setHTTPReferrer(Referrer(referrer, static_cast<ReferrerPolicy>(referrerPolicy))); + m_resourceRequest->setHTTPReferrer(Referrer(referrer, static_cast<ReferrerPolicy>(referrerPolicy))); } void WebURLRequest::addHTTPHeaderField(const WebString& name, const WebString& value) { - m_private->m_resourceRequest->addHTTPHeaderField(name, value); + m_resourceRequest->addHTTPHeaderField(name, value); } void WebURLRequest::clearHTTPHeaderField(const WebString& name) { - m_private->m_resourceRequest->clearHTTPHeaderField(name); + m_resourceRequest->clearHTTPHeaderField(name); } void WebURLRequest::visitHTTPHeaderFields(WebHTTPHeaderVisitor* visitor) const { - const HTTPHeaderMap& map = m_private->m_resourceRequest->httpHeaderFields(); + const HTTPHeaderMap& map = m_resourceRequest->httpHeaderFields(); for (HTTPHeaderMap::const_iterator it = map.begin(); it != map.end(); ++it) visitor->visitHeader(it->key, it->value); } @@ -213,199 +215,199 @@ // before any ServiceWorker has a chance to operate, which means we're // revealing data to the SW that we ought to be hiding. Baby steps. // https://crbug.com/599597 - if (m_private->m_resourceRequest->attachedCredential()) - return WebHTTPBody(m_private->m_resourceRequest->attachedCredential()); - return WebHTTPBody(m_private->m_resourceRequest->httpBody()); + if (m_resourceRequest->attachedCredential()) + return WebHTTPBody(m_resourceRequest->attachedCredential()); + return WebHTTPBody(m_resourceRequest->httpBody()); } void WebURLRequest::setHTTPBody(const WebHTTPBody& httpBody) { - m_private->m_resourceRequest->setHTTPBody(httpBody); + m_resourceRequest->setHTTPBody(httpBody); } WebHTTPBody WebURLRequest::attachedCredential() const { - return WebHTTPBody(m_private->m_resourceRequest->attachedCredential()); + return WebHTTPBody(m_resourceRequest->attachedCredential()); } void WebURLRequest::setAttachedCredential(const WebHTTPBody& attachedCredential) { - m_private->m_resourceRequest->setAttachedCredential(attachedCredential); + m_resourceRequest->setAttachedCredential(attachedCredential); } bool WebURLRequest::reportUploadProgress() const { - return m_private->m_resourceRequest->reportUploadProgress(); + return m_resourceRequest->reportUploadProgress(); } void WebURLRequest::setReportUploadProgress(bool reportUploadProgress) { - m_private->m_resourceRequest->setReportUploadProgress(reportUploadProgress); + m_resourceRequest->setReportUploadProgress(reportUploadProgress); } void WebURLRequest::setReportRawHeaders(bool reportRawHeaders) { - m_private->m_resourceRequest->setReportRawHeaders(reportRawHeaders); + m_resourceRequest->setReportRawHeaders(reportRawHeaders); } bool WebURLRequest::reportRawHeaders() const { - return m_private->m_resourceRequest->reportRawHeaders(); + return m_resourceRequest->reportRawHeaders(); } WebURLRequest::RequestContext WebURLRequest::getRequestContext() const { - return m_private->m_resourceRequest->requestContext(); + return m_resourceRequest->requestContext(); } WebURLRequest::FrameType WebURLRequest::getFrameType() const { - return m_private->m_resourceRequest->frameType(); + return m_resourceRequest->frameType(); } WebReferrerPolicy WebURLRequest::referrerPolicy() const { - return static_cast<WebReferrerPolicy>(m_private->m_resourceRequest->getReferrerPolicy()); + return static_cast<WebReferrerPolicy>(m_resourceRequest->getReferrerPolicy()); } void WebURLRequest::addHTTPOriginIfNeeded(const WebString& origin) { - m_private->m_resourceRequest->addHTTPOriginIfNeeded(WebSecurityOrigin::createFromString(origin)); + m_resourceRequest->addHTTPOriginIfNeeded(WebSecurityOrigin::createFromString(origin)); } bool WebURLRequest::hasUserGesture() const { - return m_private->m_resourceRequest->hasUserGesture(); + return m_resourceRequest->hasUserGesture(); } void WebURLRequest::setHasUserGesture(bool hasUserGesture) { - m_private->m_resourceRequest->setHasUserGesture(hasUserGesture); + m_resourceRequest->setHasUserGesture(hasUserGesture); } void WebURLRequest::setRequestContext(RequestContext requestContext) { - m_private->m_resourceRequest->setRequestContext(requestContext); + m_resourceRequest->setRequestContext(requestContext); } void WebURLRequest::setFrameType(FrameType frameType) { - m_private->m_resourceRequest->setFrameType(frameType); + m_resourceRequest->setFrameType(frameType); } int WebURLRequest::requestorID() const { - return m_private->m_resourceRequest->requestorID(); + return m_resourceRequest->requestorID(); } void WebURLRequest::setRequestorID(int requestorID) { - m_private->m_resourceRequest->setRequestorID(requestorID); + m_resourceRequest->setRequestorID(requestorID); } int WebURLRequest::requestorProcessID() const { - return m_private->m_resourceRequest->requestorProcessID(); + return m_resourceRequest->requestorProcessID(); } void WebURLRequest::setRequestorProcessID(int requestorProcessID) { - m_private->m_resourceRequest->setRequestorProcessID(requestorProcessID); + m_resourceRequest->setRequestorProcessID(requestorProcessID); } int WebURLRequest::appCacheHostID() const { - return m_private->m_resourceRequest->appCacheHostID(); + return m_resourceRequest->appCacheHostID(); } void WebURLRequest::setAppCacheHostID(int appCacheHostID) { - m_private->m_resourceRequest->setAppCacheHostID(appCacheHostID); + m_resourceRequest->setAppCacheHostID(appCacheHostID); } bool WebURLRequest::downloadToFile() const { - return m_private->m_resourceRequest->downloadToFile(); + return m_resourceRequest->downloadToFile(); } void WebURLRequest::setDownloadToFile(bool downloadToFile) { - m_private->m_resourceRequest->setDownloadToFile(downloadToFile); + m_resourceRequest->setDownloadToFile(downloadToFile); } bool WebURLRequest::useStreamOnResponse() const { - return m_private->m_resourceRequest->useStreamOnResponse(); + return m_resourceRequest->useStreamOnResponse(); } void WebURLRequest::setUseStreamOnResponse(bool useStreamOnResponse) { - m_private->m_resourceRequest->setUseStreamOnResponse(useStreamOnResponse); + m_resourceRequest->setUseStreamOnResponse(useStreamOnResponse); } WebURLRequest::SkipServiceWorker WebURLRequest::skipServiceWorker() const { - return m_private->m_resourceRequest->skipServiceWorker(); + return m_resourceRequest->skipServiceWorker(); } void WebURLRequest::setSkipServiceWorker(WebURLRequest::SkipServiceWorker skipServiceWorker) { - m_private->m_resourceRequest->setSkipServiceWorker(skipServiceWorker); + m_resourceRequest->setSkipServiceWorker(skipServiceWorker); } bool WebURLRequest::shouldResetAppCache() const { - return m_private->m_resourceRequest->shouldResetAppCache(); + return m_resourceRequest->shouldResetAppCache(); } void WebURLRequest::setShouldResetAppCache(bool setShouldResetAppCache) { - m_private->m_resourceRequest->setShouldResetAppCache(setShouldResetAppCache); + m_resourceRequest->setShouldResetAppCache(setShouldResetAppCache); } WebURLRequest::FetchRequestMode WebURLRequest::getFetchRequestMode() const { - return m_private->m_resourceRequest->fetchRequestMode(); + return m_resourceRequest->fetchRequestMode(); } void WebURLRequest::setFetchRequestMode(WebURLRequest::FetchRequestMode mode) { - return m_private->m_resourceRequest->setFetchRequestMode(mode); + return m_resourceRequest->setFetchRequestMode(mode); } WebURLRequest::FetchCredentialsMode WebURLRequest::getFetchCredentialsMode() const { - return m_private->m_resourceRequest->fetchCredentialsMode(); + return m_resourceRequest->fetchCredentialsMode(); } void WebURLRequest::setFetchCredentialsMode(WebURLRequest::FetchCredentialsMode mode) { - return m_private->m_resourceRequest->setFetchCredentialsMode(mode); + return m_resourceRequest->setFetchCredentialsMode(mode); } WebURLRequest::FetchRedirectMode WebURLRequest::getFetchRedirectMode() const { - return m_private->m_resourceRequest->fetchRedirectMode(); + return m_resourceRequest->fetchRedirectMode(); } void WebURLRequest::setFetchRedirectMode(WebURLRequest::FetchRedirectMode redirect) { - return m_private->m_resourceRequest->setFetchRedirectMode(redirect); + return m_resourceRequest->setFetchRedirectMode(redirect); } WebURLRequest::LoFiState WebURLRequest::getLoFiState() const { - return m_private->m_resourceRequest->loFiState(); + return m_resourceRequest->loFiState(); } void WebURLRequest::setLoFiState(WebURLRequest::LoFiState loFiState) { - return m_private->m_resourceRequest->setLoFiState(loFiState); + return m_resourceRequest->setLoFiState(loFiState); } WebURLRequest::ExtraData* WebURLRequest::getExtraData() const { - RefPtr<ResourceRequest::ExtraData> data = m_private->m_resourceRequest->getExtraData(); + RefPtr<ResourceRequest::ExtraData> data = m_resourceRequest->getExtraData(); if (!data) return 0; return static_cast<ExtraDataContainer*>(data.get())->getExtraData(); @@ -413,84 +415,74 @@ void WebURLRequest::setExtraData(WebURLRequest::ExtraData* extraData) { - m_private->m_resourceRequest->setExtraData(ExtraDataContainer::create(extraData)); + m_resourceRequest->setExtraData(ExtraDataContainer::create(extraData)); } ResourceRequest& WebURLRequest::toMutableResourceRequest() { - ASSERT(m_private); - ASSERT(m_private->m_resourceRequest); - - return *m_private->m_resourceRequest; + DCHECK(m_resourceRequest); + return *m_resourceRequest; } WebURLRequest::Priority WebURLRequest::getPriority() const { return static_cast<WebURLRequest::Priority>( - m_private->m_resourceRequest->priority()); + m_resourceRequest->priority()); } void WebURLRequest::setPriority(WebURLRequest::Priority priority) { - m_private->m_resourceRequest->setPriority( + m_resourceRequest->setPriority( static_cast<ResourceLoadPriority>(priority)); } bool WebURLRequest::checkForBrowserSideNavigation() const { - return m_private->m_resourceRequest->checkForBrowserSideNavigation(); + return m_resourceRequest->checkForBrowserSideNavigation(); } void WebURLRequest::setCheckForBrowserSideNavigation(bool check) { - m_private->m_resourceRequest->setCheckForBrowserSideNavigation(check); + m_resourceRequest->setCheckForBrowserSideNavigation(check); } double WebURLRequest::uiStartTime() const { - return m_private->m_resourceRequest->uiStartTime(); + return m_resourceRequest->uiStartTime(); } void WebURLRequest::setUiStartTime(double time) { - m_private->m_resourceRequest->setUIStartTime(time); + m_resourceRequest->setUIStartTime(time); } bool WebURLRequest::isExternalRequest() const { - return m_private->m_resourceRequest->isExternalRequest(); + return m_resourceRequest->isExternalRequest(); } WebURLRequest::InputToLoadPerfMetricReportPolicy WebURLRequest::inputPerfMetricReportPolicy() const { return static_cast<WebURLRequest::InputToLoadPerfMetricReportPolicy>( - m_private->m_resourceRequest->inputPerfMetricReportPolicy()); + m_resourceRequest->inputPerfMetricReportPolicy()); } void WebURLRequest::setInputPerfMetricReportPolicy( WebURLRequest::InputToLoadPerfMetricReportPolicy policy) { - m_private->m_resourceRequest->setInputPerfMetricReportPolicy( + m_resourceRequest->setInputPerfMetricReportPolicy( static_cast<blink::InputToLoadPerfMetricReportPolicy>(policy)); } const ResourceRequest& WebURLRequest::toResourceRequest() const { - ASSERT(m_private); - ASSERT(m_private->m_resourceRequest); - - return *m_private->m_resourceRequest; + DCHECK(m_resourceRequest); + return *m_resourceRequest; } -void WebURLRequest::assign(WebURLRequestPrivate* p) +WebURLRequest::WebURLRequest(ResourceRequest& r) + : m_resourceRequest(&r) { - // Subclasses may call this directly so a self-assignment check is needed - // here as well as in the public assign method. - if (m_private == p) - return; - if (m_private) - m_private->dispose(); - m_private = p; } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/exported/WebURLRequestPrivate.h b/third_party/WebKit/Source/platform/exported/WebURLRequestPrivate.h deleted file mode 100644 index 3163a9b..0000000 --- a/third_party/WebKit/Source/platform/exported/WebURLRequestPrivate.h +++ /dev/null
@@ -1,56 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WebURLRequestPrivate_h -#define WebURLRequestPrivate_h - -#include "wtf/Noncopyable.h" - -namespace blink { - -class ResourceRequest; - -class WebURLRequestPrivate { - WTF_MAKE_NONCOPYABLE(WebURLRequestPrivate); -public: - WebURLRequestPrivate() - : m_resourceRequest(0) - { - } - - // Called by WebURLRequest when it no longer needs this object. - virtual void dispose() = 0; - - ResourceRequest* m_resourceRequest; -}; - -} // namespace blink - -#endif
diff --git a/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp b/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp index 0ffcd8b..f329712 100644 --- a/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp +++ b/third_party/WebKit/Source/platform/exported/WebURLResponse.cpp
@@ -72,7 +72,7 @@ struct WebURLResponse::ResourceResponseContainer { ResourceResponseContainer() {} - ResourceResponseContainer(const ResourceResponse& r) + explicit ResourceResponseContainer(const ResourceResponse& r) : resourceResponse(r) { } @@ -512,10 +512,9 @@ m_resourceResponse->setExtraData(ExtraDataContainer::create(extraData)); } -WebURLResponse::WebURLResponse(ResourceResponse* p) - : m_resourceResponse(p) +WebURLResponse::WebURLResponse(ResourceResponse& r) + : m_resourceResponse(&r) { - DCHECK(p); } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/exported/WrappedResourceRequest.h b/third_party/WebKit/Source/platform/exported/WrappedResourceRequest.h index a81d5f79..67277e3 100644 --- a/third_party/WebKit/Source/platform/exported/WrappedResourceRequest.h +++ b/third_party/WebKit/Source/platform/exported/WrappedResourceRequest.h
@@ -31,53 +31,28 @@ #ifndef WrappedResourceRequest_h #define WrappedResourceRequest_h -#include "platform/exported/WebURLRequestPrivate.h" #include "public/platform/WebURLRequest.h" #include "wtf/Allocator.h" #include "wtf/Noncopyable.h" namespace blink { +// WrappedResourceRequest doesn't take ownership of given ResourceRequest, +// but just holds a pointer to it. It is not copyable. class WrappedResourceRequest : public WebURLRequest { + WTF_MAKE_NONCOPYABLE(WrappedResourceRequest); public: - ~WrappedResourceRequest() + ~WrappedResourceRequest() {} + + explicit WrappedResourceRequest(ResourceRequest& resourceRequest) + : WebURLRequest(resourceRequest) { - reset(); // Need to drop reference to m_handle } - WrappedResourceRequest() { } - - WrappedResourceRequest(ResourceRequest& resourceRequest) + explicit WrappedResourceRequest(const ResourceRequest& resourceRequest) + : WrappedResourceRequest(const_cast<ResourceRequest&>(resourceRequest)) { - bind(resourceRequest); } - - WrappedResourceRequest(const ResourceRequest& resourceRequest) - { - bind(resourceRequest); - } - - void bind(ResourceRequest& resourceRequest) - { - m_handle.m_resourceRequest = &resourceRequest; - assign(&m_handle); - } - - void bind(const ResourceRequest& resourceRequest) - { - bind(*const_cast<ResourceRequest*>(&resourceRequest)); - } - -private: - class Handle final : public WebURLRequestPrivate { - DISALLOW_NEW(); - public: - Handle() { } - - virtual void dispose() { m_resourceRequest = 0; } - }; - - Handle m_handle; }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/exported/WrappedResourceResponse.h b/third_party/WebKit/Source/platform/exported/WrappedResourceResponse.h index 493341f5..519e3f0 100644 --- a/third_party/WebKit/Source/platform/exported/WrappedResourceResponse.h +++ b/third_party/WebKit/Source/platform/exported/WrappedResourceResponse.h
@@ -44,7 +44,7 @@ ~WrappedResourceResponse() {} explicit WrappedResourceResponse(ResourceResponse& resourceResponse) - : WebURLResponse(&resourceResponse) + : WebURLResponse(resourceResponse) { }
diff --git a/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp b/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp index cb42fef..73a3929 100644 --- a/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp +++ b/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp
@@ -171,6 +171,14 @@ std::swap(m_maxObjectSize, other.m_maxObjectSize); } +void ContiguousContainerBase::shrinkToFit() +{ + while (m_endIndex < m_buffers.size() - 1) { + DCHECK(m_buffers.last()->isEmpty()); + m_buffers.removeLast(); + } +} + ContiguousContainerBase::Buffer* ContiguousContainerBase::allocateNewBufferForNextAllocation(size_t bufferSize, const char* typeName) {
diff --git a/third_party/WebKit/Source/platform/graphics/ContiguousContainer.h b/third_party/WebKit/Source/platform/graphics/ContiguousContainer.h index 95d21b2d..98bce195 100644 --- a/third_party/WebKit/Source/platform/graphics/ContiguousContainer.h +++ b/third_party/WebKit/Source/platform/graphics/ContiguousContainer.h
@@ -60,6 +60,10 @@ void clear(); void swap(ContiguousContainerBase&); + // Discards excess buffer capacity. Intended for use when no more appending + // is anticipated. + void shrinkToFit(); + Vector<void*> m_elements; private: @@ -142,6 +146,7 @@ using ContiguousContainerBase::capacityInBytes; using ContiguousContainerBase::usedCapacityInBytes; using ContiguousContainerBase::memoryUsageInBytes; + using ContiguousContainerBase::shrinkToFit; iterator begin() { return iterator(m_elements.begin()); } iterator end() { return iterator(m_elements.end()); }
diff --git a/third_party/WebKit/Source/platform/graphics/ExpensiveCanvasHeuristicParameters.h b/third_party/WebKit/Source/platform/graphics/ExpensiveCanvasHeuristicParameters.h index 67033a1..c69af79a 100644 --- a/third_party/WebKit/Source/platform/graphics/ExpensiveCanvasHeuristicParameters.h +++ b/third_party/WebKit/Source/platform/graphics/ExpensiveCanvasHeuristicParameters.h
@@ -65,7 +65,7 @@ // Disable Acceleration heuristic parameters //=========================================== - GetImageDataForcesNoAcceleration = 1, + GetImageDataForcesNoAcceleration = 0, // Disabled for crbug.com/626188 }; // enum
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h index 3d6f9be..f208a5ea 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.h
@@ -42,7 +42,6 @@ #include "platform/graphics/ImageOrientation.h" #include "platform/graphics/PaintInvalidationReason.h" #include "platform/graphics/filters/FilterOperations.h" -#include "platform/graphics/paint/CachedDisplayItem.h" #include "platform/graphics/paint/DisplayItemClient.h" #include "platform/graphics/paint/PaintController.h" #include "platform/heap/Handle.h"
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp index 7f85e9e..5e552c2b 100644 --- a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp +++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositor.cpp
@@ -345,14 +345,27 @@ public: PropertyTreeManager(cc::PropertyTrees& propertyTrees, cc::Layer* rootLayer) : m_propertyTrees(propertyTrees) - , m_rootLayer(rootLayer) {} + , m_rootLayer(rootLayer) +#if DCHECK_IS_ON() + , m_isFirstEffectEver(true) +#endif + { + m_effectStack.append(BlinkEffectAndCcIdPair{nullptr, kSecondaryRootNodeId}); + } int compositorIdForTransformNode(const TransformPaintPropertyNode*); int compositorIdForClipNode(const ClipPaintPropertyNode*); + int switchToEffectNode(const EffectPaintPropertyNode& nextEffect); + int compositorIdForCurrentEffectNode() const { return m_effectStack.last().id; } private: + void buildEffectNodesRecursively(const EffectPaintPropertyNode* nextEffect); + cc::TransformTree& transformTree() { return m_propertyTrees.transform_tree; } cc::ClipTree& clipTree() { return m_propertyTrees.clip_tree; } + cc::EffectTree& effectTree() { return m_propertyTrees.effect_tree; } + + const EffectPaintPropertyNode* currentEffectNode() const { return m_effectStack.last().effect; } // Property trees which should be updated by the manager. cc::PropertyTrees& m_propertyTrees; @@ -364,6 +377,17 @@ // Maps from Blink-side property tree nodes to cc property node indices. HashMap<const TransformPaintPropertyNode*, int> m_transformNodeMap; HashMap<const ClipPaintPropertyNode*, int> m_clipNodeMap; + + struct BlinkEffectAndCcIdPair { + const EffectPaintPropertyNode* effect; + int id; + }; + Vector<BlinkEffectAndCcIdPair> m_effectStack; + +#if DCHECK_IS_ON() + HashSet<const EffectPaintPropertyNode*> m_effectNodesConverted; + bool m_isFirstEffectEver; +#endif }; int PropertyTreeManager::compositorIdForTransformNode(const TransformPaintPropertyNode* transformNode) @@ -442,6 +466,91 @@ return id; } +unsigned depth(const EffectPaintPropertyNode* node) +{ + unsigned result = 0; + for (; node; node = node->parent()) + result++; + return result; +} + +const EffectPaintPropertyNode* lowestCommonAncestor(const EffectPaintPropertyNode* nodeA, const EffectPaintPropertyNode* nodeB) +{ + // Optimized common case. + if (nodeA == nodeB) + return nodeA; + + unsigned depthA = depth(nodeA), depthB = depth(nodeB); + while (depthA > depthB) { + nodeA = nodeA->parent(); + depthA--; + } + while (depthB > depthA) { + nodeB = nodeB->parent(); + depthB--; + } + DCHECK_EQ(depthA, depthB); + while (nodeA != nodeB) { + nodeA = nodeA->parent(); + nodeB = nodeB->parent(); + } + return nodeA; +} + +int PropertyTreeManager::switchToEffectNode(const EffectPaintPropertyNode& nextEffect) +{ + const EffectPaintPropertyNode* ancestor = lowestCommonAncestor(currentEffectNode(), &nextEffect); + while (currentEffectNode() != ancestor) + m_effectStack.removeLast(); + +#if DCHECK_IS_ON() + DCHECK(m_isFirstEffectEver || currentEffectNode()) << "Malformed effect tree. Nodes in the same property tree should have common root."; + m_isFirstEffectEver = false; +#endif + buildEffectNodesRecursively(&nextEffect); + + return compositorIdForCurrentEffectNode(); +} + +void PropertyTreeManager::buildEffectNodesRecursively(const EffectPaintPropertyNode* nextEffect) +{ + if (nextEffect == currentEffectNode()) + return; + DCHECK(nextEffect); + + buildEffectNodesRecursively(nextEffect->parent()); + DCHECK_EQ(nextEffect->parent(), currentEffectNode()); + +#if DCHECK_IS_ON() + DCHECK(!m_effectNodesConverted.contains(nextEffect)) << "Malformed paint artifact. Paint chunks under the same effect should be contiguous."; + m_effectNodesConverted.add(nextEffect); +#endif + + // We currently create dummy layers to host effect nodes and corresponding render surface. + // This should be removed once cc implements better support for freestanding property trees. + scoped_refptr<cc::Layer> dummyLayer = cc::Layer::Create(); + m_rootLayer->AddChild(dummyLayer); + + // Also cc assumes a clip node is always created by a layer that creates render surface. + cc::ClipNode& dummyClip = *clipTree().Node(clipTree().Insert(cc::ClipNode(), kSecondaryRootNodeId)); + dummyClip.owner_id = dummyLayer->id(); + dummyClip.transform_id = kRealRootNodeId; + dummyClip.target_transform_id = kRealRootNodeId; + + cc::EffectNode& effectNode = *effectTree().Node(effectTree().Insert(cc::EffectNode(), compositorIdForCurrentEffectNode())); + effectNode.owner_id = dummyLayer->id(); + effectNode.clip_id = dummyClip.id; + effectNode.has_render_surface = true; + effectNode.opacity = nextEffect->opacity(); + m_effectStack.append(BlinkEffectAndCcIdPair{nextEffect, effectNode.id}); + + dummyLayer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); + dummyLayer->SetTransformTreeIndex(kSecondaryRootNodeId); + dummyLayer->SetClipTreeIndex(dummyClip.id); + dummyLayer->SetEffectTreeIndex(effectNode.id); + dummyLayer->SetScrollTreeIndex(kRealRootNodeId); +} + } // namespace void PaintArtifactCompositor::updateInLayerListMode(const PaintArtifact& paintArtifact) @@ -465,6 +574,7 @@ int transformId = propertyTreeManager.compositorIdForTransformNode(paintChunk.properties.transform.get()); int clipId = propertyTreeManager.compositorIdForClipNode(paintChunk.properties.clip.get()); + int effectId = propertyTreeManager.switchToEffectNode(*paintChunk.properties.effect.get()); layer->set_offset_to_transform_parent(layerOffset); @@ -472,7 +582,7 @@ layer->set_property_tree_sequence_number(kPropertyTreeSequenceNumber); layer->SetTransformTreeIndex(transformId); layer->SetClipTreeIndex(clipId); - layer->SetEffectTreeIndex(kSecondaryRootNodeId); + layer->SetEffectTreeIndex(effectId); layer->SetScrollTreeIndex(kRealRootNodeId); if (m_extraDataForTestingEnabled)
diff --git a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp index 4640c277..f51287bf 100644 --- a/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/compositing/PaintArtifactCompositorTest.cpp
@@ -9,9 +9,11 @@ #include "cc/layers/layer.h" #include "cc/test/fake_output_surface.h" #include "cc/trees/clip_node.h" +#include "cc/trees/effect_node.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_settings.h" #include "platform/RuntimeEnabledFeatures.h" +#include "platform/graphics/paint/EffectPaintPropertyNode.h" #include "platform/graphics/paint/PaintArtifact.h" #include "platform/testing/PictureMatchers.h" #include "platform/testing/TestPaintArtifact.h" @@ -33,6 +35,12 @@ return transform; } +EffectPaintPropertyNode* dummyRootEffect() +{ + DEFINE_STATIC_REF(EffectPaintPropertyNode, node, EffectPaintPropertyNode::create(1.0)); + return node; +} + class PaintArtifactCompositorTest : public ::testing::Test { protected: void SetUp() override @@ -97,11 +105,11 @@ TransformationMatrix().rotate(90), FloatPoint3D(100, 100, 0)); TestPaintArtifact artifact; - artifact.chunk(transform, nullptr, nullptr) + artifact.chunk(transform, nullptr, dummyRootEffect()) .rectDrawing(FloatRect(0, 0, 100, 100), Color::white); - artifact.chunk(nullptr, nullptr, nullptr) + artifact.chunk(nullptr, nullptr, dummyRootEffect()) .rectDrawing(FloatRect(0, 0, 100, 100), Color::gray); - artifact.chunk(transform, nullptr, nullptr) + artifact.chunk(transform, nullptr, dummyRootEffect()) .rectDrawing(FloatRect(100, 100, 200, 100), Color::black); update(artifact.build()); @@ -139,9 +147,9 @@ TransformationMatrix().translate(5, 5), FloatPoint3D(), transform1); TestPaintArtifact artifact; - artifact.chunk(transform1, nullptr, nullptr) + artifact.chunk(transform1, nullptr, dummyRootEffect()) .rectDrawing(FloatRect(0, 0, 300, 200), Color::white); - artifact.chunk(transform2, nullptr, nullptr) + artifact.chunk(transform2, nullptr, dummyRootEffect()) .rectDrawing(FloatRect(0, 0, 300, 200), Color::black); update(artifact.build()); @@ -223,13 +231,13 @@ nullptr, FloatRoundedRect(200, 200, 700, 100), clip1); TestPaintArtifact artifact; - artifact.chunk(nullptr, clip1, nullptr) + artifact.chunk(nullptr, clip1, dummyRootEffect()) .rectDrawing(FloatRect(300, 350, 100, 100), Color::white); - artifact.chunk(nullptr, clip2, nullptr) + artifact.chunk(nullptr, clip2, dummyRootEffect()) .rectDrawing(FloatRect(300, 350, 100, 100), Color::lightGray); - artifact.chunk(nullptr, clip1, nullptr) + artifact.chunk(nullptr, clip1, dummyRootEffect()) .rectDrawing(FloatRect(300, 350, 100, 100), Color::darkGray); - artifact.chunk(nullptr, clip2, nullptr) + artifact.chunk(nullptr, clip2, dummyRootEffect()) .rectDrawing(FloatRect(300, 350, 100, 100), Color::black); update(artifact.build()); @@ -449,11 +457,11 @@ TransformationMatrix().rotate(90), FloatPoint3D(100, 100, 0)); TestPaintArtifact artifact; - artifact.chunk(transform, nullptr, nullptr) + artifact.chunk(transform, nullptr, dummyRootEffect()) .rectDrawing(FloatRect(0, 0, 100, 100), Color::white); - artifact.chunk(nullptr, nullptr, nullptr) + artifact.chunk(nullptr, nullptr, dummyRootEffect()) .rectDrawing(FloatRect(0, 0, 100, 100), Color::gray); - artifact.chunk(transform, nullptr, nullptr) + artifact.chunk(transform, nullptr, dummyRootEffect()) .rectDrawing(FloatRect(100, 100, 200, 100), Color::black); update(artifact.build()); @@ -491,9 +499,9 @@ TransformationMatrix().translate(5, 5), FloatPoint3D(), transform1); TestPaintArtifact artifact; - artifact.chunk(transform1, nullptr, nullptr) + artifact.chunk(transform1, nullptr, dummyRootEffect()) .rectDrawing(FloatRect(0, 0, 300, 200), Color::white); - artifact.chunk(transform2, nullptr, nullptr) + artifact.chunk(transform2, nullptr, dummyRootEffect()) .rectDrawing(FloatRect(0, 0, 300, 200), Color::black); update(artifact.build()); @@ -549,13 +557,13 @@ nullptr, FloatRoundedRect(200, 200, 700, 100), clip1); TestPaintArtifact artifact; - artifact.chunk(nullptr, clip1, nullptr) + artifact.chunk(nullptr, clip1, dummyRootEffect()) .rectDrawing(FloatRect(300, 350, 100, 100), Color::white); - artifact.chunk(nullptr, clip2, nullptr) + artifact.chunk(nullptr, clip2, dummyRootEffect()) .rectDrawing(FloatRect(300, 350, 100, 100), Color::lightGray); - artifact.chunk(nullptr, clip1, nullptr) + artifact.chunk(nullptr, clip1, dummyRootEffect()) .rectDrawing(FloatRect(300, 350, 100, 100), Color::darkGray); - artifact.chunk(nullptr, clip2, nullptr) + artifact.chunk(nullptr, clip2, dummyRootEffect()) .rectDrawing(FloatRect(300, 350, 100, 100), Color::black); update(artifact.build()); @@ -605,7 +613,7 @@ } TestPaintArtifact artifact; - artifact.chunk(nullptr, clips.last(), nullptr) + artifact.chunk(nullptr, clips.last(), dummyRootEffect()) .rectDrawing(FloatRect(0, 0, 200, 200), Color::white); update(artifact.build()); @@ -637,9 +645,9 @@ nullptr, FloatRoundedRect(400, 0, 400, 600), commonClip); TestPaintArtifact artifact; - artifact.chunk(nullptr, clip1, nullptr) + artifact.chunk(nullptr, clip1, dummyRootEffect()) .rectDrawing(FloatRect(0, 0, 640, 480), Color::white); - artifact.chunk(nullptr, clip2, nullptr) + artifact.chunk(nullptr, clip2, dummyRootEffect()) .rectDrawing(FloatRect(0, 0, 640, 480), Color::black); update(artifact.build()); @@ -685,5 +693,47 @@ EXPECT_EQ(translation(50, 100), layer->screen_space_transform()); } +TEST_F(PaintArtifactCompositorTestWithPropertyTrees, EffectTreeConversion) +{ + RefPtr<EffectPaintPropertyNode> effect1 = EffectPaintPropertyNode::create(0.5, dummyRootEffect()); + RefPtr<EffectPaintPropertyNode> effect2 = EffectPaintPropertyNode::create(0.3, effect1.get()); + RefPtr<EffectPaintPropertyNode> effect3 = EffectPaintPropertyNode::create(0.2, dummyRootEffect()); + + TestPaintArtifact artifact; + artifact.chunk(nullptr, nullptr, effect2.get()) + .rectDrawing(FloatRect(0, 0, 100, 100), Color::white); + artifact.chunk(nullptr, nullptr, effect1.get()) + .rectDrawing(FloatRect(0, 0, 100, 100), Color::white); + artifact.chunk(nullptr, nullptr, effect3.get()) + .rectDrawing(FloatRect(0, 0, 100, 100), Color::white); + update(artifact.build()); + + ASSERT_EQ(3u, contentLayerCount()); + + const cc::EffectTree& effectTree = propertyTrees().effect_tree; + // Node #0 reserved for null; #1 for root render surface; #2 for dummyRootEffect, + // plus 3 nodes for those created by this test. + ASSERT_EQ(6u, effectTree.size()); + + const cc::EffectNode& convertedDummyRootEffect = *effectTree.Node(2); + EXPECT_EQ(1, convertedDummyRootEffect.parent_id); + + const cc::EffectNode& convertedEffect1 = *effectTree.Node(3); + EXPECT_EQ(convertedDummyRootEffect.id, convertedEffect1.parent_id); + EXPECT_FLOAT_EQ(0.5, convertedEffect1.opacity); + + const cc::EffectNode& convertedEffect2 = *effectTree.Node(4); + EXPECT_EQ(convertedEffect1.id, convertedEffect2.parent_id); + EXPECT_FLOAT_EQ(0.3, convertedEffect2.opacity); + + const cc::EffectNode& convertedEffect3 = *effectTree.Node(5); + EXPECT_EQ(convertedDummyRootEffect.id, convertedEffect3.parent_id); + EXPECT_FLOAT_EQ(0.2, convertedEffect3.opacity); + + EXPECT_EQ(convertedEffect2.id, contentLayerAt(0)->effect_tree_index()); + EXPECT_EQ(convertedEffect1.id, contentLayerAt(1)->effect_tree_index()); + EXPECT_EQ(convertedEffect3.id, contentLayerAt(2)->effect_tree_index()); +} + } // namespace } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp index 85bf211d..5385c455 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -484,7 +484,13 @@ m_antiAliasingMode = ScreenSpaceAntialiasing; } } - m_storageTextureSupported = m_webGLVersion > WebGL1 || m_extensionsUtil->supportsExtension("GL_EXT_texture_storage"); + // TODO(dshwang): enable storage texture on all platform. crbug.com/557848 + // Linux ATI bot fails WebglConformance.conformance_textures_misc_tex_image_webgl + // So use storage texture only if ScreenSpaceAntialiasing is enabled, + // because ScreenSpaceAntialiasing is much faster with storage texture. + m_storageTextureSupported = (m_webGLVersion > WebGL1 + || m_extensionsUtil->supportsExtension("GL_EXT_texture_storage")) + && m_antiAliasingMode == ScreenSpaceAntialiasing; m_sampleCount = std::min(4, maxSampleCount); m_gl->GenFramebuffers(1, &m_fbo);
diff --git a/third_party/WebKit/Source/platform/graphics/paint/CachedDisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/CachedDisplayItem.h deleted file mode 100644 index 24b2888..0000000 --- a/third_party/WebKit/Source/platform/graphics/paint/CachedDisplayItem.h +++ /dev/null
@@ -1,32 +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 CachedDisplayItem_h -#define CachedDisplayItem_h - -#include "platform/graphics/paint/DisplayItem.h" -#include "wtf/Assertions.h" - -namespace blink { - -// A placeholder of a DrawingDisplayItem or a subtree in the new paint DisplayItemList, -// to indicate that the DrawingDisplayItem/subtree has not been changed and should be replaced with -// the cached DrawingDisplayItem/subtree when merging new paint list to cached paint list. -class CachedDisplayItem final : public DisplayItem { -public: - CachedDisplayItem(const DisplayItemClient& client, Type type) - : DisplayItem(client, type, sizeof(*this)) - { - ASSERT(isCachedType(type)); - } - -private: - // CachedDisplayItem is never replayed or appended to WebDisplayItemList. - void replay(GraphicsContext&) const final { ASSERT_NOT_REACHED(); } - void appendToWebDisplayItemList(const IntRect&, WebDisplayItemList*) const final { ASSERT_NOT_REACHED(); } -}; - -} // namespace blink - -#endif // CachedDisplayItem_h
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp index cb0b833..3f2bee5 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.cpp
@@ -185,8 +185,6 @@ { if (isDrawingType(type)) return drawingTypeAsDebugString(type); - if (isCachedDrawingType(type)) - return "Cached" + drawingTypeAsDebugString(cachedDrawingTypeToDrawingType(type)); if (isForeignLayerType(type)) return foreignLayerTypeAsDebugString(type); @@ -224,7 +222,6 @@ DEBUG_STRING_CASE(EndClipPath); DEBUG_STRING_CASE(Subsequence); DEBUG_STRING_CASE(EndSubsequence); - DEBUG_STRING_CASE(CachedSubsequence); DEBUG_STRING_CASE(UninitializedType); DEFAULT_CASE; }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h index 72c2104f..93ae1bf 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h +++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItem.h
@@ -116,9 +116,6 @@ ReflectionMask, DrawingLast = ReflectionMask, - CachedDrawingFirst, - CachedDrawingLast = CachedDrawingFirst + DrawingLast - DrawingFirst, - ForeignLayerFirst, ForeignLayerCanvas = ForeignLayerFirst, ForeignLayerPlugin, @@ -184,7 +181,6 @@ Subsequence, EndSubsequence, - CachedSubsequence, UninitializedType, TypeLast = UninitializedType @@ -224,33 +220,11 @@ : client(client) , type(type) { } - bool matches(const DisplayItem& item) const - { - // We should always convert to non-cached types before matching. - ASSERT(!isCachedType(item.m_type)); - ASSERT(!isCachedType(type)); - return &client == item.m_client && type == item.m_type; - } - const DisplayItemClient& client; const Type type; }; - // Convert cached type to non-cached type (e.g., Type::CachedSVGImage -> Type::SVGImage). - static Type nonCachedType(Type type) - { - if (isCachedDrawingType(type)) - return cachedDrawingTypeToDrawingType(type); - if (type == CachedSubsequence) - return Subsequence; - return type; - } - - // Return the Id with cached type converted to non-cached type. - Id nonCachedId() const - { - return Id(*m_client, nonCachedType(m_type)); - } + Id getId() const { return Id(*m_client, m_type); } virtual void replay(GraphicsContext&) const { } @@ -303,8 +277,6 @@ DEFINE_CATEGORY_METHODS(Drawing) DEFINE_PAINT_PHASE_CONVERSION_METHOD(Drawing) - DEFINE_CATEGORY_METHODS(CachedDrawing) - DEFINE_CONVERSION_METHODS(Drawing, drawing, CachedDrawing, cachedDrawing) DEFINE_CATEGORY_METHODS(ForeignLayer) @@ -321,8 +293,6 @@ DEFINE_PAIRED_CATEGORY_METHODS(Transform3D, transform3D) - static bool isCachedType(Type type) { return isCachedDrawingType(type) || type == CachedSubsequence; } - bool isCached() const { return isCachedType(m_type); } static bool isCacheableType(Type type) { return isDrawingType(type) || type == Subsequence; } bool isCacheable() const { return !skippedCache() && isCacheableType(m_type); } @@ -383,6 +353,16 @@ #endif }; +inline bool operator==(const DisplayItem::Id& a, const DisplayItem::Id& b) +{ + return a.client == b.client && a.type == b.type; +} + +inline bool operator!=(const DisplayItem::Id& a, const DisplayItem::Id& b) +{ + return !(a == b); +} + class PLATFORM_EXPORT PairedBeginDisplayItem : public DisplayItem { protected: PairedBeginDisplayItem(const DisplayItemClient& client, Type type, size_t derivedSize) : DisplayItem(client, type, derivedSize) { }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp index d7292ad6..c3f23f1 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.cpp
@@ -14,12 +14,8 @@ namespace blink { -DisplayItem& DisplayItemList::appendByMoving(DisplayItem& item, const IntRect& visualRect, SkPictureGpuAnalyzer& gpuAnalyzer) +DisplayItem& DisplayItemList::appendByMoving(DisplayItem& item) { - // No reason to continue the analysis once we have a veto. - if (gpuAnalyzer.suitableForGpuRasterization()) - item.analyzeForGpuRasterization(gpuAnalyzer); - #ifndef NDEBUG String originalDebugString = item.asDebugString(); #endif @@ -33,7 +29,6 @@ // Save original debug string in the old item to help debugging. item.setClientDebugString(originalDebugString); #endif - appendVisualRect(visualRect); return result; }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.h b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.h index df66a435..166619c 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.h +++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemList.h
@@ -43,7 +43,7 @@ return *this; } - DisplayItem& appendByMoving(DisplayItem&, const IntRect& visualRect, SkPictureGpuAnalyzer&); + DisplayItem& appendByMoving(DisplayItem&); IntRect visualRect(unsigned index) const {
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.cpp b/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.cpp index d75455f..eefcd8f 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.cpp
@@ -7,31 +7,11 @@ #include "platform/RuntimeEnabledFeatures.h" #include "platform/graphics/GraphicsContext.h" #include "platform/graphics/GraphicsLayer.h" -#include "platform/graphics/paint/CachedDisplayItem.h" #include "platform/graphics/paint/PaintController.h" #include "third_party/skia/include/core/SkPicture.h" namespace blink { -bool DrawingRecorder::useCachedDrawingIfPossible(GraphicsContext& context, const DisplayItemClient& client, DisplayItem::Type type) -{ - ASSERT(DisplayItem::isDrawingType(type)); - - if (!context.getPaintController().clientCacheIsValid(client)) - return false; - - context.getPaintController().createAndAppend<CachedDisplayItem>(client, DisplayItem::drawingTypeToCachedDrawingType(type)); - -#if ENABLE(ASSERT) - // When under-invalidation checking is enabled, we output CachedDrawing display item - // followed by the display item containing forced painting. - if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) - return false; -#endif - - return true; -} - DrawingRecorder::DrawingRecorder(GraphicsContext& context, const DisplayItemClient& displayItemClient, DisplayItem::Type displayItemType, const FloatRect& floatCullRect) : m_context(context) , m_displayItemClient(displayItemClient)
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.h b/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.h index 5816312..29f7184 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.h +++ b/third_party/WebKit/Source/platform/graphics/paint/DrawingRecorder.h
@@ -8,7 +8,9 @@ #include "platform/PlatformExport.h" #include "platform/geometry/FloatRect.h" +#include "platform/graphics/GraphicsContext.h" #include "platform/graphics/paint/DrawingDisplayItem.h" +#include "platform/graphics/paint/PaintController.h" #include "wtf/Allocator.h" #include "wtf/Noncopyable.h" @@ -24,7 +26,10 @@ DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); WTF_MAKE_NONCOPYABLE(DrawingRecorder); public: - static bool useCachedDrawingIfPossible(GraphicsContext&, const DisplayItemClient&, DisplayItem::Type); + static bool useCachedDrawingIfPossible(GraphicsContext& context, const DisplayItemClient& client, DisplayItem::Type type) + { + return context.getPaintController().useCachedDrawingIfPossible(client, type); + } DrawingRecorder(GraphicsContext&, const DisplayItemClient&, DisplayItem::Type, const FloatRect& cullRect); ~DrawingRecorder();
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp index 46b1bde..24e041f2 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
@@ -31,6 +31,81 @@ return m_currentPaintArtifact; } +bool PaintController::useCachedDrawingIfPossible(const DisplayItemClient& client, DisplayItem::Type type) +{ + DCHECK(DisplayItem::isDrawingType(type)); + + if (displayItemConstructionIsDisabled()) + return false; + + if (!clientCacheIsValid(client)) + return false; + +#if ENABLE(ASSERT) + // When under-invalidation checking is enabled, we output CachedDrawing display item + // followed by the display item containing forced painting. + if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) + return false; +#endif + + DisplayItemList::iterator cachedItem = findCachedItem(DisplayItem::Id(client, type)); + if (cachedItem == m_currentPaintArtifact.getDisplayItemList().end()) { + NOTREACHED(); + return false; + } + + ++m_numCachedNewItems; + ensureNewDisplayItemListInitialCapacity(); + processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem)); + + m_nextItemToMatch = cachedItem + 1; + // Items before m_nextItemToMatch have been copied so we don't need to index them. + if (m_nextItemToMatch - m_nextItemToIndex > 0) + m_nextItemToIndex = m_nextItemToMatch; + + return true; +} + +bool PaintController::useCachedSubsequenceIfPossible(const DisplayItemClient& client) +{ + // TODO(crbug.com/596983): Implement subsequence caching for spv2. + // The problem is in copyCachedSubsequence() which fails to handle PaintChunkProperties + // of chunks containing cached display items. We need to find the previous + // PaintChunkProperties and ensure they are valid in the current paint property tree. + if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) + return false; + + if (displayItemConstructionIsDisabled() || subsequenceCachingIsDisabled()) + return false; + + if (!clientCacheIsValid(client)) + return false; + +#if ENABLE(ASSERT) + // When under-invalidation checking is enabled, we output CachedDrawing display item + // followed by the display item containing forced painting. + if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) + return false; +#endif + + DisplayItemList::iterator cachedItem = findCachedItem(DisplayItem::Id(client, DisplayItem::Subsequence)); + if (cachedItem == m_currentPaintArtifact.getDisplayItemList().end()) { + NOTREACHED(); + return false; + } + + // |cachedItem| will point to the first item after the subsequence or end of the current list. + ensureNewDisplayItemListInitialCapacity(); + copyCachedSubsequence(cachedItem); + + m_nextItemToMatch = cachedItem; + // Items before |cachedItem| have been copied so we don't need to index them. + if (cachedItem - m_nextItemToIndex > 0) + m_nextItemToIndex = cachedItem; + + return true; +} + bool PaintController::lastDisplayItemIsNoopBegin() const { if (m_newDisplayItemList.isEmpty()) @@ -63,11 +138,10 @@ void PaintController::processNewItem(DisplayItem& displayItem) { DCHECK(!m_constructionDisabled); - DCHECK(!skippingCache() || !displayItem.isCached()); #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS if (!skippingCache()) { - if (displayItem.isCacheable() || displayItem.isCached()) { + if (displayItem.isCacheable()) { // Mark the client shouldKeepAlive under this PaintController. // The status will end after the new display items are committed. displayItem.client().beginShouldKeepAlive(this); @@ -88,9 +162,6 @@ } #endif - if (displayItem.isCached()) - ++m_numCachedNewItems; - #if DCHECK_IS_ON() // Verify noop begin/end pairs have been removed. if (m_newDisplayItemList.size() >= 2 && displayItem.isEnd()) { @@ -104,7 +175,7 @@ displayItem.setSkippedCache(); #if DCHECK_IS_ON() - size_t index = findMatchingItemFromIndex(displayItem.nonCachedId(), m_newDisplayItemIndicesByClient, m_newDisplayItemList); + size_t index = findMatchingItemFromIndex(displayItem.getId(), m_newDisplayItemIndicesByClient, m_newDisplayItemList); if (index != kNotFound) { #ifndef NDEBUG showDebugData(); @@ -158,7 +229,7 @@ for (size_t index : indices) { const DisplayItem& existingItem = list[index]; DCHECK(!existingItem.hasValidClient() || existingItem.client() == id.client); - if (id.matches(existingItem)) + if (id == existingItem.getId()) return index; } @@ -176,54 +247,88 @@ indices.append(index); } -struct PaintController::OutOfOrderIndexContext { - STACK_ALLOCATED(); - OutOfOrderIndexContext(DisplayItemList::iterator begin) : nextItemToIndex(begin) { } - - DisplayItemList::iterator nextItemToIndex; - DisplayItemIndicesByClientMap displayItemIndicesByClient; -}; - -DisplayItemList::iterator PaintController::findOutOfOrderCachedItem(const DisplayItem::Id& id, OutOfOrderIndexContext& context) +DisplayItemList::iterator PaintController::findCachedItem(const DisplayItem::Id& id) { DCHECK(clientCacheIsValid(id.client)); - size_t foundIndex = findMatchingItemFromIndex(id, context.displayItemIndicesByClient, m_currentPaintArtifact.getDisplayItemList()); - if (foundIndex != kNotFound) - return m_currentPaintArtifact.getDisplayItemList().begin() + foundIndex; + // Try to find the item sequentially first. This is fast if the current list and the new list are in + // the same order around the new item. If found, we don't need to update and lookup the index. + DisplayItemList::iterator end = m_currentPaintArtifact.getDisplayItemList().end(); + DisplayItemList::iterator it = m_nextItemToMatch; + for (; it != end; ++it) { + // We encounter an item that has already been copied which indicates we can't do sequential matching. + if (!it->hasValidClient()) + break; + if (id == it->getId()) { +#if DCHECK_IS_ON() + ++m_numSequentialMatches; +#endif + return it; + } + // We encounter a different cacheable item which also indicates we can't do sequential matching. + if (it->isCacheable()) + break; + } - return findOutOfOrderCachedItemForward(id, context); + size_t foundIndex = findMatchingItemFromIndex(id, m_outOfOrderItemIndices, m_currentPaintArtifact.getDisplayItemList()); + if (foundIndex != kNotFound) { +#if DCHECK_IS_ON() + ++m_numOutOfOrderMatches; +#endif + return m_currentPaintArtifact.getDisplayItemList().begin() + foundIndex; + } + + return findOutOfOrderCachedItemForward(id); } // Find forward for the item and index all skipped indexable items. -DisplayItemList::iterator PaintController::findOutOfOrderCachedItemForward(const DisplayItem::Id& id, OutOfOrderIndexContext& context) +DisplayItemList::iterator PaintController::findOutOfOrderCachedItemForward(const DisplayItem::Id& id) { - DisplayItemList::iterator currentEnd = m_currentPaintArtifact.getDisplayItemList().end(); - for (; context.nextItemToIndex != currentEnd; ++context.nextItemToIndex) { - const DisplayItem& item = *context.nextItemToIndex; + DisplayItemList::iterator end = m_currentPaintArtifact.getDisplayItemList().end(); + for (DisplayItemList::iterator it = m_nextItemToIndex; it != end; ++it) { + const DisplayItem& item = *it; DCHECK(item.hasValidClient()); - if (id.matches(item)) - return context.nextItemToIndex++; - if (item.isCacheable()) - addItemToIndexIfNeeded(item, context.nextItemToIndex - m_currentPaintArtifact.getDisplayItemList().begin(), context.displayItemIndicesByClient); + if (id == item.getId()) { +#if DCHECK_IS_ON() + ++m_numSequentialMatches; +#endif + return it; + } + if (item.isCacheable()) { +#if DCHECK_IS_ON() + ++m_numIndexedItems; +#endif + addItemToIndexIfNeeded(item, it - m_currentPaintArtifact.getDisplayItemList().begin(), m_outOfOrderItemIndices); + } } - return currentEnd; + +#ifndef NDEBUG + showDebugData(); + LOG(ERROR) << id.client.debugName() << ":" << DisplayItem::typeAsDebugString(id.type) << " not found in current display item list"; +#endif + NOTREACHED(); + // We did not find the cached display item. This should be impossible, but may occur if there is a bug + // in the system, such as under-invalidation, incorrect cache checking or duplicate display ids. + // In this case, the caller should fall back to repaint the display item. + return end; } -void PaintController::copyCachedSubsequence(const DisplayItemList& currentList, DisplayItemList::iterator& currentIt, DisplayItemList& updatedList, SkPictureGpuAnalyzer& gpuAnalyzer) +// On return, |it| points to the item after the EndSubsequence item of the subsequence. +void PaintController::copyCachedSubsequence(DisplayItemList::iterator& it) { - DCHECK(currentIt->getType() == DisplayItem::Subsequence); - DisplayItem::Id endSubsequenceId(currentIt->client(), DisplayItem::EndSubsequence); + DCHECK(it->getType() == DisplayItem::Subsequence); + DisplayItem::Id endSubsequenceId(it->client(), DisplayItem::EndSubsequence); do { // We should always find the EndSubsequence display item. - DCHECK(currentIt != m_currentPaintArtifact.getDisplayItemList().end()); - DCHECK(currentIt->hasValidClient()); + DCHECK(it != m_currentPaintArtifact.getDisplayItemList().end()); + DCHECK(it->hasValidClient()); #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS - CHECK(currentIt->client().isAlive()); + CHECK(it->client().isAlive()); #endif - updatedList.appendByMoving(*currentIt, currentList.visualRect(currentIt - m_currentPaintArtifact.getDisplayItemList().begin()), gpuAnalyzer); - ++currentIt; - } while (!endSubsequenceId.matches(updatedList.last())); + ++m_numCachedNewItems; + processNewItem(m_newDisplayItemList.appendByMoving(*it)); + ++it; + } while (endSubsequenceId != m_newDisplayItemList.last().getId()); } static IntRect visualRectForDisplayItem(const DisplayItem& displayItem, const LayoutSize& offsetFromLayoutObject) @@ -233,17 +338,12 @@ return enclosingIntRect(visualRect); } -// Update the existing display items by removing invalidated entries, updating -// repainted ones, and appending new items. -// - For cached drawing display item, copy the corresponding cached DrawingDisplayItem; -// - For cached subsequence display item, copy the cached display items between the -// corresponding SubsequenceDisplayItem and EndSubsequenceDisplayItem (incl.); -// - Otherwise, copy the new display item. -// -// The algorithm is O(|m_currentDisplayItemList| + |m_newDisplayItemList|). -// Coefficients are related to the ratio of out-of-order CachedDisplayItems -// and the average number of (Drawing|Subsequence)DisplayItems per client. -// +void PaintController::resetCurrentListIterators() +{ + m_nextItemToMatch = m_currentPaintArtifact.getDisplayItemList().begin(); + m_nextItemToIndex = m_nextItemToMatch; +} + void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutObject) { TRACE_EVENT2("blink,benchmark", "PaintController::commitNewDisplayItems", @@ -259,99 +359,37 @@ SkPictureGpuAnalyzer gpuAnalyzer; - if (m_currentPaintArtifact.isEmpty()) { -#if DCHECK_IS_ON() - for (const auto& item : m_newDisplayItemList) - DCHECK(!item.isCached()); -#endif + m_currentCacheGeneration = DisplayItemClient::CacheGenerationOrInvalidationReason::next(); + for (const auto& item : m_newDisplayItemList) { + // No reason to continue the analysis once we have a veto. + if (gpuAnalyzer.suitableForGpuRasterization()) + item.analyzeForGpuRasterization(gpuAnalyzer); - for (const auto& item : m_newDisplayItemList) { - m_newDisplayItemList.appendVisualRect(visualRectForDisplayItem(item, offsetFromLayoutObject)); - // No reason to continue the analysis once we have a veto. - if (gpuAnalyzer.suitableForGpuRasterization()) - item.analyzeForGpuRasterization(gpuAnalyzer); - } - m_currentPaintArtifact = PaintArtifact(std::move(m_newDisplayItemList), m_newPaintChunks.releasePaintChunks(), gpuAnalyzer.suitableForGpuRasterization()); - m_newDisplayItemList = DisplayItemList(kInitialDisplayItemListCapacityBytes); - updateCacheGeneration(); - return; + m_newDisplayItemList.appendVisualRect(visualRectForDisplayItem(item, offsetFromLayoutObject)); + + if (item.isCacheable()) + item.client().setDisplayItemsCached(m_currentCacheGeneration); } - // Stores indices to valid DrawingDisplayItems in m_currentDisplayItems that have not been matched - // by CachedDisplayItems during synchronized matching. The indexed items will be matched - // by later out-of-order CachedDisplayItems in m_newDisplayItemList. This ensures that when - // out-of-order CachedDisplayItems occur, we only traverse at most once over m_currentDisplayItems - // looking for potential matches. Thus we can ensure that the algorithm runs in linear time. - OutOfOrderIndexContext outOfOrderIndexContext(m_currentPaintArtifact.getDisplayItemList().begin()); + // The new list will not be appended to again so we can release unused memory. + m_newDisplayItemList.shrinkToFit(); + m_currentPaintArtifact = PaintArtifact(std::move(m_newDisplayItemList), m_newPaintChunks.releasePaintChunks(), gpuAnalyzer.suitableForGpuRasterization()); + resetCurrentListIterators(); + m_outOfOrderItemIndices.clear(); - // TODO(jbroman): Consider revisiting this heuristic. - DisplayItemList updatedList(std::max(m_currentPaintArtifact.getDisplayItemList().usedCapacityInBytes(), m_newDisplayItemList.usedCapacityInBytes())); - Vector<PaintChunk> updatedPaintChunks; - DisplayItemList::iterator currentIt = m_currentPaintArtifact.getDisplayItemList().begin(); - DisplayItemList::iterator currentEnd = m_currentPaintArtifact.getDisplayItemList().end(); - for (DisplayItemList::iterator newIt = m_newDisplayItemList.begin(); newIt != m_newDisplayItemList.end(); ++newIt) { - const DisplayItem& newDisplayItem = *newIt; - const DisplayItem::Id newDisplayItemId = newDisplayItem.nonCachedId(); - bool newDisplayItemHasCachedType = newDisplayItem.getType() != newDisplayItemId.type; + // We'll allocate the initial buffer when we start the next paint. + m_newDisplayItemList = DisplayItemList(0); - bool isSynchronized = currentIt != currentEnd && newDisplayItemId.matches(*currentIt); - - if (newDisplayItemHasCachedType) { - DCHECK(newDisplayItem.isCached()); #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS - CHECK(clientCacheIsValid(newDisplayItem.client())); + CHECK(m_currentSubsequenceClients.isEmpty()); + DisplayItemClient::endShouldKeepAliveAllClients(this); #endif - if (!isSynchronized) { - currentIt = findOutOfOrderCachedItem(newDisplayItemId, outOfOrderIndexContext); - if (currentIt == currentEnd) { -#ifndef NDEBUG - showDebugData(); - WTFLogAlways("%s not found in m_currentDisplayItemList\n", newDisplayItem.asDebugString().utf8().data()); -#endif - NOTREACHED(); - // We did not find the cached display item. This should be impossible, but may occur if there is a bug - // in the system, such as under-invalidation, incorrect cache checking or duplicate display ids. - // In this case, attempt to recover rather than crashing or bailing on display of the rest of the display list. - continue; - } - } #if DCHECK_IS_ON() - if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) { - DisplayItemList::iterator temp = currentIt; - checkUnderInvalidation(newIt, temp); - } + m_numSequentialMatches = 0; + m_numOutOfOrderMatches = 0; + m_numIndexedItems = 0; #endif - if (newDisplayItem.isCachedDrawing()) { - updatedList.appendByMoving(*currentIt, m_currentPaintArtifact.getDisplayItemList().visualRect(currentIt - m_currentPaintArtifact.getDisplayItemList().begin()), - gpuAnalyzer); - ++currentIt; - } else { - DCHECK(newDisplayItem.getType() == DisplayItem::CachedSubsequence); - copyCachedSubsequence(m_currentPaintArtifact.getDisplayItemList(), currentIt, updatedList, gpuAnalyzer); - DCHECK(updatedList.last().getType() == DisplayItem::EndSubsequence); - } - } else { - DCHECK(!newDisplayItem.isDrawing() - || newDisplayItem.skippedCache() - || !clientCacheIsValid(newDisplayItem.client())); - - updatedList.appendByMoving(*newIt, visualRectForDisplayItem(*newIt, offsetFromLayoutObject), gpuAnalyzer); - - if (isSynchronized) - ++currentIt; - } - // Items before currentIt should have been copied so we don't need to index them. - if (currentIt - outOfOrderIndexContext.nextItemToIndex > 0) - outOfOrderIndexContext.nextItemToIndex = currentIt; - } - - // TODO(jbroman): When subsequence caching applies to SPv2, we'll need to - // merge the paint chunks as well. - m_currentPaintArtifact = PaintArtifact(std::move(updatedList), m_newPaintChunks.releasePaintChunks(), gpuAnalyzer.suitableForGpuRasterization()); - - m_newDisplayItemList = DisplayItemList(kInitialDisplayItemListCapacityBytes); - updateCacheGeneration(); } size_t PaintController::approximateUnsharedMemoryUsage() const @@ -379,34 +417,23 @@ return memoryUsage; } -void PaintController::updateCacheGeneration() -{ - m_currentCacheGeneration = DisplayItemClient::CacheGenerationOrInvalidationReason::next(); - for (const DisplayItem& displayItem : m_currentPaintArtifact.getDisplayItemList()) { - if (!displayItem.isCacheable()) - continue; - displayItem.client().setDisplayItemsCached(m_currentCacheGeneration); - } -#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS - CHECK(m_currentSubsequenceClients.isEmpty()); - DisplayItemClient::endShouldKeepAliveAllClients(this); -#endif -} - void PaintController::appendDebugDrawingAfterCommit(const DisplayItemClient& displayItemClient, PassRefPtr<SkPicture> picture, const LayoutSize& offsetFromLayoutObject) { DCHECK(m_newDisplayItemList.isEmpty()); DrawingDisplayItem& displayItem = m_currentPaintArtifact.getDisplayItemList().allocateAndConstruct<DrawingDisplayItem>(displayItemClient, DisplayItem::DebugDrawing, picture); displayItem.setSkippedCache(); m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDisplayItem(displayItem, offsetFromLayoutObject)); + + // Need to reset the iterators after mutation of the DisplayItemList. + resetCurrentListIterators(); } -#if DCHECK_IS_ON() +#if 0 // DCHECK_IS_ON() +// TODO(wangxianzhu): Fix under-invalidation checking for the new caching method. void PaintController::checkUnderInvalidation(DisplayItemList::iterator& newIt, DisplayItemList::iterator& currentIt) { DCHECK(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()); - DCHECK(newIt->isCached()); // When under-invalidation-checking is enabled, the forced painting is following the cached display item. DisplayItem::Type nextItemType = DisplayItem::nonCachedType(newIt->getType());
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintController.h b/third_party/WebKit/Source/platform/graphics/paint/PaintController.h index fd1d11f4..28324670 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/PaintController.h +++ b/third_party/WebKit/Source/platform/graphics/paint/PaintController.h
@@ -75,6 +75,8 @@ if (displayItemConstructionIsDisabled()) return; + + ensureNewDisplayItemListInitialCapacity(); DisplayItemClass& displayItem = m_newDisplayItemList.allocateAndConstruct<DisplayItemClass>(std::forward<Args>(args)...); processNewItem(displayItem); } @@ -95,6 +97,14 @@ createAndAppend<DisplayItemClass>(std::forward<Args>(args)...); } + // Tries to find the cached drawing display item corresponding to the given parameters. If found, + // appends the cached display item to the new display list and returns true. Otherwise returns false. + bool useCachedDrawingIfPossible(const DisplayItemClient&, DisplayItem::Type); + + // Tries to find the cached subsequence corresponding to the given parameters. If found, copies the + // cache subsequence to the new display list and returns true. Otherwise returns false. + bool useCachedSubsequenceIfPossible(const DisplayItemClient&); + // True if the last display item is a begin that doesn't draw content. bool lastDisplayItemIsNoopBegin() const; void removeLastDisplayItem(); @@ -148,16 +158,34 @@ protected: PaintController() - : m_newDisplayItemList(kInitialDisplayItemListCapacityBytes) + : m_newDisplayItemList(0) , m_constructionDisabled(false) , m_subsequenceCachingDisabled(false) , m_textPainted(false) , m_imagePainted(false) , m_skippingCacheCount(0) , m_numCachedNewItems(0) - { } +#if DCHECK_IS_ON() + , m_numSequentialMatches(0) + , m_numOutOfOrderMatches(0) + , m_numIndexedItems(0) +#endif + { + resetCurrentListIterators(); + } private: + friend class PaintControllerTest; + friend class PaintControllerPaintTestBase; + + void ensureNewDisplayItemListInitialCapacity() + { + if (m_newDisplayItemList.isEmpty()) { + // TODO(wangxianzhu): Consider revisiting this heuristic. + m_newDisplayItemList = DisplayItemList(m_currentPaintArtifact.getDisplayItemList().isEmpty() ? kInitialDisplayItemListCapacityBytes : m_currentPaintArtifact.getDisplayItemList().usedCapacityInBytes()); + } + } + // Set new item state (cache skipping, etc) for a new item. void processNewItem(DisplayItem&); @@ -172,10 +200,14 @@ static size_t findMatchingItemFromIndex(const DisplayItem::Id&, const DisplayItemIndicesByClientMap&, const DisplayItemList&); static void addItemToIndexIfNeeded(const DisplayItem&, size_t index, DisplayItemIndicesByClientMap&); - struct OutOfOrderIndexContext; - DisplayItemList::iterator findOutOfOrderCachedItem(const DisplayItem::Id&, OutOfOrderIndexContext&); - DisplayItemList::iterator findOutOfOrderCachedItemForward(const DisplayItem::Id&, OutOfOrderIndexContext&); - void copyCachedSubsequence(const DisplayItemList& currentList, DisplayItemList::iterator& currentIt, DisplayItemList& updatedList, SkPictureGpuAnalyzer&); + DisplayItemList::iterator findCachedItem(const DisplayItem::Id&); + DisplayItemList::iterator findOutOfOrderCachedItemForward(const DisplayItem::Id&); + void copyCachedSubsequence(DisplayItemList::iterator&); + + // Resets the iterators (e.g. m_nextItemToMatch) of m_currentPaintArtifact.getDisplayItemList() + // to their initial values. This should be called when the DisplayItemList in m_currentPaintArtifact + // is newly created, or is changed causing the previous iterators to be invalid. + void resetCurrentListIterators(); #if DCHECK_IS_ON() // The following two methods are for checking under-invalidations @@ -184,8 +216,6 @@ void checkCachedDisplayItemIsUnchanged(const char* messagePrefix, const DisplayItem& newItem, const DisplayItem& oldItem); #endif - void updateCacheGeneration(); - // The last complete paint artifact. // In SPv2, this includes paint chunks as well as display items. PaintArtifact m_currentPaintArtifact; @@ -209,15 +239,31 @@ int m_numCachedNewItems; -#if DCHECK_IS_ON() - // This is used to check duplicated ids during add(). We could also check - // during commitNewDisplayItems(), but checking during add() helps developer - // easily find where the duplicated ids are from. - DisplayItemIndicesByClientMap m_newDisplayItemIndicesByClient; -#endif + // Stores indices to valid DrawingDisplayItems in current display list that have not been + // matched by CachedDisplayItems during sequential matching. The indexed items will be + // matched by later out-of-order requests of cached display items. This ensures that when + // out-of-order cached display items are requested, we only traverse at most once over + // the current display list looking for potential matches. Thus we can ensure that the + // algorithm runs in linear time. + DisplayItemIndicesByClientMap m_outOfOrderItemIndices; + + // The next item in the current list for sequential match. + DisplayItemList::iterator m_nextItemToMatch; + + // The next item in the current list to be indexed for out-of-order cache requests. + DisplayItemList::iterator m_nextItemToIndex; DisplayItemClient::CacheGenerationOrInvalidationReason m_currentCacheGeneration; +#if DCHECK_IS_ON() + int m_numSequentialMatches; + int m_numOutOfOrderMatches; + int m_numIndexedItems; + + // This is used to check duplicated ids during createAndAppend(). + DisplayItemIndicesByClientMap m_newDisplayItemIndicesByClient; +#endif + #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS // A stack recording subsequence clients that are currently painting. Vector<const DisplayItemClient*> m_currentSubsequenceClients;
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp index 826c05d..22798a2 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
@@ -6,7 +6,6 @@ #include "platform/RuntimeEnabledFeatures.h" #include "platform/graphics/GraphicsContext.h" -#include "platform/graphics/paint/CachedDisplayItem.h" #include "platform/graphics/paint/ClipPathDisplayItem.h" #include "platform/graphics/paint/ClipPathRecorder.h" #include "platform/graphics/paint/ClipRecorder.h" @@ -33,6 +32,14 @@ protected: PaintController& getPaintController() { return *m_paintController; } + int numCachedNewItems() const { return m_paintController->m_numCachedNewItems; } + +#if DCHECK_IS_ON() + int numSequentialMatches() const { return m_paintController->m_numSequentialMatches; } + int numOutOfOrderMatches() const { return m_paintController->m_numOutOfOrderMatches; } + int numIndexedItems() const { return m_paintController->m_numIndexedItems; } +#endif + private: void TearDown() override { @@ -115,6 +122,9 @@ drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 300, 300)); drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 200, 200)); drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 300, 300)); + + EXPECT_EQ(0, numCachedNewItems()); + getPaintController().commitNewDisplayItems(); EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 3, @@ -125,6 +135,14 @@ second.setDisplayItemsUncached(); drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 300, 300)); drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 300, 300)); + + EXPECT_EQ(2, numCachedNewItems()); +#if DCHECK_IS_ON() + EXPECT_EQ(2, numSequentialMatches()); + EXPECT_EQ(0, numOutOfOrderMatches()); + EXPECT_EQ(1, numIndexedItems()); +#endif + getPaintController().commitNewDisplayItems(); EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 2, @@ -140,25 +158,93 @@ GraphicsContext context(getPaintController()); drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100)); + drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 100, 100)); drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200)); + drawRect(context, second, foregroundDrawingType, FloatRect(100, 100, 50, 200)); drawRect(context, unaffected, backgroundDrawingType, FloatRect(300, 300, 10, 10)); + drawRect(context, unaffected, foregroundDrawingType, FloatRect(300, 300, 10, 10)); getPaintController().commitNewDisplayItems(); - EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 3, + EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 6, TestDisplayItem(first, backgroundDrawingType), + TestDisplayItem(first, foregroundDrawingType), TestDisplayItem(second, backgroundDrawingType), - TestDisplayItem(unaffected, backgroundDrawingType)); + TestDisplayItem(second, foregroundDrawingType), + TestDisplayItem(unaffected, backgroundDrawingType), + TestDisplayItem(unaffected, foregroundDrawingType)); - second.setDisplayItemsUncached(); drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200)); + drawRect(context, second, foregroundDrawingType, FloatRect(100, 100, 50, 200)); drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100)); + drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 100, 100)); drawRect(context, unaffected, backgroundDrawingType, FloatRect(300, 300, 10, 10)); + drawRect(context, unaffected, foregroundDrawingType, FloatRect(300, 300, 10, 10)); + + EXPECT_EQ(6, numCachedNewItems()); +#if DCHECK_IS_ON() + EXPECT_EQ(5, numSequentialMatches()); // second, first foreground, unaffected + EXPECT_EQ(1, numOutOfOrderMatches()); // first + EXPECT_EQ(2, numIndexedItems()); // first +#endif + getPaintController().commitNewDisplayItems(); - EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 3, + EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 6, TestDisplayItem(second, backgroundDrawingType), + TestDisplayItem(second, foregroundDrawingType), TestDisplayItem(first, backgroundDrawingType), - TestDisplayItem(unaffected, backgroundDrawingType)); + TestDisplayItem(first, foregroundDrawingType), + TestDisplayItem(unaffected, backgroundDrawingType), + TestDisplayItem(unaffected, foregroundDrawingType)); +} + +TEST_F(PaintControllerTest, UpdateSwapOrderWithInvalidation) +{ + FakeDisplayItemClient first("first"); + FakeDisplayItemClient second("second"); + FakeDisplayItemClient unaffected("unaffected"); + GraphicsContext context(getPaintController()); + + drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100)); + drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 100, 100)); + drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200)); + drawRect(context, second, foregroundDrawingType, FloatRect(100, 100, 50, 200)); + drawRect(context, unaffected, backgroundDrawingType, FloatRect(300, 300, 10, 10)); + drawRect(context, unaffected, foregroundDrawingType, FloatRect(300, 300, 10, 10)); + getPaintController().commitNewDisplayItems(); + + EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 6, + TestDisplayItem(first, backgroundDrawingType), + TestDisplayItem(first, foregroundDrawingType), + TestDisplayItem(second, backgroundDrawingType), + TestDisplayItem(second, foregroundDrawingType), + TestDisplayItem(unaffected, backgroundDrawingType), + TestDisplayItem(unaffected, foregroundDrawingType)); + + first.setDisplayItemsUncached(); + drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200)); + drawRect(context, second, foregroundDrawingType, FloatRect(100, 100, 50, 200)); + drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100)); + drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 100, 100)); + drawRect(context, unaffected, backgroundDrawingType, FloatRect(300, 300, 10, 10)); + drawRect(context, unaffected, foregroundDrawingType, FloatRect(300, 300, 10, 10)); + + EXPECT_EQ(4, numCachedNewItems()); +#if DCHECK_IS_ON() + EXPECT_EQ(4, numSequentialMatches()); // second, unaffected + EXPECT_EQ(0, numOutOfOrderMatches()); + EXPECT_EQ(2, numIndexedItems()); +#endif + + getPaintController().commitNewDisplayItems(); + + EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 6, + TestDisplayItem(second, backgroundDrawingType), + TestDisplayItem(second, foregroundDrawingType), + TestDisplayItem(first, backgroundDrawingType), + TestDisplayItem(first, foregroundDrawingType), + TestDisplayItem(unaffected, backgroundDrawingType), + TestDisplayItem(unaffected, foregroundDrawingType)); } TEST_F(PaintControllerTest, UpdateNewItemInMiddle) @@ -179,6 +265,14 @@ drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 100, 100)); drawRect(context, third, backgroundDrawingType, FloatRect(125, 100, 200, 50)); drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 50, 200)); + + EXPECT_EQ(2, numCachedNewItems()); +#if DCHECK_IS_ON() + EXPECT_EQ(2, numSequentialMatches()); // first, second + EXPECT_EQ(0, numOutOfOrderMatches()); + EXPECT_EQ(0, numIndexedItems()); +#endif + getPaintController().commitNewDisplayItems(); EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 3, @@ -217,6 +311,14 @@ drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 100, 100)); drawRect(context, second, foregroundDrawingType, FloatRect(100, 100, 50, 200)); drawRect(context, third, foregroundDrawingType, FloatRect(300, 100, 50, 50)); + + EXPECT_EQ(4, numCachedNewItems()); +#if DCHECK_IS_ON() + EXPECT_EQ(4, numSequentialMatches()); + EXPECT_EQ(0, numOutOfOrderMatches()); + EXPECT_EQ(2, numIndexedItems()); +#endif + getPaintController().commitNewDisplayItems(); EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 6, @@ -248,6 +350,7 @@ drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 150, 150)); drawRect(context, second, backgroundDrawingType, FloatRect(200, 200, 50, 50)); drawRect(context, second, foregroundDrawingType, FloatRect(200, 200, 50, 50)); + EXPECT_EQ(0, numCachedNewItems()); getPaintController().commitNewDisplayItems(); EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 4, @@ -259,6 +362,14 @@ first.setDisplayItemsUncached(); drawRect(context, second, backgroundDrawingType, FloatRect(200, 200, 50, 50)); drawRect(context, second, foregroundDrawingType, FloatRect(200, 200, 50, 50)); + + EXPECT_EQ(2, numCachedNewItems()); +#if DCHECK_IS_ON() + EXPECT_EQ(2, numSequentialMatches()); + EXPECT_EQ(0, numOutOfOrderMatches()); + EXPECT_EQ(2, numIndexedItems()); +#endif + getPaintController().commitNewDisplayItems(); EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 2, @@ -286,6 +397,7 @@ drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 150, 150)); drawRect(context, second, backgroundDrawingType, FloatRect(200, 200, 50, 50)); drawRect(context, second, foregroundDrawingType, FloatRect(200, 200, 50, 50)); + EXPECT_EQ(0, numCachedNewItems()); getPaintController().commitNewDisplayItems(); EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 4, @@ -298,6 +410,7 @@ second.setDisplayItemsUncached(); drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150, 150)); drawRect(context, first, foregroundDrawingType, FloatRect(100, 100, 150, 150)); + EXPECT_EQ(0, numCachedNewItems()); getPaintController().commitNewDisplayItems(); EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 2, @@ -327,6 +440,14 @@ first.setDisplayItemsUncached(); drawRect(context, first, backgroundDrawingType, FloatRect(100, 100, 150, 150)); drawRect(context, second, backgroundDrawingType, FloatRect(100, 100, 150, 150)); + + EXPECT_EQ(1, numCachedNewItems()); +#if DCHECK_IS_ON() + EXPECT_EQ(1, numSequentialMatches()); + EXPECT_EQ(0, numOutOfOrderMatches()); + EXPECT_EQ(1, numIndexedItems()); +#endif + getPaintController().commitNewDisplayItems(); EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 2, @@ -483,9 +604,12 @@ EXPECT_TRUE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, container2)); EXPECT_TRUE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, container1)); - EXPECT_DISPLAY_LIST(getPaintController().newDisplayItemList(), 2, - TestDisplayItem(container2, DisplayItem::CachedSubsequence), - TestDisplayItem(container1, DisplayItem::CachedSubsequence)); + EXPECT_EQ(12, numCachedNewItems()); +#if DCHECK_IS_ON() + EXPECT_EQ(1, numSequentialMatches()); + EXPECT_EQ(1, numOutOfOrderMatches()); + EXPECT_EQ(5, numIndexedItems()); +#endif getPaintController().commitNewDisplayItems(); @@ -602,14 +726,13 @@ EXPECT_TRUE(SubsequenceRecorder::useCachedSubsequenceIfPossible(context, content1)); drawRect(context, container1, foregroundDrawingType, FloatRect(100, 100, 100, 100)); } - EXPECT_DISPLAY_LIST(getPaintController().newDisplayItemList(), 7, - TestDisplayItem(content2, DisplayItem::Subsequence), - TestDisplayItem(content2, foregroundDrawingType), - TestDisplayItem(content2, DisplayItem::EndSubsequence), - TestDisplayItem(container1, DisplayItem::Subsequence), - TestDisplayItem(content1, DisplayItem::CachedSubsequence), - TestDisplayItem(container1, foregroundDrawingType), - TestDisplayItem(container1, DisplayItem::EndSubsequence)); + + EXPECT_EQ(4, numCachedNewItems()); +#if DCHECK_IS_ON() + EXPECT_EQ(1, numSequentialMatches()); + EXPECT_EQ(0, numOutOfOrderMatches()); + EXPECT_EQ(2, numIndexedItems()); +#endif getPaintController().commitNewDisplayItems(); @@ -667,10 +790,12 @@ drawRect(context, content, foregroundDrawingType, rect2); getPaintController().endSkippingCache(); - EXPECT_DISPLAY_LIST(getPaintController().newDisplayItemList(), 3, - TestDisplayItem(multicol, DisplayItem::drawingTypeToCachedDrawingType(backgroundDrawingType)), - TestDisplayItem(content, foregroundDrawingType), - TestDisplayItem(content, foregroundDrawingType)); + EXPECT_EQ(1, numCachedNewItems()); +#if DCHECK_IS_ON() + EXPECT_EQ(1, numSequentialMatches()); + EXPECT_EQ(0, numOutOfOrderMatches()); + EXPECT_EQ(0, numIndexedItems()); +#endif getPaintController().commitNewDisplayItems();
diff --git a/third_party/WebKit/Source/platform/graphics/paint/README.md b/third_party/WebKit/Source/platform/graphics/paint/README.md index 618a5fc9..009a752 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/README.md +++ b/third_party/WebKit/Source/platform/graphics/paint/README.md
@@ -134,10 +134,6 @@ ### Standalone display items -#### [CachedDisplayItem](CachedDisplayItem.h) - -See [Display item caching](../../../core/paint/README.md#paint-result-caching). - #### [DrawingDisplayItem](DrawingDisplayItem.h) Holds an `SkPicture` which contains the Skia commands required to draw some atom @@ -164,14 +160,17 @@ a `PaintController`. `PaintController` is responsible for producing the paint artifact. It contains -the *current* paint artifact, which is always complete (i.e. it has no -`CachedDisplayItem` objects), and *new* display items and paint chunks, which +the *current* paint artifact, and *new* display items and paint chunks, which are added as content is painted. +Painters should call `PaintController::useCachedDrawingIfPossible()` or +`PaintController::useCachedSubsequenceIfPossible()` and if the function returns +`true`, existing display items that are still valid in the *current* paint artifact +will be reused and the painter should skip real painting of the drawing or subsequence. + When the new display items have been populated, clients call -`commitNewDisplayItems`, which merges the previous artifact with the new data, -producing a new paint artifact, where `CachedDisplayItem` objects have been -replaced with the cached content from the previous artifact. +`commitNewDisplayItems`, which replaces the previous artifact with the new data, +producing a new paint artifact. At this point, the paint artifact is ready to be drawn or composited. @@ -193,11 +192,12 @@ A display item is treated as validly cached in a paint controller if its cache generation matches the paint controller's cache generation. -`kInvalidCacheGeneration` is a special cache generation value which matches no -other cache generations. When a `DisplayItemClient` is invalidated, we set its -cache generation to `kInvalidCacheGeneration`. When a `PaintController` is -cleared (e.g. when the corresponding `GraphicsLayer` is fully invalidated), we -also set its cache generation to `kInvalidCacheGeneration`. +A cache generation value smaller than `kFirstValidGeneration` matches no +other cache generations thus is always treated as invalid. When a +`DisplayItemClient` is invalidated, we set its cache generation to one of +`PaintInvalidationReason` values which are smaller than `kFirstValidGeneration`. +When a `PaintController` is cleared (e.g. when the corresponding `GraphicsLayer` +is fully invalidated), we also invalidate its cache generation. For now we use a uint32_t variable to store cache generation. Assuming there is an animation in 60fps needing main-thread repaint, the cache generation will
diff --git a/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.cpp b/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.cpp index 19648b8e..861529e 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.cpp +++ b/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.cpp
@@ -6,36 +6,11 @@ #include "platform/RuntimeEnabledFeatures.h" #include "platform/graphics/GraphicsContext.h" -#include "platform/graphics/paint/CachedDisplayItem.h" #include "platform/graphics/paint/PaintController.h" #include "platform/graphics/paint/SubsequenceDisplayItem.h" namespace blink { -bool SubsequenceRecorder::useCachedSubsequenceIfPossible(GraphicsContext& context, const DisplayItemClient& client) -{ - if (context.getPaintController().displayItemConstructionIsDisabled() || context.getPaintController().subsequenceCachingIsDisabled()) - return false; - - if (!context.getPaintController().clientCacheIsValid(client)) - return false; - - // TODO(pdr): Implement subsequence caching for spv2 (crbug.com/596983). - if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) - return false; - - context.getPaintController().createAndAppend<CachedDisplayItem>(client, DisplayItem::CachedSubsequence); - -#if ENABLE(ASSERT) - // When under-invalidation checking is enabled, we output CachedSubsequence display item - // followed by forced painting of the subsequence. - if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) - return false; -#endif - - return true; -} - SubsequenceRecorder::SubsequenceRecorder(GraphicsContext& context, const DisplayItemClient& client) : m_paintController(context.getPaintController()) , m_client(client)
diff --git a/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.h b/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.h index 8840ce45..3d2bbbea 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.h +++ b/third_party/WebKit/Source/platform/graphics/paint/SubsequenceRecorder.h
@@ -5,7 +5,9 @@ #ifndef SubsequenceRecorder_h #define SubsequenceRecorder_h +#include "platform/graphics/GraphicsContext.h" #include "platform/graphics/paint/DisplayItem.h" +#include "platform/graphics/paint/PaintController.h" #include "wtf/Allocator.h" #include "wtf/Noncopyable.h" @@ -26,7 +28,10 @@ DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); WTF_MAKE_NONCOPYABLE(SubsequenceRecorder); public: - static bool useCachedSubsequenceIfPossible(GraphicsContext&, const DisplayItemClient&); + static bool useCachedSubsequenceIfPossible(GraphicsContext& context, const DisplayItemClient& client) + { + return context.getPaintController().useCachedSubsequenceIfPossible(client); + } SubsequenceRecorder(GraphicsContext&, const DisplayItemClient&); ~SubsequenceRecorder();
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTestHelpers.cpp b/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTestHelpers.cpp index 6e11a895..af147d1 100644 --- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTestHelpers.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoderTestHelpers.cpp
@@ -10,6 +10,7 @@ #include "platform/testing/UnitTestHelpers.h" #include "testing/gtest/include/gtest/gtest.h" #include "wtf/StringHasher.h" +#include "wtf/text/StringBuilder.h" #include <memory> namespace blink { @@ -23,13 +24,13 @@ PassRefPtr<SharedBuffer> readFile(const char* dir, const char* fileName) { - String filePath = testing::blinkRootDir(); - filePath.append("/"); + StringBuilder filePath; + filePath.append(testing::blinkRootDir()); + filePath.append('/'); filePath.append(dir); - filePath.append("/"); + filePath.append('/'); filePath.append(fileName); - - return testing::readFromFile(filePath); + return testing::readFromFile(filePath.toString()); } unsigned hashBitmap(const SkBitmap& bitmap)
diff --git a/third_party/WebKit/Source/platform/inspector_protocol/ErrorSupport.cpp b/third_party/WebKit/Source/platform/inspector_protocol/ErrorSupport.cpp index 4f58a39..0ad89ade 100644 --- a/third_party/WebKit/Source/platform/inspector_protocol/ErrorSupport.cpp +++ b/third_party/WebKit/Source/platform/inspector_protocol/ErrorSupport.cpp
@@ -42,7 +42,7 @@ String16Builder builder; for (size_t i = 0; i < m_path.size(); ++i) { if (i) - builder.append("."); + builder.append('.'); builder.append(m_path[i]); } builder.append(": ");
diff --git a/third_party/WebKit/Source/platform/inspector_protocol/String16WTF.h b/third_party/WebKit/Source/platform/inspector_protocol/String16WTF.h index 3406a8c..bd937b8 100644 --- a/third_party/WebKit/Source/platform/inspector_protocol/String16WTF.h +++ b/third_party/WebKit/Source/platform/inspector_protocol/String16WTF.h
@@ -11,6 +11,7 @@ #include "wtf/text/StringConcatenate.h" #include "wtf/text/StringHash.h" #include "wtf/text/StringToNumber.h" +#include "wtf/text/StringView.h" #include "wtf/text/WTFString.h" namespace blink { @@ -34,6 +35,7 @@ String16(WTF::HashTableDeletedValueType) : m_impl(WTF::HashTableDeletedValue) { } bool isHashTableDeletedValue() const { return m_impl.isHashTableDeletedValue(); } operator WTF::String() const { return m_impl; } + operator WTF::StringView() const { return StringView(m_impl); } operator WebString() { return m_impl; } const WTF::String& impl() const { return m_impl; } String16 isolatedCopy() const { return String16(m_impl.isolatedCopy()); } @@ -75,7 +77,7 @@ class String16Builder { public: String16Builder() { } - void append(const String16& str) { m_impl.append(StringView(str)); }; + void append(const String16& str) { m_impl.append(str); }; void append(UChar c) { m_impl.append(c); }; void append(LChar c) { m_impl.append(c); }; void append(char c) { m_impl.append(c); };
diff --git a/third_party/WebKit/Source/platform/network/ResourceRequest.cpp b/third_party/WebKit/Source/platform/network/ResourceRequest.cpp index c05ad618..99b0af3 100644 --- a/third_party/WebKit/Source/platform/network/ResourceRequest.cpp +++ b/third_party/WebKit/Source/platform/network/ResourceRequest.cpp
@@ -40,6 +40,21 @@ double ResourceRequest::s_defaultTimeoutInterval = INT_MAX; +ResourceRequest::ResourceRequest() +{ + initialize(KURL()); +} + +ResourceRequest::ResourceRequest(const String& urlString) +{ + initialize(KURL(ParsedURLString, urlString)); +} + +ResourceRequest::ResourceRequest(const KURL& url) +{ + initialize(url); +} + ResourceRequest::ResourceRequest(CrossThreadResourceRequestData* data) : ResourceRequest() { @@ -80,6 +95,10 @@ m_redirectStatus = data->m_redirectStatus; } +ResourceRequest::ResourceRequest(const ResourceRequest&) = default; + +ResourceRequest& ResourceRequest::operator=(const ResourceRequest&) = default; + std::unique_ptr<CrossThreadResourceRequestData> ResourceRequest::copyData() const { std::unique_ptr<CrossThreadResourceRequestData> data = wrapUnique(new CrossThreadResourceRequestData());
diff --git a/third_party/WebKit/Source/platform/network/ResourceRequest.h b/third_party/WebKit/Source/platform/network/ResourceRequest.h index ffcac5b..568a000 100644 --- a/third_party/WebKit/Source/platform/network/ResourceRequest.h +++ b/third_party/WebKit/Source/platform/network/ResourceRequest.h
@@ -73,22 +73,12 @@ virtual ~ExtraData() { } }; - ResourceRequest() - { - initialize(KURL()); - } - - ResourceRequest(const String& urlString) - { - initialize(KURL(ParsedURLString, urlString)); - } - - ResourceRequest(const KURL& url) - { - initialize(url); - } - + ResourceRequest(); + ResourceRequest(const String& urlString); + ResourceRequest(const KURL&); explicit ResourceRequest(CrossThreadResourceRequestData*); + ResourceRequest(const ResourceRequest&); + ResourceRequest& operator=(const ResourceRequest&); // Gets a copy of the data suitable for passing to another thread. std::unique_ptr<CrossThreadResourceRequestData> copyData() const;
diff --git a/third_party/WebKit/Source/platform/network/ResourceResponse.cpp b/third_party/WebKit/Source/platform/network/ResourceResponse.cpp index d1a85c9..f29d13ea 100644 --- a/third_party/WebKit/Source/platform/network/ResourceResponse.cpp +++ b/third_party/WebKit/Source/platform/network/ResourceResponse.cpp
@@ -33,6 +33,20 @@ namespace blink { +namespace { + +Vector<ResourceResponse::SignedCertificateTimestamp> isolatedCopy(const Vector<ResourceResponse::SignedCertificateTimestamp>& src) +{ + Vector<ResourceResponse::SignedCertificateTimestamp> result; + result.reserveCapacity(src.size()); + for (const auto& timestamp : src) { + result.append(timestamp.isolatedCopy()); + } + return result; +} + +} // namespace + ResourceResponse::SignedCertificateTimestamp::SignedCertificateTimestamp( const blink::WebURLResponse::SignedCertificateTimestamp& sct) : m_status(sct.status) @@ -46,6 +60,19 @@ { } +ResourceResponse::SignedCertificateTimestamp ResourceResponse::SignedCertificateTimestamp::isolatedCopy() const +{ + return SignedCertificateTimestamp( + m_status.isolatedCopy(), + m_origin.isolatedCopy(), + m_logDescription.isolatedCopy(), + m_logId.isolatedCopy(), + m_timestamp, + m_hashAlgorithm.isolatedCopy(), + m_signatureAlgorithm.isolatedCopy(), + m_signatureData.isolatedCopy()); +} + ResourceResponse::ResourceResponse() : m_expectedContentLength(0) , m_httpStatusCode(0) @@ -164,6 +191,9 @@ // whatever values may be present in the opaque m_extraData structure. } +ResourceResponse::ResourceResponse(const ResourceResponse&) = default; +ResourceResponse& ResourceResponse::operator=(const ResourceResponse&) = default; + std::unique_ptr<CrossThreadResourceResponseData> ResourceResponse::copyData() const { std::unique_ptr<CrossThreadResourceResponseData> data = wrapUnique(new CrossThreadResourceResponseData); @@ -189,7 +219,7 @@ data->m_securityDetails.numUnknownSCTs = m_securityDetails.numUnknownSCTs; data->m_securityDetails.numInvalidSCTs = m_securityDetails.numInvalidSCTs; data->m_securityDetails.numValidSCTs = m_securityDetails.numValidSCTs; - data->m_securityDetails.sctList = m_securityDetails.sctList; + data->m_securityDetails.sctList = isolatedCopy(m_securityDetails.sctList); data->m_httpVersion = m_httpVersion; data->m_appCacheID = m_appCacheID; data->m_appCacheManifestURL = m_appCacheManifestURL.copy();
diff --git a/third_party/WebKit/Source/platform/network/ResourceResponse.h b/third_party/WebKit/Source/platform/network/ResourceResponse.h index a87900a..68b63877 100644 --- a/third_party/WebKit/Source/platform/network/ResourceResponse.h +++ b/third_party/WebKit/Source/platform/network/ResourceResponse.h
@@ -61,7 +61,7 @@ SecurityStyleAuthenticated }; - class SignedCertificateTimestamp { + class PLATFORM_EXPORT SignedCertificateTimestamp final { public: SignedCertificateTimestamp( String status, @@ -84,6 +84,8 @@ } explicit SignedCertificateTimestamp( const struct blink::WebURLResponse::SignedCertificateTimestamp&); + SignedCertificateTimestamp isolatedCopy() const; + String m_status; String m_origin; String m_logDescription; @@ -131,6 +133,8 @@ ResourceResponse(); ResourceResponse(const KURL&, const AtomicString& mimeType, long long expectedLength, const AtomicString& textEncodingName, const String& filename); + ResourceResponse(const ResourceResponse&); + ResourceResponse& operator=(const ResourceResponse&); bool isNull() const { return m_isNull; } bool isHTTP() const;
diff --git a/third_party/WebKit/Source/platform/network/ResourceResponseTest.cpp b/third_party/WebKit/Source/platform/network/ResourceResponseTest.cpp new file mode 100644 index 0000000..1a20323 --- /dev/null +++ b/third_party/WebKit/Source/platform/network/ResourceResponseTest.cpp
@@ -0,0 +1,42 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "platform/network/ResourceResponse.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace blink { + +TEST(ResourceResponseTest, SignedCertificateTimestampIsolatedCopy) +{ + ResourceResponse::SignedCertificateTimestamp src( + "status", + "origin", + "logDescription", + "logId", + 7, + "hashAlgorithm", + "signatureAlgorithm", + "signatureData"); + + ResourceResponse::SignedCertificateTimestamp dest = src.isolatedCopy(); + + EXPECT_EQ(src.m_status, dest.m_status); + EXPECT_NE(src.m_status.impl(), dest.m_status.impl()); + EXPECT_EQ(src.m_origin, dest.m_origin); + EXPECT_NE(src.m_origin.impl(), dest.m_origin.impl()); + EXPECT_EQ(src.m_logDescription, dest.m_logDescription); + EXPECT_NE(src.m_logDescription.impl(), dest.m_logDescription.impl()); + EXPECT_EQ(src.m_logId, dest.m_logId); + EXPECT_NE(src.m_logId.impl(), dest.m_logId.impl()); + EXPECT_EQ(src.m_timestamp, dest.m_timestamp); + EXPECT_EQ(src.m_hashAlgorithm, dest.m_hashAlgorithm); + EXPECT_NE(src.m_hashAlgorithm.impl(), dest.m_hashAlgorithm.impl()); + EXPECT_EQ(src.m_signatureAlgorithm, dest.m_signatureAlgorithm); + EXPECT_NE(src.m_signatureAlgorithm.impl(), dest.m_signatureAlgorithm.impl()); + EXPECT_EQ(src.m_signatureData, dest.m_signatureData); + EXPECT_NE(src.m_signatureData.impl(), dest.m_signatureData.impl()); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h index 6284c86..9499855 100644 --- a/third_party/WebKit/Source/platform/scroll/ScrollableArea.h +++ b/third_party/WebKit/Source/platform/scroll/ScrollableArea.h
@@ -278,6 +278,10 @@ virtual bool isPaintLayerScrollableArea() const { return false; } virtual bool isRootFrameViewport() const { return false; } + // Returns true if the scroller adjusts the scroll position to compensate + // for layout movements (bit.ly/scroll-anchoring). + virtual bool shouldPerformScrollAnchoring() const { return false; } + // Need to promptly let go of owned animator objects. EAGERLY_FINALIZE(); DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/platform/testing/weburl_loader_mock.cc b/third_party/WebKit/Source/platform/testing/weburl_loader_mock.cc index 3984742..45affb8 100644 --- a/third_party/WebKit/Source/platform/testing/weburl_loader_mock.cc +++ b/third_party/WebKit/Source/platform/testing/weburl_loader_mock.cc
@@ -67,7 +67,6 @@ ParsedURLString, redirectResponse.httpHeaderField("Location")); WebURLRequest newRequest; - newRequest.initialize(); newRequest.setURL(redirectURL); newRequest.setFirstPartyForCookies(redirectURL); newRequest.setDownloadToFile(request.downloadToFile());
diff --git a/third_party/WebKit/Source/platform/text/DateTimeFormatTest.cpp b/third_party/WebKit/Source/platform/text/DateTimeFormatTest.cpp index cacbd786..53729df9 100644 --- a/third_party/WebKit/Source/platform/text/DateTimeFormatTest.cpp +++ b/third_party/WebKit/Source/platform/text/DateTimeFormatTest.cpp
@@ -147,10 +147,10 @@ builder.append("Tokens("); for (unsigned index = 0; index < m_tokens.size(); ++index) { if (index) - builder.append(","); + builder.append(','); builder.append(m_tokens[index].toString()); } - builder.append(")"); + builder.append(')'); return builder.toString(); }
diff --git a/third_party/WebKit/Source/platform/text/TextEncodingDetector.cpp b/third_party/WebKit/Source/platform/text/TextEncodingDetector.cpp index 616aac0..abda74b 100644 --- a/third_party/WebKit/Source/platform/text/TextEncodingDetector.cpp +++ b/third_party/WebKit/Source/platform/text/TextEncodingDetector.cpp
@@ -30,9 +30,8 @@ #include "platform/text/TextEncodingDetector.h" +#include "third_party/ced/src/compact_enc_det/compact_enc_det.h" #include "wtf/text/TextEncoding.h" -#include <unicode/ucnv.h> -#include <unicode/ucsdet.h> namespace blink { @@ -40,75 +39,20 @@ const char* hintEncodingName, WTF::TextEncoding* detectedEncoding) { *detectedEncoding = WTF::TextEncoding(); - int matchesCount = 0; - UErrorCode status = U_ZERO_ERROR; - UCharsetDetector* detector = ucsdet_open(&status); - if (U_FAILURE(status)) - return false; - ucsdet_enableInputFilter(detector, true); - ucsdet_setText(detector, data, static_cast<int32_t>(length), &status); - if (U_FAILURE(status)) - return false; - - // FIXME: A few things we can do other than improving - // the ICU detector itself. - // 1. Use ucsdet_detectAll and pick the most likely one given - // "the context" (parent-encoding, referrer encoding, etc). - // 2. 'Emulate' Firefox/IE's non-Universal detectors (e.g. - // Chinese, Japanese, Russian, Korean and Hebrew) by picking the - // encoding with a highest confidence among the detector-specific - // limited set of candidate encodings. - // Below is a partial implementation of the first part of what's outlined - // above. - const UCharsetMatch** matches = ucsdet_detectAll(detector, &matchesCount, &status); - if (U_FAILURE(status)) { - ucsdet_close(detector); - return false; - } - - const char* encoding = 0; - if (hintEncodingName) { - WTF::TextEncoding hintEncoding(hintEncodingName); - // 10 is the minimum confidence value consistent with the codepoint - // allocation in a given encoding. The size of a chunk passed to - // us varies even for the same html file (apparently depending on - // the network load). When we're given a rather short chunk, we - // don't have a sufficiently reliable signal other than the fact that - // the chunk is consistent with a set of encodings. So, instead of - // setting an arbitrary threshold, we have to scan all the encodings - // consistent with the data. - const int32_t kThresold = 10; - for (int i = 0; i < matchesCount; ++i) { - int32_t confidence = ucsdet_getConfidence(matches[i], &status); - if (U_FAILURE(status)) { - status = U_ZERO_ERROR; - continue; - } - if (confidence < kThresold) - break; - const char* matchEncoding = ucsdet_getName(matches[i], &status); - if (U_FAILURE(status)) { - status = U_ZERO_ERROR; - continue; - } - if (WTF::TextEncoding(matchEncoding) == hintEncoding) { - encoding = hintEncodingName; - break; - } - } - } - // If no match is found so far, just pick the top match. - // This can happen, say, when a parent frame in EUC-JP refers to - // a child frame in Shift_JIS and both frames do NOT specify the encoding - // making us resort to auto-detection (when it IS turned on). - if (!encoding && matchesCount > 0) - encoding = ucsdet_getName(matches[0], &status); - if (U_SUCCESS(status)) { - *detectedEncoding = WTF::TextEncoding(encoding); - ucsdet_close(detector); + int consumedBytes; + bool isReliable; + Encoding encoding = CompactEncDet::DetectEncoding( + data, length, nullptr, nullptr, nullptr, + EncodingNameAliasToEncoding(hintEncodingName), + UNKNOWN_LANGUAGE, + CompactEncDet::WEB_CORPUS, + false, // Include 7-bit encodings + &consumedBytes, + &isReliable); + if (encoding != UNKNOWN_ENCODING) { + *detectedEncoding = WTF::TextEncoding(MimeEncodingName(encoding)); return true; } - ucsdet_close(detector); return false; }
diff --git a/third_party/WebKit/Source/platform/text/android/HyphenationAndroid.cpp b/third_party/WebKit/Source/platform/text/android/HyphenationAndroid.cpp deleted file mode 100644 index ca2b39fe..0000000 --- a/third_party/WebKit/Source/platform/text/android/HyphenationAndroid.cpp +++ /dev/null
@@ -1,14 +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 "platform/text/Hyphenation.h" - -namespace blink { - -PassRefPtr<Hyphenation> Hyphenation::platformGetHyphenation(const AtomicString&) -{ - return nullptr; -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/platform/text/hyphenation/HyphenationMinikin.cpp b/third_party/WebKit/Source/platform/text/hyphenation/HyphenationMinikin.cpp new file mode 100644 index 0000000..01af49b0 --- /dev/null +++ b/third_party/WebKit/Source/platform/text/hyphenation/HyphenationMinikin.cpp
@@ -0,0 +1,93 @@ +// 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 "platform/text/Hyphenation.h" + +#include "base/files/file.h" +#include "base/files/memory_mapped_file.h" +#include "base/metrics/histogram.h" +#include "base/timer/elapsed_timer.h" +#include "mojo/public/cpp/system/platform_handle.h" +#include "public/platform/Platform.h" +#include "public/platform/ServiceRegistry.h" +#include "public/platform/modules/hyphenation/hyphenation.mojom-blink.h" + +namespace blink { + +class HyphenationMinikin : public Hyphenation { +public: + bool openDictionary(const AtomicString& locale); + + size_t lastHyphenLocation(const StringView& text, size_t beforeIndex) const override; + +private: + static base::PlatformFile openDictionaryFile(const AtomicString& locale); + + base::MemoryMappedFile m_file; +}; + +static mojom::blink::HyphenationPtr connectToRemoteService() +{ + mojom::blink::HyphenationPtr service; + Platform::current()->serviceRegistry()->connectToRemoteService( + mojo::GetProxy(&service)); + return service; +} + +static const mojom::blink::HyphenationPtr& getService() +{ + DEFINE_STATIC_LOCAL(mojom::blink::HyphenationPtr, service, + (connectToRemoteService())); + return service; +} + +base::PlatformFile HyphenationMinikin::openDictionaryFile(const AtomicString& locale) +{ + const mojom::blink::HyphenationPtr& service = getService(); + mojo::ScopedHandle handle; + base::ElapsedTimer timer; + service->OpenDictionary(locale, &handle); + UMA_HISTOGRAM_TIMES("Hyphenation.Open", timer.Elapsed()); + if (!handle.is_valid()) + return base::kInvalidPlatformFile; + + base::PlatformFile file; + MojoResult result = mojo::UnwrapPlatformFile(std::move(handle), &file); + if (result != MOJO_RESULT_OK) { + DLOG(ERROR) << "UnwrapPlatformFile failed"; + return base::kInvalidPlatformFile; + } + return file; +} + +bool HyphenationMinikin::openDictionary(const AtomicString& locale) +{ + base::PlatformFile file = openDictionaryFile(locale); + if (file == base::kInvalidPlatformFile) + return false; + if (!m_file.Initialize(base::File(file))) { + DLOG(ERROR) << "mmap failed"; + return false; + } + + // TODO(kojii): Create dictionary from m_file when Minikin is ready. + + return true; +} + +size_t HyphenationMinikin::lastHyphenLocation(const StringView& text, size_t beforeIndex) const +{ + // TODO(kojii): Call minikin using the dictionary when Minikin is ready. + return 0; +} + +PassRefPtr<Hyphenation> Hyphenation::platformGetHyphenation(const AtomicString& locale) +{ + RefPtr<HyphenationMinikin> hyphenation(adoptRef(new HyphenationMinikin)); + if (!hyphenation->openDictionary(locale)) + return nullptr; + return hyphenation.release(); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.cpp b/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.cpp index 6594dbe..c985e9d 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/InjectedScript.cpp
@@ -51,7 +51,6 @@ using blink::protocol::Array; using blink::protocol::Debugger::CallFrame; -using blink::protocol::Debugger::FunctionDetails; using blink::protocol::Runtime::PropertyDescriptor; using blink::protocol::Runtime::InternalPropertyDescriptor; using blink::protocol::Runtime::RemoteObject; @@ -400,7 +399,7 @@ { DCHECK(!m_ignoreExceptionsAndMuteConsole); m_ignoreExceptionsAndMuteConsole = true; - m_debugger->muteConsole(); + m_debugger->client()->muteWarningsAndDeprecations(); m_previousPauseOnExceptionsState = setPauseOnExceptionsState(V8DebuggerImpl::DontPauseOnExceptions); } @@ -434,7 +433,7 @@ { if (m_ignoreExceptionsAndMuteConsole) { setPauseOnExceptionsState(m_previousPauseOnExceptionsState); - m_debugger->unmuteConsole(); + m_debugger->client()->unmuteWarningsAndDeprecations(); } if (m_userGesture) m_debugger->client()->endUserGesture();
diff --git a/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js b/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js index a310ea8..d2b3b27 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js +++ b/third_party/WebKit/Source/platform/v8_inspector/InjectedScriptSource.js
@@ -199,6 +199,20 @@ __proto__: null } +/** + * @type {!Map<string, string>} + * @const + */ +InjectedScript.closureTypes = new Map([ + ["local", "Local"], + ["closure", "Closure"], + ["catch", "Catch"], + ["block", "Block"], + ["script", "Script"], + ["with", "With Block"], + ["global", "Global"] +]); + InjectedScript.prototype = { /** * @param {*} object @@ -324,10 +338,20 @@ */ getProperties: function(object, objectGroupName, ownProperties, accessorPropertiesOnly, generatePreview) { + var subtype = this._subtype(object); + if (subtype === "internal#scope") { + // Internally, scope contains object with scope variables and additional information like type, + // we use additional information for preview and would like to report variables as scope + // properties. + object = object.object; + } + var descriptors = []; var iter = this._propertyDescriptors(object, ownProperties, accessorPropertiesOnly, undefined); // Go over properties, wrap object values. for (var descriptor of iter) { + if (subtype === "internal#scopeList" && descriptor.name === "length") + continue; if ("get" in descriptor) descriptor.get = this._wrapObject(descriptor.get, objectGroupName); if ("set" in descriptor) @@ -627,6 +651,12 @@ return this._describeIncludingPrimitives(obj.value); } + if (subtype === "internal#scopeList") + return "Scopes[" + obj.length + "]"; + + if (subtype === "internal#scope") + return (InjectedScript.closureTypes.get(obj.type) || "Unknown") + (obj.name ? " (" + obj.name + ")" : ""); + return className; },
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8Console.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8Console.cpp index 7cf80d6..b452fa9 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8Console.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8Console.cpp
@@ -76,7 +76,7 @@ return m_debuggerClient; } - void reportMessageToConsole(v8::Local<v8::Context> context, MessageType type, MessageLevel level, const String16& message, const v8::FunctionCallbackInfo<v8::Value>* arguments, unsigned skipArgumentCount) + void reportMessageToConsole(v8::Local<v8::Context> context, ConsoleAPIType type, MessageLevel level, const String16& message, const v8::FunctionCallbackInfo<v8::Value>* arguments, unsigned skipArgumentCount) { InspectedContext* inspectedContext = ensureInspectedContext(); if (!inspectedContext) @@ -95,14 +95,14 @@ debugger->ensureConsoleMessageStorage(inspectedContext->contextGroupId())->addMessage(std::move(consoleMessage)); } - void addMessage(MessageType type, MessageLevel level, String16 emptyText, int skipArgumentCount) + void addMessage(ConsoleAPIType type, MessageLevel level, String16 emptyText, int skipArgumentCount) { if (emptyText.isEmpty() && !m_info.Length()) return; reportMessageToConsole(m_context, type, level, m_info.Length() <= skipArgumentCount ? emptyText : String16(), &m_info, skipArgumentCount); } - void addMessage(MessageType type, MessageLevel level, const String16& message) + void addMessage(ConsoleAPIType type, MessageLevel level, const String16& message) { reportMessageToConsole(m_context, type, level, message, nullptr, 0 /* skipArgumentsCount */); } @@ -111,7 +111,7 @@ { if (checkAndSetPrivateFlagOnConsole(id, false)) return; - reportMessageToConsole(m_context, LogMessageType, WarningMessageLevel, message, nullptr, 0 /* skipArgumentsCount */); + reportMessageToConsole(m_context, ConsoleAPIType::kLog, WarningMessageLevel, message, nullptr, 0 /* skipArgumentsCount */); } bool firstArgToBoolean(bool defaultValue) @@ -282,67 +282,67 @@ void V8Console::debugCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ConsoleHelper(info).addMessage(LogMessageType, DebugMessageLevel, String16(), 0); + ConsoleHelper(info).addMessage(ConsoleAPIType::kLog, DebugMessageLevel, String16(), 0); } void V8Console::errorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ConsoleHelper(info).addMessage(LogMessageType, ErrorMessageLevel, String16(), 0); + ConsoleHelper(info).addMessage(ConsoleAPIType::kLog, ErrorMessageLevel, String16(), 0); } void V8Console::infoCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ConsoleHelper(info).addMessage(LogMessageType, InfoMessageLevel, String16(), 0); + ConsoleHelper(info).addMessage(ConsoleAPIType::kLog, InfoMessageLevel, String16(), 0); } void V8Console::logCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ConsoleHelper(info).addMessage(LogMessageType, LogMessageLevel, String16(), 0); + ConsoleHelper(info).addMessage(ConsoleAPIType::kLog, LogMessageLevel, String16(), 0); } void V8Console::warnCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ConsoleHelper(info).addMessage(LogMessageType, WarningMessageLevel, String16(), 0); + ConsoleHelper(info).addMessage(ConsoleAPIType::kLog, WarningMessageLevel, String16(), 0); } void V8Console::dirCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ConsoleHelper(info).addMessage(DirMessageType, LogMessageLevel, String16(), 0); + ConsoleHelper(info).addMessage(ConsoleAPIType::kDir, LogMessageLevel, String16(), 0); } void V8Console::dirxmlCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ConsoleHelper(info).addMessage(DirXMLMessageType, LogMessageLevel, String16(), 0); + ConsoleHelper(info).addMessage(ConsoleAPIType::kDirXML, LogMessageLevel, String16(), 0); } void V8Console::tableCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ConsoleHelper(info).addMessage(TableMessageType, LogMessageLevel, String16(), 0); + ConsoleHelper(info).addMessage(ConsoleAPIType::kTable, LogMessageLevel, String16(), 0); } void V8Console::traceCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ConsoleHelper(info).addMessage(TraceMessageType, LogMessageLevel, String16("console.trace"), 0); + ConsoleHelper(info).addMessage(ConsoleAPIType::kTrace, LogMessageLevel, String16("console.trace"), 0); } void V8Console::groupCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ConsoleHelper(info).addMessage(StartGroupMessageType, LogMessageLevel, String16("console.group"), 0); + ConsoleHelper(info).addMessage(ConsoleAPIType::kStartGroup, LogMessageLevel, String16("console.group"), 0); } void V8Console::groupCollapsedCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ConsoleHelper(info).addMessage(StartGroupCollapsedMessageType, LogMessageLevel, String16("console.groupCollapsed"), 0); + ConsoleHelper(info).addMessage(ConsoleAPIType::kStartGroupCollapsed, LogMessageLevel, String16("console.groupCollapsed"), 0); } void V8Console::groupEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ConsoleHelper(info).addMessage(EndGroupMessageType, LogMessageLevel, String16("console.groupEnd"), 0); + ConsoleHelper(info).addMessage(ConsoleAPIType::kEndGroup, LogMessageLevel, String16("console.groupEnd"), 0); } void V8Console::clearCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { - ConsoleHelper(info).addMessage(ClearMessageType, LogMessageLevel, String16("console.clear"), 0); + ConsoleHelper(info).addMessage(ConsoleAPIType::kClear, LogMessageLevel, String16("console.clear"), 0); } void V8Console::countCallback(const v8::FunctionCallbackInfo<v8::Value>& info) @@ -364,7 +364,7 @@ return; int64_t count = helper.getIntFromMap(countMap, identifier, 0) + 1; helper.setIntOnMap(countMap, identifier, count); - helper.addMessage(CountMessageType, DebugMessageLevel, title + ": " + String16::number(count)); + helper.addMessage(ConsoleAPIType::kCount, DebugMessageLevel, title + ": " + String16::number(count)); } void V8Console::assertCallback(const v8::FunctionCallbackInfo<v8::Value>& info) @@ -372,7 +372,7 @@ ConsoleHelper helper(info); if (helper.firstArgToBoolean(false)) return; - helper.addMessage(AssertMessageType, ErrorMessageLevel, String16("console.assert"), 1); + helper.addMessage(ConsoleAPIType::kAssert, ErrorMessageLevel, String16("console.assert"), 1); if (V8DebuggerAgentImpl* debuggerAgent = helper.debuggerAgent()) debuggerAgent->breakProgramOnException(protocol::Debugger::Paused::ReasonEnum::Assert, nullptr); } @@ -427,7 +427,7 @@ return; double elapsed = client->currentTimeMS() - helper.getDoubleFromMap(timeMap, protocolTitle, 0.0); String16 message = protocolTitle + ": " + String16::fromDoubleFixedPrecision(elapsed, 3) + "ms"; - helper.addMessage(TimeEndMessageType, DebugMessageLevel, message); + helper.addMessage(ConsoleAPIType::kTimeEnd, DebugMessageLevel, message); } }
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleAgentImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleAgentImpl.cpp index 55eff2c4..cce207b 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleAgentImpl.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleAgentImpl.cpp
@@ -35,7 +35,6 @@ m_enabled = true; m_session->debugger()->enableStackCapturingIfNeeded(); reportAllMessages(); - m_session->client()->consoleEnabled(); } void V8ConsoleAgentImpl::disable(ErrorString* errorString)
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp index d59b983a..fb6bc1b7 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.cpp
@@ -30,26 +30,27 @@ case SecurityMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Security; case OtherMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Other; case DeprecationMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Deprecation; + case WorkerMessageSource: return protocol::Console::ConsoleMessage::SourceEnum::Worker; } return protocol::Console::ConsoleMessage::SourceEnum::Other; } -String16 messageTypeValue(MessageType type) +String16 consoleAPITypeValue(ConsoleAPIType type) { switch (type) { - case LogMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Log; - case ClearMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Clear; - case DirMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Dir; - case DirXMLMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Dirxml; - case TableMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Table; - case TraceMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Trace; - case StartGroupMessageType: return protocol::Console::ConsoleMessage::TypeEnum::StartGroup; - case StartGroupCollapsedMessageType: return protocol::Console::ConsoleMessage::TypeEnum::StartGroupCollapsed; - case EndGroupMessageType: return protocol::Console::ConsoleMessage::TypeEnum::EndGroup; - case AssertMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Assert; - case TimeEndMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Log; - case CountMessageType: return protocol::Console::ConsoleMessage::TypeEnum::Log; + case ConsoleAPIType::kLog: return protocol::Console::ConsoleMessage::TypeEnum::Log; + case ConsoleAPIType::kClear: return protocol::Console::ConsoleMessage::TypeEnum::Clear; + case ConsoleAPIType::kDir: return protocol::Console::ConsoleMessage::TypeEnum::Dir; + case ConsoleAPIType::kDirXML: return protocol::Console::ConsoleMessage::TypeEnum::Dirxml; + case ConsoleAPIType::kTable: return protocol::Console::ConsoleMessage::TypeEnum::Table; + case ConsoleAPIType::kTrace: return protocol::Console::ConsoleMessage::TypeEnum::Trace; + case ConsoleAPIType::kStartGroup: return protocol::Console::ConsoleMessage::TypeEnum::StartGroup; + case ConsoleAPIType::kStartGroupCollapsed: return protocol::Console::ConsoleMessage::TypeEnum::StartGroupCollapsed; + case ConsoleAPIType::kEndGroup: return protocol::Console::ConsoleMessage::TypeEnum::EndGroup; + case ConsoleAPIType::kAssert: return protocol::Console::ConsoleMessage::TypeEnum::Assert; + case ConsoleAPIType::kTimeEnd: return protocol::Console::ConsoleMessage::TypeEnum::Log; + case ConsoleAPIType::kCount: return protocol::Console::ConsoleMessage::TypeEnum::Log; } return protocol::Console::ConsoleMessage::TypeEnum::Log; } @@ -199,30 +200,17 @@ } // namespace -V8ConsoleMessage::V8ConsoleMessage( - double timestamp, - MessageSource source, - MessageLevel level, - const String16& message, - const String16& url, - unsigned lineNumber, - unsigned columnNumber, - std::unique_ptr<V8StackTrace> stackTrace, - int scriptId, - const String16& requestIdentifier) - : m_origin(V8MessageOrigin::kConsole) +V8ConsoleMessage::V8ConsoleMessage(V8MessageOrigin origin, double timestamp, MessageSource source, MessageLevel level, const String16& message) + : m_origin(origin) , m_timestamp(timestamp) , m_source(source) , m_level(level) , m_message(message) - , m_url(url) - , m_lineNumber(lineNumber) - , m_columnNumber(columnNumber) - , m_stackTrace(std::move(stackTrace)) - , m_scriptId(scriptId) - , m_requestIdentifier(requestIdentifier) + , m_lineNumber(0) + , m_columnNumber(0) + , m_scriptId(0) , m_contextId(0) - , m_type(LogMessageType) + , m_type(ConsoleAPIType::kLog) , m_exceptionId(0) , m_revokedExceptionId(0) { @@ -232,6 +220,15 @@ { } +void V8ConsoleMessage::setLocation(const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace> stackTrace, int scriptId) +{ + m_url = url; + m_lineNumber = lineNumber; + m_columnNumber = columnNumber; + m_stackTrace = std::move(stackTrace); + m_scriptId = scriptId; +} + void V8ConsoleMessage::reportToFrontend(protocol::Console::Frontend* frontend, V8InspectorSessionImpl* session, bool generatePreview) const { DCHECK_EQ(V8MessageOrigin::kConsole, m_origin); @@ -242,7 +239,7 @@ .setText(m_message) .setTimestamp(m_timestamp / 1000) // TODO(dgozman): migrate this to milliseconds. .build(); - result->setType(messageTypeValue(m_type)); + result->setType(consoleAPITypeValue(m_type)); result->setLine(static_cast<int>(m_lineNumber)); result->setColumn(static_cast<int>(m_columnNumber)); if (m_scriptId) @@ -257,6 +254,8 @@ result->setParameters(std::move(args)); if (m_stackTrace) result->setStack(m_stackTrace->buildInspectorObject()); + if (m_source == WorkerMessageSource && !m_workerId.isEmpty()) + result->setWorkerId(m_workerId); frontend->messageAdded(std::move(result)); } @@ -273,7 +272,7 @@ v8::Local<v8::Context> context = inspectedContext->context(); std::unique_ptr<protocol::Array<protocol::Runtime::RemoteObject>> args = protocol::Array<protocol::Runtime::RemoteObject>::create(); - if (m_type == TableMessageType && generatePreview) { + if (m_type == ConsoleAPIType::kTable && generatePreview) { v8::Local<v8::Value> table = m_arguments[0]->Get(isolate); v8::Local<v8::Value> columns = m_arguments.size() > 1 ? m_arguments[1]->Get(isolate) : v8::Local<v8::Value>(); std::unique_ptr<protocol::Runtime::RemoteObject> wrapped = session->wrapTable(context, table, columns); @@ -349,13 +348,13 @@ return m_arguments.size(); } -MessageType V8ConsoleMessage::type() const +ConsoleAPIType V8ConsoleMessage::type() const { return m_type; } // static -std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForConsoleAPI(double timestamp, MessageType type, MessageLevel level, const String16& messageText, std::vector<v8::Local<v8::Value>>* arguments, std::unique_ptr<V8StackTrace> stackTrace, InspectedContext* context) +std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForConsoleAPI(double timestamp, ConsoleAPIType type, MessageLevel level, const String16& messageText, std::vector<v8::Local<v8::Value>>* arguments, std::unique_ptr<V8StackTrace> stackTrace, InspectedContext* context) { String16 url; unsigned lineNumber = 0; @@ -376,7 +375,8 @@ actualMessage = V8ValueStringBuilder::toString(messageArguments.at(0)->Get(context->isolate()), context->isolate()); } - std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage(timestamp, ConsoleAPIMessageSource, level, actualMessage, url, lineNumber, columnNumber, std::move(stackTrace), 0 /* scriptId */, String16() /* requestIdentifier */)); + std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage(V8MessageOrigin::kConsole, timestamp, ConsoleAPIMessageSource, level, actualMessage)); + message->setLocation(url, lineNumber, columnNumber, std::move(stackTrace), 0); message->m_type = type; if (messageArguments.size()) { message->m_contextId = context->contextId(); @@ -390,9 +390,9 @@ // static std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForException(double timestamp, const String16& messageText, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace> stackTrace, int scriptId, v8::Isolate* isolate, int contextId, v8::Local<v8::Value> exception, unsigned exceptionId) { - std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage(timestamp, JSMessageSource, ErrorMessageLevel, messageText, url, lineNumber, columnNumber, std::move(stackTrace), scriptId, String16() /* requestIdentifier */)); + std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage(V8MessageOrigin::kException, timestamp, JSMessageSource, ErrorMessageLevel, messageText)); + message->setLocation(url, lineNumber, columnNumber, std::move(stackTrace), scriptId); message->m_exceptionId = exceptionId; - message->m_origin = V8MessageOrigin::kException; if (contextId && !exception.IsEmpty()) { message->m_contextId = contextId; message->m_arguments.push_back(wrapUnique(new v8::Global<v8::Value>(isolate, exception))); @@ -403,12 +403,21 @@ // static std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createForRevokedException(double timestamp, const String16& messageText, unsigned revokedExceptionId) { - std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage(timestamp, JSMessageSource, ErrorMessageLevel, messageText, String16(), 0, 0, nullptr, 0, String16())); - message->m_origin = V8MessageOrigin::kRevokedException; + std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage(V8MessageOrigin::kRevokedException, timestamp, JSMessageSource, ErrorMessageLevel, messageText)); message->m_revokedExceptionId = revokedExceptionId; return message; } +// static +std::unique_ptr<V8ConsoleMessage> V8ConsoleMessage::createExternal(double timestamp, MessageSource source, MessageLevel level, const String16& messageText, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace> stackTrace, int scriptId, const String16& requestIdentifier, const String16& workerId) +{ + std::unique_ptr<V8ConsoleMessage> message = wrapUnique(new V8ConsoleMessage(V8MessageOrigin::kConsole, timestamp, source, level, messageText)); + message->setLocation(url, lineNumber, columnNumber, std::move(stackTrace), scriptId); + message->m_requestIdentifier = requestIdentifier; + message->m_workerId = workerId; + return message; +} + void V8ConsoleMessage::contextDestroyed(int contextId) { if (contextId != m_contextId) @@ -436,7 +445,7 @@ void V8ConsoleMessageStorage::addMessage(std::unique_ptr<V8ConsoleMessage> message) { - if (message->type() == ClearMessageType) + if (message->type() == ConsoleAPIType::kClear) clear(); V8InspectorSessionImpl* session = m_debugger->sessionForContextGroup(m_contextGroupId);
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.h b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.h index 9cdf132..d6ada615 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.h +++ b/third_party/WebKit/Source/platform/v8_inspector/V8ConsoleMessage.h
@@ -23,24 +23,15 @@ enum class V8MessageOrigin { kConsole, kException, kRevokedException }; +enum class ConsoleAPIType { kLog, kDir, kDirXML, kTable, kTrace, kStartGroup, kStartGroupCollapsed, kEndGroup, kClear, kAssert, kTimeEnd, kCount }; + class V8ConsoleMessage { public: - V8ConsoleMessage( - double timestamp, - MessageSource, - MessageLevel, - const String16& message, - const String16& url, - unsigned lineNumber, - unsigned columnNumber, - std::unique_ptr<V8StackTrace>, - int scriptId, - const String16& requestIdentifier); ~V8ConsoleMessage(); static std::unique_ptr<V8ConsoleMessage> createForConsoleAPI( double timestamp, - MessageType, + ConsoleAPIType, MessageLevel, const String16& message, std::vector<v8::Local<v8::Value>>* arguments, @@ -65,17 +56,33 @@ const String16& message, unsigned revokedExceptionId); + static std::unique_ptr<V8ConsoleMessage> createExternal( + double timestamp, + MessageSource, + MessageLevel, + const String16& message, + const String16& url, + unsigned lineNumber, + unsigned columnNumber, + std::unique_ptr<V8StackTrace>, + int scriptId, + const String16& requestIdentifier, + const String16& workerId); + V8MessageOrigin origin() const; void reportToFrontend(protocol::Console::Frontend*, V8InspectorSessionImpl*, bool generatePreview) const; void reportToFrontend(protocol::Runtime::Frontend*, V8InspectorSessionImpl*, bool generatePreview) const; unsigned argumentCount() const; - MessageType type() const; + ConsoleAPIType type() const; void contextDestroyed(int contextId); private: + V8ConsoleMessage(V8MessageOrigin, double timestamp, MessageSource, MessageLevel, const String16& message); + using Arguments = std::vector<std::unique_ptr<v8::Global<v8::Value>>>; std::unique_ptr<protocol::Array<protocol::Runtime::RemoteObject>> wrapArguments(V8InspectorSessionImpl*, bool generatePreview) const; std::unique_ptr<protocol::Runtime::RemoteObject> wrapException(V8InspectorSessionImpl*, bool generatePreview) const; + void setLocation(const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId); V8MessageOrigin m_origin; double m_timestamp; @@ -88,8 +95,9 @@ std::unique_ptr<V8StackTrace> m_stackTrace; int m_scriptId; String16 m_requestIdentifier; + String16 m_workerId; int m_contextId; - MessageType m_type; + ConsoleAPIType m_type; unsigned m_exceptionId; unsigned m_revokedExceptionId; Arguments m_arguments;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp index 1bc5962..6432807 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp
@@ -28,7 +28,6 @@ using blink::protocol::Debugger::BreakpointId; using blink::protocol::Debugger::CallFrame; using blink::protocol::Runtime::ExceptionDetails; -using blink::protocol::Debugger::FunctionDetails; using blink::protocol::Runtime::ScriptId; using blink::protocol::Runtime::StackTrace; using blink::protocol::Runtime::RemoteObject; @@ -595,43 +594,6 @@ *scriptSource = toProtocolString(it->second->source(m_isolate)); } -void V8DebuggerAgentImpl::getFunctionDetails(ErrorString* errorString, const String16& functionId, std::unique_ptr<FunctionDetails>* details) -{ - if (!checkEnabled(errorString)) - return; - InjectedScript::ObjectScope scope(errorString, m_debugger, m_session->contextGroupId(), functionId); - if (!scope.initialize()) - return; - if (!scope.object()->IsFunction()) { - *errorString = "Value with given id is not a function"; - return; - } - v8::Local<v8::Function> function = scope.object().As<v8::Function>(); - - v8::Local<v8::Value> scopesValue; - v8::Local<v8::Array> scopes; - if (m_debugger->functionScopes(function).ToLocal(&scopesValue) && scopesValue->IsArray()) { - scopes = scopesValue.As<v8::Array>(); - if (!scope.injectedScript()->wrapPropertyInArray(errorString, scopes, toV8StringInternalized(m_isolate, "object"), scope.objectGroupName())) - return; - } - - std::unique_ptr<FunctionDetails> functionDetails = FunctionDetails::create() - .setLocation(buildProtocolLocation(String16::number(function->ScriptId()), function->GetScriptLineNumber(), function->GetScriptColumnNumber())) - .setFunctionName(toProtocolStringWithTypeCheck(function->GetDebugName())) - .setIsGenerator(function->IsGeneratorFunction()).build(); - - if (!scopes.IsEmpty()) { - protocol::ErrorSupport errorSupport; - std::unique_ptr<protocol::Array<protocol::Debugger::Scope>> scopeChain = protocol::Array<protocol::Debugger::Scope>::parse(toProtocolValue(scope.context(), scopes).get(), &errorSupport); - if (hasInternalError(errorString, errorSupport.hasErrors())) - return; - functionDetails->setScopeChain(std::move(scopeChain)); - } - - *details = std::move(functionDetails); -} - void V8DebuggerAgentImpl::schedulePauseOnNextStatement(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data) { if (!enabled() || m_scheduledDebuggerStep == StepInto || m_javaScriptPauseScheduled || debugger().isPaused() || !debugger().breakpointsActivated()) @@ -842,10 +804,13 @@ } String16Builder patternBuilder; - patternBuilder.append("("); - for (size_t i = 0; i < patterns->length() - 1; ++i) - patternBuilder.append(patterns->get(i) + "|"); - patternBuilder.append(patterns->get(patterns->length() - 1) + ")"); + patternBuilder.append('('); + for (size_t i = 0; i < patterns->length() - 1; ++i) { + patternBuilder.append(patterns->get(i)); + patternBuilder.append("|"); + } + patternBuilder.append(patterns->get(patterns->length() - 1)); + patternBuilder.append(')'); String16 pattern = patternBuilder.toString(); if (!setBlackboxPattern(errorString, pattern)) return;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.h b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.h index fdae2de..f1960cc 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.h +++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.h
@@ -92,9 +92,6 @@ std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>* newCallFrames, Maybe<protocol::Runtime::StackTrace>* asyncStackTrace) override; void getScriptSource(ErrorString*, const String16& scriptId, String16* scriptSource) override; - void getFunctionDetails(ErrorString*, - const String16& functionId, - std::unique_ptr<protocol::Debugger::FunctionDetails>*) override; void pause(ErrorString*) override; void resume(ErrorString*) override; void stepOver(ErrorString*) override;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp index a0b0639..57e91e8 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.cpp
@@ -41,6 +41,7 @@ #include "platform/v8_inspector/V8DebuggerAgentImpl.h" #include "platform/v8_inspector/V8InjectedScriptHost.h" #include "platform/v8_inspector/V8InspectorSessionImpl.h" +#include "platform/v8_inspector/V8InternalValueType.h" #include "platform/v8_inspector/V8RuntimeAgentImpl.h" #include "platform/v8_inspector/V8StackTraceImpl.h" #include "platform/v8_inspector/V8StringUtil.h" @@ -84,7 +85,6 @@ : m_isolate(isolate) , m_client(client) , m_capturingStackTracesCount(0) - , m_muteConsoleCount(0) , m_lastExceptionId(0) , m_enabledAgentsCount(0) , m_breakpointsActivated(true) @@ -651,7 +651,18 @@ return v8::Local<v8::Value>::New(m_isolate, v8::Undefined(m_isolate)); } v8::Local<v8::Value> argv[] = { function }; - return callDebuggerMethod("getFunctionScopes", 1, argv); + v8::Local<v8::Value> scopesValue; + if (!callDebuggerMethod("getFunctionScopes", 1, argv).ToLocal(&scopesValue) || !scopesValue->IsArray()) + return v8::MaybeLocal<v8::Value>(); + v8::Local<v8::Array> scopes = scopesValue.As<v8::Array>(); + v8::Local<v8::Context> context = m_debuggerContext.Get(m_isolate); + if (!markAsInternal(context, scopes, V8InternalValueType::kScopeList)) + return v8::MaybeLocal<v8::Value>(); + if (!markArrayEntriesAsInternal(context, scopes, V8InternalValueType::kScope)) + return v8::MaybeLocal<v8::Value>(); + if (!scopes->SetPrototype(context, v8::Null(m_isolate)).FromMaybe(false)) + return v8::Undefined(m_isolate); + return scopes; } v8::MaybeLocal<v8::Array> V8DebuggerImpl::internalProperties(v8::Local<v8::Context> context, v8::Local<v8::Value> value) @@ -659,6 +670,18 @@ v8::Local<v8::Array> properties; if (!v8::Debug::GetInternalProperties(m_isolate, value).ToLocal(&properties)) return v8::MaybeLocal<v8::Array>(); + if (value->IsFunction()) { + v8::Local<v8::Function> function = value.As<v8::Function>(); + v8::Local<v8::Value> location = functionLocation(context, function); + if (location->IsObject()) { + properties->Set(properties->Length(), v8InternalizedString("[[FunctionLocation]]")); + properties->Set(properties->Length(), location); + } + if (function->IsGeneratorFunction()) { + properties->Set(properties->Length(), v8InternalizedString("[[IsGenerator]]")); + properties->Set(properties->Length(), v8::True(m_isolate)); + } + } if (!enabled()) return properties; if (value->IsMap() || value->IsWeakMap() || value->IsSet() || value->IsWeakSet() || value->IsSetIterator() || value->IsMapIterator()) { @@ -675,6 +698,15 @@ properties->Set(properties->Length(), location); } } + if (value->IsFunction()) { + v8::Local<v8::Function> function = value.As<v8::Function>(); + v8::Local<v8::Value> boundFunction = function->GetBoundFunction(); + v8::Local<v8::Value> scopes; + if (boundFunction->IsUndefined() && functionScopes(function).ToLocal(&scopes)) { + properties->Set(properties->Length(), v8InternalizedString("[[Scopes]]")); + properties->Set(properties->Length(), scopes); + } + } return properties; } @@ -689,13 +721,8 @@ if (!entriesValue->IsArray()) return v8::Undefined(m_isolate); v8::Local<v8::Array> entries = entriesValue.As<v8::Array>(); - for (size_t i = 0; i < entries->Length(); ++i) { - v8::Local<v8::Value> entry; - if (!entries->Get(context, i).ToLocal(&entry) || !entry->IsObject()) - continue; - if (!entry.As<v8::Object>()->SetPrivate(context, V8InjectedScriptHost::internalEntryPrivate(m_isolate), v8::True(m_isolate)).FromMaybe(false)) - continue; - } + if (!markArrayEntriesAsInternal(context, entries, V8InternalValueType::kEntry)) + return v8::Undefined(m_isolate); if (!entries->SetPrototype(context, v8::Null(m_isolate)).FromMaybe(false)) return v8::Undefined(m_isolate); return entries; @@ -712,7 +739,28 @@ if (!location->IsObject()) return v8::Null(m_isolate); v8::Local<v8::Context> context = m_debuggerContext.Get(m_isolate); - if (!location.As<v8::Object>()->SetPrivate(context, V8InjectedScriptHost::internalLocationPrivate(m_isolate), v8::True(m_isolate)).FromMaybe(false)) + if (!markAsInternal(context, v8::Local<v8::Object>::Cast(location), V8InternalValueType::kLocation)) + return v8::Null(m_isolate); + return location; +} + +v8::Local<v8::Value> V8DebuggerImpl::functionLocation(v8::Local<v8::Context> context, v8::Local<v8::Function> function) +{ + int scriptId = function->ScriptId(); + if (scriptId == v8::UnboundScript::kNoScriptId) + return v8::Null(m_isolate); + int lineNumber = function->GetScriptLineNumber(); + int columnNumber = function->GetScriptColumnNumber(); + if (lineNumber == v8::Function::kLineOffsetNotFound || columnNumber == v8::Function::kLineOffsetNotFound) + return v8::Null(m_isolate); + v8::Local<v8::Object> location = v8::Object::New(m_isolate); + if (!location->Set(context, v8InternalizedString("scriptId"), toV8String(m_isolate, String16::number(scriptId))).FromMaybe(false)) + return v8::Null(m_isolate); + if (!location->Set(context, v8InternalizedString("lineNumber"), v8::Integer::New(m_isolate, lineNumber)).FromMaybe(false)) + return v8::Null(m_isolate); + if (!location->Set(context, v8InternalizedString("columnNumber"), v8::Integer::New(m_isolate, columnNumber)).FromMaybe(false)) + return v8::Null(m_isolate); + if (!markAsInternal(context, location, V8InternalValueType::kLocation)) return v8::Null(m_isolate); return location; } @@ -1007,12 +1055,9 @@ m_isolate->GetCpuProfiler()->SetIdle(false); } -bool V8DebuggerImpl::addConsoleMessage(int contextGroupId, MessageSource source, MessageLevel level, const String16& message, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace> stackTrace, int scriptId, const String16& requestIdentifier) +void V8DebuggerImpl::addConsoleMessage(int contextGroupId, MessageSource source, MessageLevel level, const String16& message, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace> stackTrace, int scriptId, const String16& requestIdentifier, const String16& workerId) { - if (m_muteConsoleCount) - return false; - ensureConsoleMessageStorage(contextGroupId)->addMessage(wrapUnique(new V8ConsoleMessage(m_client->currentTimeMS(), source, level, message, url, lineNumber, columnNumber, std::move(stackTrace), scriptId, requestIdentifier))); - return true; + ensureConsoleMessageStorage(contextGroupId)->addMessage(V8ConsoleMessage::createExternal(m_client->currentTimeMS(), source, level, message, url, lineNumber, columnNumber, std::move(stackTrace), scriptId, requestIdentifier, workerId)); } void V8DebuggerImpl::logToConsole(v8::Local<v8::Context> context, const String16& message, v8::Local<v8::Value> arg1, v8::Local<v8::Value> arg2) @@ -1026,13 +1071,11 @@ arguments.push_back(arg1); if (!arg2.IsEmpty()) arguments.push_back(arg2); - ensureConsoleMessageStorage(contextGroupId)->addMessage(V8ConsoleMessage::createForConsoleAPI(m_client->currentTimeMS(), LogMessageType, LogMessageLevel, message, arguments.size() ? &arguments : nullptr, captureStackTrace(false), inspectedContext)); + ensureConsoleMessageStorage(contextGroupId)->addMessage(V8ConsoleMessage::createForConsoleAPI(m_client->currentTimeMS(), ConsoleAPIType::kLog, LogMessageLevel, message, arguments.size() ? &arguments : nullptr, captureStackTrace(false), inspectedContext)); } void V8DebuggerImpl::exceptionThrown(int contextGroupId, const String16& errorMessage, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace> stackTrace, int scriptId) { - if (m_muteConsoleCount || !contextGroupId) - return; m_client->messageAddedToConsole(contextGroupId, JSMessageSource, ErrorMessageLevel, errorMessage, url, lineNumber, columnNumber, stackTrace.get()); unsigned exceptionId = ++m_lastExceptionId; std::unique_ptr<V8ConsoleMessage> consoleMessage = V8ConsoleMessage::createForException(m_client->currentTimeMS(), errorMessage, url, lineNumber, columnNumber, std::move(stackTrace), scriptId, m_isolate, 0, v8::Local<v8::Value>(), exceptionId); @@ -1041,8 +1084,6 @@ unsigned V8DebuggerImpl::promiseRejected(v8::Local<v8::Context> context, const String16& errorMessage, v8::Local<v8::Value> exception, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace> stackTrace, int scriptId) { - if (m_muteConsoleCount) - return 0; int contextGroupId = getGroupId(context); if (!contextGroupId) return 0; @@ -1063,8 +1104,6 @@ void V8DebuggerImpl::promiseRejectionRevoked(v8::Local<v8::Context> context, unsigned promiseRejectionId) { - if (m_muteConsoleCount) - return; int contextGroupId = getGroupId(context); if (!contextGroupId) return;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.h b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.h index a4596af..c093f5f6 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.h +++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerImpl.h
@@ -98,7 +98,7 @@ void debuggerAgentEnabled(); void debuggerAgentDisabled(); - bool isPaused() override; + bool isPaused(); v8::Local<v8::Context> pausedContext() { return m_pausedContext; } int maxAsyncCallChainDepth() { return m_maxAsyncCallStackDepth; } V8StackTraceImpl* currentAsyncCallChain(); @@ -129,7 +129,7 @@ void didExecuteScript(v8::Local<v8::Context>) override; void idleStarted() override; void idleFinished() override; - bool addConsoleMessage(int contextGroupId, MessageSource, MessageLevel, const String16& message, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId, const String16& requestIdentifier) override; + void addConsoleMessage(int contextGroupId, MessageSource, MessageLevel, const String16& message, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId, const String16& requestIdentifier, const String16& workerId) override; void logToConsole(v8::Local<v8::Context>, const String16& message, v8::Local<v8::Value> arg1, v8::Local<v8::Value> arg2) override; void exceptionThrown(int contextGroupId, const String16& errorMessage, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId) override; unsigned promiseRejected(v8::Local<v8::Context>, const String16& errorMessage, v8::Local<v8::Value> exception, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId) override; @@ -142,8 +142,6 @@ void asyncTaskStarted(void* task) override; void asyncTaskFinished(void* task) override; void allAsyncTasksCanceled() override; - void muteConsole() override { m_muteConsoleCount++; } - void unmuteConsole() override { m_muteConsoleCount--; } using ContextByIdMap = protocol::HashMap<int, std::unique_ptr<InspectedContext>>; void discardInspectedContext(int contextGroupId, int contextId); @@ -177,6 +175,7 @@ v8::Local<v8::Value> collectionEntries(v8::Local<v8::Context>, v8::Local<v8::Object>); v8::Local<v8::Value> generatorObjectLocation(v8::Local<v8::Object>); + v8::Local<v8::Value> functionLocation(v8::Local<v8::Context>, v8::Local<v8::Function>); v8::Isolate* m_isolate; V8DebuggerClient* m_client; @@ -186,7 +185,6 @@ using ConsoleStorageMap = protocol::HashMap<int, std::unique_ptr<V8ConsoleMessageStorage>>; ConsoleStorageMap m_consoleStorageMap; int m_capturingStackTracesCount; - int m_muteConsoleCount; unsigned m_lastExceptionId; int m_enabledAgentsCount; bool m_breakpointsActivated;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp index 6c4111a..151295ac 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8HeapProfilerAgentImpl.cpp
@@ -258,7 +258,7 @@ return; } - *result = m_session->wrapObject(heapObject->CreationContext(), heapObject, objectGroup.fromMaybe("")); + *result = m_session->wrapObject(heapObject->CreationContext(), heapObject, objectGroup.fromMaybe(""), false); if (!result) *error = "Object is not available"; }
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp index 1ef3bbba..cc2c844 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.cpp
@@ -8,6 +8,7 @@ #include "platform/v8_inspector/InjectedScriptNative.h" #include "platform/v8_inspector/V8Compat.h" #include "platform/v8_inspector/V8DebuggerImpl.h" +#include "platform/v8_inspector/V8InternalValueType.h" #include "platform/v8_inspector/V8StringUtil.h" #include "platform/v8_inspector/public/V8DebuggerClient.h" @@ -54,16 +55,6 @@ return injectedScriptHost; } -v8::Local<v8::Private> V8InjectedScriptHost::internalEntryPrivate(v8::Isolate* isolate) -{ - return v8::Private::ForApi(isolate, toV8StringInternalized(isolate, "V8InjectedScriptHost#internalEntry")); -} - -v8::Local<v8::Private> V8InjectedScriptHost::internalLocationPrivate(v8::Isolate* isolate) -{ - return v8::Private::ForApi(isolate, toV8StringInternalized(isolate, "V8InjectedScriptHost#internalLocation")); -} - void V8InjectedScriptHost::internalConstructorNameCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { if (info.Length() < 1 || !info[0]->IsObject()) @@ -100,6 +91,13 @@ v8::Isolate* isolate = info.GetIsolate(); v8::Local<v8::Value> value = info[0]; + if (value->IsObject()) { + v8::Local<v8::Value> internalType = v8InternalValueTypeFrom(isolate->GetCurrentContext(), v8::Local<v8::Object>::Cast(value)); + if (internalType->IsString()) { + info.GetReturnValue().Set(internalType); + return; + } + } if (value->IsArray() || value->IsTypedArray() || value->IsArgumentsObject()) { info.GetReturnValue().Set(toV8StringInternalized(isolate, "array")); return; @@ -136,17 +134,6 @@ info.GetReturnValue().Set(toV8StringInternalized(isolate, "proxy")); return; } - if (value->IsObject()) { - v8::Local<v8::Object> obj = value.As<v8::Object>(); - if (obj->HasPrivate(isolate->GetCurrentContext(), internalEntryPrivate(isolate)).FromMaybe(false)) { - info.GetReturnValue().Set(toV8StringInternalized(isolate, "internal#entry")); - return; - } - if (obj->HasPrivate(isolate->GetCurrentContext(), internalLocationPrivate(isolate)).FromMaybe(false)) { - info.GetReturnValue().Set(toV8StringInternalized(isolate, "internal#location")); - return; - } - } String16 subtype = unwrapDebugger(info)->client()->valueSubtype(value); if (!subtype.isEmpty()) { info.GetReturnValue().Set(toV8String(isolate, subtype)); @@ -194,14 +181,12 @@ V8DebuggerImpl* debugger = unwrapDebugger(info); debugger->client()->muteWarningsAndDeprecations(); - debugger->muteConsole(); v8::MicrotasksScope microtasks(isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Local<v8::Value> result; if (function->Call(context, receiver, argc, argv.get()).ToLocal(&result)) info.GetReturnValue().Set(result); - debugger->unmuteConsole(); debugger->client()->unmuteWarningsAndDeprecations(); }
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.h b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.h index 9a25824..bf49fa71 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.h +++ b/third_party/WebKit/Source/platform/v8_inspector/V8InjectedScriptHost.h
@@ -21,10 +21,6 @@ // We expect that debugger outlives any JS context and thus V8InjectedScriptHost (owned by JS) // is destroyed before debugger. static v8::Local<v8::Object> create(v8::Local<v8::Context>, V8DebuggerImpl*); - - static v8::Local<v8::Private> internalEntryPrivate(v8::Isolate*); - static v8::Local<v8::Private> internalLocationPrivate(v8::Isolate*); - private: static void internalConstructorNameCallback(const v8::FunctionCallbackInfo<v8::Value>&); static void formatAccessorsAsProperties(const v8::FunctionCallbackInfo<v8::Value>&);
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8InspectorSessionImpl.h b/third_party/WebKit/Source/platform/v8_inspector/V8InspectorSessionImpl.h index f031e7f..21753da 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8InspectorSessionImpl.h +++ b/third_party/WebKit/Source/platform/v8_inspector/V8InspectorSessionImpl.h
@@ -61,8 +61,8 @@ void stepOver() override; void releaseObjectGroup(const String16& objectGroup) override; v8::Local<v8::Value> findObject(ErrorString*, const String16& objectId, v8::Local<v8::Context>* = nullptr, String16* groupName = nullptr) override; - std::unique_ptr<protocol::Runtime::RemoteObject> wrapObject(v8::Local<v8::Context>, v8::Local<v8::Value>, const String16& groupName, bool generatePreview = false) override; - std::unique_ptr<protocol::Runtime::RemoteObject> wrapTable(v8::Local<v8::Context>, v8::Local<v8::Value> table, v8::Local<v8::Value> columns) override; + std::unique_ptr<protocol::Runtime::RemoteObject> wrapObject(v8::Local<v8::Context>, v8::Local<v8::Value>, const String16& groupName, bool generatePreview) override; + std::unique_ptr<protocol::Runtime::RemoteObject> wrapTable(v8::Local<v8::Context>, v8::Local<v8::Value> table, v8::Local<v8::Value> columns); V8InspectorSession::Inspectable* inspectedObject(unsigned num); static const unsigned kInspectedObjectBufferSize = 5;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8InternalValueType.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8InternalValueType.cpp new file mode 100644 index 0000000..52e7677 --- /dev/null +++ b/third_party/WebKit/Source/platform/v8_inspector/V8InternalValueType.cpp
@@ -0,0 +1,72 @@ +// 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 "platform/v8_inspector/V8InternalValueType.h" + +#include "platform/inspector_protocol/Platform.h" +#include "platform/v8_inspector/V8StringUtil.h" + +namespace blink { + +namespace { + +v8::Local<v8::Private> internalSubtypePrivate(v8::Isolate* isolate) +{ + return v8::Private::ForApi(isolate, toV8StringInternalized(isolate, "V8InternalType#internalSubtype")); +} + +v8::Local<v8::String> subtypeForInternalType(v8::Isolate* isolate, V8InternalValueType type) +{ + switch (type) { + case V8InternalValueType::kEntry: + return toV8StringInternalized(isolate, "internal#entry"); + case V8InternalValueType::kLocation: + return toV8StringInternalized(isolate, "internal#location"); + case V8InternalValueType::kScope: + return toV8StringInternalized(isolate, "internal#scope"); + case V8InternalValueType::kScopeList: + return toV8StringInternalized(isolate, "internal#scopeList"); + } + NOTREACHED(); + return v8::Local<v8::String>(); +} + +} // namespace + +bool markAsInternal(v8::Local<v8::Context> context, v8::Local<v8::Object> object, V8InternalValueType type) +{ + v8::Isolate* isolate = context->GetIsolate(); + v8::Local<v8::Private> privateValue = internalSubtypePrivate(isolate); + v8::Local<v8::String> subtype = subtypeForInternalType(isolate, type); + return object->SetPrivate(context, privateValue, subtype).FromMaybe(false); +} + +bool markArrayEntriesAsInternal(v8::Local<v8::Context> context, v8::Local<v8::Array> array, V8InternalValueType type) +{ + v8::Isolate* isolate = context->GetIsolate(); + v8::Local<v8::Private> privateValue = internalSubtypePrivate(isolate); + v8::Local<v8::String> subtype = subtypeForInternalType(isolate, type); + for (size_t i = 0; i < array->Length(); ++i) { + v8::Local<v8::Value> entry; + if (!array->Get(context, i).ToLocal(&entry) || !entry->IsObject()) + return false; + if (!entry.As<v8::Object>()->SetPrivate(context, privateValue, subtype).FromMaybe(false)) + return false; + } + return true; +} + +v8::Local<v8::Value> v8InternalValueTypeFrom(v8::Local<v8::Context> context, v8::Local<v8::Object> object) +{ + v8::Isolate* isolate = context->GetIsolate(); + v8::Local<v8::Private> privateValue = internalSubtypePrivate(isolate); + if (!object->HasPrivate(context, privateValue).FromMaybe(false)) + return v8::Null(isolate); + v8::Local<v8::Value> subtypeValue; + if (!object->GetPrivate(context, privateValue).ToLocal(&subtypeValue) || !subtypeValue->IsString()) + return v8::Null(isolate); + return subtypeValue; +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8InternalValueType.h b/third_party/WebKit/Source/platform/v8_inspector/V8InternalValueType.h new file mode 100644 index 0000000..4bb7172 --- /dev/null +++ b/third_party/WebKit/Source/platform/v8_inspector/V8InternalValueType.h
@@ -0,0 +1,21 @@ +// 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 V8InternalValueType_h +#define V8InternalValueType_h + +#include <v8.h> + +namespace blink { + +enum class V8InternalValueType { kEntry, kLocation, kScope, kScopeList }; + +bool markAsInternal(v8::Local<v8::Context>, v8::Local<v8::Object>, V8InternalValueType); +bool markArrayEntriesAsInternal(v8::Local<v8::Context>, v8::Local<v8::Array>, V8InternalValueType); +v8::Local<v8::Value> v8InternalValueTypeFrom(v8::Local<v8::Context>, v8::Local<v8::Object>); + + +} // namespace blink + +#endif // V8InternalValueType_h
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8StackTraceImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8StackTraceImpl.cpp index 5c79b57..e7fb57a 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/V8StackTraceImpl.cpp +++ b/third_party/WebKit/Source/platform/v8_inspector/V8StackTraceImpl.cpp
@@ -72,6 +72,8 @@ , m_lineNumber(lineNumber) , m_columnNumber(column) { + DCHECK(m_lineNumber != v8::Message::kNoLineNumberInfo); + DCHECK(m_columnNumber != v8::Message::kNoColumnInfo); } V8StackTraceImpl::Frame::~Frame() @@ -86,8 +88,8 @@ .setFunctionName(m_functionName) .setScriptId(m_scriptId) .setUrl(m_scriptName) - .setLineNumber(m_lineNumber) - .setColumnNumber(m_columnNumber) + .setLineNumber(m_lineNumber - 1) + .setColumnNumber(m_columnNumber - 1) .build(); }
diff --git a/third_party/WebKit/Source/platform/v8_inspector/js_protocol.json b/third_party/WebKit/Source/platform/v8_inspector/js_protocol.json index 1a630c2..b01d7a4c 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/js_protocol.json +++ b/third_party/WebKit/Source/platform/v8_inspector/js_protocol.json
@@ -152,8 +152,8 @@ { "name": "functionName", "type": "string", "description": "JavaScript function name." }, { "name": "scriptId", "$ref": "ScriptId", "description": "JavaScript script id." }, { "name": "url", "type": "string", "description": "JavaScript script name or url." }, - { "name": "lineNumber", "type": "integer", "description": "JavaScript script line number." }, - { "name": "columnNumber", "type": "integer", "description": "JavaScript script column number." } + { "name": "lineNumber", "type": "integer", "description": "JavaScript script line number (0-based)." }, + { "name": "columnNumber", "type": "integer", "description": "JavaScript script column number (0-based)." } ] }, { @@ -376,18 +376,6 @@ "description": "Location in the source code." }, { - "id": "FunctionDetails", - "hidden": true, - "type": "object", - "properties": [ - { "name": "location", "$ref": "Location", "optional": true, "description": "Location of the function, none for native functions." }, - { "name": "functionName", "type": "string", "description": "Name of the function." }, - { "name": "isGenerator", "type": "boolean", "description": "Whether this is a generator function." }, - { "name": "scopeChain", "type": "array", "optional": true, "items": { "$ref": "Scope" }, "description": "Scope chain for this closure." } - ], - "description": "Information about the function." - }, - { "id": "CallFrame", "type": "object", "properties": [ @@ -579,17 +567,6 @@ "description": "Returns source for the script with given id." }, { - "name": "getFunctionDetails", - "hidden": true, - "parameters": [ - { "name": "functionId", "$ref": "Runtime.RemoteObjectId", "description": "Id of the function to get details for." } - ], - "returns": [ - { "name": "details", "$ref": "FunctionDetails", "description": "Information about the function." } - ], - "description": "Returns detailed information on given function." - }, - { "name": "setPauseOnExceptions", "parameters": [ { "name": "state", "type": "string", "enum": ["none", "uncaught", "all"], "description": "Pause on exceptions mode." } @@ -741,7 +718,7 @@ "type": "object", "description": "Console message.", "properties": [ - { "name": "source", "type": "string", "enum": ["xml", "javascript", "network", "console-api", "storage", "appcache", "rendering", "security", "other", "deprecation"], "description": "Message source." }, + { "name": "source", "type": "string", "enum": ["xml", "javascript", "network", "console-api", "storage", "appcache", "rendering", "security", "other", "deprecation", "worker"], "description": "Message source." }, { "name": "level", "type": "string", "enum": ["log", "warning", "error", "debug", "info"], "description": "Message severity." }, { "name": "text", "type": "string", "description": "Message text." }, { "name": "type", "type": "string", "optional": true, "enum": ["log", "dir", "dirxml", "table", "trace", "clear", "startGroup", "startGroupCollapsed", "endGroup", "assert", "profile", "profileEnd"], "description": "Console message type." }, @@ -754,7 +731,8 @@ { "name": "stack", "$ref": "Runtime.StackTrace", "optional": true, "description": "JavaScript stack trace for assertions and error messages." }, { "name": "networkRequestId", "type": "string", "optional": true, "description": "Identifier of the network request associated with this message." }, { "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp, when this message was fired.", "hidden": true }, - { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "optional": true, "description": "Identifier of the context where this message was created", "hidden": true } + { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "optional": true, "description": "Identifier of the context where this message was created", "hidden": true }, + { "name": "workerId", "type": "string", "optional": true, "description": "Identifier of the worker this message came from.", "hidden": true } ] } ],
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8ConsoleTypes.h b/third_party/WebKit/Source/platform/v8_inspector/public/V8ConsoleTypes.h index 75f26fe2..c7e2b1c 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/public/V8ConsoleTypes.h +++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8ConsoleTypes.h
@@ -18,6 +18,7 @@ SecurityMessageSource, OtherMessageSource, DeprecationMessageSource, + WorkerMessageSource }; enum MessageLevel { @@ -28,22 +29,6 @@ ErrorMessageLevel = 3 }; -// TODO(dgozman): move from public to private. -enum MessageType { - LogMessageType = 1, - DirMessageType, - DirXMLMessageType, - TableMessageType, - TraceMessageType, - StartGroupMessageType, - StartGroupCollapsedMessageType, - EndGroupMessageType, - ClearMessageType, - AssertMessageType, - TimeEndMessageType, - CountMessageType -}; - } #endif // !defined(V8ConsoleTypes_h)
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8ContentSearchUtil.h b/third_party/WebKit/Source/platform/v8_inspector/public/V8ContentSearchUtil.h index 35cf1233..a932b7a 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/public/V8ContentSearchUtil.h +++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8ContentSearchUtil.h
@@ -7,6 +7,7 @@ #include "platform/inspector_protocol/Platform.h" #include "platform/inspector_protocol/String16.h" +#include "platform/v8_inspector/protocol/Debugger.h" namespace blink {
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8ContextInfo.h b/third_party/WebKit/Source/platform/v8_inspector/public/V8ContextInfo.h index d0dca79..0dc1de2 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/public/V8ContextInfo.h +++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8ContextInfo.h
@@ -32,6 +32,7 @@ bool isDefault; const String16 origin; const String16 humanReadableName; + // TODO(dgozman): aux data? const String16 frameId; bool hasMemoryOnConsole; };
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8Debugger.h b/third_party/WebKit/Source/platform/v8_inspector/public/V8Debugger.h index c0ebce29..576e2df 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/public/V8Debugger.h +++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8Debugger.h
@@ -5,13 +5,11 @@ #ifndef V8Debugger_h #define V8Debugger_h -#include "platform/inspector_protocol/Collections.h" #include "platform/inspector_protocol/Platform.h" #include "platform/inspector_protocol/String16.h" #include "platform/v8_inspector/public/V8ConsoleTypes.h" #include <v8.h> -#include <vector> namespace blink { @@ -22,7 +20,6 @@ class V8StackTrace; namespace protocol { -class DictionaryValue; class FrontendChannel; } @@ -31,39 +28,41 @@ static std::unique_ptr<V8Debugger> create(v8::Isolate*, V8DebuggerClient*); virtual ~V8Debugger() { } + // Contexts instrumentation. virtual void contextCreated(const V8ContextInfo&) = 0; virtual void contextDestroyed(v8::Local<v8::Context>) = 0; - // TODO(dgozman): remove this one. virtual void resetContextGroup(int contextGroupId) = 0; + + // Various instrumentation. virtual void willExecuteScript(v8::Local<v8::Context>, int scriptId) = 0; virtual void didExecuteScript(v8::Local<v8::Context>) = 0; virtual void idleStarted() = 0; virtual void idleFinished() = 0; - // TODO(dgozman): remove requestIdentifier. - virtual bool addConsoleMessage(int contextGroupId, MessageSource, MessageLevel, const String16& message, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId, const String16& requestIdentifier) = 0; - // TODO(dgozman): can we remove this method? - virtual void logToConsole(v8::Local<v8::Context>, const String16& message, v8::Local<v8::Value> arg1, v8::Local<v8::Value> arg2) = 0; - // TODO(dgozman): can we pass exception object? - virtual void exceptionThrown(int contextGroupId, const String16& errorMessage, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId) = 0; - virtual unsigned promiseRejected(v8::Local<v8::Context>, const String16& errorMessage, v8::Local<v8::Value> exception, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId) = 0; - virtual void promiseRejectionRevoked(v8::Local<v8::Context>, unsigned promiseRejectionId) = 0; - virtual void consoleMessagesCount(int contextGroupId, unsigned* total, unsigned* withArguments) = 0; - // TODO(dgozman): remove mute methods. - virtual void muteConsole() = 0; - virtual void unmuteConsole() = 0; - virtual std::unique_ptr<V8InspectorSession> connect(int contextGroupId, protocol::FrontendChannel*, V8InspectorSessionClient*, const String16* state) = 0; - virtual bool isPaused() = 0; - - virtual std::unique_ptr<V8StackTrace> createStackTrace(v8::Local<v8::StackTrace>) = 0; - virtual std::unique_ptr<V8StackTrace> captureStackTrace(bool fullStack) = 0; - - // API to report async call stacks. + // Async call stacks instrumentation. virtual void asyncTaskScheduled(const String16& taskName, void* task, bool recurring) = 0; virtual void asyncTaskCanceled(void* task) = 0; virtual void asyncTaskStarted(void* task) = 0; virtual void asyncTaskFinished(void* task) = 0; virtual void allAsyncTasksCanceled() = 0; + + // Runtime instrumentation. + // TODO(dgozman): can we pass exception object? + virtual void exceptionThrown(int contextGroupId, const String16& errorMessage, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId) = 0; + virtual unsigned promiseRejected(v8::Local<v8::Context>, const String16& errorMessage, v8::Local<v8::Value> exception, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId) = 0; + virtual void promiseRejectionRevoked(v8::Local<v8::Context>, unsigned promiseRejectionId) = 0; + + // TODO(dgozman): remove requestIdentifier. + virtual void addConsoleMessage(int contextGroupId, MessageSource, MessageLevel, const String16& message, const String16& url, unsigned lineNumber, unsigned columnNumber, std::unique_ptr<V8StackTrace>, int scriptId, const String16& requestIdentifier, const String16& workerId) = 0; + // TODO(dgozman): can we remove this method? + virtual void logToConsole(v8::Local<v8::Context>, const String16& message, v8::Local<v8::Value> arg1, v8::Local<v8::Value> arg2) = 0; + // TODO(dgozman): try to remove this. + virtual void consoleMessagesCount(int contextGroupId, unsigned* total, unsigned* withArguments) = 0; + + // API methods. + virtual std::unique_ptr<V8InspectorSession> connect(int contextGroupId, protocol::FrontendChannel*, V8InspectorSessionClient*, const String16* state) = 0; + virtual std::unique_ptr<V8StackTrace> createStackTrace(v8::Local<v8::StackTrace>) = 0; + virtual std::unique_ptr<V8StackTrace> captureStackTrace(bool fullStack) = 0; }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8DebuggerClient.h b/third_party/WebKit/Source/platform/v8_inspector/public/V8DebuggerClient.h index dff99a2..6944c35 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/public/V8DebuggerClient.h +++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8DebuggerClient.h
@@ -20,7 +20,6 @@ virtual ~V8DebuggerClient() { } virtual void runMessageLoopOnPause(int contextGroupId) = 0; virtual void quitMessageLoopOnPause() = 0; - // TODO(dgozman): we don't really need to mute warnings and deprecations. virtual void muteWarningsAndDeprecations() = 0; virtual void unmuteWarningsAndDeprecations() = 0; virtual void beginUserGesture() = 0;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.h b/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.h index 3f689ae..c545060 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.h +++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8Inspector.h
@@ -68,7 +68,6 @@ bool canExecuteScripts() override; void profilingStarted() override { }; void profilingStopped() override { }; - void consoleEnabled() override { }; void consoleCleared() override { }; std::unique_ptr<V8Debugger> m_debugger;
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8InspectorSession.h b/third_party/WebKit/Source/platform/v8_inspector/public/V8InspectorSession.h index 6264b97..2103467 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/public/V8InspectorSession.h +++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8InspectorSession.h
@@ -12,15 +12,9 @@ namespace blink { -class V8DebuggerAgent; -class V8HeapProfilerAgent; -class V8InspectorSessionClient; -class V8ProfilerAgent; -class V8RuntimeAgent; - class PLATFORM_EXPORT V8InspectorSession { public: - static const char backtraceObjectGroup[]; + virtual ~V8InspectorSession() { } // Cross-context inspectable values (DOM nodes in different worlds, etc.). class Inspectable { @@ -28,15 +22,15 @@ virtual v8::Local<v8::Value> get(v8::Local<v8::Context>) = 0; virtual ~Inspectable() { } }; + virtual void addInspectedObject(std::unique_ptr<Inspectable>) = 0; - virtual ~V8InspectorSession() { } - + // Dispatching protocol messages. + // TODO(dgozman): generate this one. static bool isV8ProtocolMethod(const String16& method); virtual void dispatchProtocolMessage(const String16& message) = 0; virtual String16 stateJSON() = 0; - virtual void addInspectedObject(std::unique_ptr<Inspectable>) = 0; - // API for the embedder to report native activities. + // Debugger actions. virtual void schedulePauseOnNextStatement(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data) = 0; virtual void cancelPauseOnNextStatement() = 0; virtual void breakProgram(const String16& breakReason, std::unique_ptr<protocol::DictionaryValue> data) = 0; @@ -44,10 +38,9 @@ virtual void resume() = 0; virtual void stepOver() = 0; - // API to work with remote objects. - virtual std::unique_ptr<protocol::Runtime::RemoteObject> wrapObject(v8::Local<v8::Context>, v8::Local<v8::Value>, const String16& groupName, bool generatePreview = false) = 0; - // FIXME: remove when InspectorConsoleAgent moves into V8 inspector. - virtual std::unique_ptr<protocol::Runtime::RemoteObject> wrapTable(v8::Local<v8::Context>, v8::Local<v8::Value> table, v8::Local<v8::Value> columns) = 0; + // Remote objects. + static const char backtraceObjectGroup[]; + virtual std::unique_ptr<protocol::Runtime::RemoteObject> wrapObject(v8::Local<v8::Context>, v8::Local<v8::Value>, const String16& groupName, bool generatePreview) = 0; virtual v8::Local<v8::Value> findObject(ErrorString*, const String16& objectId, v8::Local<v8::Context>* = nullptr, String16* objectGroup = nullptr) = 0; virtual void releaseObjectGroup(const String16&) = 0; };
diff --git a/third_party/WebKit/Source/platform/v8_inspector/public/V8InspectorSessionClient.h b/third_party/WebKit/Source/platform/v8_inspector/public/V8InspectorSessionClient.h index fb52973..e9e7c33 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/public/V8InspectorSessionClient.h +++ b/third_party/WebKit/Source/platform/v8_inspector/public/V8InspectorSessionClient.h
@@ -5,24 +5,22 @@ #ifndef V8InspectorSessionClient_h #define V8InspectorSessionClient_h -#include "platform/inspector_protocol/FrontendChannel.h" #include "platform/inspector_protocol/Platform.h" #include <v8.h> namespace blink { -class PLATFORM_EXPORT V8InspectorSessionClient -{ +class PLATFORM_EXPORT V8InspectorSessionClient { public: virtual ~V8InspectorSessionClient() { } virtual void runtimeEnabled() = 0; virtual void runtimeDisabled() = 0; virtual void resumeStartup() = 0; + // TODO(dgozman): this was added to support service worker shadow page. We should not connect at all. virtual bool canExecuteScripts() = 0; virtual void profilingStarted() = 0; virtual void profilingStopped() = 0; - virtual void consoleEnabled() = 0; virtual void consoleCleared() = 0; };
diff --git a/third_party/WebKit/Source/platform/v8_inspector/v8_inspector.gyp b/third_party/WebKit/Source/platform/v8_inspector/v8_inspector.gyp index 4433b04..a4d9b0b 100644 --- a/third_party/WebKit/Source/platform/v8_inspector/v8_inspector.gyp +++ b/third_party/WebKit/Source/platform/v8_inspector/v8_inspector.gyp
@@ -214,6 +214,8 @@ 'V8InjectedScriptHost.h', 'V8InspectorSessionImpl.cpp', 'V8InspectorSessionImpl.h', + 'V8InternalValueType.cpp', + 'V8InternalValueType.h', 'V8ProfilerAgentImpl.cpp', 'V8ProfilerAgentImpl.h', 'V8Regex.cpp',
diff --git a/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp b/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp index be4f185c..e99659a 100644 --- a/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp +++ b/third_party/WebKit/Source/platform/weborigin/SchemeRegistry.cpp
@@ -65,50 +65,40 @@ static URLSchemesSet& mixedContentRestrictingSchemes() { - DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, mixedContentRestrictingSchemes, ()); - - if (mixedContentRestrictingSchemes.isEmpty()) - mixedContentRestrictingSchemes.add("https"); - + DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, mixedContentRestrictingSchemes, ({ + "https", + })); return mixedContentRestrictingSchemes; } static URLSchemesSet& secureSchemes() { - DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, secureSchemes, ()); - - if (secureSchemes.isEmpty()) { - secureSchemes.add("https"); - secureSchemes.add("about"); - secureSchemes.add("data"); - secureSchemes.add("wss"); - } - + DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, secureSchemes, ({ + "https", + "about", + "data", + "wss", + })); return secureSchemes; } static URLSchemesSet& schemesWithUniqueOrigins() { - DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, schemesWithUniqueOrigins, ()); - - if (schemesWithUniqueOrigins.isEmpty()) { - schemesWithUniqueOrigins.add("about"); - schemesWithUniqueOrigins.add("javascript"); + DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, schemesWithUniqueOrigins, ({ + "about", + "javascript", // This is a willful violation of HTML5. // See https://bugs.webkit.org/show_bug.cgi?id=11885 - schemesWithUniqueOrigins.add("data"); - } - + "data", + })); return schemesWithUniqueOrigins; } static URLSchemesSet& emptyDocumentSchemes() { - DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, emptyDocumentSchemes, ()); - - if (emptyDocumentSchemes.isEmpty()) - emptyDocumentSchemes.add("about"); - + DEFINE_STATIC_LOCAL_WITH_LOCK(URLSchemesSet, emptyDocumentSchemes, ({ + "about", + })); return emptyDocumentSchemes; }
diff --git a/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp b/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp index 4560bab..e2ad63b 100644 --- a/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp +++ b/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp
@@ -505,7 +505,7 @@ builder.append("://"); if (includeSuborigin && hasSuborigin()) { builder.append(m_suborigin.name()); - builder.append("_"); + builder.append('_'); } builder.append(m_host);
diff --git a/third_party/WebKit/Source/web/AssociatedURLLoaderTest.cpp b/third_party/WebKit/Source/web/AssociatedURLLoaderTest.cpp index f1a6a401..1fdf3d3 100644 --- a/third_party/WebKit/Source/web/AssociatedURLLoaderTest.cpp +++ b/third_party/WebKit/Source/web/AssociatedURLLoaderTest.cpp
@@ -184,7 +184,6 @@ void CheckMethodFails(const char* unsafeMethod) { WebURLRequest request; - request.initialize(); request.setURL(toKURL("http://www.test.com/success.html")); request.setHTTPMethod(WebString::fromUTF8(unsafeMethod)); WebURLLoaderOptions options; @@ -200,7 +199,6 @@ void CheckHeaderFails(const char* headerField, const char* headerValue) { WebURLRequest request; - request.initialize(); request.setURL(toKURL("http://www.test.com/success.html")); if (equalIgnoringCase(WebString::fromUTF8(headerField), "referer")) request.setHTTPReferrer(WebString::fromUTF8(headerValue), WebReferrerPolicyDefault); @@ -235,7 +233,6 @@ KURL url = toKURL(id); WebURLRequest request; - request.initialize(); request.setURL(url); WebString headerNameString(WebString::fromUTF8(headerName)); @@ -288,7 +285,6 @@ { KURL url = toKURL("http://www.test.com/SameOriginSuccess.html"); WebURLRequest request; - request.initialize(); request.setURL(url); m_expectedResponse = WebURLResponse(); @@ -311,7 +307,6 @@ // This is cross-origin since the frame was loaded from www.test.com. KURL url = toKURL("http://www.other.com/SameOriginRestriction.html"); WebURLRequest request; - request.initialize(); request.setURL(url); CheckFails(request); } @@ -322,7 +317,6 @@ // This is cross-origin since the frame was loaded from www.test.com. KURL url = toKURL("http://www.other.com/CrossOriginSuccess"); WebURLRequest request; - request.initialize(); request.setURL(url); // No-CORS requests (CrossOriginRequestPolicyAllow) aren't allowed for the // default context. So we set the context as Script here. @@ -350,7 +344,6 @@ // This is cross-origin since the frame was loaded from www.test.com. KURL url = toKURL("http://www.other.com/CrossOriginWithAccessControlSuccess.html"); WebURLRequest request; - request.initialize(); request.setURL(url); m_expectedResponse = WebURLResponse(); @@ -376,7 +369,6 @@ // This is cross-origin since the frame was loaded from www.test.com. KURL url = toKURL("http://www.other.com/CrossOriginWithAccessControlFailure.html"); WebURLRequest request; - request.initialize(); request.setURL(url); m_expectedResponse = WebURLResponse(); @@ -408,7 +400,6 @@ // This is cross-origin since the frame was loaded from www.test.com. KURL url = toKURL("http://www.other.com/CrossOriginWithAccessControlFailure.html"); WebURLRequest request; - request.initialize(); request.setURL(url); m_expectedResponse = WebURLResponse(); @@ -439,7 +430,6 @@ KURL redirectURL = toKURL(redirect); WebURLRequest request; - request.initialize(); request.setURL(url); m_expectedRedirectResponse = WebURLResponse(); @@ -449,7 +439,6 @@ Platform::current()->getURLLoaderMockFactory()->registerURL(url, m_expectedRedirectResponse, m_frameFilePath); m_expectedNewRequest = WebURLRequest(); - m_expectedNewRequest.initialize(); m_expectedNewRequest.setURL(redirectURL); m_expectedResponse = WebURLResponse(); @@ -475,7 +464,6 @@ KURL redirectURL = toKURL(redirect); WebURLRequest request; - request.initialize(); request.setURL(url); m_expectedRedirectResponse = WebURLResponse(); @@ -485,7 +473,6 @@ Platform::current()->getURLLoaderMockFactory()->registerURL(url, m_expectedRedirectResponse, m_frameFilePath); m_expectedNewRequest = WebURLRequest(); - m_expectedNewRequest.initialize(); m_expectedNewRequest.setURL(redirectURL); m_expectedResponse = WebURLResponse(); @@ -512,7 +499,6 @@ KURL redirectURL = toKURL(redirect); WebURLRequest request; - request.initialize(); request.setURL(url); m_expectedRedirectResponse = WebURLResponse(); @@ -522,7 +508,6 @@ Platform::current()->getURLLoaderMockFactory()->registerURL(url, m_expectedRedirectResponse, m_frameFilePath); m_expectedNewRequest = WebURLRequest(); - m_expectedNewRequest.initialize(); m_expectedNewRequest.setURL(redirectURL); m_expectedResponse = WebURLResponse(); @@ -552,7 +537,6 @@ KURL redirectURL = toKURL(redirect); WebURLRequest request; - request.initialize(); request.setURL(url); // Add a CORS simple header. request.setHTTPHeaderField("accept", "application/json"); @@ -566,7 +550,6 @@ Platform::current()->getURLLoaderMockFactory()->registerURL(url, m_expectedRedirectResponse, m_frameFilePath); m_expectedNewRequest = WebURLRequest(); - m_expectedNewRequest.initialize(); m_expectedNewRequest.setURL(redirectURL); m_expectedNewRequest.setHTTPHeaderField("accept", "application/json"); @@ -678,7 +661,6 @@ TEST_F(AssociatedURLLoaderTest, CrossOriginHeaderAllowResponseHeaders) { WebURLRequest request; - request.initialize(); KURL url = toKURL("http://www.other.com/CrossOriginHeaderAllowResponseHeaders.html"); request.setURL(url);
diff --git a/third_party/WebKit/Source/web/ChromeClientImpl.cpp b/third_party/WebKit/Source/web/ChromeClientImpl.cpp index c122b748..9ff0edf 100644 --- a/third_party/WebKit/Source/web/ChromeClientImpl.cpp +++ b/third_party/WebKit/Source/web/ChromeClientImpl.cpp
@@ -732,13 +732,13 @@ return m_lastSetMouseCursorForTesting; } -void ChromeClientImpl::setCursor(const Cursor& cursor, LocalFrame* localRoot) +void ChromeClientImpl::setCursor(const Cursor& cursor, LocalFrame* localFrame) { m_lastSetMouseCursorForTesting = cursor; - setCursor(WebCursorInfo(cursor), localRoot); + setCursor(WebCursorInfo(cursor), localFrame); } -void ChromeClientImpl::setCursor(const WebCursorInfo& cursor, LocalFrame* localRoot) +void ChromeClientImpl::setCursor(const WebCursorInfo& cursor, LocalFrame* localFrame) { if (m_cursorOverridden) return; @@ -749,25 +749,15 @@ if (m_webView->hasOpenedPopup()) return; #endif - if (!m_webView->client()) - return; - // TODO(kenrb, dcheng): For top-level frames we still use the WebView as - // a WebWidget. This special case will be removed when top-level frames - // get WebFrameWidgets. - if (localRoot->isMainFrame()) { - m_webView->client()->didChangeCursor(cursor); - } else { - WebLocalFrameImpl* webFrame = WebLocalFrameImpl::fromFrame(localRoot); - DCHECK(webFrame); - DCHECK(webFrame->frameWidget()); - if (toWebFrameWidgetImpl(webFrame->frameWidget())->client()) - toWebFrameWidgetImpl(webFrame->frameWidget())->client()->didChangeCursor(cursor); - } + + LocalFrame* localRoot = localFrame->localFrameRoot(); + if (WebFrameWidget* widget = WebLocalFrameImpl::fromFrame(localRoot)->frameWidget()) + widget->client()->didChangeCursor(cursor); } -void ChromeClientImpl::setCursorForPlugin(const WebCursorInfo& cursor, LocalFrame* localRoot) +void ChromeClientImpl::setCursorForPlugin(const WebCursorInfo& cursor, LocalFrame* localFrame) { - setCursor(cursor, localRoot); + setCursor(cursor, localFrame); } void ChromeClientImpl::setCursorOverridden(bool overridden)
diff --git a/third_party/WebKit/Source/web/ChromeClientImpl.h b/third_party/WebKit/Source/web/ChromeClientImpl.h index 9d575c4..85c94d0 100644 --- a/third_party/WebKit/Source/web/ChromeClientImpl.h +++ b/third_party/WebKit/Source/web/ChromeClientImpl.h
@@ -117,7 +117,7 @@ DateTimeChooser* openDateTimeChooser(DateTimeChooserClient*, const DateTimeChooserParameters&) override; void openFileChooser(LocalFrame*, PassRefPtr<FileChooser>) override; void enumerateChosenDirectory(FileChooser*) override; - void setCursor(const Cursor&, LocalFrame* localRoot) override; + void setCursor(const Cursor&, LocalFrame*) override; Cursor lastSetCursorForTesting() const override; void setEventListenerProperties(WebEventListenerClass, WebEventListenerProperties) override; WebEventListenerProperties eventListenerProperties(WebEventListenerClass) const override; @@ -144,7 +144,7 @@ String acceptLanguages() override; // ChromeClientImpl: - void setCursorForPlugin(const WebCursorInfo&, LocalFrame* localRoot); + void setCursorForPlugin(const WebCursorInfo&, LocalFrame*); void setNewWindowNavigationPolicy(WebNavigationPolicy); void setCursorOverridden(bool); @@ -197,7 +197,7 @@ void registerPopupOpeningObserver(PopupOpeningObserver*) override; void unregisterPopupOpeningObserver(PopupOpeningObserver*) override; - void setCursor(const WebCursorInfo&, LocalFrame* localRoot); + void setCursor(const WebCursorInfo&, LocalFrame*); WebViewImpl* m_webView; // Weak pointer. WindowFeatures m_windowFeatures;
diff --git a/third_party/WebKit/Source/web/ExternalPopupMenu.cpp b/third_party/WebKit/Source/web/ExternalPopupMenu.cpp index 59c77900..7d62cd9 100644 --- a/third_party/WebKit/Source/web/ExternalPopupMenu.cpp +++ b/third_party/WebKit/Source/web/ExternalPopupMenu.cpp
@@ -194,11 +194,12 @@ if (m_ownerElement) { m_ownerElement->popupDidHide(); - m_ownerElement->valueChanged(popupMenuItemIndex); + m_ownerElement->selectOptionByPopup(popupMenuItemIndex); } m_webExternalPopupMenu = 0; } +// Android uses this function even for single SELECT. void ExternalPopupMenu::didAcceptIndices(const WebVector<int>& indices) { if (!m_ownerElement) { @@ -210,10 +211,15 @@ ownerElement->popupDidHide(); if (indices.size() == 0) { - ownerElement->valueChanged(static_cast<unsigned>(-1)); + ownerElement->selectOptionByPopup(-1); + } else if (!ownerElement->multiple()) { + ownerElement->selectOptionByPopup(toPopupMenuItemIndex(indices[indices.size() - 1], *ownerElement)); } else { + Vector<int> listIndices; + listIndices.reserveCapacity(indices.size()); for (size_t i = 0; i < indices.size(); ++i) - ownerElement->listBoxSelectItem(toPopupMenuItemIndex(indices[i], *ownerElement), (i > 0), false, (i == indices.size() - 1)); + listIndices.append(toPopupMenuItemIndex(indices[i], *ownerElement)); + ownerElement->selectMultipleOptionsByPopup(listIndices); } m_webExternalPopupMenu = 0;
diff --git a/third_party/WebKit/Source/web/FullscreenController.cpp b/third_party/WebKit/Source/web/FullscreenController.cpp index 39914a7..0b506896 100644 --- a/third_party/WebKit/Source/web/FullscreenController.cpp +++ b/third_party/WebKit/Source/web/FullscreenController.cpp
@@ -60,7 +60,7 @@ { } -void FullscreenController::didEnterFullScreen() +void FullscreenController::didEnterFullscreen() { if (!m_provisionalFullScreenElement) return; @@ -81,7 +81,7 @@ m_haveEnteredFullscreen = true; } - Fullscreen::from(document).didEnterFullScreenForElement(element); + Fullscreen::from(document).didEnterFullscreenForElement(element); DCHECK_EQ(Fullscreen::currentFullScreenElementFrom(document), element); if (isHTMLVideoElement(element)) { @@ -91,7 +91,7 @@ } } -void FullscreenController::didExitFullScreen() +void FullscreenController::didExitFullscreen() { if (!m_fullScreenFrame) return; @@ -120,7 +120,7 @@ m_webViewImpl->setVisualViewportOffset(m_exitFullscreenVisualViewportOffset); } - fullscreen->didExitFullScreenForElement(); + fullscreen->didExitFullscreen(); } } } @@ -140,11 +140,11 @@ // We are already in fullscreen mode. if (m_fullScreenFrame) { m_provisionalFullScreenElement = element; - didEnterFullScreen(); + didEnterFullscreen(); return; } - // We need to store these values here rather than didEnterFullScreen since + // We need to store these values here rather than didEnterFullscreen since // by the time the latter is called, a Resize has already occured, clamping // the scroll offset. if (!m_haveEnteredFullscreen) { @@ -156,7 +156,7 @@ // We need to transition to fullscreen mode. WebLocalFrameImpl* frame = WebLocalFrameImpl::fromFrame(element->document().frame()); if (frame && frame->client()) { - if (!Fullscreen::from(element->document()).forCrossProcessAncestor()) + if (!Fullscreen::from(element->document()).forCrossProcessDescendant()) frame->client()->enterFullscreen(); m_provisionalFullScreenElement = element; } @@ -216,4 +216,3 @@ } } // namespace blink -
diff --git a/third_party/WebKit/Source/web/FullscreenController.h b/third_party/WebKit/Source/web/FullscreenController.h index 039535c..a4e1ffd 100644 --- a/third_party/WebKit/Source/web/FullscreenController.h +++ b/third_party/WebKit/Source/web/FullscreenController.h
@@ -46,8 +46,8 @@ public: static FullscreenController* create(WebViewImpl*); - void didEnterFullScreen(); - void didExitFullScreen(); + void didEnterFullscreen(); + void didExitFullscreen(); void enterFullScreenForElement(Element*); void exitFullScreenForElement(Element*);
diff --git a/third_party/WebKit/Source/web/InspectorOverlay.cpp b/third_party/WebKit/Source/web/InspectorOverlay.cpp index 25e495b5..955e043 100644 --- a/third_party/WebKit/Source/web/InspectorOverlay.cpp +++ b/third_party/WebKit/Source/web/InspectorOverlay.cpp
@@ -142,7 +142,7 @@ void setCursor(const Cursor& cursor, LocalFrame* localRoot) override { toChromeClientImpl(m_client)->setCursorOverridden(false); - toChromeClientImpl(m_client)->setCursor(cursor, localRoot); + toChromeClientImpl(m_client)->setCursor(cursor, m_overlay->m_webViewImpl->mainFrameImpl()->frame()); bool overrideCursor = m_overlay->m_layoutEditor; toChromeClientImpl(m_client)->setCursorOverridden(overrideCursor); }
diff --git a/third_party/WebKit/Source/web/PageOverlay.h b/third_party/WebKit/Source/web/PageOverlay.h index 2f39d28..09a6c3a 100644 --- a/third_party/WebKit/Source/web/PageOverlay.h +++ b/third_party/WebKit/Source/web/PageOverlay.h
@@ -39,14 +39,9 @@ namespace blink { class GraphicsContext; -class WebPageOverlay; class WebViewImpl; // Manages a layer that is overlaid on a WebView's content. -// Clients can paint by implementing WebPageOverlay. -// -// With Slimming Paint, internal clients can extract a GraphicsContext to add -// to the PaintController owned by the GraphicsLayer class WEB_EXPORT PageOverlay : public GraphicsLayerClient, public DisplayItemClient { public: class Delegate : public GarbageCollectedFinalized<Delegate> {
diff --git a/third_party/WebKit/Source/web/PopupMenuImpl.cpp b/third_party/WebKit/Source/web/PopupMenuImpl.cpp index d40ba44..f581262 100644 --- a/third_party/WebKit/Source/web/PopupMenuImpl.cpp +++ b/third_party/WebKit/Source/web/PopupMenuImpl.cpp
@@ -398,7 +398,7 @@ DCHECK(success); { EventQueueScope scope; - m_ownerElement->valueChanged(listIndex); + m_ownerElement->selectOptionByPopup(listIndex); if (m_popup) m_chromeClient->closePagePopup(m_popup); // 'change' event is dispatched here. For compatbility with
diff --git a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp index c664b86..abfa8f8 100644 --- a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp +++ b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.cpp
@@ -133,6 +133,7 @@ void ServiceWorkerGlobalScopeProxy::dispatchFetchEvent(int responseID, int eventFinishID, const WebServiceWorkerRequest& webRequest) { + ScriptState::Scope scope(workerGlobalScope()->scriptController()->getScriptState()); WaitUntilObserver* waitUntilObserver = WaitUntilObserver::create(workerGlobalScope(), WaitUntilObserver::Fetch, eventFinishID); RespondWithObserver* respondWithObserver = RespondWithObserver::create(workerGlobalScope(), responseID, webRequest.url(), webRequest.mode(), webRequest.frameType(), webRequest.requestContext(), waitUntilObserver); Request* request = Request::create(workerGlobalScope()->scriptController()->getScriptState(), webRequest); @@ -153,6 +154,7 @@ void ServiceWorkerGlobalScopeProxy::dispatchForeignFetchEvent(int responseID, int eventFinishID, const WebServiceWorkerRequest& webRequest) { + ScriptState::Scope scope(workerGlobalScope()->scriptController()->getScriptState()); RefPtr<SecurityOrigin> origin = SecurityOrigin::create(webRequest.referrerUrl()); WaitUntilObserver* waitUntilObserver = WaitUntilObserver::create(workerGlobalScope(), WaitUntilObserver::Fetch, eventFinishID); ForeignFetchRespondWithObserver* respondWithObserver = ForeignFetchRespondWithObserver::create(workerGlobalScope(), responseID, webRequest.url(), webRequest.mode(), webRequest.frameType(), webRequest.requestContext(), origin, waitUntilObserver);
diff --git a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.h b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.h index 6d3b95b..60750e1 100644 --- a/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.h +++ b/third_party/WebKit/Source/web/ServiceWorkerGlobalScopeProxy.h
@@ -87,7 +87,6 @@ void reportException(const String& errorMessage, std::unique_ptr<SourceLocation>) override; void reportConsoleMessage(ConsoleMessage*) override; void postMessageToPageInspector(const String&) override; - void postWorkerConsoleAgentEnabled() override { } void didEvaluateWorkerScript(bool success) override; void didInitializeWorkerContext() override; void workerGlobalScopeStarted(WorkerGlobalScope*) override;
diff --git a/third_party/WebKit/Source/web/TextFinder.cpp b/third_party/WebKit/Source/web/TextFinder.cpp index 8cd0d33..916a97a 100644 --- a/third_party/WebKit/Source/web/TextFinder.cpp +++ b/third_party/WebKit/Source/web/TextFinder.cpp
@@ -360,7 +360,7 @@ identifier); } - addMarker(resultRange, foundActiveMatch); + ownerFrame().frame()->document()->markers().addTextMatchMarker(resultRange, foundActiveMatch); m_findMatchesCache.append(FindMatch(resultRange, m_lastMatchCount + matchCount)); @@ -656,11 +656,6 @@ { } -void TextFinder::addMarker(Range* range, bool activeMatch) -{ - ownerFrame().frame()->document()->markers().addTextMatchMarker(range, activeMatch); -} - bool TextFinder::setMarkerActive(Range* range, bool active) { if (!range || range->collapsed())
diff --git a/third_party/WebKit/Source/web/TextFinder.h b/third_party/WebKit/Source/web/TextFinder.h index 7466c43c11..36644a83 100644 --- a/third_party/WebKit/Source/web/TextFinder.h +++ b/third_party/WebKit/Source/web/TextFinder.h
@@ -140,9 +140,6 @@ // propagating the invalidation to child frames. void updateFindMatchRects(); - // Add a WebKit TextMatch-highlight marker to nodes in a range. - void addMarker(Range*, bool activeMatch); - // Sets the markers within a range as active or inactive. Returns true if at least // one such marker found. bool setMarkerActive(Range*, bool active);
diff --git a/third_party/WebKit/Source/web/WebDataSourceImpl.cpp b/third_party/WebKit/Source/web/WebDataSourceImpl.cpp index 6a086e9a..4f97c50 100644 --- a/third_party/WebKit/Source/web/WebDataSourceImpl.cpp +++ b/third_party/WebKit/Source/web/WebDataSourceImpl.cpp
@@ -47,13 +47,11 @@ const WebURLRequest& WebDataSourceImpl::originalRequest() const { - m_originalRequestWrapper.bind(DocumentLoader::originalRequest()); return m_originalRequestWrapper; } const WebURLRequest& WebDataSourceImpl::request() const { - m_requestWrapper.bind(DocumentLoader::request()); return m_requestWrapper; } @@ -134,6 +132,8 @@ WebDataSourceImpl::WebDataSourceImpl(LocalFrame* frame, const ResourceRequest& request, const SubstituteData& data) : DocumentLoader(frame, request, data) + , m_originalRequestWrapper(DocumentLoader::originalRequest()) + , m_requestWrapper(DocumentLoader::request()) , m_responseWrapper(DocumentLoader::response()) { }
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp index c126931..2195baa 100644 --- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp +++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.cpp
@@ -228,14 +228,14 @@ m_ignoreInputEvents = newValue; } -void WebFrameWidgetImpl::didEnterFullScreen() +void WebFrameWidgetImpl::didEnterFullscreen() { - view()->didEnterFullScreen(); + view()->didEnterFullscreen(); } -void WebFrameWidgetImpl::didExitFullScreen() +void WebFrameWidgetImpl::didExitFullscreen() { - view()->didExitFullScreen(); + view()->didExitFullscreen(); } void WebFrameWidgetImpl::beginFrame(double lastFrameTimeMonotonic)
diff --git a/third_party/WebKit/Source/web/WebFrameWidgetImpl.h b/third_party/WebKit/Source/web/WebFrameWidgetImpl.h index e06018a..b6ebe6a9 100644 --- a/third_party/WebKit/Source/web/WebFrameWidgetImpl.h +++ b/third_party/WebKit/Source/web/WebFrameWidgetImpl.h
@@ -74,8 +74,8 @@ WebSize size() override; void resize(const WebSize&) override; void resizeVisualViewport(const WebSize&) override; - void didEnterFullScreen() override; - void didExitFullScreen() override; + void didEnterFullscreen() override; + void didExitFullscreen() override; void beginFrame(double lastFrameTimeMonotonic) override; void updateAllLifecyclePhases() override; void paint(WebCanvas*, const WebRect&) override;
diff --git a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp index a4a1f40..a889e406 100644 --- a/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp +++ b/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp
@@ -995,6 +995,11 @@ Element* editable = frame()->selection().rootEditableElementOrDocumentElement(); if (!editable) return false; + + // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited. + // see http://crbug.com/590369 for more details. + editable->document().updateStyleAndLayoutIgnorePendingStylesheets(); + const EphemeralRange range = PlainTextRange(location, location + length).createRange(*editable); if (range.isNull()) return false;
diff --git a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp index 5b8f766..94757f0 100644 --- a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp +++ b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
@@ -160,10 +160,9 @@ return IntSize(0, 0); } - void setCursor(const Cursor& cursor, LocalFrame* localRoot) override + void setCursor(const Cursor& cursor, LocalFrame* localFrame) override { - if (m_popup->m_webView->client()) - m_popup->m_webView->client()->didChangeCursor(WebCursorInfo(cursor)); + m_popup->m_widgetClient->didChangeCursor(WebCursorInfo(cursor)); } void setEventListenerProperties(WebEventListenerClass eventClass, WebEventListenerProperties properties) override
diff --git a/third_party/WebKit/Source/web/WebRange.cpp b/third_party/WebKit/Source/web/WebRange.cpp index 261bbe9..49cd2fa9 100644 --- a/third_party/WebKit/Source/web/WebRange.cpp +++ b/third_party/WebKit/Source/web/WebRange.cpp
@@ -79,6 +79,11 @@ LocalFrame* webFrame = toWebLocalFrameImpl(frame)->frame(); Element* selectionRoot = webFrame->selection().rootEditableElement(); ContainerNode* scope = selectionRoot ? selectionRoot : webFrame->document()->documentElement(); + + // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets needs to be audited. + // see http://crbug.com/590369 for more details. + scope->document().updateStyleAndLayoutIgnorePendingStylesheets(); + return createRange(PlainTextRange(start, start + length).createRange(*scope)); }
diff --git a/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp b/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp index 17e6630a5..ef3f0a4 100644 --- a/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp +++ b/third_party/WebKit/Source/web/WebRemoteFrameImpl.cpp
@@ -524,7 +524,7 @@ return owner->layoutObject()->style()->pointerEvents() == PE_NONE; } -void WebRemoteFrameImpl::willEnterFullScreen() +void WebRemoteFrameImpl::willEnterFullscreen() { // This should only ever be called when the FrameOwner is local. HTMLFrameOwnerElement* ownerElement = toHTMLFrameOwnerElement(frame()->owner());
diff --git a/third_party/WebKit/Source/web/WebRemoteFrameImpl.h b/third_party/WebKit/Source/web/WebRemoteFrameImpl.h index 82cde800..6bb8a28 100644 --- a/third_party/WebKit/Source/web/WebRemoteFrameImpl.h +++ b/third_party/WebKit/Source/web/WebRemoteFrameImpl.h
@@ -129,7 +129,7 @@ bool isIgnoredForHitTest() const override; - void willEnterFullScreen() override; + void willEnterFullscreen() override; DECLARE_TRACE();
diff --git a/third_party/WebKit/Source/web/WebScopedUserGesture.cpp b/third_party/WebKit/Source/web/WebScopedUserGesture.cpp index ce53beb..e3b134d 100644 --- a/third_party/WebKit/Source/web/WebScopedUserGesture.cpp +++ b/third_party/WebKit/Source/web/WebScopedUserGesture.cpp
@@ -35,20 +35,19 @@ namespace blink { -void WebScopedUserGesture::initialize() -{ - m_indicator.reset(new UserGestureIndicator(DefinitelyProcessingNewUserGesture)); -} - -void WebScopedUserGesture::initializeWithToken(const WebUserGestureToken& token) +WebScopedUserGesture::WebScopedUserGesture(const WebUserGestureToken& token) { if (!token.isNull()) m_indicator.reset(new UserGestureIndicator(token)); } -void WebScopedUserGesture::reset() +WebScopedUserGesture::WebScopedUserGesture() { - m_indicator.reset(0); + m_indicator.reset(new UserGestureIndicator(DefinitelyProcessingNewUserGesture)); +} + +WebScopedUserGesture::~WebScopedUserGesture() +{ } } // namespace blink
diff --git a/third_party/WebKit/Source/web/WebScopedWindowFocusAllowedIndicator.cpp b/third_party/WebKit/Source/web/WebScopedWindowFocusAllowedIndicator.cpp index e32eb89..5491535e 100644 --- a/third_party/WebKit/Source/web/WebScopedWindowFocusAllowedIndicator.cpp +++ b/third_party/WebKit/Source/web/WebScopedWindowFocusAllowedIndicator.cpp
@@ -36,16 +36,15 @@ namespace blink { -void WebScopedWindowFocusAllowedIndicator::initialize(WebDocument* webDocument) +WebScopedWindowFocusAllowedIndicator::WebScopedWindowFocusAllowedIndicator(WebDocument* webDocument) { Document* document = webDocument->unwrap<Document>(); DCHECK(document); m_private.reset(new ScopedWindowFocusAllowedIndicator(document)); } -void WebScopedWindowFocusAllowedIndicator::reset() +WebScopedWindowFocusAllowedIndicator::~WebScopedWindowFocusAllowedIndicator() { - m_private.reset(0); } } // namespace blink
diff --git a/third_party/WebKit/Source/web/WebSharedWorkerImpl.h b/third_party/WebKit/Source/web/WebSharedWorkerImpl.h index 3c675336..f0d5a88 100644 --- a/third_party/WebKit/Source/web/WebSharedWorkerImpl.h +++ b/third_party/WebKit/Source/web/WebSharedWorkerImpl.h
@@ -78,7 +78,6 @@ void reportException(const WTF::String&, std::unique_ptr<SourceLocation>) override; void reportConsoleMessage(ConsoleMessage*) override; void postMessageToPageInspector(const WTF::String&) override; - void postWorkerConsoleAgentEnabled() override { } void didEvaluateWorkerScript(bool success) override { } void workerGlobalScopeStarted(WorkerGlobalScope*) override; void workerGlobalScopeClosed() override;
diff --git a/third_party/WebKit/Source/web/WebSurroundingText.cpp b/third_party/WebKit/Source/web/WebSurroundingText.cpp index 0095871..6fd33f8e 100644 --- a/third_party/WebKit/Source/web/WebSurroundingText.cpp +++ b/third_party/WebKit/Source/web/WebSurroundingText.cpp
@@ -36,6 +36,14 @@ namespace blink { +WebSurroundingText::WebSurroundingText() +{ +} + +WebSurroundingText::~WebSurroundingText() +{ +} + void WebSurroundingText::initialize(const WebNode& webNode, const WebPoint& nodePoint, size_t maxLength) { const Node* node = webNode.constUnwrap<Node>(); @@ -82,9 +90,4 @@ return !m_private.get(); } -void WebSurroundingText::reset() -{ - m_private.reset(0); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/web/WebViewFrameWidget.cpp b/third_party/WebKit/Source/web/WebViewFrameWidget.cpp index 8f59183..0b95d8a 100644 --- a/third_party/WebKit/Source/web/WebViewFrameWidget.cpp +++ b/third_party/WebKit/Source/web/WebViewFrameWidget.cpp
@@ -53,14 +53,14 @@ return m_webView->resizeVisualViewport(size); } -void WebViewFrameWidget::didEnterFullScreen() +void WebViewFrameWidget::didEnterFullscreen() { - return m_webView->didEnterFullScreen(); + return m_webView->didEnterFullscreen(); } -void WebViewFrameWidget::didExitFullScreen() +void WebViewFrameWidget::didExitFullscreen() { - return m_webView->didExitFullScreen(); + return m_webView->didExitFullscreen(); } void WebViewFrameWidget::beginFrame(double lastFrameTimeMonotonic)
diff --git a/third_party/WebKit/Source/web/WebViewFrameWidget.h b/third_party/WebKit/Source/web/WebViewFrameWidget.h index 9f8f6aa7..8f39239 100644 --- a/third_party/WebKit/Source/web/WebViewFrameWidget.h +++ b/third_party/WebKit/Source/web/WebViewFrameWidget.h
@@ -42,8 +42,8 @@ WebSize size() override; void resize(const WebSize&) override; void resizeVisualViewport(const WebSize&) override; - void didEnterFullScreen() override; - void didExitFullScreen() override; + void didEnterFullscreen() override; + void didExitFullscreen() override; void beginFrame(double lastFrameTimeMonotonic) override; void updateAllLifecyclePhases() override; void paint(WebCanvas*, const WebRect& viewPort) override;
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp index 1e2ee8b..80b2f31 100644 --- a/third_party/WebKit/Source/web/WebViewImpl.cpp +++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -88,6 +88,7 @@ #include "core/page/PointerLockController.h" #include "core/page/ScopedPageLoadDeferrer.h" #include "core/page/TouchDisambiguation.h" +#include "core/page/scrolling/RootScrollerController.h" #include "core/paint/PaintLayer.h" #include "core/timing/DOMWindowPerformance.h" #include "core/timing/Performance.h" @@ -1952,14 +1953,14 @@ newSize, topControls().height(), topControls().shrinkViewport()); } -void WebViewImpl::didEnterFullScreen() +void WebViewImpl::didEnterFullscreen() { - m_fullscreenController->didEnterFullScreen(); + m_fullscreenController->didEnterFullscreen(); } -void WebViewImpl::didExitFullScreen() +void WebViewImpl::didExitFullscreen() { - m_fullscreenController->didExitFullScreen(); + m_fullscreenController->didExitFullscreen(); } void WebViewImpl::didUpdateFullScreenSize() @@ -4192,31 +4193,33 @@ void WebViewImpl::registerViewportLayersWithCompositor() { DCHECK(m_layerTreeView); - DCHECK(!page()->deprecatedLocalMainFrame()->contentLayoutItem().isNull()); - PaintLayerCompositor* compositor = - page()->deprecatedLocalMainFrame()->contentLayoutItem().compositor(); + if (!page()->mainFrame() || !page()->mainFrame()->isLocalFrame()) + return; - DCHECK(compositor); + Document* document = page()->deprecatedLocalMainFrame()->document(); + + DCHECK(document); // Get the outer viewport scroll layer. - WebLayer* scrollLayer = - compositor->scrollLayer() - ? compositor->scrollLayer()->platformLayer() - : nullptr; + GraphicsLayer* layoutViewportScrollLayer = + document->rootScrollerController()->rootScrollerLayer(); + WebLayer* layoutViewportWebLayer = layoutViewportScrollLayer + ? layoutViewportScrollLayer->platformLayer() + : nullptr; VisualViewport& visualViewport = page()->frameHost().visualViewport(); // TODO(bokan): This was moved here from when registerViewportLayers was a // part of VisualViewport and maybe doesn't belong here. See comment inside // the mehtod. - visualViewport.setScrollLayerOnScrollbars(scrollLayer); + visualViewport.setScrollLayerOnScrollbars(layoutViewportWebLayer); m_layerTreeView->registerViewportLayers( visualViewport.overscrollElasticityLayer()->platformLayer(), visualViewport.pageScaleLayer()->platformLayer(), visualViewport.scrollLayer()->platformLayer(), - scrollLayer); + layoutViewportWebLayer); } void WebViewImpl::setRootGraphicsLayer(GraphicsLayer* layer)
diff --git a/third_party/WebKit/Source/web/WebViewImpl.h b/third_party/WebKit/Source/web/WebViewImpl.h index 75da1eb..24a70c7 100644 --- a/third_party/WebKit/Source/web/WebViewImpl.h +++ b/third_party/WebKit/Source/web/WebViewImpl.h
@@ -108,8 +108,8 @@ WebSize size() override; void resize(const WebSize&) override; void resizeVisualViewport(const WebSize&) override; - void didEnterFullScreen() override; - void didExitFullScreen() override; + void didEnterFullscreen() override; + void didExitFullscreen() override; void beginFrame(double lastFrameTimeMonotonic) override;
diff --git a/third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp b/third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp index 5ad77bd..763c01b 100644 --- a/third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp +++ b/third_party/WebKit/Source/web/tests/FrameSerializerTest.cpp
@@ -183,7 +183,7 @@ StringBuilder uriBuilder; uriBuilder.append(m_rewriteFolder); - uriBuilder.append("/"); + uriBuilder.append('/'); uriBuilder.append(m_rewriteURLs.get(completeURL)); rewrittenLink = uriBuilder.toString(); return true;
diff --git a/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp b/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp index 46cde927..2fd3ccc 100644 --- a/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp +++ b/third_party/WebKit/Source/web/tests/FrameTestHelpers.cpp
@@ -113,7 +113,7 @@ static int uniqueNameCounter = 0; StringBuilder uniqueName; uniqueName.append(name); - uniqueName.append(" "); + uniqueName.append(' '); uniqueName.appendNumber(uniqueNameCounter++); return uniqueName.toString(); } @@ -123,7 +123,6 @@ void loadFrame(WebFrame* frame, const std::string& url) { WebURLRequest urlRequest; - urlRequest.initialize(); urlRequest.setURL(URLTestHelpers::toKURL(url)); urlRequest.setRequestorOrigin(WebSecurityOrigin::createUnique()); frame->loadRequest(urlRequest);
diff --git a/third_party/WebKit/Source/web/tests/RootScrollerTest.cpp b/third_party/WebKit/Source/web/tests/RootScrollerTest.cpp index 2f48e5c..ae6cd44 100644 --- a/third_party/WebKit/Source/web/tests/RootScrollerTest.cpp +++ b/third_party/WebKit/Source/web/tests/RootScrollerTest.cpp
@@ -7,6 +7,7 @@ #include "core/frame/TopControls.h" #include "core/html/HTMLFrameOwnerElement.h" #include "core/page/Page.h" +#include "core/page/scrolling/RootScrollerController.h" #include "platform/testing/URLTestHelpers.h" #include "platform/testing/UnitTestHelpers.h" #include "public/platform/Platform.h" @@ -155,6 +156,11 @@ return frameHost().topControls(); } + Element* effectiveRootScroller(Document* doc) const + { + return doc->rootScrollerController()->effectiveRootScroller(); + } + protected: std::string m_baseURL; RootScrollerTestWebViewClient m_client; @@ -172,7 +178,7 @@ ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller()); Element* htmlElement = mainFrame()->document()->documentElement(); - EXPECT_EQ(htmlElement, mainFrame()->document()->effectiveRootScroller()); + EXPECT_EQ(htmlElement, effectiveRootScroller(mainFrame()->document())); } // Tests that setting an element as the root scroller causes it to control url @@ -294,13 +300,13 @@ mainFrame()->document()->setRootScroller(container, exceptionState); ASSERT_EQ(container, mainFrame()->document()->rootScroller()); - ASSERT_EQ(container, mainFrame()->document()->effectiveRootScroller()); + ASSERT_EQ(container, effectiveRootScroller(mainFrame()->document())); mainFrame()->document()->body()->removeChild(container); mainFrameView()->updateAllLifecyclePhases(); ASSERT_EQ(container, mainFrame()->document()->rootScroller()); - ASSERT_NE(container, mainFrame()->document()->effectiveRootScroller()); + ASSERT_NE(container, effectiveRootScroller(mainFrame()->document())); } // Tests that setting an element that isn't a valid scroller as the root @@ -317,7 +323,7 @@ mainFrame()->document()->setRootScroller(element, exceptionState); mainFrameView()->updateAllLifecyclePhases(); ASSERT_EQ(element, mainFrame()->document()->rootScroller()); - ASSERT_NE(element, mainFrame()->document()->effectiveRootScroller()); + ASSERT_NE(element, effectiveRootScroller(mainFrame()->document())); } { @@ -327,7 +333,7 @@ mainFrame()->document()->setRootScroller(element, exceptionState); mainFrameView()->updateAllLifecyclePhases(); ASSERT_EQ(element, mainFrame()->document()->rootScroller()); - ASSERT_NE(element, mainFrame()->document()->effectiveRootScroller()); + ASSERT_NE(element, effectiveRootScroller(mainFrame()->document())); } } @@ -342,14 +348,14 @@ TrackExceptionState exceptionState; ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller()); - ASSERT_EQ(htmlElement, mainFrame()->document()->effectiveRootScroller()); + ASSERT_EQ(htmlElement, effectiveRootScroller(mainFrame()->document())); { mainFrame()->document()->setRootScroller(container, exceptionState); mainFrameView()->updateAllLifecyclePhases(); ASSERT_EQ(container, mainFrame()->document()->rootScroller()); - ASSERT_EQ(container, mainFrame()->document()->effectiveRootScroller()); + ASSERT_EQ(container, effectiveRootScroller(mainFrame()->document())); executeScript( "document.querySelector('#container').style.display = 'inline'"); @@ -357,7 +363,7 @@ ASSERT_EQ(container, mainFrame()->document()->rootScroller()); ASSERT_EQ(htmlElement, - mainFrame()->document()->effectiveRootScroller()); + effectiveRootScroller(mainFrame()->document())); } executeScript( @@ -365,14 +371,14 @@ mainFrame()->document()->setRootScroller(nullptr, exceptionState); mainFrameView()->updateAllLifecyclePhases(); ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller()); - ASSERT_EQ(htmlElement, mainFrame()->document()->effectiveRootScroller()); + ASSERT_EQ(htmlElement, effectiveRootScroller(mainFrame()->document())); { mainFrame()->document()->setRootScroller(container, exceptionState); mainFrameView()->updateAllLifecyclePhases(); ASSERT_EQ(container, mainFrame()->document()->rootScroller()); - ASSERT_EQ(container, mainFrame()->document()->effectiveRootScroller()); + ASSERT_EQ(container, effectiveRootScroller(mainFrame()->document())); executeScript( "document.querySelector('#container').style.width = '98%'"); @@ -380,7 +386,7 @@ ASSERT_EQ(container, mainFrame()->document()->rootScroller()); ASSERT_EQ(htmlElement, - mainFrame()->document()->effectiveRootScroller()); + effectiveRootScroller(mainFrame()->document())); } } @@ -407,7 +413,7 @@ ASSERT_EQ(innerContainer, mainFrame()->document()->rootScroller()); ASSERT_EQ(innerContainer, - mainFrame()->document()->effectiveRootScroller()); + effectiveRootScroller(mainFrame()->document())); } { @@ -420,7 +426,7 @@ mainFrameView()->updateAllLifecyclePhases(); ASSERT_EQ(iframe, mainFrame()->document()->rootScroller()); - ASSERT_EQ(iframe, mainFrame()->document()->effectiveRootScroller()); + ASSERT_EQ(iframe, effectiveRootScroller(mainFrame()->document())); } } @@ -437,7 +443,7 @@ mainFrame()->document()->getElementById("iframe")); ASSERT_EQ(iframe->contentDocument()->documentElement(), - iframe->contentDocument()->effectiveRootScroller()); + effectiveRootScroller(iframe->contentDocument())); Element* innerContainer = iframe->contentDocument()->getElementById("container"); @@ -449,7 +455,7 @@ ASSERT_EQ(innerContainer, iframe->contentDocument()->rootScroller()); ASSERT_EQ(innerContainer, - iframe->contentDocument()->effectiveRootScroller()); + effectiveRootScroller(iframe->contentDocument())); } }
diff --git a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp index 12fa421..6cf1755 100644 --- a/third_party/WebKit/Source/web/tests/WebFrameTest.cpp +++ b/third_party/WebKit/Source/web/tests/WebFrameTest.cpp
@@ -3320,7 +3320,6 @@ FrameTestHelpers::WebViewHelper webViewHelper(this); webViewHelper.initialize(); WebURLRequest request; - request.initialize(); request.setURL(toKURL(m_baseURL + "fixed_layout.html")); request.setRequestorOrigin(WebSecurityOrigin::createUnique()); webViewHelper.webView()->mainFrame()->loadRequest(request); @@ -6288,7 +6287,6 @@ WebFrame* frame = webViewHelper.webView()->mainFrame(); const FrameLoader& mainFrameLoader = webViewHelper.webViewImpl()->mainFrameImpl()->frame()->loader(); WebURLRequest request; - request.initialize(); request.setURL(toKURL(url)); request.setRequestorOrigin(WebSecurityOrigin::createUnique()); frame->loadRequest(request); @@ -6470,7 +6468,7 @@ UserGestureIndicator gesture(DefinitelyProcessingUserGesture); Element* divFullscreen = document->getElementById("div1"); Fullscreen::from(*document).requestFullscreen(*divFullscreen, Fullscreen::PrefixedRequest); - webViewImpl->didEnterFullScreen(); + webViewImpl->didEnterFullscreen(); webViewImpl->updateAllLifecyclePhases(); ASSERT_TRUE(Fullscreen::isFullScreen(*document)); @@ -6503,7 +6501,7 @@ UserGestureIndicator gesture(DefinitelyProcessingUserGesture); Element* divFullscreen = document->getElementById("div1"); Fullscreen::from(*document).requestFullscreen(*divFullscreen, Fullscreen::PrefixedRequest); - webViewImpl->didEnterFullScreen(); + webViewImpl->didEnterFullscreen(); webViewImpl->updateAllLifecyclePhases(); // Verify that the viewports are nonscrollable. @@ -6517,7 +6515,7 @@ ASSERT_FALSE(visualViewportScrollLayer->userScrollableVertical()); // Verify that the viewports are scrollable upon exiting fullscreen. - webViewImpl->didExitFullScreen(); + webViewImpl->didExitFullscreen(); webViewImpl->updateAllLifecyclePhases(); ASSERT_FALSE(Fullscreen::isFullScreen(*document)); ASSERT_TRUE(layoutViewportScrollLayer->userScrollableHorizontal()); @@ -6540,7 +6538,7 @@ Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document(); UserGestureIndicator gesture(DefinitelyProcessingUserGesture); Fullscreen::from(*document).requestFullscreen(*document->documentElement(), Fullscreen::PrefixedRequest); - webViewImpl->didEnterFullScreen(); + webViewImpl->didEnterFullscreen(); webViewImpl->updateAllLifecyclePhases(); // Verify that the main frame is still scrollable. @@ -6575,7 +6573,7 @@ UserGestureIndicator gesture(DefinitelyProcessingUserGesture); Element* divFullscreen = document->getElementById("div1"); Fullscreen::from(*document).requestFullscreen(*divFullscreen, Fullscreen::PrefixedRequest); - webViewImpl->didEnterFullScreen(); + webViewImpl->didEnterFullscreen(); webViewImpl->updateAllLifecyclePhases(); // Verify that the element is sized to the viewport. @@ -6615,7 +6613,7 @@ Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document(); UserGestureIndicator gesture(DefinitelyProcessingUserGesture); Fullscreen::from(*document).requestFullscreen(*document->documentElement(), Fullscreen::PrefixedRequest); - webViewImpl->didEnterFullScreen(); + webViewImpl->didEnterFullscreen(); webViewImpl->updateAllLifecyclePhases(); EXPECT_EQ(384, layoutViewItem.logicalWidth().floor()); EXPECT_EQ(640, layoutViewItem.logicalHeight().floor()); @@ -6623,7 +6621,7 @@ EXPECT_FLOAT_EQ(1.0, webViewImpl->minimumPageScaleFactor()); EXPECT_FLOAT_EQ(1.0, webViewImpl->maximumPageScaleFactor()); - webViewImpl->didExitFullScreen(); + webViewImpl->didExitFullscreen(); webViewImpl->updateAllLifecyclePhases(); EXPECT_EQ(320, layoutViewItem.logicalWidth().floor()); EXPECT_EQ(533, layoutViewItem.logicalHeight().floor()); @@ -6649,7 +6647,7 @@ Document* document = toWebLocalFrameImpl(webViewImpl->mainFrame())->frame()->document(); UserGestureIndicator gesture(DefinitelyProcessingUserGesture); Fullscreen::from(*document).requestFullscreen(*document->documentElement(), Fullscreen::PrefixedRequest); - webViewImpl->didEnterFullScreen(); + webViewImpl->didEnterFullscreen(); webViewImpl->updateAllLifecyclePhases(); EXPECT_EQ(384, layoutViewItem.logicalWidth().floor()); EXPECT_EQ(640, layoutViewItem.logicalHeight().floor()); @@ -6669,7 +6667,7 @@ EXPECT_FLOAT_EQ(1.0, webViewImpl->minimumPageScaleFactor()); EXPECT_FLOAT_EQ(1.0, webViewImpl->maximumPageScaleFactor()); - webViewImpl->didExitFullScreen(); + webViewImpl->didExitFullscreen(); webViewImpl->updateAllLifecyclePhases(); EXPECT_EQ(320, layoutViewItem.logicalWidth().floor()); EXPECT_EQ(192, layoutViewItem.logicalHeight().floor()); @@ -6708,7 +6706,7 @@ Fullscreen::from(*document).requestFullscreen(*document->body(), Fullscreen::PrefixedRequest); } - webViewImpl->didEnterFullScreen(); + webViewImpl->didEnterFullscreen(); webViewImpl->updateAllLifecyclePhases(); client.m_screenInfo.rect.width = screenSizeMinusStatusBars.width; client.m_screenInfo.rect.height = screenSizeMinusStatusBars.height; @@ -6722,7 +6720,7 @@ EXPECT_FLOAT_EQ(1.0, webViewImpl->minimumPageScaleFactor()); EXPECT_FLOAT_EQ(1.0, webViewImpl->maximumPageScaleFactor()); - webViewImpl->didExitFullScreen(); + webViewImpl->didExitFullscreen(); webViewImpl->updateAllLifecyclePhases(); client.m_screenInfo.rect.width = screenSizeMinusStatusBars.width; client.m_screenInfo.rect.height = screenSizeMinusStatusBars.height; @@ -6772,7 +6770,7 @@ UserGestureIndicator gesture(DefinitelyProcessingUserGesture); Fullscreen::from(*document).requestFullscreen( *document->documentElement(), Fullscreen::PrefixedRequest); - webViewImpl->didEnterFullScreen(); + webViewImpl->didEnterFullscreen(); webViewImpl->updateAllLifecyclePhases(); // Entering fullscreen causes layout size and page scale limits to be @@ -6789,7 +6787,7 @@ KURL testURL = toKURL("about:blank"); WebFrame* frame = webViewHelper.webView()->mainFrame(); FrameTestHelpers::loadHTMLString(frame, source, testURL); - webViewImpl->didExitFullScreen(); + webViewImpl->didExitFullscreen(); webViewImpl->updateAllLifecyclePhases(); // Make sure the new page's layout size and scale factor limits aren't @@ -8808,7 +8806,6 @@ WebURLRequest request; std::string redirectURL = m_baseURL + "foo.html"; URLTestHelpers::registerMockedURLLoad(toKURL(redirectURL), "foo.html"); - request.initialize(); request.setURL(toKURL("javascript:location='" + redirectURL + "'")); request.setRequestorOrigin(WebSecurityOrigin::createUnique()); helper.webViewImpl()->mainFrame()->toWebLocalFrame()->loadRequest(request);
diff --git a/third_party/WebKit/Source/web/tests/WebURLRequestTest.cpp b/third_party/WebKit/Source/web/tests/WebURLRequestTest.cpp index 8e4ab33..fac8a317 100644 --- a/third_party/WebKit/Source/web/tests/WebURLRequestTest.cpp +++ b/third_party/WebKit/Source/web/tests/WebURLRequestTest.cpp
@@ -60,7 +60,6 @@ TestExtraData* extraData = new TestExtraData(&alive); EXPECT_TRUE(alive); - urlRequest.initialize(); urlRequest.setExtraData(extraData); EXPECT_EQ(extraData, urlRequest.getExtraData()); {
diff --git a/third_party/WebKit/Source/web/tests/WebViewTest.cpp b/third_party/WebKit/Source/web/tests/WebViewTest.cpp index fdd36128..3d5dab5 100644 --- a/third_party/WebKit/Source/web/tests/WebViewTest.cpp +++ b/third_party/WebKit/Source/web/tests/WebViewTest.cpp
@@ -1186,7 +1186,7 @@ Element* element = static_cast<Element*>(webViewImpl->mainFrame()->document().body()); webViewImpl->enterFullScreenForElement(element); - webViewImpl->didEnterFullScreen(); + webViewImpl->didEnterFullscreen(); // Page scale factor must be 1.0 during fullscreen for elements to be sized // properly. @@ -1197,7 +1197,7 @@ webViewImpl->enterFullScreenForElement(otherElement); // Confirm that exiting fullscreen restores the parameters. - webViewImpl->didExitFullScreen(); + webViewImpl->didExitFullscreen(); EXPECT_EQ(2.0f, webViewImpl->pageScaleFactor()); EXPECT_EQ(94, webViewImpl->mainFrame()->scrollOffset().width); EXPECT_EQ(111, webViewImpl->mainFrame()->scrollOffset().height); @@ -2057,7 +2057,6 @@ // Make a request from a local frame. WebURLRequest webURLRequestWithTargetStart; - webURLRequestWithTargetStart.initialize(); LocalFrame* localFrame = toWebLocalFrameImpl(webViewImpl->mainFrame()->firstChild())->frame(); FrameLoadRequest requestWithTargetStart(localFrame->document(), webURLRequestWithTargetStart.toResourceRequest(), "_top"); localFrame->loader().load(requestWithTargetStart); @@ -2077,7 +2076,6 @@ // Make a request that will open a new window WebURLRequest webURLRequest; - webURLRequest.initialize(); FrameLoadRequest request(0, webURLRequest.toResourceRequest(), "_blank"); toLocalFrame(webViewImpl->page()->mainFrame())->loader().load(request); ASSERT_TRUE(client.createdWebView()); @@ -2085,7 +2083,6 @@ // Make a request from the new window that will navigate the original window. The original window should be focused. WebURLRequest webURLRequestWithTargetStart; - webURLRequestWithTargetStart.initialize(); FrameLoadRequest requestWithTargetStart(0, webURLRequestWithTargetStart.toResourceRequest(), "_start"); toLocalFrame(toWebViewImpl(client.createdWebView())->page()->mainFrame())->loader().load(requestWithTargetStart); EXPECT_TRUE(client.didFocusCalled());
diff --git a/third_party/WebKit/Source/web/tests/sim/SimTest.cpp b/third_party/WebKit/Source/web/tests/sim/SimTest.cpp index 984f7a1..e583b2d 100644 --- a/third_party/WebKit/Source/web/tests/sim/SimTest.cpp +++ b/third_party/WebKit/Source/web/tests/sim/SimTest.cpp
@@ -41,7 +41,6 @@ void SimTest::loadURL(const String& url) { WebURLRequest request; - request.initialize(); request.setURL(KURL(ParsedURLString, url)); request.setRequestorOrigin(WebSecurityOrigin::createUnique()); webView().mainFrameImpl()->loadRequest(request);
diff --git a/third_party/WebKit/Source/wtf/RetainPtr.h b/third_party/WebKit/Source/wtf/RetainPtr.h index 56c155a..4528231 100644 --- a/third_party/WebKit/Source/wtf/RetainPtr.h +++ b/third_party/WebKit/Source/wtf/RetainPtr.h
@@ -106,11 +106,7 @@ PtrType operator->() const { return m_ptr; } bool operator!() const { return !m_ptr; } - - // This conversion operator allows implicit conversion to bool but not to - // other integer types. - typedef PtrType RetainPtr::*UnspecifiedBoolType; - operator UnspecifiedBoolType() const { return m_ptr ? &RetainPtr::m_ptr : 0; } + explicit operator bool() const { return m_ptr; } RetainPtr& operator=(const RetainPtr&); template <typename U> RetainPtr& operator=(const RetainPtr<U>&);
diff --git a/third_party/WebKit/Source/wtf/WeakPtr.h b/third_party/WebKit/Source/wtf/WeakPtr.h index c377957..8bec53f 100644 --- a/third_party/WebKit/Source/wtf/WeakPtr.h +++ b/third_party/WebKit/Source/wtf/WeakPtr.h
@@ -107,8 +107,7 @@ return get(); } - typedef RefPtr<WeakReference<T>> (WeakPtr::*UnspecifiedBoolType); - operator UnspecifiedBoolType() const { return get() ? &WeakPtr::m_ref : 0; } + explicit operator bool() const { return get(); } private: RefPtr<WeakReference<T>> m_ref;
diff --git a/third_party/WebKit/Source/wtf/text/AtomicString.h b/third_party/WebKit/Source/wtf/text/AtomicString.h index 7345d82..f5d1df0e 100644 --- a/third_party/WebKit/Source/wtf/text/AtomicString.h +++ b/third_party/WebKit/Source/wtf/text/AtomicString.h
@@ -25,6 +25,7 @@ #include "wtf/HashTableDeletedValueType.h" #include "wtf/WTFExport.h" #include "wtf/text/CString.h" +#include "wtf/text/StringView.h" #include "wtf/text/WTFString.h" #include <cstring> #include <iosfwd> @@ -86,21 +87,15 @@ size_t find(const String& s, size_t start = 0, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const { return m_string.find(s, start, caseSensitivity); } - bool startsWith(const String& s, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const - { return m_string.startsWith(s, caseSensitivity); } + bool startsWith(const StringView& prefix, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const + { return m_string.startsWith(prefix, caseSensitivity); } bool startsWith(UChar character) const { return m_string.startsWith(character); } - template<unsigned matchLength> - bool startsWith(const char (&prefix)[matchLength], TextCaseSensitivity caseSensitivity = TextCaseSensitive) const - { return m_string.startsWith<matchLength>(prefix, caseSensitivity); } - bool endsWith(const String& s, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const - { return m_string.endsWith(s, caseSensitivity); } + bool endsWith(const StringView& suffix, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const + { return m_string.endsWith(suffix, caseSensitivity); } bool endsWith(UChar character) const { return m_string.endsWith(character); } - template<unsigned matchLength> - bool endsWith(const char (&prefix)[matchLength], TextCaseSensitivity caseSensitivity = TextCaseSensitive) const - { return m_string.endsWith<matchLength>(prefix, caseSensitivity); } AtomicString lower() const; AtomicString lowerASCII() const; @@ -183,9 +178,6 @@ inline bool equalIgnoringCase(const char* a, const AtomicString& b) { return equalIgnoringCase(reinterpret_cast<const LChar*>(a), b.impl()); } inline bool equalIgnoringCase(const String& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); } -inline bool equalIgnoringASCIICase(const AtomicString& a, const AtomicString& b) { return equalIgnoringASCIICase(a.impl(), b.impl()); } -inline bool equalIgnoringASCIICase(const AtomicString& a, const char* b) { return equalIgnoringASCIICase(a.impl(), reinterpret_cast<const LChar*>(b)); } - // Define external global variables for the commonly used atomic strings. // These are only usable from the main thread. WTF_EXPORT extern const AtomicString& nullAtom; @@ -206,6 +198,13 @@ // double-quotes, and escapes chracters other than ASCII printables. WTF_EXPORT std::ostream& operator<<(std::ostream&, const AtomicString&); +inline StringView::StringView(const AtomicString& string, unsigned offset, unsigned length) + : StringView(string.impl(), offset, length) {} +inline StringView::StringView(const AtomicString& string, unsigned offset) + : StringView(string.impl(), offset) {} +inline StringView::StringView(const AtomicString& string) + : StringView(string.impl()) {} + } // namespace WTF WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(AtomicString);
diff --git a/third_party/WebKit/Source/wtf/text/StringImpl.cpp b/third_party/WebKit/Source/wtf/text/StringImpl.cpp index e7004b92..a18498f 100644 --- a/third_party/WebKit/Source/wtf/text/StringImpl.cpp +++ b/third_party/WebKit/Source/wtf/text/StringImpl.cpp
@@ -707,15 +707,14 @@ return newImpl.release(); } -static inline bool localeIdMatchesLang(const AtomicString& localeId, const char* lang) +static inline bool localeIdMatchesLang(const AtomicString& localeId, const StringView& lang) { - size_t langLength = strlen(lang); - RELEASE_ASSERT(langLength >= 2 && langLength <= 3); - if (!localeId.impl() || !localeId.impl()->startsWithIgnoringCase(lang, langLength)) + RELEASE_ASSERT(lang.length() >= 2 && lang.length() <= 3); + if (!localeId.impl() || !localeId.impl()->startsWithIgnoringCase(lang)) return false; - if (localeId.impl()->length() == langLength) + if (localeId.impl()->length() == lang.length()) return true; - const UChar maybeDelimiter = (*localeId.impl())[langLength]; + const UChar maybeDelimiter = (*localeId.impl())[lang.length()]; return maybeDelimiter == '-' || maybeDelimiter == '_' || maybeDelimiter == '@'; } @@ -1431,26 +1430,6 @@ return findIgnoringASCIICaseInner(searchStart, matchString->characters16(), index, searchLength, matchLength); } -size_t StringImpl::findNextLineStart(unsigned index) -{ - if (is8Bit()) - return WTF::findNextLineStart(characters8(), m_length, index); - return WTF::findNextLineStart(characters16(), m_length, index); -} - -size_t StringImpl::count(LChar c) const -{ - int count = 0; - if (is8Bit()) { - for (size_t i = 0; i < m_length; ++i) - count += characters8()[i] == c; - } else { - for (size_t i = 0; i < m_length; ++i) - count += characters16()[i] == c; - } - return count; -} - size_t StringImpl::reverseFind(UChar c, unsigned index) { if (is8Bit()) @@ -1518,135 +1497,51 @@ return reverseFindInner(characters16(), matchString->characters16(), index, ourLength, matchLength); } -ALWAYS_INLINE static bool equalSubstring(const StringImpl* stringImpl, unsigned startOffset, const LChar* matchString, unsigned matchLength) -{ - ASSERT(stringImpl); - ASSERT(matchLength <= stringImpl->length()); - ASSERT(startOffset + matchLength <= stringImpl->length()); - - if (stringImpl->is8Bit()) - return equal(stringImpl->characters8() + startOffset, matchString, matchLength); - return equal(stringImpl->characters16() + startOffset, matchString, matchLength); -} - bool StringImpl::startsWith(UChar character) const { return m_length && (*this)[0] == character; } -bool StringImpl::startsWith(const char* prefixString, unsigned prefixLength) const +bool StringImpl::startsWith(const StringView& prefix) const { - ASSERT(prefixLength); - if (prefixLength > length()) + if (prefix.length() > length()) return false; - return equalSubstring(this, 0, reinterpret_cast<const LChar*>(prefixString), prefixLength); + if (is8Bit()) { + if (prefix.is8Bit()) + return equal(characters8(), prefix.characters8(), prefix.length()); + return equal(characters8(), prefix.characters16(), prefix.length()); + } + if (prefix.is8Bit()) + return equal(characters16(), prefix.characters8(), prefix.length()); + return equal(characters16(), prefix.characters16(), prefix.length()); } -ALWAYS_INLINE static bool equalSubstring(const StringImpl* stringImpl, unsigned startOffset, const StringImpl* matchString) +bool StringImpl::startsWithIgnoringCase(const StringView& prefix) const { - ASSERT(stringImpl); - ASSERT(matchString); - ASSERT(matchString->length() <= stringImpl->length()); - ASSERT(startOffset + matchString->length() <= stringImpl->length()); - - unsigned matchLength = matchString->length(); - if (matchString->is8Bit()) - return equalSubstring(stringImpl, startOffset, matchString->characters8(), matchLength); - if (stringImpl->is8Bit()) - return equal(stringImpl->characters8() + startOffset, matchString->characters16(), matchLength); - return equal(stringImpl->characters16() + startOffset, matchString->characters16(), matchLength); -} - -bool StringImpl::startsWith(const StringImpl* prefix) const -{ - ASSERT(prefix); - if (prefix->length() > length()) + if (prefix.length() > length()) return false; - return equalSubstring(this, 0, prefix); + if (is8Bit()) { + if (prefix.is8Bit()) + return equalIgnoringCase(characters8(), prefix.characters8(), prefix.length()); + return equalIgnoringCase(characters8(), prefix.characters16(), prefix.length()); + } + if (prefix.is8Bit()) + return equalIgnoringCase(characters16(), prefix.characters8(), prefix.length()); + return equalIgnoringCase(characters16(), prefix.characters16(), prefix.length()); } -ALWAYS_INLINE static bool equalSubstringIgnoringCase(const StringImpl* stringImpl, unsigned startOffset, const LChar* matchString, unsigned matchLength) +bool StringImpl::startsWithIgnoringASCIICase(const StringView& prefix) const { - ASSERT(stringImpl); - ASSERT(matchLength <= stringImpl->length()); - ASSERT(startOffset + matchLength <= stringImpl->length()); - - if (stringImpl->is8Bit()) - return equalIgnoringCase(stringImpl->characters8() + startOffset, matchString, matchLength); - return equalIgnoringCase(stringImpl->characters16() + startOffset, matchString, matchLength); -} - -bool StringImpl::startsWithIgnoringCase(const char* prefixString, unsigned prefixLength) const -{ - ASSERT(prefixLength); - if (prefixLength > length()) + if (prefix.length() > length()) return false; - return equalSubstringIgnoringCase(this, 0, reinterpret_cast<const LChar*>(prefixString), prefixLength); -} - -ALWAYS_INLINE static bool equalSubstringIgnoringCase(const StringImpl* stringImpl, unsigned startOffset, const StringImpl* matchString) -{ - ASSERT(stringImpl); - ASSERT(matchString); - ASSERT(matchString->length() <= stringImpl->length()); - ASSERT(startOffset + matchString->length() <= stringImpl->length()); - - unsigned matchLength = matchString->length(); - if (matchString->is8Bit()) - return equalSubstringIgnoringCase(stringImpl, startOffset, matchString->characters8(), matchLength); - if (stringImpl->is8Bit()) - return equalIgnoringCase(stringImpl->characters8() + startOffset, matchString->characters16(), matchLength); - return equalIgnoringCase(stringImpl->characters16() + startOffset, matchString->characters16(), matchLength); -} - -bool StringImpl::startsWithIgnoringCase(const StringImpl* prefix) const -{ - ASSERT(prefix); - if (prefix->length() > length()) - return false; - return equalSubstringIgnoringCase(this, 0, prefix); -} - -ALWAYS_INLINE static bool equalSubstringIgnoringASCIICase(const StringImpl* stringImpl, unsigned startOffset, const LChar* matchString, unsigned matchLength) -{ - ASSERT(stringImpl); - ASSERT(matchLength <= stringImpl->length()); - ASSERT(startOffset + matchLength <= stringImpl->length()); - - if (stringImpl->is8Bit()) - return equalIgnoringASCIICase(stringImpl->characters8() + startOffset, matchString, matchLength); - return equalIgnoringASCIICase(stringImpl->characters16() + startOffset, matchString, matchLength); -} - -bool StringImpl::startsWithIgnoringASCIICase(const char* prefixString, unsigned prefixLength) const -{ - ASSERT(prefixLength); - if (prefixLength > length()) - return false; - return equalSubstringIgnoringASCIICase(this, 0, reinterpret_cast<const LChar*>(prefixString), prefixLength); -} - -ALWAYS_INLINE static bool equalSubstringIgnoringASCIICase(const StringImpl* stringImpl, unsigned startOffset, const StringImpl* matchString) -{ - ASSERT(stringImpl); - ASSERT(matchString); - ASSERT(matchString->length() <= stringImpl->length()); - ASSERT(startOffset + matchString->length() <= stringImpl->length()); - - unsigned matchLength = matchString->length(); - if (matchString->is8Bit()) - return equalSubstringIgnoringASCIICase(stringImpl, startOffset, matchString->characters8(), matchLength); - if (stringImpl->is8Bit()) - return equalIgnoringASCIICase(stringImpl->characters8() + startOffset, matchString->characters16(), matchLength); - return equalIgnoringASCIICase(stringImpl->characters16() + startOffset, matchString->characters16(), matchLength); -} - -bool StringImpl::startsWithIgnoringASCIICase(const StringImpl* prefix) const -{ - ASSERT(prefix); - if (prefix->length() > length()) - return false; - return equalSubstringIgnoringASCIICase(this, 0, prefix); + if (is8Bit()) { + if (prefix.is8Bit()) + return equalIgnoringASCIICase(characters8(), prefix.characters8(), prefix.length()); + return equalIgnoringASCIICase(characters8(), prefix.characters16(), prefix.length()); + } + if (prefix.is8Bit()) + return equalIgnoringASCIICase(characters16(), prefix.characters8(), prefix.length()); + return equalIgnoringASCIICase(characters16(), prefix.characters16(), prefix.length()); } bool StringImpl::endsWith(UChar character) const @@ -1654,55 +1549,49 @@ return m_length && (*this)[m_length - 1] == character; } -bool StringImpl::endsWith(const char* suffixString, unsigned suffixLength) const +bool StringImpl::endsWith(const StringView& suffix) const { - ASSERT(suffixLength); - if (suffixLength > length()) + if (suffix.length() > length()) return false; - return equalSubstring(this, length() - suffixLength, reinterpret_cast<const LChar*>(suffixString), suffixLength); + unsigned startOffset = length() - suffix.length(); + if (is8Bit()) { + if (suffix.is8Bit()) + return equal(characters8() + startOffset, suffix.characters8(), suffix.length()); + return equal(characters8() + startOffset, suffix.characters16(), suffix.length()); + } + if (suffix.is8Bit()) + return equal(characters16() + startOffset, suffix.characters8(), suffix.length()); + return equal(characters16() + startOffset, suffix.characters16(), suffix.length()); } -bool StringImpl::endsWith(const StringImpl* suffix) const +bool StringImpl::endsWithIgnoringCase(const StringView& suffix) const { - ASSERT(suffix); - unsigned suffixLength = suffix->length(); - if (suffixLength > length()) + if (suffix.length() > length()) return false; - return equalSubstring(this, length() - suffixLength, suffix); + unsigned startOffset = length() - suffix.length(); + if (is8Bit()) { + if (suffix.is8Bit()) + return equalIgnoringCase(characters8() + startOffset, suffix.characters8(), suffix.length()); + return equalIgnoringCase(characters8() + startOffset, suffix.characters16(), suffix.length()); + } + if (suffix.is8Bit()) + return equalIgnoringCase(characters16() + startOffset, suffix.characters8(), suffix.length()); + return equalIgnoringCase(characters16() + startOffset, suffix.characters16(), suffix.length()); } -bool StringImpl::endsWithIgnoringCase(const char* suffixString, unsigned suffixLength) const +bool StringImpl::endsWithIgnoringASCIICase(const StringView& suffix) const { - ASSERT(suffixLength); - if (suffixLength > length()) + if (suffix.length() > length()) return false; - return equalSubstringIgnoringCase(this, length() - suffixLength, reinterpret_cast<const LChar*>(suffixString), suffixLength); -} - -bool StringImpl::endsWithIgnoringCase(const StringImpl* suffix) const -{ - ASSERT(suffix); - unsigned suffixLength = suffix->length(); - if (suffixLength > length()) - return false; - return equalSubstringIgnoringCase(this, length() - suffixLength, suffix); -} - -bool StringImpl::endsWithIgnoringASCIICase(const char* suffixString, unsigned suffixLength) const -{ - ASSERT(suffixLength); - if (suffixLength > length()) - return false; - return equalSubstringIgnoringASCIICase(this, length() - suffixLength, reinterpret_cast<const LChar*>(suffixString), suffixLength); -} - -bool StringImpl::endsWithIgnoringASCIICase(const StringImpl* suffix) const -{ - ASSERT(suffix); - unsigned suffixLength = suffix->length(); - if (suffixLength > length()) - return false; - return equalSubstringIgnoringASCIICase(this, length() - suffixLength, suffix); + unsigned startOffset = length() - suffix.length(); + if (is8Bit()) { + if (suffix.is8Bit()) + return equalIgnoringASCIICase(characters8() + startOffset, suffix.characters8(), suffix.length()); + return equalIgnoringASCIICase(characters8() + startOffset, suffix.characters16(), suffix.length()); + } + if (suffix.is8Bit()) + return equalIgnoringASCIICase(characters16() + startOffset, suffix.characters8(), suffix.length()); + return equalIgnoringASCIICase(characters16() + startOffset, suffix.characters16(), suffix.length()); } PassRefPtr<StringImpl> StringImpl::replace(UChar oldC, UChar newC) @@ -2277,32 +2166,6 @@ return equal(a, b); } -bool equalIgnoringASCIICase(const StringImpl* a, const StringImpl* b) -{ - if (!a || !b) - return !a == !b; - unsigned length = b->length(); - if (a->length() != length) - return false; - if (a->is8Bit()) { - if (b->is8Bit()) - return equalIgnoringASCIICase(a->characters8(), b->characters8(), length); - return equalIgnoringASCIICase(a->characters8(), b->characters16(), length); - } - if (b->is8Bit()) - return equalIgnoringASCIICase(a->characters16(), b->characters8(), length); - return equalIgnoringASCIICase(a->characters16(), b->characters16(), length); -} - -bool equalIgnoringASCIICase(const StringImpl* a, const LChar* b, unsigned length) -{ - if (!a || !b) - return !a == !b; - if (length != a->length()) - return false; - return equalSubstringIgnoringASCIICase(a, 0, b, length); -} - template<typename CharacterType1, typename CharacterType2> int codePointCompareIgnoringASCIICase(unsigned l1, unsigned l2, const CharacterType1* c1, const CharacterType2* c2) {
diff --git a/third_party/WebKit/Source/wtf/text/StringImpl.h b/third_party/WebKit/Source/wtf/text/StringImpl.h index 22897f1..a95a0d9 100644 --- a/third_party/WebKit/Source/wtf/text/StringImpl.h +++ b/third_party/WebKit/Source/wtf/text/StringImpl.h
@@ -379,28 +379,18 @@ size_t findIgnoringCase(StringImpl*, unsigned index = 0); size_t findIgnoringASCIICase(StringImpl*, unsigned index = 0); - size_t findNextLineStart(unsigned index = UINT_MAX); - size_t reverseFind(UChar, unsigned index = UINT_MAX); size_t reverseFind(StringImpl*, unsigned index = UINT_MAX); - size_t count(LChar) const; - bool startsWith(UChar) const; - bool startsWith(const char*, unsigned prefixLength) const; - bool startsWith(const StringImpl*) const; - bool startsWithIgnoringCase(const char*, unsigned prefixLength) const; - bool startsWithIgnoringCase(const StringImpl*) const; - bool startsWithIgnoringASCIICase(const char*, unsigned prefixLength) const; - bool startsWithIgnoringASCIICase(const StringImpl*) const; + bool startsWith(const StringView&) const; + bool startsWithIgnoringCase(const StringView&) const; + bool startsWithIgnoringASCIICase(const StringView&) const; bool endsWith(UChar) const; - bool endsWith(const char*, unsigned suffixLength) const; - bool endsWith(const StringImpl*) const; - bool endsWithIgnoringCase(const char*, unsigned suffixLength) const; - bool endsWithIgnoringCase(const StringImpl*) const; - bool endsWithIgnoringASCIICase(const char*, unsigned suffixLength) const; - bool endsWithIgnoringASCIICase(const StringImpl*) const; + bool endsWith(const StringView&) const; + bool endsWithIgnoringCase(const StringView&) const; + bool endsWithIgnoringASCIICase(const StringView&) const; PassRefPtr<StringImpl> replace(UChar, UChar); PassRefPtr<StringImpl> replace(UChar, StringImpl*); @@ -515,16 +505,6 @@ return true; } -WTF_EXPORT bool equalIgnoringASCIICase(const StringImpl*, const StringImpl*); -WTF_EXPORT bool equalIgnoringASCIICase(const StringImpl*, const LChar*, unsigned length); -inline bool equalIgnoringASCIICase(const StringImpl* a, const char* b, unsigned length) { return equalIgnoringASCIICase(a, reinterpret_cast<const LChar*>(b), length); } -inline bool equalIgnoringASCIICase(const StringImpl* a, const LChar* b) -{ - size_t length = b ? strlen(reinterpret_cast<const char*>(b)) : 0; - return equalIgnoringASCIICase(a, b, length); -} -inline bool equalIgnoringASCIICase(const StringImpl* a, const char* b) { return equalIgnoringASCIICase(a, reinterpret_cast<const LChar*>(b)); } - WTF_EXPORT int codePointCompareIgnoringASCIICase(const StringImpl*, const LChar*); inline size_t find(const LChar* characters, unsigned length, LChar matchCharacter, unsigned index = 0) @@ -586,53 +566,6 @@ } template<typename CharacterType> -inline size_t findNextLineStart(const CharacterType* characters, unsigned length, unsigned index = 0) -{ - while (index < length) { - CharacterType c = characters[index++]; - if ((c != '\n') && (c != '\r')) - continue; - - // There can only be a start of a new line if there are more characters - // beyond the current character. - if (index < length) { - // The 3 common types of line terminators are 1. \r\n (Windows), - // 2. \r (old MacOS) and 3. \n (Unix'es). - - if (c == '\n') - return index; // Case 3: just \n. - - CharacterType c2 = characters[index]; - if (c2 != '\n') - return index; // Case 2: just \r. - - // Case 1: \r\n. - // But, there's only a start of a new line if there are more - // characters beyond the \r\n. - if (++index < length) - return index; - } - } - return kNotFound; -} - -template<typename CharacterType> -inline size_t reverseFindLineTerminator(const CharacterType* characters, unsigned length, unsigned index = UINT_MAX) -{ - if (!length) - return kNotFound; - if (index >= length) - index = length - 1; - CharacterType c = characters[index]; - while ((c != '\n') && (c != '\r')) { - if (!index--) - return kNotFound; - c = characters[index]; - } - return index; -} - -template<typename CharacterType> inline size_t reverseFind(const CharacterType* characters, unsigned length, CharacterType matchCharacter, unsigned index = UINT_MAX) { if (!length)
diff --git a/third_party/WebKit/Source/wtf/text/StringView.cpp b/third_party/WebKit/Source/wtf/text/StringView.cpp index e88703b..115ac206 100644 --- a/third_party/WebKit/Source/wtf/text/StringView.cpp +++ b/third_party/WebKit/Source/wtf/text/StringView.cpp
@@ -4,6 +4,9 @@ #include "wtf/text/StringView.h" +#include "wtf/text/AtomicString.h" +#include "wtf/text/WTFString.h" + namespace WTF { StringView::StringView(const UChar* chars)
diff --git a/third_party/WebKit/Source/wtf/text/StringView.h b/third_party/WebKit/Source/wtf/text/StringView.h index 7b47931..6433c38 100644 --- a/third_party/WebKit/Source/wtf/text/StringView.h +++ b/third_party/WebKit/Source/wtf/text/StringView.h
@@ -10,14 +10,15 @@ #if DCHECK_IS_ON() #include "wtf/RefPtr.h" #endif -#include "wtf/text/AtomicString.h" #include "wtf/text/StringImpl.h" #include "wtf/text/Unicode.h" -#include "wtf/text/WTFString.h" #include <cstring> namespace WTF { +class AtomicString; +class String; + // A string like object that wraps either an 8bit or 16bit byte sequence // and keeps track of the length and the type, it does NOT own the bytes. // @@ -42,25 +43,21 @@ StringView(StringImpl*, unsigned offset); StringView(StringImpl*, unsigned offset, unsigned length); - // From a String: - StringView(const String& string, unsigned offset, unsigned length) - : StringView(string.impl(), offset, length) {} - StringView(const String& string, unsigned offset) - : StringView(string.impl(), offset) {} - StringView(const String& string) - : StringView(string.impl()) {} + // From an String, implemented in String.h + inline StringView(const String&, unsigned offset, unsigned length); + inline StringView(const String&, unsigned offset); + inline StringView(const String&); - // From an AtomicString: - StringView(const AtomicString& string, unsigned offset, unsigned length) - : StringView(string.impl(), offset, length) {} - StringView(const AtomicString& string, unsigned offset) - : StringView(string.impl(), offset) {} - StringView(const AtomicString& string) - : StringView(string.impl()) {} + // From an AtomicString, implemented in AtomicString.h + inline StringView(const AtomicString&, unsigned offset, unsigned length); + inline StringView(const AtomicString&, unsigned offset); + inline StringView(const AtomicString&); // From a literal string or LChar buffer: StringView(const LChar* chars, unsigned length) - : StringView(reinterpret_cast<const void*>(chars), length, true) {} + : m_impl(StringImpl::empty()) + , m_characters8(chars) + , m_length(length) {} StringView(const char* chars, unsigned length) : StringView(reinterpret_cast<const LChar*>(chars), length) {} StringView(const LChar* chars) @@ -70,14 +67,10 @@ // From a wide literal string or UChar buffer. StringView(const UChar* chars, unsigned length) - : StringView(reinterpret_cast<const void*>(chars), length, false) {} - StringView(const UChar* chars); - - // From a byte pointer. - StringView(const void* bytes, unsigned length, bool is8Bit) - : m_impl(is8Bit ? StringImpl::empty() : StringImpl::empty16Bit()) - , m_bytes(bytes) + : m_impl(StringImpl::empty16Bit()) + , m_characters16(chars) , m_length(length) {} + StringView(const UChar* chars); #if DCHECK_IS_ON() ~StringView();
diff --git a/third_party/WebKit/Source/wtf/text/StringViewTest.cpp b/third_party/WebKit/Source/wtf/text/StringViewTest.cpp index 1b0b72e7..6c8c620 100644 --- a/third_party/WebKit/Source/wtf/text/StringViewTest.cpp +++ b/third_party/WebKit/Source/wtf/text/StringViewTest.cpp
@@ -289,20 +289,6 @@ EXPECT_EQ(String("12"), StringView(kChars16, 2).toString()); } -TEST(StringViewTest, ConstructionRawBytes) -{ - // StringView(const void* bytes, unsigned length, bool is8Bit); - StringView view8(reinterpret_cast<const void*>(kChars), 2, true); - ASSERT_TRUE(view8.is8Bit()); - EXPECT_EQ(2u, view8.length()); - EXPECT_EQ("12", view8); - - StringView view16(reinterpret_cast<const void*>(kChars16), 3, false); - ASSERT_FALSE(view16.is8Bit()); - EXPECT_EQ(3u, view16.length()); - EXPECT_EQ("123", view16); -} - TEST(StringViewTest, IsEmpty) { EXPECT_FALSE(StringView(kChars).isEmpty());
diff --git a/third_party/WebKit/Source/wtf/text/WTFString.h b/third_party/WebKit/Source/wtf/text/WTFString.h index 839454d9..54e58a6 100644 --- a/third_party/WebKit/Source/wtf/text/WTFString.h +++ b/third_party/WebKit/Source/wtf/text/WTFString.h
@@ -30,6 +30,7 @@ #include "wtf/WTFExport.h" #include "wtf/text/ASCIIFastPath.h" #include "wtf/text/StringImpl.h" +#include "wtf/text/StringView.h" #include <algorithm> #include <iosfwd> @@ -191,9 +192,6 @@ size_t find(const LChar* str, unsigned start = 0) const { return m_impl ? m_impl->find(str, start) : kNotFound; } - size_t findNextLineStart(unsigned start = 0) const - { return m_impl ? m_impl->findNextLineStart(start) : kNotFound; } - // Find the last instance of a single character or string. size_t reverseFind(UChar c, unsigned start = UINT_MAX) const { return m_impl ? m_impl->reverseFind(c, start) : kNotFound; } @@ -234,21 +232,15 @@ bool contains(const LChar* str, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const { return find(str, 0, caseSensitivity) != kNotFound; } bool contains(const String& str, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const { return find(str, 0, caseSensitivity) != kNotFound; } - bool startsWith(const String& s, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const - { return m_impl ? DISPATCH_CASE_OP(caseSensitivity, m_impl->startsWith, (s.impl())) : s.isEmpty(); } + bool startsWith(const StringView& prefix, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const + { return m_impl ? DISPATCH_CASE_OP(caseSensitivity, m_impl->startsWith, (prefix)) : prefix.isEmpty(); } bool startsWith(UChar character) const { return m_impl ? m_impl->startsWith(character) : false; } - template<unsigned matchLength> - bool startsWith(const char (&prefix)[matchLength], TextCaseSensitivity caseSensitivity = TextCaseSensitive) const - { return m_impl ? DISPATCH_CASE_OP(caseSensitivity, m_impl->startsWith, (prefix, matchLength - 1)) : !matchLength; } - bool endsWith(const String& s, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const - { return m_impl ? DISPATCH_CASE_OP(caseSensitivity, m_impl->endsWith, (s.impl())) : s.isEmpty(); } + bool endsWith(const StringView& suffix, TextCaseSensitivity caseSensitivity = TextCaseSensitive) const + { return m_impl ? DISPATCH_CASE_OP(caseSensitivity, m_impl->endsWith, (suffix)) : suffix.isEmpty(); } bool endsWith(UChar character) const { return m_impl ? m_impl->endsWith(character) : false; } - template<unsigned matchLength> - bool endsWith(const char (&prefix)[matchLength], TextCaseSensitivity caseSensitivity = TextCaseSensitive) const - { return m_impl ? DISPATCH_CASE_OP(caseSensitivity, m_impl->endsWith, (prefix, matchLength - 1)) : !matchLength; } void append(const String&); void append(LChar); @@ -457,10 +449,6 @@ inline bool equalIgnoringCase(const LChar* a, const String& b) { return equalIgnoringCase(a, b.impl()); } inline bool equalIgnoringCase(const char* a, const String& b) { return equalIgnoringCase(reinterpret_cast<const LChar*>(a), b.impl()); } -inline bool equalIgnoringASCIICase(const String& a, const String& b) { return equalIgnoringASCIICase(a.impl(), b.impl()); } -inline bool equalIgnoringASCIICase(const String& a, const LChar* b) { return equalIgnoringASCIICase(a.impl(), b); } -inline bool equalIgnoringASCIICase(const String& a, const char* b) { return equalIgnoringASCIICase(a.impl(), b); } - inline bool equalPossiblyIgnoringCase(const String& a, const String& b, bool ignoreCase) { return ignoreCase ? equalIgnoringCase(a, b) : (a == b); @@ -639,6 +627,13 @@ // double-quotes, and escapes chracters other than ASCII printables. WTF_EXPORT std::ostream& operator<<(std::ostream&, const String&); +inline StringView::StringView(const String& string, unsigned offset, unsigned length) + : StringView(string.impl(), offset, length) {} +inline StringView::StringView(const String& string, unsigned offset) + : StringView(string.impl(), offset) {} +inline StringView::StringView(const String& string) + : StringView(string.impl()) {} + } // namespace WTF WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(String);
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py index bd8cdf11..d8617bb 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs.py
@@ -11,6 +11,7 @@ import logging import optparse +from webkitpy.common.checkout.scm.git import Git from webkitpy.common.net.rietveld import latest_try_jobs from webkitpy.common.net.web import Web from webkitpy.layout_tests.models.test_expectations import BASELINE_SUFFIX_LIST @@ -29,7 +30,7 @@ super(RebaselineFromTryJobs, self).__init__(options=[ optparse.make_option( '--issue', type='int', default=None, - help='Rietveld issue number.'), + help='Rietveld issue number; if none given, this will be obtained via `git cl issue`.'), optparse.make_option( '--dry-run', action='store_true', default=False, help='Dry run mode; list actions that would be performed but do not do anything.'), @@ -39,25 +40,40 @@ self.web = Web() def execute(self, options, args, tool): - if not options.issue: - # TODO(qyearsley): If no issue number is given, get the one for the current branch. - _log.info('No issue number provided.') + issue_number = self._get_issue_number(options) + if not issue_number: return - if args: test_prefix_list = {} - try_jobs = latest_try_jobs(options.issue, self._try_bots(), self.web) + try_jobs = latest_try_jobs(issue_number, self._try_bots(), self.web) builders = [j.builder_name for j in try_jobs] for t in args: test_prefix_list[t] = {b: BASELINE_SUFFIX_LIST for b in builders} else: - test_prefix_list = self._test_prefix_list(options.issue) + test_prefix_list = self._test_prefix_list(issue_number) self._log_test_prefix_list(test_prefix_list) if options.dry_run: return self._rebaseline(options, test_prefix_list, skip_checking_actual_results=True) + def _get_issue_number(self, options): + """Gets the Rietveld CL number from either |options| or from the current local branch.""" + if options.issue: + return options.issue + issue_number = self._git().get_issue_number() + _log.debug('Issue number for current branch: %s' % issue_number) + if not issue_number.isdigit(): + _log.error('No issue number given and no issue for current branch.') + return None + return int(issue_number) + + def _git(self): + """Returns a Git instance; can be overridden for tests.""" + # Pass in a current working directory inside of the repo so + # that this command can be called from outside of the repo. + return Git(cwd=self._tool.filesystem.dirname(self._tool.path())) + def _test_prefix_list(self, issue_number): """Returns a collection of test, builder and file extensions to get new baselines for.""" builders_to_tests = self._builders_to_tests(issue_number)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py index 30820fca..b8650b68 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_from_try_jobs_unittest.py
@@ -11,6 +11,7 @@ from webkitpy.tool.commands.rebaseline_unittest import BaseTestCase from webkitpy.tool.mock_tool import MockOptions from webkitpy.layout_tests.builder_list import BuilderList +from webkitpy.common.checkout.scm.scm_mock import MockSCM class RebaselineFromTryJobsTest(BaseTestCase): @@ -47,16 +48,29 @@ "is_try_builder": True, }, }) + self.git = MockSCM() + self.git.get_issue_number = lambda: 'None' + self.command._git = lambda: self.git + + @staticmethod + def command_options(**kwargs): + options = { + 'issue': None, + 'dry_run': False, + 'optimize': True, + 'verbose': False, + } + options.update(kwargs) + return MockOptions(**options) def test_execute_with_issue_number_given(self): oc = OutputCapture() try: oc.capture_output() - options = MockOptions(issue=11112222, dry_run=False, optimize=True, verbose=False) - self.command.execute(options, [], self.tool) + self.command.execute(self.command_options(issue=11112222), [], self.tool) finally: _, _, logs = oc.restore_output() - self.assertEqual( + self.assertMultiLineEqual( logs, ('Tests to rebaseline:\n' ' svg/dynamic-updates/SVGFEDropShadowElement-dom-stdDeviation-attr.html: MOCK Try Win\n' @@ -70,7 +84,25 @@ oc = OutputCapture() try: oc.capture_output() - self.command.execute(MockOptions(issue=None), [], self.tool) + self.command.execute(self.command_options(), [], self.tool) finally: _, _, logs = oc.restore_output() - self.assertEqual(logs, 'No issue number provided.\n') + self.assertEqual(logs, 'No issue number given and no issue for current branch.\n') + + def test_execute_with_issue_number_from_branch(self): + self.git.get_issue_number = lambda: '11112222' + oc = OutputCapture() + try: + oc.capture_output() + self.command.execute(self.command_options(), [], self.tool) + finally: + _, _, logs = oc.restore_output() + self.assertMultiLineEqual( + logs, + ('Tests to rebaseline:\n' + ' svg/dynamic-updates/SVGFEDropShadowElement-dom-stdDeviation-attr.html: MOCK Try Win\n' + ' fast/dom/prototype-inheritance.html: MOCK Try Win\n' + ' fast/dom/prototype-taco.html: MOCK Try Win\n' + 'Rebaselining fast/dom/prototype-inheritance.html\n' + 'Rebaselining fast/dom/prototype-taco.html\n' + 'Rebaselining svg/dynamic-updates/SVGFEDropShadowElement-dom-stdDeviation-attr.html\n'))
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py index 03a437f..152b5f74 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater.py
@@ -202,9 +202,6 @@ return False dir_from_wpt = fs.relpath(dirname, self.path_from_webkit_base('LayoutTests', 'imported', 'wpt')) automation_dir = self.path_from_webkit_base('LayoutTests', 'imported', 'wpt_automation', dir_from_wpt) - # TODO(qyearsley): Update this when all *-input.js are renamed to *-automation.js. - if fs.isfile(fs.join(automation_dir, '%s-input.js' % basename_without_extension)): - return False if fs.isfile(fs.join(automation_dir, '%s-automation.js' % basename_without_extension)): return False return True
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py index 5789130..f1b31e6 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/deps_updater_unittest.py
@@ -66,5 +66,5 @@ imported_dir + 'wpt_automation/a/x-manual-input.js': '', imported_dir + 'wpt_automation/a/y-manual-automation.js': '', }) + self.assertTrue(updater.is_manual_test(fs, imported_dir + 'wpt/a', 'x-manual.html')) self.assertFalse(updater.is_manual_test(fs, imported_dir + 'wpt/a', 'y-manual.html')) - self.assertFalse(updater.is_manual_test(fs, imported_dir + 'wpt/a', 'x-manual.html'))
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn index 12057da..5a9f7ac5 100644 --- a/third_party/WebKit/public/BUILD.gn +++ b/third_party/WebKit/public/BUILD.gn
@@ -164,6 +164,7 @@ "platform/modules/background_sync/background_sync.mojom", "platform/modules/bluetooth/web_bluetooth.mojom", "platform/modules/geolocation/geolocation.mojom", + "platform/modules/hyphenation/hyphenation.mojom", "platform/modules/notifications/notification.mojom", "platform/modules/notifications/notification_service.mojom", "platform/modules/offscreencanvas/offscreen_canvas_surface.mojom",
diff --git a/third_party/WebKit/public/blink.gyp b/third_party/WebKit/public/blink.gyp index 7a443094..ec66f60b 100644 --- a/third_party/WebKit/public/blink.gyp +++ b/third_party/WebKit/public/blink.gyp
@@ -38,6 +38,7 @@ 'platform/modules/background_sync/background_sync.mojom', 'platform/modules/bluetooth/web_bluetooth.mojom', 'platform/modules/geolocation/geolocation.mojom', + 'platform/modules/hyphenation/hyphenation.mojom', 'platform/modules/notifications/notification.mojom', 'platform/modules/notifications/notification_service.mojom', 'platform/modules/offscreencanvas/offscreen_canvas_surface.mojom',
diff --git a/third_party/WebKit/public/blink_headers.gypi b/third_party/WebKit/public/blink_headers.gypi index b7e9a2b..c5f74b8 100644 --- a/third_party/WebKit/public/blink_headers.gypi +++ b/third_party/WebKit/public/blink_headers.gypi
@@ -152,7 +152,6 @@ "platform/WebPrerender.h", "platform/WebPrerenderingSupport.h", "platform/WebPrescientNetworking.h", - "platform/WebPrivateOwnPtr.h", "platform/WebPrivatePtr.h", "platform/WebPublicSuffixList.h", "platform/WebRTCCertificate.h",
diff --git a/third_party/WebKit/public/platform/WebBlobData.h b/third_party/WebKit/public/platform/WebBlobData.h index 6c028ae..00e27c8 100644 --- a/third_party/WebKit/public/platform/WebBlobData.h +++ b/third_party/WebKit/public/platform/WebBlobData.h
@@ -32,7 +32,6 @@ #define WebBlobData_h #include "WebNonCopyable.h" -#include "WebPrivateOwnPtr.h" #include "WebString.h" #include "WebThreadSafeData.h" #include "WebURL.h" @@ -83,7 +82,7 @@ #endif private: - WebPrivateOwnPtr<BlobData> m_private; + std::unique_ptr<BlobData> m_private; }; } // namespace blink
diff --git a/third_party/WebKit/public/platform/WebCrypto.h b/third_party/WebKit/public/platform/WebCrypto.h index d327197..cfd49c5 100644 --- a/third_party/WebKit/public/platform/WebCrypto.h +++ b/third_party/WebKit/public/platform/WebCrypto.h
@@ -38,6 +38,8 @@ #include "WebString.h" #include "WebVector.h" +#include <memory> + #if INSIDE_BLINK #include "platform/heap/Handle.h" #endif @@ -214,11 +216,8 @@ // This is the exception to the "Completing the request" guarantees // outlined above. This is useful for Blink internal crypto and is not part // of the WebCrypto standard. createDigestor must provide the result via - // the WebCryptoDigestor object synchronously. createDigestor may return 0 - // if it fails to create a WebCryptoDigestor. If it succeeds, the - // WebCryptoDigestor returned by createDigestor must be freed by the - // caller. - virtual WebCryptoDigestor* createDigestor(WebCryptoAlgorithmId algorithmId) { return nullptr; } + // the WebCryptoDigestor object synchronously. This will never return null. + virtual std::unique_ptr<WebCryptoDigestor> createDigestor(WebCryptoAlgorithmId algorithmId) { return nullptr; } // ----------------------- // Structured clone
diff --git a/third_party/WebKit/public/platform/WebFont.h b/third_party/WebKit/public/platform/WebFont.h index 6084238..97b436b5 100644 --- a/third_party/WebKit/public/platform/WebFont.h +++ b/third_party/WebKit/public/platform/WebFont.h
@@ -8,7 +8,7 @@ #include "WebCanvas.h" #include "WebColor.h" #include "WebCommon.h" -#include "WebPrivateOwnPtr.h" +#include <memory> namespace blink { @@ -45,7 +45,7 @@ explicit WebFont(const WebFontDescription&); class Impl; - WebPrivateOwnPtr<Impl> m_private; + std::unique_ptr<Impl> m_private; }; } // namespace blink
diff --git a/third_party/WebKit/public/platform/WebLayerTreeView.h b/third_party/WebKit/public/platform/WebLayerTreeView.h index 6c8770c4..48f41ae 100644 --- a/third_party/WebKit/public/platform/WebLayerTreeView.h +++ b/third_party/WebKit/public/platform/WebLayerTreeView.h
@@ -31,8 +31,6 @@ #include "WebCompositorMutatorClient.h" #include "WebEventListenerProperties.h" #include "WebFloatPoint.h" -#include "WebNonCopyable.h" -#include "WebPrivateOwnPtr.h" #include "WebSize.h" #include "WebTopControlsState.h"
diff --git a/third_party/WebKit/public/platform/WebPrivateOwnPtr.h b/third_party/WebKit/public/platform/WebPrivateOwnPtr.h deleted file mode 100644 index 9f29792..0000000 --- a/third_party/WebKit/public/platform/WebPrivateOwnPtr.h +++ /dev/null
@@ -1,113 +0,0 @@ -/* - * Copyright (C) 2010 Google Inc. All rights reserved. - * Copyright (C) 2013 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WebPrivateOwnPtr_h -#define WebPrivateOwnPtr_h - -#include "WebCommon.h" -#include "WebNonCopyable.h" -#include "base/logging.h" -#include <cstddef> - -#if INSIDE_BLINK -#include "wtf/PtrUtil.h" -#include <memory> -#endif - -namespace blink { - -// This class is an implementation detail of the WebKit API. It exists -// to help simplify the implementation of WebKit interfaces that merely -// wrap a pointer to a WebCore class. It's similar to WebPrivatePtr, but it -// wraps a naked pointer rather than a reference counted. -// Note: you must call reset(0) on the implementation side in order to delete -// the WebCore pointer. -template <typename T> -class WebPrivateOwnPtr : public WebNonCopyable { -public: - WebPrivateOwnPtr() : m_ptr(nullptr) {} - WebPrivateOwnPtr(std::nullptr_t) : m_ptr(nullptr) {} - ~WebPrivateOwnPtr() { DCHECK(!m_ptr); } - - explicit WebPrivateOwnPtr(T* ptr) - : m_ptr(ptr) - { - } - - T* get() const { return m_ptr; } - -#if INSIDE_BLINK - template <typename U> - WebPrivateOwnPtr(std::unique_ptr<U>, EnsurePtrConvertibleArgDecl(U, T)); - - void reset(T* ptr) - { - delete m_ptr; - m_ptr = ptr; - } - - void reset(std::unique_ptr<T> o) - { - reset(o.release()); - } - - std::unique_ptr<T> release() - { - T* ptr = m_ptr; - m_ptr = nullptr; - return wrapUnique(ptr); - } - - T& operator*() const - { - DCHECK(m_ptr); - return *m_ptr; - } - - T* operator->() const - { - DCHECK(m_ptr); - return m_ptr; - } -#endif // INSIDE_BLINK - -private: - T* m_ptr; -}; - -#if INSIDE_BLINK -template <typename T> -template <typename U> -inline WebPrivateOwnPtr<T>::WebPrivateOwnPtr(std::unique_ptr<U> o, EnsurePtrConvertibleArgDefn(U, T)) - : m_ptr(o.release()) -{ - static_assert(!std::is_array<T>::value, "Pointers to array must never be converted"); -} -#endif - -} // namespace blink - -#endif
diff --git a/third_party/WebKit/public/platform/WebURLRequest.h b/third_party/WebKit/public/platform/WebURLRequest.h index 3563123..283c90c6 100644 --- a/third_party/WebKit/public/platform/WebURLRequest.h +++ b/third_party/WebKit/public/platform/WebURLRequest.h
@@ -35,6 +35,7 @@ #include "WebCommon.h" #include "WebHTTPBody.h" #include "WebReferrerPolicy.h" +#include <memory> namespace blink { @@ -44,7 +45,6 @@ class WebSecurityOrigin; class WebString; class WebURL; -class WebURLRequestPrivate; enum class WebCachePolicy; class WebURLRequest { @@ -158,25 +158,11 @@ virtual ~ExtraData() { } }; - ~WebURLRequest() { reset(); } - - WebURLRequest() : m_private(0) { } - WebURLRequest(const WebURLRequest& r) : m_private(0) { assign(r); } - WebURLRequest& operator=(const WebURLRequest& r) - { - assign(r); - return *this; - } - - explicit WebURLRequest(const WebURL& url) : m_private(0) - { - initialize(); - setURL(url); - } - - BLINK_PLATFORM_EXPORT void initialize(); - BLINK_PLATFORM_EXPORT void reset(); - BLINK_PLATFORM_EXPORT void assign(const WebURLRequest&); + BLINK_PLATFORM_EXPORT ~WebURLRequest(); + BLINK_PLATFORM_EXPORT WebURLRequest(); + BLINK_PLATFORM_EXPORT WebURLRequest(const WebURLRequest&); + BLINK_PLATFORM_EXPORT explicit WebURLRequest(const WebURL&); + BLINK_PLATFORM_EXPORT WebURLRequest& operator=(const WebURLRequest&); BLINK_PLATFORM_EXPORT bool isNull() const; @@ -323,13 +309,23 @@ #if INSIDE_BLINK BLINK_PLATFORM_EXPORT ResourceRequest& toMutableResourceRequest(); BLINK_PLATFORM_EXPORT const ResourceRequest& toResourceRequest() const; -#endif protected: - BLINK_PLATFORM_EXPORT void assign(WebURLRequestPrivate*); + // Permit subclasses to set arbitrary ResourceRequest pointer as + // |m_resourceRequest|. |m_ownedResourceRequest| is not set in this case. + BLINK_PLATFORM_EXPORT explicit WebURLRequest(ResourceRequest&); +#endif private: - WebURLRequestPrivate* m_private; + struct ResourceRequestContainer; + + // If this instance owns a ResourceRequest then |m_ownedResourceRequest| + // is non-null and |m_resourceRequest| points to the ResourceRequest + // instance it contains. + std::unique_ptr<ResourceRequestContainer> m_ownedResourceRequest; + + // Should never be null. + ResourceRequest* m_resourceRequest; }; } // namespace blink
diff --git a/third_party/WebKit/public/platform/WebURLResponse.h b/third_party/WebKit/public/platform/WebURLResponse.h index 5fbe8b3e..89edecd 100644 --- a/third_party/WebKit/public/platform/WebURLResponse.h +++ b/third_party/WebKit/public/platform/WebURLResponse.h
@@ -33,7 +33,6 @@ #include "public/platform/WebCString.h" #include "public/platform/WebCommon.h" -#include "public/platform/WebPrivateOwnPtr.h" #include "public/platform/WebString.h" #include "public/platform/WebVector.h" #include "public/platform/modules/serviceworker/WebServiceWorkerResponseType.h" @@ -294,9 +293,8 @@ #if INSIDE_BLINK protected: // Permit subclasses to set arbitrary ResourceResponse pointer as - // |m_resourceResponse|. Parameter must be non-null. - // |m_ownedResourceResponse| is not set in this case. - BLINK_PLATFORM_EXPORT explicit WebURLResponse(ResourceResponse*); + // |m_resourceResponse|. |m_ownedResourceResponse| is not set in this case. + BLINK_PLATFORM_EXPORT explicit WebURLResponse(ResourceResponse&); #endif private:
diff --git a/third_party/WebKit/public/platform/modules/hyphenation/OWNERS b/third_party/WebKit/public/platform/modules/hyphenation/OWNERS new file mode 100644 index 0000000..fa10e2f --- /dev/null +++ b/third_party/WebKit/public/platform/modules/hyphenation/OWNERS
@@ -0,0 +1,7 @@ +eae@chromium.org +drott@chromium.org +kojii@chromium.org +szager@chromium.org + +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS \ No newline at end of file
diff --git a/third_party/WebKit/public/platform/modules/hyphenation/hyphenation.mojom b/third_party/WebKit/public/platform/modules/hyphenation/hyphenation.mojom new file mode 100644 index 0000000..65c3d3c8 --- /dev/null +++ b/third_party/WebKit/public/platform/modules/hyphenation/hyphenation.mojom
@@ -0,0 +1,12 @@ +// 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. + +module blink.mojom; + +// Loads hyphenation dictionary. +interface Hyphenation { + // Returns a handle to the raw hyphneation dictionary. + [Sync] + OpenDictionary(string locale) => (handle? hyphenation_dictionary_handle); +};
diff --git a/third_party/WebKit/public/platform/modules/websockets/WebSocketHandle.h b/third_party/WebKit/public/platform/modules/websockets/WebSocketHandle.h index df17eba..189a9bf 100644 --- a/third_party/WebKit/public/platform/modules/websockets/WebSocketHandle.h +++ b/third_party/WebKit/public/platform/modules/websockets/WebSocketHandle.h
@@ -57,7 +57,7 @@ virtual ~WebSocketHandle() { } - virtual void connect(const WebURL&, const WebVector<WebString>& protocols, const WebSecurityOrigin&, const WebString& user_agent_override, WebSocketHandleClient*) = 0; + virtual void connect(const WebURL&, const WebVector<WebString>& protocols, const WebSecurityOrigin&, const WebURL& first_party_for_cookies, const WebString& user_agent_override, WebSocketHandleClient*) = 0; virtual void send(bool fin, MessageType, const char* data, size_t /* size */) = 0; virtual void flowControl(int64_t quota) = 0; virtual void close(unsigned short code, const WebString& reason) = 0;
diff --git a/third_party/WebKit/public/platform/modules/websockets/WebSocketHandshakeResponseInfo.h b/third_party/WebKit/public/platform/modules/websockets/WebSocketHandshakeResponseInfo.h index 74a1b96..ec8847f 100644 --- a/third_party/WebKit/public/platform/modules/websockets/WebSocketHandshakeResponseInfo.h +++ b/third_party/WebKit/public/platform/modules/websockets/WebSocketHandshakeResponseInfo.h
@@ -33,7 +33,7 @@ #include "public/platform/WebCommon.h" #include "public/platform/WebNonCopyable.h" -#include "public/platform/WebPrivateOwnPtr.h" +#include <memory> namespace blink { @@ -55,7 +55,7 @@ #endif // INSIDE_BLINK private: - WebPrivateOwnPtr<WebSocketHandshakeResponse> m_private; + std::unique_ptr<WebSocketHandshakeResponse> m_private; }; } // namespace blink
diff --git a/third_party/WebKit/public/web/WebAXObject.h b/third_party/WebKit/public/web/WebAXObject.h index 9bd99ee..57259bb 100644 --- a/third_party/WebKit/public/web/WebAXObject.h +++ b/third_party/WebKit/public/web/WebAXObject.h
@@ -33,10 +33,10 @@ #include "../platform/WebCommon.h" #include "../platform/WebPoint.h" -#include "../platform/WebPrivateOwnPtr.h" #include "../platform/WebPrivatePtr.h" #include "../platform/WebVector.h" #include "WebAXEnums.h" +#include <memory> #if BLINK_IMPLEMENTATION namespace WTF { template <typename T> class PassRefPtr; } @@ -68,7 +68,7 @@ BLINK_EXPORT WebAXObject root() const; private: - WebPrivateOwnPtr<ScopedAXObjectCache> m_private; + std::unique_ptr<ScopedAXObjectCache> m_private; }; // A container for passing around a reference to AXObject.
diff --git a/third_party/WebKit/public/web/WebFrame.h b/third_party/WebKit/public/web/WebFrame.h index 39f6dc6..5a295c7 100644 --- a/third_party/WebKit/public/web/WebFrame.h +++ b/third_party/WebKit/public/web/WebFrame.h
@@ -40,12 +40,12 @@ #include "public/platform/WebCanvas.h" #include "public/platform/WebInsecureRequestPolicy.h" #include "public/platform/WebMessagePortChannel.h" -#include "public/platform/WebPrivateOwnPtr.h" #include "public/platform/WebReferrerPolicy.h" #include "public/platform/WebURL.h" #include "public/platform/WebURLRequest.h" #include "public/web/WebFrameLoadType.h" #include "public/web/WebTreeScopeType.h" +#include <memory> struct NPObject; @@ -516,7 +516,7 @@ WebFrame* m_lastChild; WebFrame* m_opener; - WebPrivateOwnPtr<OpenedFrameTracker> m_openedFrameTracker; + std::unique_ptr<OpenedFrameTracker> m_openedFrameTracker; }; } // namespace blink
diff --git a/third_party/WebKit/public/web/WebFrameClient.h b/third_party/WebKit/public/web/WebFrameClient.h index 3c34e68ed..2aef5e036 100644 --- a/third_party/WebKit/public/web/WebFrameClient.h +++ b/third_party/WebKit/public/web/WebFrameClient.h
@@ -654,14 +654,11 @@ // Fullscreen ---------------------------------------------------------- // Called to enter/exit fullscreen mode. - // After calling enterFullscreen, WebWidget::{will,Did}EnterFullScreen - // should bound resizing the WebWidget into fullscreen mode. - // Similarly, when exitFullScreen is called, - // WebWidget::{will,Did}ExitFullScreen should bound resizing the WebWidget - // out of fullscreen mode. - // Note: the return value is ignored. - virtual bool enterFullscreen() { return false; } - virtual bool exitFullscreen() { return false; } + // After calling enterFullscreen or exitFullscreen, + // WebWidget::didEnterFullscreen or WebWidget::didExitFullscreen + // respectively will be called once the fullscreen mode has changed. + virtual void enterFullscreen() { } + virtual void exitFullscreen() { } // Sudden termination --------------------------------------------------
diff --git a/third_party/WebKit/public/web/WebRemoteFrame.h b/third_party/WebKit/public/web/WebRemoteFrame.h index 37ca0a3..804d33d 100644 --- a/third_party/WebKit/public/web/WebRemoteFrame.h +++ b/third_party/WebKit/public/web/WebRemoteFrame.h
@@ -68,7 +68,7 @@ // corresponds to the HTMLFrameOwnerElement to be fullscreened. Calling // this prepares FullscreenController to enter fullscreen for that frame // owner. - virtual void willEnterFullScreen() = 0; + virtual void willEnterFullscreen() = 0; // Temporary method to allow embedders to get the script context of a // remote frame. This should only be used by legacy code that has not yet
diff --git a/third_party/WebKit/public/web/WebScopedUserGesture.h b/third_party/WebKit/public/web/WebScopedUserGesture.h index a4e3903..4210f7c0 100644 --- a/third_party/WebKit/public/web/WebScopedUserGesture.h +++ b/third_party/WebKit/public/web/WebScopedUserGesture.h
@@ -31,7 +31,8 @@ #ifndef WebScopedUserGesture_h #define WebScopedUserGesture_h -#include "../platform/WebPrivateOwnPtr.h" +#include "public/platform/WebCommon.h" +#include <memory> namespace blink { @@ -53,16 +54,12 @@ // gesture. class WebScopedUserGesture { public: - explicit WebScopedUserGesture(const WebUserGestureToken& token) { initializeWithToken(token); } - WebScopedUserGesture() { initialize(); } - ~WebScopedUserGesture() { reset(); } + BLINK_EXPORT explicit WebScopedUserGesture(const WebUserGestureToken& token); + BLINK_EXPORT WebScopedUserGesture(); + BLINK_EXPORT ~WebScopedUserGesture(); private: - BLINK_EXPORT void initialize(); - BLINK_EXPORT void initializeWithToken(const WebUserGestureToken&); - BLINK_EXPORT void reset(); - - WebPrivateOwnPtr<UserGestureIndicator> m_indicator; + std::unique_ptr<UserGestureIndicator> m_indicator; }; } // namespace blink
diff --git a/third_party/WebKit/public/web/WebScopedWindowFocusAllowedIndicator.h b/third_party/WebKit/public/web/WebScopedWindowFocusAllowedIndicator.h index 2a020b5..31c36f40 100644 --- a/third_party/WebKit/public/web/WebScopedWindowFocusAllowedIndicator.h +++ b/third_party/WebKit/public/web/WebScopedWindowFocusAllowedIndicator.h
@@ -31,7 +31,8 @@ #ifndef WebScopedWindowFocusAllowedIndicator_h #define WebScopedWindowFocusAllowedIndicator_h -#include "public/platform/WebPrivateOwnPtr.h" +#include "public/platform/WebCommon.h" +#include <memory> namespace blink { @@ -40,14 +41,11 @@ class WebScopedWindowFocusAllowedIndicator { public: - explicit WebScopedWindowFocusAllowedIndicator(WebDocument* document) { initialize(document); } - ~WebScopedWindowFocusAllowedIndicator() { reset(); } + BLINK_EXPORT explicit WebScopedWindowFocusAllowedIndicator(WebDocument* document); + BLINK_EXPORT ~WebScopedWindowFocusAllowedIndicator(); private: - BLINK_EXPORT void initialize(WebDocument*); - BLINK_EXPORT void reset(); - - WebPrivateOwnPtr<ScopedWindowFocusAllowedIndicator> m_private; + std::unique_ptr<ScopedWindowFocusAllowedIndicator> m_private; }; }
diff --git a/third_party/WebKit/public/web/WebSurroundingText.h b/third_party/WebKit/public/web/WebSurroundingText.h index 464837c3..4b7af237 100644 --- a/third_party/WebKit/public/web/WebSurroundingText.h +++ b/third_party/WebKit/public/web/WebSurroundingText.h
@@ -25,10 +25,10 @@ #ifndef WebSurroundingText_h #define WebSurroundingText_h -#include "../platform/WebPrivateOwnPtr.h" #include "../platform/WebString.h" #include "WebNode.h" #include "WebRange.h" +#include <memory> namespace blink { @@ -41,11 +41,10 @@ // API. It allows caller to know the text surrounding a point or a range. class WebSurroundingText { public: - WebSurroundingText() { } - ~WebSurroundingText() { reset(); } + BLINK_EXPORT WebSurroundingText(); + BLINK_EXPORT ~WebSurroundingText(); BLINK_EXPORT bool isNull() const; - BLINK_EXPORT void reset(); // Initializes the object to get the surrounding text centered in the // position relative to a provided node. @@ -78,7 +77,7 @@ BLINK_EXPORT WebRange rangeFromContentOffsets(size_t startOffsetInContent, size_t endOffsetInContent); protected: - WebPrivateOwnPtr<SurroundingText> m_private; + std::unique_ptr<SurroundingText> m_private; }; } // namespace blink
diff --git a/third_party/WebKit/public/web/WebView.h b/third_party/WebKit/public/web/WebView.h index f7748f4..4f81bb6 100644 --- a/third_party/WebKit/public/web/WebView.h +++ b/third_party/WebKit/public/web/WebView.h
@@ -53,7 +53,6 @@ class WebHitTestResult; class WebLocalFrame; class WebPageImportanceSignals; -class WebPageOverlay; class WebPrerendererClient; class WebRemoteFrame; class WebSettings; @@ -85,8 +84,8 @@ using WebWidget::size; using WebWidget::resize; using WebWidget::resizeVisualViewport; - using WebWidget::didEnterFullScreen; - using WebWidget::didExitFullScreen; + using WebWidget::didEnterFullscreen; + using WebWidget::didExitFullscreen; using WebWidget::beginFrame; using WebWidget::updateAllLifecyclePhases; using WebWidget::paint;
diff --git a/third_party/WebKit/public/web/WebViewClient.h b/third_party/WebKit/public/web/WebViewClient.h index a2bb2f9..d0b42277 100644 --- a/third_party/WebKit/public/web/WebViewClient.h +++ b/third_party/WebKit/public/web/WebViewClient.h
@@ -255,7 +255,6 @@ void convertViewportToWindow(WebRect* rect) override {} void convertWindowToViewport(WebFloatRect* rect) override {} void didAutoResize(const WebSize& newSize) override {} - void didChangeCursor(const WebCursorInfo&) override {} void didFocus() override {} void didHandleGestureEvent(const WebGestureEvent& event, bool eventCancelled) override {} void didInvalidateRect(const WebRect&) override {}
diff --git a/third_party/WebKit/public/web/WebWidget.h b/third_party/WebKit/public/web/WebWidget.h index bfaa2ee..5f959da 100644 --- a/third_party/WebKit/public/web/WebWidget.h +++ b/third_party/WebKit/public/web/WebWidget.h
@@ -72,8 +72,8 @@ virtual void resizeVisualViewport(const WebSize&) { } // Called to notify the WebWidget of entering/exiting fullscreen mode. - virtual void didEnterFullScreen() { } - virtual void didExitFullScreen() { } + virtual void didEnterFullscreen() { } + virtual void didExitFullscreen() { } // Called to update imperative animation state. This should be called before // paint, although the client can rate-limit these calls.
diff --git a/third_party/boringssl/BUILD.generated.gni b/third_party/boringssl/BUILD.generated.gni index 5d1aa79..d1ac9be 100644 --- a/third_party/boringssl/BUILD.generated.gni +++ b/third_party/boringssl/BUILD.generated.gni
@@ -282,16 +282,15 @@ "src/ssl/custom_extensions.c", "src/ssl/d1_both.c", "src/ssl/d1_lib.c", - "src/ssl/d1_meth.c", "src/ssl/d1_pkt.c", "src/ssl/d1_srtp.c", + "src/ssl/dtls_method.c", "src/ssl/dtls_record.c", "src/ssl/handshake_client.c", "src/ssl/handshake_server.c", "src/ssl/s3_both.c", "src/ssl/s3_enc.c", "src/ssl/s3_lib.c", - "src/ssl/s3_meth.c", "src/ssl/s3_pkt.c", "src/ssl/ssl_aead_ctx.c", "src/ssl/ssl_asn1.c", @@ -306,6 +305,7 @@ "src/ssl/ssl_stat.c", "src/ssl/t1_enc.c", "src/ssl/t1_lib.c", + "src/ssl/tls_method.c", "src/ssl/tls_record.c", ]
diff --git a/third_party/boringssl/boringssl.gypi b/third_party/boringssl/boringssl.gypi index 399fb58..2c7e7c7 100644 --- a/third_party/boringssl/boringssl.gypi +++ b/third_party/boringssl/boringssl.gypi
@@ -10,16 +10,15 @@ 'src/ssl/custom_extensions.c', 'src/ssl/d1_both.c', 'src/ssl/d1_lib.c', - 'src/ssl/d1_meth.c', 'src/ssl/d1_pkt.c', 'src/ssl/d1_srtp.c', + 'src/ssl/dtls_method.c', 'src/ssl/dtls_record.c', 'src/ssl/handshake_client.c', 'src/ssl/handshake_server.c', 'src/ssl/s3_both.c', 'src/ssl/s3_enc.c', 'src/ssl/s3_lib.c', - 'src/ssl/s3_meth.c', 'src/ssl/s3_pkt.c', 'src/ssl/ssl_aead_ctx.c', 'src/ssl/ssl_asn1.c', @@ -34,6 +33,7 @@ 'src/ssl/ssl_stat.c', 'src/ssl/t1_enc.c', 'src/ssl/t1_lib.c', + 'src/ssl/tls_method.c', 'src/ssl/tls_record.c', ], 'boringssl_crypto_sources': [
diff --git a/third_party/wayland-protocols/BUILD.gn b/third_party/wayland-protocols/BUILD.gn index cfbf3eb..f584dbd 100644 --- a/third_party/wayland-protocols/BUILD.gn +++ b/third_party/wayland-protocols/BUILD.gn
@@ -148,3 +148,24 @@ public_configs = [ ":remote_shell_protocol_config" ] } + +config("gaming_input_protocol_config") { + include_dirs = [ "include/protocol" ] +} + +source_set("gaming_input_protocol") { + sources = [ + "include/protocol/gaming-input-unstable-v1-client-protocol.h", + "include/protocol/gaming-input-unstable-v1-server-protocol.h", + "protocol/gaming-input-protocol.c", + ] + + deps = [ + "//third_party/wayland:wayland_util", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + + public_configs = [ ":gaming_input_protocol_config" ] +}
diff --git a/third_party/wayland-protocols/README.chromium b/third_party/wayland-protocols/README.chromium index 5aacfcf..24bad15 100644 --- a/third_party/wayland-protocols/README.chromium +++ b/third_party/wayland-protocols/README.chromium
@@ -37,4 +37,7 @@ wayland-scanner code < */vsync-feedback/vsync-feedback-unstable-v1.xml > protocol/vsync-feedback-protocol.c wayland-scanner server-header < unstable/vsync-feedback/vsync-feedback-unstable-v1.xml > include/protocol/vsync-feedback-unstable-v1-server-protocol.h wayland-scanner client-header < unstable/vsync-feedback/vsync-feedback-unstable-v1.xml > include/protocol/vsync-feedback-unstable-v1-client-protocol.h + wayland-scanner code < */gaming-input/gaming-input-unstable-v1.xml > protocol/gaming-input-protocol.c + wayland-scanner server-header < unstable/gaming-input/gaming-input-unstable-v1.xml > include/protocol/gaming-input-unstable-v1-server-protocol.h + wayland-scanner client-header < unstable/gaming-input/gaming-input-unstable-v1.xml > include/protocol/gaming-input-unstable-v1-client-protocol.h - Update this README to reflect the new version number.
diff --git a/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v1-client-protocol.h b/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v1-client-protocol.h new file mode 100644 index 0000000..6885851 --- /dev/null +++ b/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v1-client-protocol.h
@@ -0,0 +1,217 @@ +/* + * Copyright 2016 The Chromium Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef GAMING_INPUT_UNSTABLE_V1_CLIENT_PROTOCOL_H +#define GAMING_INPUT_UNSTABLE_V1_CLIENT_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <stddef.h> +#include "wayland-client.h" + +struct wl_client; +struct wl_resource; + +struct zwp_gaming_input_v1; +struct zwp_gamepad_v1; + +extern const struct wl_interface zwp_gaming_input_v1_interface; +extern const struct wl_interface zwp_gamepad_v1_interface; + +#define ZWP_GAMING_INPUT_V1_GET_GAMEPAD 0 + +static inline void +zwp_gaming_input_v1_set_user_data(struct zwp_gaming_input_v1 *zwp_gaming_input_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_gaming_input_v1, user_data); +} + +static inline void * +zwp_gaming_input_v1_get_user_data(struct zwp_gaming_input_v1 *zwp_gaming_input_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_gaming_input_v1); +} + +static inline void +zwp_gaming_input_v1_destroy(struct zwp_gaming_input_v1 *zwp_gaming_input_v1) +{ + wl_proxy_destroy((struct wl_proxy *) zwp_gaming_input_v1); +} + +static inline struct zwp_gamepad_v1 * +zwp_gaming_input_v1_get_gamepad(struct zwp_gaming_input_v1 *zwp_gaming_input_v1, struct wl_seat *seat) +{ + struct wl_proxy *id; + + id = wl_proxy_marshal_constructor((struct wl_proxy *) zwp_gaming_input_v1, + ZWP_GAMING_INPUT_V1_GET_GAMEPAD, &zwp_gamepad_v1_interface, NULL, seat); + + return (struct zwp_gamepad_v1 *) id; +} + +#ifndef ZWP_GAMEPAD_V1_GAMEPAD_STATE_ENUM +#define ZWP_GAMEPAD_V1_GAMEPAD_STATE_ENUM +/** + * zwp_gamepad_v1_gamepad_state - connection state + * @ZWP_GAMEPAD_V1_GAMEPAD_STATE_OFF: no gamepads are connected or on. + * @ZWP_GAMEPAD_V1_GAMEPAD_STATE_ON: at least one gamepad is connected. + * + * + */ +enum zwp_gamepad_v1_gamepad_state { + ZWP_GAMEPAD_V1_GAMEPAD_STATE_OFF = 0, + ZWP_GAMEPAD_V1_GAMEPAD_STATE_ON = 1, +}; +#endif /* ZWP_GAMEPAD_V1_GAMEPAD_STATE_ENUM */ + +#ifndef ZWP_GAMEPAD_V1_BUTTON_STATE_ENUM +#define ZWP_GAMEPAD_V1_BUTTON_STATE_ENUM +/** + * zwp_gamepad_v1_button_state - physical button state + * @ZWP_GAMEPAD_V1_BUTTON_STATE_RELEASED: the button is not pressed + * @ZWP_GAMEPAD_V1_BUTTON_STATE_PRESSED: the button is pressed + * + * Describes the physical state of a button that produced the button + * event. + */ +enum zwp_gamepad_v1_button_state { + ZWP_GAMEPAD_V1_BUTTON_STATE_RELEASED = 0, + ZWP_GAMEPAD_V1_BUTTON_STATE_PRESSED = 1, +}; +#endif /* ZWP_GAMEPAD_V1_BUTTON_STATE_ENUM */ + +/** + * zwp_gamepad_v1 - gamepad input device + * @state_change: state change event + * @axis: axis change event + * @button: Gamepad button changed + * @frame: Notifies end of a series of gamepad changes. + * + * The zwp_gamepad_v1 interface represents one or more gamepad input + * devices, which are reported as a normalized 'Standard Gamepad' as it is + * specified by the W3C Gamepad API at: + * https://w3c.github.io/gamepad/#remapping + */ +struct zwp_gamepad_v1_listener { + /** + * state_change - state change event + * @state: new state + * + * Notification that this seat's connection state has changed. + */ + void (*state_change)(void *data, + struct zwp_gamepad_v1 *zwp_gamepad_v1, + uint32_t state); + /** + * axis - axis change event + * @time: timestamp with millisecond granularity + * @axis: axis that produced this event + * @value: new value of axis + * + * Notification of axis change. + * + * The axis id specifies which axis has changed as defined by the + * W3C 'Standard Gamepad'. + * + * The value is calibrated and normalized to the -1 to 1 range. + */ + void (*axis)(void *data, + struct zwp_gamepad_v1 *zwp_gamepad_v1, + uint32_t time, + uint32_t axis, + wl_fixed_t value); + /** + * button - Gamepad button changed + * @time: timestamp with millisecond granularity + * @button: id of button + * @state: digital state of the button + * @analog: analog value of the button + * + * Notification of button change. + * + * The button id specifies which button has changed as defined by + * the W3C 'Standard Gamepad'. + * + * A button can have a digital and an analog value. The analog + * value is normalized to a 0 to 1 range. If a button does not + * provide an analog value, it will be derived from the digital + * state. + */ + void (*button)(void *data, + struct zwp_gamepad_v1 *zwp_gamepad_v1, + uint32_t time, + uint32_t button, + uint32_t state, + wl_fixed_t analog); + /** + * frame - Notifies end of a series of gamepad changes. + * @time: timestamp with millisecond granularity + * + * Indicates the end of a set of events that logically belong + * together. A client is expected to accumulate the data in all + * events within the frame before proceeding. + */ + void (*frame)(void *data, + struct zwp_gamepad_v1 *zwp_gamepad_v1, + uint32_t time); +}; + +static inline int +zwp_gamepad_v1_add_listener(struct zwp_gamepad_v1 *zwp_gamepad_v1, + const struct zwp_gamepad_v1_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) zwp_gamepad_v1, + (void (**)(void)) listener, data); +} + +#define ZWP_GAMEPAD_V1_DESTROY 0 + +static inline void +zwp_gamepad_v1_set_user_data(struct zwp_gamepad_v1 *zwp_gamepad_v1, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) zwp_gamepad_v1, user_data); +} + +static inline void * +zwp_gamepad_v1_get_user_data(struct zwp_gamepad_v1 *zwp_gamepad_v1) +{ + return wl_proxy_get_user_data((struct wl_proxy *) zwp_gamepad_v1); +} + +static inline void +zwp_gamepad_v1_destroy(struct zwp_gamepad_v1 *zwp_gamepad_v1) +{ + wl_proxy_marshal((struct wl_proxy *) zwp_gamepad_v1, + ZWP_GAMEPAD_V1_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) zwp_gamepad_v1); +} + +#ifdef __cplusplus +} +#endif + +#endif
diff --git a/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v1-server-protocol.h b/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v1-server-protocol.h new file mode 100644 index 0000000..6b2fefb --- /dev/null +++ b/third_party/wayland-protocols/include/protocol/gaming-input-unstable-v1-server-protocol.h
@@ -0,0 +1,159 @@ +/* + * Copyright 2016 The Chromium Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef GAMING_INPUT_UNSTABLE_V1_SERVER_PROTOCOL_H +#define GAMING_INPUT_UNSTABLE_V1_SERVER_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <stddef.h> +#include "wayland-util.h" + +struct wl_client; +struct wl_resource; + +struct zwp_gaming_input_v1; +struct zwp_gamepad_v1; + +extern const struct wl_interface zwp_gaming_input_v1_interface; +extern const struct wl_interface zwp_gamepad_v1_interface; + +/** + * zwp_gaming_input_v1 - extends wl_seat with gaming input devices + * @get_gamepad: get gamepad device assigned to seat + * + * A global interface to provide gaming input devices for a given seat. + * + * Currently only gamepad devices are supported. + * + * Warning! The protocol described in this file is experimental and + * backward incompatible changes may be made. Backward compatible changes + * may be added together with the corresponding uinterface version bump. + * Backward incompatible changes are done by bumping the version number in + * the protocol and uinterface names and resetting the interface version. + * Once the protocol is to be declared stable, the 'z' prefix and the + * version number in the protocol and interface names are removed and the + * interface version number is reset. + */ +struct zwp_gaming_input_v1_interface { + /** + * get_gamepad - get gamepad device assigned to seat + * @id: (none) + * @seat: (none) + * + * Create gamepad object. See zwp_gamepad_v1 interface for + * details. + */ + void (*get_gamepad)(struct wl_client *client, + struct wl_resource *resource, + uint32_t id, + struct wl_resource *seat); +}; + +#ifndef ZWP_GAMEPAD_V1_GAMEPAD_STATE_ENUM +#define ZWP_GAMEPAD_V1_GAMEPAD_STATE_ENUM +/** + * zwp_gamepad_v1_gamepad_state - connection state + * @ZWP_GAMEPAD_V1_GAMEPAD_STATE_OFF: no gamepads are connected or on. + * @ZWP_GAMEPAD_V1_GAMEPAD_STATE_ON: at least one gamepad is connected. + * + * + */ +enum zwp_gamepad_v1_gamepad_state { + ZWP_GAMEPAD_V1_GAMEPAD_STATE_OFF = 0, + ZWP_GAMEPAD_V1_GAMEPAD_STATE_ON = 1, +}; +#endif /* ZWP_GAMEPAD_V1_GAMEPAD_STATE_ENUM */ + +#ifndef ZWP_GAMEPAD_V1_BUTTON_STATE_ENUM +#define ZWP_GAMEPAD_V1_BUTTON_STATE_ENUM +/** + * zwp_gamepad_v1_button_state - physical button state + * @ZWP_GAMEPAD_V1_BUTTON_STATE_RELEASED: the button is not pressed + * @ZWP_GAMEPAD_V1_BUTTON_STATE_PRESSED: the button is pressed + * + * Describes the physical state of a button that produced the button + * event. + */ +enum zwp_gamepad_v1_button_state { + ZWP_GAMEPAD_V1_BUTTON_STATE_RELEASED = 0, + ZWP_GAMEPAD_V1_BUTTON_STATE_PRESSED = 1, +}; +#endif /* ZWP_GAMEPAD_V1_BUTTON_STATE_ENUM */ + +/** + * zwp_gamepad_v1 - gamepad input device + * @destroy: destroy gamepad object + * + * The zwp_gamepad_v1 interface represents one or more gamepad input + * devices, which are reported as a normalized 'Standard Gamepad' as it is + * specified by the W3C Gamepad API at: + * https://w3c.github.io/gamepad/#remapping + */ +struct zwp_gamepad_v1_interface { + /** + * destroy - destroy gamepad object + * + * + */ + void (*destroy)(struct wl_client *client, + struct wl_resource *resource); +}; + +#define ZWP_GAMEPAD_V1_STATE_CHANGE 0 +#define ZWP_GAMEPAD_V1_AXIS 1 +#define ZWP_GAMEPAD_V1_BUTTON 2 +#define ZWP_GAMEPAD_V1_FRAME 3 + +static inline void +zwp_gamepad_v1_send_state_change(struct wl_resource *resource_, uint32_t state) +{ + wl_resource_post_event(resource_, ZWP_GAMEPAD_V1_STATE_CHANGE, state); +} + +static inline void +zwp_gamepad_v1_send_axis(struct wl_resource *resource_, uint32_t time, uint32_t axis, wl_fixed_t value) +{ + wl_resource_post_event(resource_, ZWP_GAMEPAD_V1_AXIS, time, axis, value); +} + +static inline void +zwp_gamepad_v1_send_button(struct wl_resource *resource_, uint32_t time, uint32_t button, uint32_t state, wl_fixed_t analog) +{ + wl_resource_post_event(resource_, ZWP_GAMEPAD_V1_BUTTON, time, button, state, analog); +} + +static inline void +zwp_gamepad_v1_send_frame(struct wl_resource *resource_, uint32_t time) +{ + wl_resource_post_event(resource_, ZWP_GAMEPAD_V1_FRAME, time); +} + +#ifdef __cplusplus +} +#endif + +#endif
diff --git a/third_party/wayland-protocols/protocol/gaming-input-protocol.c b/third_party/wayland-protocols/protocol/gaming-input-protocol.c new file mode 100644 index 0000000..beaddbd --- /dev/null +++ b/third_party/wayland-protocols/protocol/gaming-input-protocol.c
@@ -0,0 +1,66 @@ +/* + * Copyright 2016 The Chromium Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <stdlib.h> +#include <stdint.h> +#include "wayland-util.h" + +extern const struct wl_interface zwp_gamepad_v1_interface; +extern const struct wl_interface wl_seat_interface; + +static const struct wl_interface *types[] = { + NULL, + NULL, + NULL, + NULL, + &zwp_gamepad_v1_interface, + &wl_seat_interface, +}; + +static const struct wl_message zwp_gaming_input_v1_requests[] = { + { "get_gamepad", "no", types + 4 }, +}; + +WL_EXPORT const struct wl_interface zwp_gaming_input_v1_interface = { + "zwp_gaming_input_v1", 1, + 1, zwp_gaming_input_v1_requests, + 0, NULL, +}; + +static const struct wl_message zwp_gamepad_v1_requests[] = { + { "destroy", "", types + 0 }, +}; + +static const struct wl_message zwp_gamepad_v1_events[] = { + { "state_change", "u", types + 0 }, + { "axis", "uuf", types + 0 }, + { "button", "uuuf", types + 0 }, + { "frame", "u", types + 0 }, +}; + +WL_EXPORT const struct wl_interface zwp_gamepad_v1_interface = { + "zwp_gamepad_v1", 1, + 1, zwp_gamepad_v1_requests, + 4, zwp_gamepad_v1_events, +}; +
diff --git a/third_party/wayland-protocols/unstable/gaming-input/README b/third_party/wayland-protocols/unstable/gaming-input/README new file mode 100644 index 0000000..388c8aa4 --- /dev/null +++ b/third_party/wayland-protocols/unstable/gaming-input/README
@@ -0,0 +1,4 @@ +Gamepads protocol + +Maintainers: +Dennis Kempin <denniskempin@chromium.org>
diff --git a/third_party/wayland-protocols/unstable/gaming-input/gaming-input-unstable-v1.xml b/third_party/wayland-protocols/unstable/gaming-input/gaming-input-unstable-v1.xml new file mode 100644 index 0000000..96561277 --- /dev/null +++ b/third_party/wayland-protocols/unstable/gaming-input/gaming-input-unstable-v1.xml
@@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="gaming_input_unstable_v1"> + + <copyright> + Copyright 2016 The Chromium Authors. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + </copyright> + + <interface name="zwp_gaming_input_v1" version="1"> + <description summary="extends wl_seat with gaming input devices"> + A global interface to provide gaming input devices for a given seat. + + Currently only gamepad devices are supported. + + Warning! The protocol described in this file is experimental and + backward incompatible changes may be made. Backward compatible changes + may be added together with the corresponding uinterface version bump. + Backward incompatible changes are done by bumping the version number in + the protocol and uinterface names and resetting the interface version. + Once the protocol is to be declared stable, the 'z' prefix and the + version number in the protocol and interface names are removed and the + interface version number is reset. + </description> + + <request name="get_gamepad"> + <description summary="get gamepad device assigned to seat"> + Create gamepad object. See zwp_gamepad_v1 interface for details. + </description> + <arg name="id" type="new_id" interface="zwp_gamepad_v1"/> + <arg name="seat" type="object" interface="wl_seat"/> + </request> + </interface> + + <interface name="zwp_gamepad_v1" version="1"> + <description summary="gamepad input device"> + The zwp_gamepad_v1 interface represents one or more gamepad input devices, + which are reported as a normalized 'Standard Gamepad' as it is specified + by the W3C Gamepad API at: https://w3c.github.io/gamepad/#remapping + </description> + + <request name="destroy" type="destructor"> + <description summary="destroy gamepad object"/> + </request> + + <enum name="gamepad_state"> + <description summary="connection state"/> + <entry name="off" value="0" summary="no gamepads are connected or on."/> + <entry name="on" value="1" summary="at least one gamepad is connected."/> + </enum> + + <event name="state_change"> + <description summary="state change event"> + Notification that this seat's connection state has changed. + </description> + <arg name="state" type="uint" enum="gamepad_state" summary="new state"/> + </event> + + <event name="axis"> + <description summary="axis change event"> + Notification of axis change. + + The axis id specifies which axis has changed as defined by the W3C + 'Standard Gamepad'. + + The value is calibrated and normalized to the -1 to 1 range. + </description> + <arg name="time" type="uint" summary="timestamp with millisecond granularity"/> + <arg name="axis" type="uint" summary="axis that produced this event"/> + <arg name="value" type="fixed" summary="new value of axis"/> + </event> + + <enum name="button_state"> + <description summary="physical button state"> + Describes the physical state of a button that produced the button + event. + </description> + <entry name="released" value="0" summary="the button is not pressed"/> + <entry name="pressed" value="1" summary="the button is pressed"/> + </enum> + + <event name="button"> + <description summary="Gamepad button changed"> + Notification of button change. + + The button id specifies which button has changed as defined by the W3C + 'Standard Gamepad'. + + A button can have a digital and an analog value. The analog value is + normalized to a 0 to 1 range. + If a button does not provide an analog value, it will be derived from + the digital state. + </description> + <arg name="time" type="uint" summary="timestamp with millisecond granularity"/> + <arg name="button" type="uint" summary="id of button"/> + <arg name="state" type="uint" enum="button_state" summary="digital state of the button"/> + <arg name="analog" type="fixed" summary="analog value of the button"/> + </event> + + <event name="frame"> + <description summary="Notifies end of a series of gamepad changes."> + Indicates the end of a set of events that logically belong together. + A client is expected to accumulate the data in all events within the + frame before proceeding. + </description> + <arg name="time" type="uint" summary="timestamp with millisecond granularity"/> + </event> + </interface> +</protocol>
diff --git a/third_party/wayland-protocols/wayland-protocols.gyp b/third_party/wayland-protocols/wayland-protocols.gyp index 660b935f..2c318c9 100644 --- a/third_party/wayland-protocols/wayland-protocols.gyp +++ b/third_party/wayland-protocols/wayland-protocols.gyp
@@ -144,5 +144,25 @@ ], }, }, + { + 'target_name': 'gaming_input_protocol', + 'type': 'static_library', + 'dependencies' : [ + '../wayland/wayland.gyp:wayland_util', + ], + 'sources': [ + 'include/protocol/gaming-input-unstable-v1-client-protocol.h', + 'include/protocol/gaming-input-unstable-v1-server-protocol.h', + 'protocol/gaming-input-protocol.c', + ], + 'include_dirs': [ + 'include/protocol', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + 'include/protocol', + ], + }, + }, ], }
diff --git a/tools/android/forwarder2/host_forwarder_main.cc b/tools/android/forwarder2/host_forwarder_main.cc index 2fae616f..9613660 100644 --- a/tools/android/forwarder2/host_forwarder_main.cc +++ b/tools/android/forwarder2/host_forwarder_main.cc
@@ -240,7 +240,7 @@ const std::string prefix = base::StringPrintf("%d:", port); for (HostControllerMap::const_iterator others = controllers_->begin(); others != controllers_->end(); ++others) { - if (others->first.find(prefix) == 0U) + if (base::StartsWith(others->first, prefix, base::CompareCase::SENSITIVE)) return; } // No other port is being forwarded to this device: @@ -318,7 +318,7 @@ class ServerDelegate : public Daemon::ServerDelegate { public: - ServerDelegate(const std::string& adb_path) + explicit ServerDelegate(const std::string& adb_path) : adb_path_(adb_path), has_failed_(false) {} bool has_failed() const { @@ -370,7 +370,7 @@ class ClientDelegate : public Daemon::ClientDelegate { public: - ClientDelegate(const base::Pickle& command_pickle) + explicit ClientDelegate(const base::Pickle& command_pickle) : command_pickle_(command_pickle), has_failed_(false) {} bool has_failed() const { return has_failed_; }
diff --git a/tools/android/loading/sandwich_prefetch.py b/tools/android/loading/sandwich_prefetch.py index 22c9b00..0f53263 100644 --- a/tools/android/loading/sandwich_prefetch.py +++ b/tools/android/loading/sandwich_prefetch.py
@@ -651,7 +651,7 @@ runner = self._common_builder.CreateSandwichRunner() for transformer in transformer_list: transformer(runner) - runner.wpr_archive_path = self._wpr_archive_path + runner.wpr_archive_path = self._common_builder.original_wpr_task.path runner.wpr_out_log_path = os.path.join( RunBenchmark.path, sandwich_runner.WPR_LOG_FILENAME) runner.cache_archive_path = BuildBenchmarkCacheArchive.path
diff --git a/tools/gn/args.cc b/tools/gn/args.cc index accdf7e..823a8ccd 100644 --- a/tools/gn/args.cc +++ b/tools/gn/args.cc
@@ -184,6 +184,12 @@ declared_arguments.insert(arg); } + // In all the cases below, mark the variable used. If a variable is set + // that's only used in one toolchain, we don't want to report unused + // variable errors in other toolchains. Also, in some cases it's reasonable + // for the build file to overwrite the value with a different value based + // on some other condition without dereferencing the value first. + // Check whether this argument has been overridden on the toolchain level // and use the override instead. Scope::KeyValueMap::const_iterator toolchain_override = @@ -192,6 +198,7 @@ scope_to_set->SetValue(toolchain_override->first, toolchain_override->second, toolchain_override->second.origin()); + scope_to_set->MarkUsed(arg.first); continue; } @@ -201,11 +208,10 @@ if (override != overrides_.end()) { scope_to_set->SetValue(override->first, override->second, override->second.origin()); + scope_to_set->MarkUsed(override->first); continue; } - // Mark the variable used so the build script can override it in - // certain cases without getting unused value errors. scope_to_set->SetValue(arg.first, arg.second, arg.second.origin()); scope_to_set->MarkUsed(arg.first); }
diff --git a/tools/gn/builder.cc b/tools/gn/builder.cc index 036d390..93aec154 100644 --- a/tools/gn/builder.cc +++ b/tools/gn/builder.cc
@@ -33,7 +33,7 @@ bool RecursiveFindCycle(const BuilderRecord* search_in, std::vector<const BuilderRecord*>* path) { path->push_back(search_in); - for (const auto& cur : search_in->unresolved_deps()) { + for (auto* cur : search_in->unresolved_deps()) { std::vector<const BuilderRecord*>::iterator found = std::find(path->begin(), path->end(), cur); if (found != path->end()) { @@ -182,7 +182,7 @@ bad_records.push_back(src); // Check dependencies. - for (const auto& dest : src->unresolved_deps()) { + for (auto* dest : src->unresolved_deps()) { if (!dest->item()) { depstring += src->label().GetUserVisibleName(true) + "\n needs " + dest->label().GetUserVisibleName(true) + "\n"; @@ -204,7 +204,7 @@ // Something's very wrong, just dump out the bad nodes. depstring = "I have no idea what went wrong, but these are unresolved, " "possibly due to an\ninternal error:"; - for (const auto& bad_record : bad_records) { + for (auto* bad_record : bad_records) { depstring += "\n\"" + bad_record->label().GetUserVisibleName(false) + "\""; } @@ -252,7 +252,7 @@ // anything they depend on is actually written, the "generate" flag isn't // relevant and means extra book keeping. Just force load any deps of this // config. - for (const auto& cur : record->all_deps()) + for (auto* cur : record->all_deps()) ScheduleItemLoadIfNecessary(cur); return true; @@ -408,7 +408,7 @@ return; // Already set. record->set_should_generate(true); - for (const auto& cur : record->all_deps()) { + for (auto* cur : record->all_deps()) { if (!cur->should_generate()) { ScheduleItemLoadIfNecessary(cur); RecursiveSetShouldGenerate(cur, false);
diff --git a/tools/gn/command_ls.cc b/tools/gn/command_ls.cc index c9b9672..f53a727 100644 --- a/tools/gn/command_ls.cc +++ b/tools/gn/command_ls.cc
@@ -100,7 +100,7 @@ matches = setup->builder()->GetAllResolvedTargets(); } else { // List all resolved targets in the default toolchain. - for (const auto& target : setup->builder()->GetAllResolvedTargets()) { + for (auto* target : setup->builder()->GetAllResolvedTargets()) { if (target->settings()->is_default()) matches.push_back(target); }
diff --git a/tools/gn/command_refs.cc b/tools/gn/command_refs.cc index 413a98f..014d7e89 100644 --- a/tools/gn/command_refs.cc +++ b/tools/gn/command_refs.cc
@@ -32,7 +32,7 @@ // Populates the reverse dependency map for the targets in the Setup. void FillDepMap(Setup* setup, DepMap* dep_map) { - for (const auto& target : setup->builder()->GetAllResolvedTargets()) { + for (auto* target : setup->builder()->GetAllResolvedTargets()) { for (const auto& dep_pair : target->GetDeps(Target::DEPS_ALL)) dep_map->insert(std::make_pair(dep_pair.ptr, target)); } @@ -160,7 +160,7 @@ bool all_toolchains, UniqueVector<const Target*>* matches) { Label default_toolchain = setup->loader()->default_toolchain_label(); - for (const auto& target : all_targets) { + for (auto* target : all_targets) { if (!all_toolchains) { // Only check targets in the default toolchain. if (target->label().GetToolchainLabel() != default_toolchain) @@ -189,7 +189,7 @@ bool all_toolchains, UniqueVector<const Target*>* matches) { Label default_toolchain = setup->loader()->default_toolchain_label(); - for (const auto& target : all_targets) { + for (auto* target : all_targets) { if (!all_toolchains) { // Only check targets in the default toolchain. if (target->label().GetToolchainLabel() != default_toolchain) @@ -442,7 +442,7 @@ GetTargetsContainingFile(setup, all_targets, file, all_toolchains, &explicit_target_matches); } - for (const auto& config : config_matches) { + for (auto* config : config_matches) { GetTargetsReferencingConfig(setup, all_targets, config, all_toolchains, &explicit_target_matches); }
diff --git a/tools/gn/commands.cc b/tools/gn/commands.cc index 8682d92..a646679 100644 --- a/tools/gn/commands.cc +++ b/tools/gn/commands.cc
@@ -298,7 +298,7 @@ const std::vector<const Target*>& targets) { // Putting the labels into a set automatically sorts them for us. std::set<Label> unique_labels; - for (const auto& target : targets) + for (auto* target : targets) unique_labels.insert(target->label()); // Grab the label of the default toolchain from the first target. @@ -446,7 +446,7 @@ void FilterTargetsByPatterns(const std::vector<const Target*>& input, const std::vector<LabelPattern>& filter, std::vector<const Target*>* output) { - for (const auto& target : input) { + for (auto* target : input) { for (const auto& pattern : filter) { if (pattern.Matches(target->label())) { output->push_back(target); @@ -459,7 +459,7 @@ void FilterTargetsByPatterns(const std::vector<const Target*>& input, const std::vector<LabelPattern>& filter, UniqueVector<const Target*>* output) { - for (const auto& target : input) { + for (auto* target : input) { for (const auto& pattern : filter) { if (pattern.Matches(target->label())) { output->push_back(target);
diff --git a/tools/gn/docs/cookbook.md b/tools/gn/docs/cookbook.md index 942b572..a11bc13 100644 --- a/tools/gn/docs/cookbook.md +++ b/tools/gn/docs/cookbook.md
@@ -261,7 +261,6 @@ | `enable_service_discovery` (0/1) | `enable_service_discovery` (true/false) | `//build/config/features.gni` | | `enable_spellcheck` (0/1) | `enable_spellcheck` (true/false) | `//build/config/features.gni` | | `enable_session_service` (0/1) | `enable_session_service` (true/false) | `//build/config/features.gni` | -| `enable_settings_app` (0/1) | `enable_settings_app` (true/false) | `//build/config/features.gni` | | `enable_task_manager` (0/1) | `enable_task_manager` (true/false) | `//build/config/features.gni` | | `enable_themes` (0/1) | `enable_themes` (true/false) | `//build/config/features.gni` | | `enable_webrtc` (0/1) | `enable_webrtc` (true/false) | `//build/config/features.gni` |
diff --git a/tools/gn/function_get_target_outputs.cc b/tools/gn/function_get_target_outputs.cc index 6e3cf656..4e1baf8 100644 --- a/tools/gn/function_get_target_outputs.cc +++ b/tools/gn/function_get_target_outputs.cc
@@ -92,7 +92,7 @@ *err = Err(function, "No targets defined in this context."); return Value(); } - for (const auto& item : *collector) { + for (auto* item : *collector) { if (item->label() != label) continue;
diff --git a/tools/gn/header_checker.cc b/tools/gn/header_checker.cc index 1002081a8..5b15643 100644 --- a/tools/gn/header_checker.cc +++ b/tools/gn/header_checker.cc
@@ -129,7 +129,7 @@ const std::vector<const Target*>& targets) : main_loop_(base::MessageLoop::current()), build_settings_(build_settings) { - for (const auto& target : targets) + for (auto* target : targets) AddTargetToFileMap(target, &file_map_); } @@ -140,7 +140,7 @@ bool force_check, std::vector<Err>* errors) { FileMap files_to_check; - for (const auto& check : to_check) + for (auto* check : to_check) AddTargetToFileMap(check, &files_to_check); RunCheckOverFiles(files_to_check, force_check); @@ -567,9 +567,9 @@ std::string msg = "It is not in any dependency of\n " + from_target->label().GetUserVisibleName(include_toolchain); msg += "\nThe include file is in the target(s):\n"; - for (const auto& target : targets_with_matching_toolchains) + for (auto* target : targets_with_matching_toolchains) msg += " " + target->label().GetUserVisibleName(include_toolchain) + "\n"; - for (const auto& target : targets_with_other_toolchains) + for (auto* target : targets_with_other_toolchains) msg += " " + target->label().GetUserVisibleName(include_toolchain) + "\n"; if (targets_with_other_toolchains.size() + targets_with_matching_toolchains.size() > 1)
diff --git a/tools/gn/input_conversion_unittest.cc b/tools/gn/input_conversion_unittest.cc index 2c4afea..c5209b06 100644 --- a/tools/gn/input_conversion_unittest.cc +++ b/tools/gn/input_conversion_unittest.cc
@@ -158,7 +158,7 @@ "[rebase_path(\"//\")]", }; - for (auto test : kTests) { + for (auto* test : kTests) { Err err; std::string input(test); Value result = ConvertInputToValue(settings(), input, nullptr,
diff --git a/tools/gn/loader.cc b/tools/gn/loader.cc index 69fb7668..1899df7d 100644 --- a/tools/gn/loader.cc +++ b/tools/gn/loader.cc
@@ -273,7 +273,7 @@ // Pass all of the items that were defined off to the builder. - for (auto& item : collected_items) { + for (auto*& item : collected_items) { settings->build_settings()->ItemDefined(base::WrapUnique(item)); item = nullptr; }
diff --git a/tools/gn/ninja_binary_target_writer.cc b/tools/gn/ninja_binary_target_writer.cc index 9b0458a..129ddb1 100644 --- a/tools/gn/ninja_binary_target_writer.cc +++ b/tools/gn/ninja_binary_target_writer.cc
@@ -948,7 +948,7 @@ DCHECK(extra_object_files.empty()); std::vector<OutputFile> order_only_deps; - for (const auto& dep : non_linkable_deps) + for (auto* dep : non_linkable_deps) order_only_deps.push_back(dep->dependency_output_file()); WriteStampForTarget(object_files, order_only_deps); @@ -965,8 +965,7 @@ } // Inherited libraries. - for (const auto& inherited_target : - target_->inherited_libraries().GetOrdered()) { + for (auto* inherited_target : target_->inherited_libraries().GetOrdered()) { ClassifyDependency(inherited_target, extra_object_files, linkable_deps, non_linkable_deps); } @@ -1029,7 +1028,7 @@ out_ << " ||"; // Non-linkable targets. - for (const auto& non_linkable_dep : non_linkable_deps) { + for (auto* non_linkable_dep : non_linkable_deps) { out_ << " "; path_output_.WriteFile(out_, non_linkable_dep->dependency_output_file()); }
diff --git a/tools/gn/ninja_build_writer.cc b/tools/gn/ninja_build_writer.cc index 627edb27..8ee90b0 100644 --- a/tools/gn/ninja_build_writer.cc +++ b/tools/gn/ninja_build_writer.cc
@@ -242,7 +242,7 @@ } void NinjaBuildWriter::WriteSubninjas() { - for (const auto& elem : all_settings_) { + for (auto* elem : all_settings_) { out_ << "subninja "; path_output_.WriteFile(out_, GetNinjaFileForToolchain(elem)); out_ << std::endl;
diff --git a/tools/gn/ninja_target_writer.cc b/tools/gn/ninja_target_writer.cc index 7843d75..69e9d90 100644 --- a/tools/gn/ninja_target_writer.cc +++ b/tools/gn/ninja_target_writer.cc
@@ -255,7 +255,7 @@ std::sort( input_deps_targets.begin(), input_deps_targets.end(), [](const Target* a, const Target* b) { return a->label() < b->label(); }); - for (const auto& dep : input_deps_targets) { + for (auto* dep : input_deps_targets) { DCHECK(!dep->dependency_output_file().value().empty()); out_ << " "; path_output_.WriteFile(out_, dep->dependency_output_file());
diff --git a/tools/gn/ninja_toolchain_writer.cc b/tools/gn/ninja_toolchain_writer.cc index 1deff58e..9b699b8 100644 --- a/tools/gn/ninja_toolchain_writer.cc +++ b/tools/gn/ninja_toolchain_writer.cc
@@ -136,7 +136,7 @@ void NinjaToolchainWriter::WriteSubninjas() { // Write subninja commands for each generated target. - for (const auto& target : targets_) { + for (auto* target : targets_) { OutputFile ninja_file(target->settings()->build_settings(), GetNinjaFileForTarget(target)); out_ << "subninja ";
diff --git a/tools/gn/ninja_writer.cc b/tools/gn/ninja_writer.cc index 7d26f484..22a97ec4 100644 --- a/tools/gn/ninja_writer.cc +++ b/tools/gn/ninja_writer.cc
@@ -58,7 +58,7 @@ CategorizedMap categorized; std::vector<const BuilderRecord*> all_records = builder_->GetAllRecords(); - for (const auto& all_record : all_records) { + for (auto* all_record : all_records) { if (all_record->type() == BuilderRecord::ITEM_TARGET && all_record->should_generate()) { categorized[all_record->label().GetToolchainLabel()].push_back(
diff --git a/tools/gn/parse_tree_unittest.cc b/tools/gn/parse_tree_unittest.cc index f5edbc8..a6850a7 100644 --- a/tools/gn/parse_tree_unittest.cc +++ b/tools/gn/parse_tree_unittest.cc
@@ -225,7 +225,7 @@ "9223372036854775807", // INT64_MAX "-9223372036854775808", // INT64_MIN }; - for (auto s : kGood) { + for (auto* s : kGood) { TestParseInput input(std::string("x = ") + s); EXPECT_FALSE(input.has_error()); @@ -242,7 +242,7 @@ "9223372036854775808", // INT64_MAX + 1 "-9223372036854775809", // INT64_MIN - 1 }; - for (auto s : kBad) { + for (auto* s : kBad) { TestParseInput input(std::string("x = ") + s); EXPECT_FALSE(input.has_error());
diff --git a/tools/gn/parser.cc b/tools/gn/parser.cc index 977ddad..7e5886f 100644 --- a/tools/gn/parser.cc +++ b/tools/gn/parser.cc
@@ -711,7 +711,7 @@ // Assign line comments to syntax immediately following. int cur_comment = 0; - for (const auto& node : pre) { + for (auto* node : pre) { const Location& start = node->GetRange().begin(); while (cur_comment < static_cast<int>(line_comment_tokens_.size())) { if (start.byte() >= line_comment_tokens_[cur_comment].location().byte()) {
diff --git a/tools/gn/scope.cc b/tools/gn/scope.cc index 93ce966..3869f3b 100644 --- a/tools/gn/scope.cc +++ b/tools/gn/scope.cc
@@ -69,7 +69,7 @@ const Value* Scope::GetValue(const base::StringPiece& ident, bool counts_as_used) { // First check for programmatically-provided values. - for (const auto& provider : programmatic_providers_) { + for (auto* provider : programmatic_providers_) { const Value* v = provider->GetProgrammaticValue(ident); if (v) return v;
diff --git a/tools/gn/target.cc b/tools/gn/target.cc index 85955a71..aa1fcf6 100644 --- a/tools/gn/target.cc +++ b/tools/gn/target.cc
@@ -128,7 +128,7 @@ return true; // Found a path. } if (target->output_type() == Target::CREATE_BUNDLE) { - for (const auto& dep : target->bundle_data().bundle_deps()) { + for (auto* dep : target->bundle_data().bundle_deps()) { if (EnsureFileIsGeneratedByDependency(dep, file, false, consider_object_files, check_data_deps, seen_targets)) @@ -424,14 +424,11 @@ return !outputs->empty(); } -void Target::PullDependentTargetConfigsFrom(const Target* dep) { - MergeAllDependentConfigsFrom(dep, &configs_, &all_dependent_configs_); - MergePublicConfigsFrom(dep, &configs_); -} - void Target::PullDependentTargetConfigs() { for (const auto& pair : GetDeps(DEPS_LINKED)) - PullDependentTargetConfigsFrom(pair.ptr); + MergeAllDependentConfigsFrom(pair.ptr, &configs_, &all_dependent_configs_); + for (const auto& pair : GetDeps(DEPS_LINKED)) + MergePublicConfigsFrom(pair.ptr, &configs_); } void Target::PullDependentTargetLibsFrom(const Target* dep, bool is_public) { @@ -524,7 +521,7 @@ bundle_data_.AddBundleData(pair.ptr); // Recursive bundle_data informations from all dependencies. - for (const auto& target : pair.ptr->bundle_data().bundle_deps()) + for (auto* target : pair.ptr->bundle_data().bundle_deps()) bundle_data_.AddBundleData(target); }
diff --git a/tools/gn/target.h b/tools/gn/target.h index 495a9c15..bd84ec3 100644 --- a/tools/gn/target.h +++ b/tools/gn/target.h
@@ -313,7 +313,6 @@ // Pulls necessary information from dependencies to this one when all // dependencies have been resolved. - void PullDependentTargetConfigsFrom(const Target* dep); void PullDependentTargetConfigs(); void PullDependentTargetLibsFrom(const Target* dep, bool is_public); void PullDependentTargetLibs();
diff --git a/tools/gn/target_unittest.cc b/tools/gn/target_unittest.cc index d1c7ab9d1..2e2e63e 100644 --- a/tools/gn/target_unittest.cc +++ b/tools/gn/target_unittest.cc
@@ -462,6 +462,71 @@ ASSERT_TRUE(forward.OnResolved(&err)); } +// Tests that configs are ordered properly between local and pulled ones. +TEST(Target, ConfigOrdering) { + TestWithScope setup; + Err err; + + // Make Dep1. It has all_dependent_configs and public_configs. + TestTarget dep1(setup, "//:dep1", Target::SOURCE_SET); + Label dep1_all_config_label(SourceDir("//"), "dep1_all_config"); + Config dep1_all_config(setup.settings(), dep1_all_config_label); + ASSERT_TRUE(dep1_all_config.OnResolved(&err)); + dep1.all_dependent_configs().push_back(LabelConfigPair(&dep1_all_config)); + + Label dep1_public_config_label(SourceDir("//"), "dep1_public_config"); + Config dep1_public_config(setup.settings(), dep1_public_config_label); + ASSERT_TRUE(dep1_public_config.OnResolved(&err)); + dep1.public_configs().push_back(LabelConfigPair(&dep1_public_config)); + ASSERT_TRUE(dep1.OnResolved(&err)); + + // Make Dep2 with the same structure. + TestTarget dep2(setup, "//:dep2", Target::SOURCE_SET); + Label dep2_all_config_label(SourceDir("//"), "dep2_all_config"); + Config dep2_all_config(setup.settings(), dep2_all_config_label); + ASSERT_TRUE(dep2_all_config.OnResolved(&err)); + dep2.all_dependent_configs().push_back(LabelConfigPair(&dep2_all_config)); + + Label dep2_public_config_label(SourceDir("//"), "dep2_public_config"); + Config dep2_public_config(setup.settings(), dep2_public_config_label); + ASSERT_TRUE(dep2_public_config.OnResolved(&err)); + dep2.public_configs().push_back(LabelConfigPair(&dep2_public_config)); + ASSERT_TRUE(dep2.OnResolved(&err)); + + // This target depends on both previous targets. + TestTarget target(setup, "//:foo", Target::SOURCE_SET); + target.private_deps().push_back(LabelTargetPair(&dep1)); + target.private_deps().push_back(LabelTargetPair(&dep2)); + + // It also has a private and public config. + Label public_config_label(SourceDir("//"), "public"); + Config public_config(setup.settings(), public_config_label); + ASSERT_TRUE(public_config.OnResolved(&err)); + target.public_configs().push_back(LabelConfigPair(&public_config)); + + Label private_config_label(SourceDir("//"), "private"); + Config private_config(setup.settings(), private_config_label); + ASSERT_TRUE(private_config.OnResolved(&err)); + target.configs().push_back(LabelConfigPair(&private_config)); + + // Resolve to get the computed list of configs applying. + ASSERT_TRUE(target.OnResolved(&err)); + const auto& computed = target.configs(); + + // Order should be: + // 1. local private + // 2. local public + // 3. inherited all dependent + // 4. inherited public + ASSERT_EQ(6u, computed.size()); + EXPECT_EQ(private_config_label, computed[0].label); + EXPECT_EQ(public_config_label, computed[1].label); + EXPECT_EQ(dep1_all_config_label, computed[2].label); + EXPECT_EQ(dep2_all_config_label, computed[3].label); + EXPECT_EQ(dep1_public_config_label, computed[4].label); + EXPECT_EQ(dep2_public_config_label, computed[5].label); +} + // Tests that different link/depend outputs work for solink tools. TEST(Target, LinkAndDepOutputs) { TestWithScope setup;
diff --git a/tools/gn/trace.cc b/tools/gn/trace.cc index 13ebf62..2a1b460d 100644 --- a/tools/gn/trace.cc +++ b/tools/gn/trace.cc
@@ -70,7 +70,7 @@ out << "File parse times: (time in ms, name)\n"; std::sort(loads.begin(), loads.end(), &DurationGreater); - for (const auto& load : loads) { + for (auto* load : loads) { out << base::StringPrintf(" %8.2f ", load->delta().InMillisecondsF()); out << load->name() << std::endl; } @@ -80,7 +80,7 @@ std::ostream& out) { // Group by file name. std::map<std::string, Coalesced> coalesced; - for (const auto& item : items) { + for (auto* item : items) { Coalesced& c = coalesced[item->name()]; c.name_ptr = &item->name(); c.total_duration += item->delta().InMillisecondsF(); @@ -186,7 +186,7 @@ std::vector<const TraceItem*> script_execs; std::vector<const TraceItem*> check_headers; int headers_checked = 0; - for (const auto& event : events) { + for (auto* event : events) { switch (event->type()) { case TraceItem::TRACE_FILE_PARSE: parses.push_back(event); @@ -225,7 +225,7 @@ // parallel. Just report the total of all of them. if (!check_headers.empty()) { double check_headers_time = 0; - for (const auto& cur : check_headers) + for (auto* cur : check_headers) check_headers_time += cur->delta().InMillisecondsF(); out << "Header check time: (total time in ms, files checked)\n";
diff --git a/tools/gn/xcode_writer.cc b/tools/gn/xcode_writer.cc index e076339..d60f4f77 100644 --- a/tools/gn/xcode_writer.cc +++ b/tools/gn/xcode_writer.cc
@@ -419,7 +419,7 @@ [](const PBXObject* a, const PBXObject* b) { return a->id() < b->id(); }); - for (const auto& object : pair.second) { + for (auto* object : pair.second) { object->Print(out, 2); } out << "/* End " << ToString(pair.first) << " section */\n";
diff --git a/tools/grit/grit_rule.gni b/tools/grit/grit_rule.gni index 107a4bc..b77a24d 100644 --- a/tools/grit/grit_rule.gni +++ b/tools/grit/grit_rule.gni
@@ -263,12 +263,6 @@ "enable_app_list", ] } -if (enable_settings_app) { - grit_defines += [ - "-D", - "enable_settings_app", - ] -} if (enable_webrtc) { grit_defines += [ "-D",
diff --git a/tools/ipc_fuzzer/fuzzer/fuzzer.cc b/tools/ipc_fuzzer/fuzzer/fuzzer.cc index cba3809..5a7db7f5 100644 --- a/tools/ipc_fuzzer/fuzzer/fuzzer.cc +++ b/tools/ipc_fuzzer/fuzzer/fuzzer.cc
@@ -705,14 +705,7 @@ template <> struct FuzzTraits<cc::CompositorFrameAck> { static bool Fuzz(cc::CompositorFrameAck* p, Fuzzer* fuzzer) { - if (!FuzzParam(&p->resources, fuzzer)) - return false; - - if (!p->gl_frame_data) - p->gl_frame_data.reset(new cc::GLFrameData); - if (!FuzzParam(p->gl_frame_data.get(), fuzzer)) - return false; - return true; + return FuzzParam(&p->resources, fuzzer); } };
diff --git a/tools/ipc_fuzzer/message_lib/all_messages.h b/tools/ipc_fuzzer/message_lib/all_messages.h index 6173a1a..7800140 100644 --- a/tools/ipc_fuzzer/message_lib/all_messages.h +++ b/tools/ipc_fuzzer/message_lib/all_messages.h
@@ -17,7 +17,9 @@ #include "chrome/common/all_messages.h" #include "components/autofill/content/common/autofill_message_generator.h" #include "components/content_settings/content/common/content_settings_message_generator.h" +#if !defined(DISABLE_NACL) #include "components/nacl/common/nacl_host_messages.h" +#endif #include "components/network_hints/common/network_hints_message_generator.h" #include "components/page_load_metrics/common/page_load_metrics_messages.h" #include "components/pdf/common/pdf_message_generator.h"
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index d9a8204a..81d2fda 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -29,6 +29,8 @@ 'Android Cronet Builder': 'android_cronet_gn_release_bot_minimal_symbols', 'Android Cronet Builder (dbg)': 'android_cronet_gn_debug_static_bot', + 'Android Cronet Builder Asan': + 'android_cronet_gn_release_bot_minimal_symbols_clang_asan', 'Android Cronet Data Reduction Proxy Builder': 'android_cronet_data_reduction_proxy_gn_release_bot_minimal_symbols', 'Android Cronet MIPS Builder': @@ -63,7 +65,7 @@ 'chromium.chrome': { 'Google Chrome ChromeOS': 'gn_official_goma_chromeos', 'Google Chrome Linux x64': 'gn_official_goma', - 'Google Chrome Mac': 'gyp_official_goma', + 'Google Chrome Mac': 'gn_official_goma', 'Google Chrome Win': 'gn_official_goma_minimal_symbols_x86', }, @@ -77,7 +79,7 @@ 'Linux ChromiumOS GN (dbg)': 'chromeos_gn_debug_bot', 'Linux ChromiumOS GN': 'chromeos_ozone_gn_release_bot', 'Linux ChromiumOS Ozone Builder': - 'swarming_chromeos_ozone_gyp_release_bot', + 'swarming_chromeos_ozone_gn_release_bot', 'Linux ChromiumOS Ozone Tests (1)': 'none', 'Linux ChromiumOS Tests (1)': 'none', 'Linux ChromiumOS Tests (dbg)(1)': 'none', @@ -334,10 +336,10 @@ 'gyp_chromeos_asan_lsan_edge_fuzzer_v8_heap_release_bot', 'MSAN Release (chained origins)': 'gn_msan_edge_release_bot', 'MSAN Release (no origins)': 'gn_msan_no_origins_edge_release_bot', - 'Mac ASAN Debug': 'gyp_asan_fuzzer_v8_heap_debug_symbols_static_bot', + 'Mac ASAN Debug': 'gyp_asan_edge_fuzzer_v8_heap_debug_symbols_static_bot', 'Mac ASAN Release Media': - 'gyp_asan_fuzzer_v8_heap_chrome_with_codecs_release_bot', - 'Mac ASAN Release': 'gyp_asan_fuzzer_v8_heap_release_bot', + 'gyp_asan_edge_fuzzer_v8_heap_chrome_with_codecs_release_bot', + 'Mac ASAN Release': 'gyp_asan_edge_fuzzer_v8_heap_release_bot', 'TSAN Debug': 'gyp_tsan_disable_nacl_line_tables_debug_bot', 'TSAN Release': 'gyp_tsan_disable_nacl_line_tables_release_bot', 'Telemetry Harness Upload': 'none', @@ -367,13 +369,14 @@ }, 'chromium.memory': { - 'Linux ASan LSan Builder': 'swarming_asan_lsan_gn_release_bot', + 'Linux ASan LSan Builder': 'swarming_asan_lsan_gn_release_trybot', 'Linux ASan LSan Tests (1)': 'none', 'Linux ASan Tests (sandboxed)': 'none', - 'Mac ASan 64 Builder': 'swarming_asan_lsan_full_symbols_gyp_release_bot', + 'Mac ASan 64 Builder': + 'swarming_asan_lsan_full_symbols_gyp_release_trybot', 'Mac ASan 64 Tests (1)': 'none', 'Linux Chromium OS ASan LSan Builder': - 'swarming_asan_lsan_chromeos_gn_release_bot', + 'swarming_asan_lsan_chromeos_gn_release_trybot', 'Linux Chromium OS ASan LSan Tests (1)': 'none', }, @@ -461,7 +464,7 @@ 'Mac 10.11 Perf (3)': 'none', 'Mac 10.11 Perf (4)': 'none', 'Mac 10.11 Perf (5)': 'none', - 'Mac Builder': 'gyp_official_goma', + 'Mac Builder': 'gn_official_goma', 'Mac HDD Perf (1)': 'none', 'Mac HDD Perf (2)': 'none', 'Mac HDD Perf (3)': 'none', @@ -612,7 +615,7 @@ 'official.desktop': { 'blimp-engine': '//build/args/bots/official.desktop/blimp-engine.gn', - 'mac64': 'gyp_official', + 'mac64': 'gn_official', 'precise64': 'gn_official', # Currently the official bots set mini_installer_official_deps=1 @@ -627,7 +630,7 @@ 'official.desktop.continuous': { 'mac beta': 'gyp_official', 'mac stable': 'gyp_official', - 'mac trunk': 'gyp_official', + 'mac trunk': 'gn_official', 'precise64 beta': 'gn_official', 'precise64 stable': 'gn_official', 'precise64 trunk': 'gn_official', @@ -736,7 +739,7 @@ 'linux_chromium_chromeos_msan_rel_ng': 'swarming_chromeos_msan_gn_release_bot', 'linux_chromium_chromeos_ozone_rel_ng': - 'swarming_chromeos_gyp_ozone_release_trybot', + 'swarming_chromeos_gn_ozone_release_trybot', 'linux_chromium_chromeos_rel_ng': 'swarming_chromeos_gn_release_trybot', 'linux_chromium_chromeos_variable': 'findit', 'linux_chromium_chromeos_variable_chrome': 'findit', @@ -785,7 +788,7 @@ 'ios-simulator-gn': 'ios_gn', 'mac_chromium_10.10_rel_ng': 'swarming_gpu_tests_gn_release_trybot', 'mac_chromium_10.10_macviews': 'mac_views_browser_gyp_release_trybot', - 'mac_chromium_archive_rel_ng': 'noswarming_gn_release_bot_mac_strip', + 'mac_chromium_archive_rel_ng': 'noswarming_gyp_release_bot_mac_strip', 'mac_chromium_asan_rel_ng': 'swarming_asan_dcheck_gyp_release_bot', 'mac_chromium_asan_variable': 'findit', 'mac_chromium_compile_dbg_ng': 'swarming_gn_debug_trybot', @@ -953,6 +956,11 @@ 'android', 'cronet', 'gn', 'release_bot_minimal_symbols', 'armv6' ], + 'android_cronet_gn_release_bot_minimal_symbols_clang_asan': [ + 'android', 'cronet', 'gn', 'release_bot_minimal_symbols', 'arm', 'clang', + 'asan' + ], + 'android_cronet_gn_release_bot_minimal_symbols_mipsel': [ 'android', 'cronet', 'gn', 'release_bot_minimal_symbols', 'mipsel' ], @@ -1200,8 +1208,7 @@ ], 'gn_windows_analyze': [ - 'gn', 'no_symbols', 'disable_precompiled_headers', - 'shared', 'x86', 'win_analyze', + 'gn', 'no_symbols', 'no_pch', 'shared', 'x86', 'win_analyze', ], 'gn_ubsan_vptr_release_bot': [ @@ -1225,8 +1232,17 @@ 'gyp', 'asan', 'edge', 'fuzzer', 'v8_heap', 'release_bot', 'x86', ], - 'gyp_asan_fuzzer_v8_heap_chrome_with_codecs_release_bot': [ - 'gyp', 'asan', 'fuzzer', 'v8_heap', 'chrome_with_codecs', 'release_bot', + 'gyp_asan_edge_fuzzer_v8_heap_chrome_with_codecs_release_bot': [ + 'gyp', 'asan', 'edge', 'fuzzer', 'v8_heap', 'chrome_with_codecs', + 'release_bot', + ], + + 'gyp_asan_edge_fuzzer_v8_heap_debug_symbols_static_bot': [ + 'gyp', 'asan', 'edge', 'fuzzer', 'v8_heap', 'debug_symbols_static_bot', + ], + + 'gyp_asan_edge_fuzzer_v8_heap_release_bot': [ + 'gyp', 'asan', 'edge', 'fuzzer', 'v8_heap', 'release_bot', ], 'gyp_asan_fuzzer_v8_heap_chrome_with_codecs_release_bot_x86': [ @@ -1234,14 +1250,6 @@ 'release_bot', 'x86', ], - 'gyp_asan_fuzzer_v8_heap_debug_symbols_static_bot': [ - 'gyp', 'asan', 'fuzzer', 'v8_heap', 'debug_symbols_static_bot', - ], - - 'gyp_asan_fuzzer_v8_heap_release_bot': [ - 'gyp', 'asan', 'fuzzer', 'v8_heap', 'release_bot', - ], - 'gyp_asan_fuzzer_v8_heap_release_bot_x86': [ 'gyp', 'asan', 'fuzzer', 'v8_heap', 'release_bot', 'x86', ], @@ -1425,10 +1433,6 @@ 'noswarming', 'gn', 'release_bot', 'x64', ], - 'noswarming_gn_release_bot_mac_strip': [ - 'noswarming', 'gn', 'release_bot', 'mac_strip', - ], - 'noswarming_gyp_release_bot_mac_strip': [ 'noswarming', 'gyp', 'release_bot', 'mac_strip', ], @@ -1477,16 +1481,13 @@ 'swarming', 'asan', 'dcheck_always_on', 'gyp', 'release_bot', ], - 'swarming_asan_lsan_chromeos_gn_release_bot': [ - 'swarming', 'asan', 'lsan', 'chromeos', 'gn', 'release_bot', - ], - 'swarming_asan_lsan_chromeos_gn_release_trybot': [ 'swarming', 'asan', 'lsan', 'chromeos', 'gyp', 'release_trybot', ], - 'swarming_asan_lsan_full_symbols_gyp_release_bot': [ + 'swarming_asan_lsan_full_symbols_gyp_release_trybot': [ 'swarming', 'asan', 'lsan', 'full_symbols', 'gyp', 'release_bot', + 'dcheck_always_on', ], 'swarming_asan_lsan_gn_release_bot': [ @@ -1505,8 +1506,8 @@ 'swarming', 'chromeos_with_codecs', 'gn', 'debug_trybot', ], - 'swarming_chromeos_gyp_ozone_release_trybot': [ - 'swarming', 'chromeos_with_codecs', 'gyp', 'ozone', 'release_trybot', + 'swarming_chromeos_gn_ozone_release_trybot': [ + 'swarming', 'chromeos_with_codecs', 'gn', 'ozone', 'release_trybot', ], 'swarming_chromeos_gn_release_bot': [ @@ -1521,8 +1522,8 @@ 'swarming', 'chromeos', 'msan', 'gn', 'release_bot', ], - 'swarming_chromeos_ozone_gyp_release_bot': [ - 'swarming', 'chromeos_with_codecs', 'ozone', 'gyp', 'release_bot', + 'swarming_chromeos_ozone_gn_release_bot': [ + 'swarming', 'chromeos_with_codecs', 'ozone', 'gn', 'release_bot', ], 'swarming_clang_tot_lld_release_shared': [ @@ -2026,11 +2027,6 @@ 'gyp_defines': 'disable_nacl=1', }, - 'disable_precompiled_headers': { - 'gn_args': 'disable_precompiled_headers=true', - 'gyp_defines': 'chromium_win_pch=0', - }, - 'edge': { 'gn_args': 'sanitizer_coverage_flags="edge"', 'gyp_defines': 'sanitizer_coverage=edge',
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index c14d60a..89300f41 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -13304,6 +13304,13 @@ </description> </action> +<action name="Signin_Impression_FromAutofillDropdown"> + <owner>mathp@chromium.org</owner> + <description> + Recorded when showing sign in entry in the Autofill dropdown. + </description> +</action> + <action name="Signin_Impression_FromAvatarBubbleSignin"> <owner>gogerald@chromium.org</owner> <description> @@ -13358,6 +13365,13 @@ </description> </action> +<action name="Signin_Impression_FromPasswordBubble"> + <owner>gogerald@chromium.org</owner> + <description> + Recorded when showing sign in entry in the saving password bubble. + </description> +</action> + <action name="Signin_Impression_FromRecentTabs"> <owner>gogerald@chromium.org</owner> <description> @@ -13810,6 +13824,59 @@ </description> </action> +<action name="StatusArea_Display_Default_Selected"> + <owner>bruthig@chromium.org</owner> + <owner>tbuckley@chromium.org</owner> + <description> + Counts the number of times the user selects the display row in the system + menu. This action does not always open the display settings, e.g. if the row + is slected from the lock screen. Use the + StatusArea_Display_Default_ShowSettings metric to see how often the settings + are actually launched. + </description> +</action> + +<action name="StatusArea_Display_Default_ShowSettings"> + <owner>bruthig@chromium.org</owner> + <owner>tbuckley@chromium.org</owner> + <description> + Counts the number of times the display settings are opened as a result of + the user selecting the display row in the system menu. + </description> +</action> + +<action name="StatusArea_Display_Notification_Created"> + <owner>bruthig@chromium.org</owner> + <owner>tbuckley@chromium.org</owner> + <description> + Counts the number of times a new display notification is added to the + notification center. + </description> +</action> + +<action name="StatusArea_Display_Notification_Selected"> + <owner>bruthig@chromium.org</owner> + <owner>tbuckley@chromium.org</owner> + <description> + Counts the number of times the user selects the display notification. This + action does not always open the display settings, e.g. if the notification + is selected from the lock screen. Use the + StatusArea_Display_Notification_Show_Settings metric to see how often the + settings are actually launched. Note these notifications are managed by the + notification center. + </description> +</action> + +<action name="StatusArea_Display_Notification_Show_Settings"> + <owner>bruthig@chromium.org</owner> + <owner>tbuckley@chromium.org</owner> + <description> + Counts the number of times the display settings are opened as a result of + the user selecting the display notification. Note these notifications are + managed by the notification center. + </description> +</action> + <action name="StatusArea_Drive_CancelOperation"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 78e185b6..b9d2af2 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -3074,6 +3074,14 @@ </summary> </histogram> +<histogram name="Autofill.QueriedCreditCardFormIsSecure" enum="BooleanSecure"> + <owner>mathp@chromium.org</owner> + <summary> + For credit card forms that are queried for Autofill, a ratio of how many are + within secure contexts (which includes mixed passive content). + </summary> +</histogram> + <histogram name="Autofill.SaveCreditCardPrompt" enum="AutofillSaveCreditCardPrompt"> <owner>jdonnelly@chromium.org</owner> @@ -18574,6 +18582,11 @@ <summary>The type of Vary header for a given GET response.</summary> </histogram> +<histogram name="Hyphenation.Open" units="ms"> + <owner>kojii@chromium.org</owner> + <summary>The time it takes to open a hyphenation dictionary.</summary> +</histogram> + <histogram name="Import.ImporterType.AutoImport" enum="ImporterType"> <owner>gab@chromium.org</owner> <summary>The importer used on first run Auto Import.</summary> @@ -21231,6 +21244,15 @@ </summary> </histogram> +<histogram name="Media.Audio.OutputDeviceAuthorizationTime" units="ms"> + <owner>olka@chromium.org</owner> + <summary> + Time delta between the moment output device authorization request is + received by the browser and the moment its processessing is finished (and + reply is to be sent back to the renderer if IPC is not closed yet). + </summary> +</histogram> + <histogram name="Media.Audio.PhysicalProcessorsMac"> <owner>henrika@chromium.org</owner> <summary> @@ -21348,6 +21370,35 @@ </summary> </histogram> +<histogram + name="Media.Audio.Render.SinkCache.GetOutputDeviceInfoCacheUtilization" + enum="GetOutputDeviceInfoCacheHit"> + <owner>olka@chromium.org</owner> + <summary> + Whether a cached sink was used to get audio output device information, or a + new sink was created for that. + </summary> +</histogram> + +<histogram name="Media.Audio.Render.SinkCache.InfoSinkReusedForOutput" + enum="BooleanReused"> + <owner>olka@chromium.org</owner> + <summary> + When a new sink is created to get output device information, it is cached. + This metric shows if such a sink is later reused for audio output (can + happen no more than once) or deleted unused after timeout expires. Logged + when one of the abovementioned events takes place. + </summary> +</histogram> + +<histogram name="Media.Audio.Render.SinkCache.UsedForSinkCreation" + enum="BooleanUsage"> + <owner>olka@chromium.org</owner> + <summary> + Whether a sink was created through the sink cache or directly. + </summary> +</histogram> + <histogram name="Media.Audio.RenderFailsWhenBufferSizeChangesMac" enum="BooleanChanged"> <owner>henrika@chromium.org</owner> @@ -25236,6 +25287,14 @@ </summary> </histogram> +<histogram name="Navigation.EngagementTime.Ratio" units="%"> + <owner>felt@chromium.org</owner> + <summary> + The percentage of time that HTTPS pages were in the foreground, as compared + to total foreground time. Recorded whenever user metrics are uploaded. + </summary> +</histogram> + <histogram name="Navigation.FrameHasEmbeddedCredentials" enum="Boolean"> <owner>palmer@chromium.org</owner> <owner>cbentzel@chromium.org</owner> @@ -28095,6 +28154,11 @@ </summary> </histogram> +<histogram name="Net.HttpAuthPromptType" enum="HttpAuthPromptType"> + <owner>meacer@chromium.org</owner> + <summary>Type of the HTTP auth prompt displayed.</summary> +</histogram> + <histogram name="Net.HttpAuthResource" enum="HttpAuthResource"> <obsolete> Removed in https://crrev.com/209100 @@ -35936,6 +36000,14 @@ </summary> </histogram> +<histogram name="OfflinePages.Background.OfflinerRequestStatus" + enum="OfflinePagesBackgroundOfflinerRequestStatus"> + <owner>dougarnett@chromium.org</owner> + <summary> + Status code of background offlining (loading and saving) requests. + </summary> +</histogram> + <histogram name="OfflinePages.BatchDelete.Count"> <owner>jianli@chromium.org</owner> <summary>Number of offline pages that are deleted in a batch.</summary> @@ -43914,6 +43986,26 @@ </summary> </histogram> +<histogram name="Process.Sandbox.Launch.Warning" units="GetLastError"> + <owner>forshaw@chromium.org</owner> + <summary> + Warnings returned while launching sandboxed process on Windows. For decoding + error code please refer to http://goo.gl/fJJiAv. This will only be logged + when SpawnTarget succeeds with SBOX_ALL_OK but the last warning result does + not equal SBOX_ALL_OK. + </summary> +</histogram> + +<histogram name="Process.Sandbox.Launch.WarningResultCode" + units="LaunchErrorCodes"> + <owner>forshaw@chromium.org</owner> + <summary> + The warning launch error returned while launching sandboxed process on + Windows. This will only be logged when SpawnTarget succeeds with SBOX_ALL_OK + but the last warning result does not equal SBOX_ALL_OK. + </summary> +</histogram> + <histogram name="Process.Sandbox.Lowbox.Launch.Error" units="GetLastError"> <owner>shrikant@chromium.org</owner> <summary> @@ -47130,6 +47222,15 @@ </summary> </histogram> +<histogram name="SafeBrowsing.V4ApplyUpdateResult" + enum="SafeBrowsingV4ApplyUpdateResult"> + <owner>vakh@chromium.org</owner> + <summary> + Track the result of applying the update fetched from the PVer4 service for a + particular store. + </summary> +</histogram> + <histogram name="SafeBrowsing.V4StoreReadResult" enum="SafeBrowsingStoreReadResult"> <owner>vakh@chromium.org</owner> @@ -59958,6 +60059,15 @@ </summary> </histogram> +<histogram name="UMA.PersistentHistograms.InitResult" + enum="PersistentHistogramsInitResult"> + <owner>bcwhite@chromium.org</owner> + <summary> + A count of successes and various failure modes related to collecting and + processing performance data obtained through "perf" on Chrome OS. + </summary> +</histogram> + <histogram name="UMA.ProfilesCount.AfterErase"> <obsolete> Deprecated as of Jun 2016. The histogram was added for debugging purpose and @@ -63169,6 +63279,18 @@ </summary> </histogram> +<histogram name="WebFont.InterventionResult.MissedCache" + enum="WebFontInterventionResult"> + <owner>toyoshim@chromium.org</owner> + <owner>kenjibaheux@chromium.org</owner> + <summary> + Like InterventionResult, this records whether User Agent Intervention was + triggered, and whether the request (would have) timed out or not. But this + version records only when data actually comes from network, not from disk or + memory cache, and is not provided in a data URL format. + </summary> +</histogram> + <histogram name="WebFont.LayoutLatency" units="ms"> <obsolete> Renamed to WebFont.StyleRecalcToDownloadLatency for clarity. @@ -63794,6 +63916,22 @@ </summary> </histogram> +<histogram name="WebRTC.ICE.TcpSocketWriteErrorCode" enum="SocketErrorCode"> + <owner>zhihuang@chromium.org</owner> + <summary> + Counters on different types of TCP socket error code. Collected when we hit + the error code when writing. + </summary> +</histogram> + +<histogram name="WebRTC.ICE.UdpSocketWriteErrorCode" enum="SocketErrorCode"> + <owner>zhihuang@chromium.org</owner> + <summary> + Counters on different types of UDP socket error code. Collected when we hit + the error code when writing. + </summary> +</histogram> + <histogram name="WebRTC.NAT.Metrics" enum="NatTypeCounters"> <owner>guoweis@chromium.org</owner> <summary> @@ -70573,6 +70711,7 @@ <int value="2" label="Ignore"> The user did not interact with the info bar. </int> + <int value="3" label="Dismiss">The user explicitly closed the infobar.</int> </enum> <enum name="DefaultBrowserState" type="int"> @@ -76596,6 +76735,7 @@ <int value="1437" label="BeforeInstallPromptEventUserChoice"/> <int value="1438" label="BeforeInstallPromptEventPreventDefault"/> <int value="1439" label="BeforeInstallPromptEventPrompt"/> + <int value="1440" label="ExecCommandAltersHTMLStructure"/> </enum> <enum name="FetchRequestMode" type="int"> @@ -78351,6 +78491,21 @@ <int value="2" label="Gesture predicted but didn't occur"/> </enum> +<enum name="GetOutputDeviceInfoCacheHit" type="int"> + <int value="0" label="Miss: no cached sink found"> + Output parmeters for a device are requested, and there is no corresponding + sink cached; new sink is created and cached. + </int> + <int value="1" label="Miss: cannot lookup by session id"> + If session id is used to specify a device, we always have to create and + cache a new sink. + </int> + <int value="2" label="Hit"> + Output parmeters for a device are requested, and there is a corresponding + sink cached. + </int> +</enum> + <enum name="GetPerfDataOutcome" type="int"> <int value="0" label="Success."> Perf data was collected, parsed and attached to the UMA protobuf @@ -78865,6 +79020,18 @@ <int value="7" label="Negotiate Reject"/> </enum> +<enum name="HttpAuthPromptType" type="int"> + <int value="0" label="Main frame with interstitial"> + Auth prompt displayed over a blank interstitial + </int> + <int value="1" label="Main frame without interstitial"> + Auth prompt displayed for the main frame, without a blank interstitial + </int> + <int value="2" label="Subresource"> + Auth prompt displayed for a subresource + </int> +</enum> + <enum name="HttpAuthResource" type="int"> <int value="0" label="Top Page Allowed"/> <int value="1" label="Same-domain Sub-resource Allowed"/> @@ -82441,7 +82608,7 @@ <int value="410" label="webkit-dashboard-region"/> <int value="411" label="webkit-overflow-scrolling"/> <int value="412" label="webkit-app-region"/> - <int value="413" label="webkit-filter"/> + <int value="413" label="alias-webkit-filter"/> <int value="414" label="webkit-box-decoration-break"/> <int value="415" label="webkit-tap-highlight-color"/> <int value="416" label="buffered-rendering"/> @@ -82564,6 +82731,9 @@ <int value="533" label="font-variant-caps"/> <int value="534" label="hyphens"/> <int value="535" label="font-variant-numeric"/> + <int value="536" label="text-size-adjust"/> + <int value="537" label="alias-webkit-text-size-adjust"/> + <int value="538" label="overflow-anchor"/> </enum> <enum name="MappedEditingCommands" type="int"> @@ -84471,6 +84641,18 @@ label="Account was not seeded before FireRefreshTokenAvailable"/> </enum> +<enum name="OfflinePagesBackgroundOfflinerRequestStatus" type="int"> +<!-- Generated from components/offline_pages/background/offliner.h --> + + <int value="0" label="Unknown (not expected to be recorded)"/> + <int value="1" label="Loaded (not expected to be recorded)"/> + <int value="2" label="Saved"/> + <int value="3" label="RequestCoordinator canceled"/> + <int value="4" label="Prerendering canceled"/> + <int value="5" label="Prerendering failed"/> + <int value="6" label="Save failed"/> +</enum> + <enum name="OfflinePagesClearAllStatus" type="int"> <int value="0" label="Success"/> <int value="1" label="Store reset failed"/> @@ -86128,6 +86310,13 @@ <int value="10" label="PERMISSION_BACKGROUND_SYNC"/> </enum> +<enum name="PersistentHistogramsInitResult" type="int"> + <int value="0" label="Local-Memory Success"/> + <int value="1" label="Local-Memory Failure"/> + <int value="2" label="Mapped-File Success"/> + <int value="3" label="Mapped-File Failure"/> +</enum> + <enum name="PhotoEditorFileType" type="int"> <int value="0" label="jpg"/> <int value="1" label="png"/> @@ -88397,6 +88586,16 @@ <int value="4" label="UNABLE_TO_RENAME_FAILURE"/> </enum> +<enum name="SafeBrowsingV4ApplyUpdateResult" type="int"> + <int value="0" label="APPLY_UPDATE_SUCCESS"/> + <int value="1" label="UNEXPECTED_APPLY_UPDATE_FAILURE"/> + <int value="2" label="PREFIX_SIZE_TOO_SMALL_FAILURE"/> + <int value="3" label="PREFIX_SIZE_TOO_LARGE_FAILURE"/> + <int value="4" label="ADDITIONS_SIZE_UNEXPECTED_FAILURE"/> + <int value="5" label="ADDITIONS_HAS_EXISTING_PREFIX_FAILURE"/> + <int value="6" label="UNEXPECTED_RESPONSE_TYPE_FAILURE"/> +</enum> + <enum name="SafeBrowsingV4OperationResult" type="int"> <int value="0" label="STATUS_200"/> <int value="1" label="PARSE_ERROR (subset of STATUS_200)"/> @@ -90248,6 +90447,17 @@ label="User scrolled below the fold (max once per NTP load). Obsolete."/> </enum> +<enum name="SocketErrorCode" type="int"> + <int value="0" label="ERR_MSG_TOO_BIG"/> + <int value="1" label="ERR_ADDRESS_UNREACHABLE"/> + <int value="2" label="ERR_ADDRESS_INVALID"/> + <int value="3" label="ERR_INTERNET_DISCONNECTED"/> + <int value="4" label="ERR_TIMED_OUT"/> + <int value="5" label="ERR_INSUFFICIENT_RESOURCES"/> + <int value="6" label="ERR_OUT_OF_MEMORY"/> + <int value="7" label="ERR_OTHER"/> +</enum> + <enum name="SocketStreamConnectionType" type="int"> <int value="0" label="None"/> <int value="1" label="All"/> @@ -95470,6 +95680,7 @@ <suffix name="Autofill"/> <suffix name="Policy"/> <suffix name="SpellChecker"/> + <suffix name="NTPSnippets"/> <affected-histogram name="DataUse.MessageSize"/> </histogram_suffixes> @@ -97973,19 +98184,40 @@ <histogram_suffixes name="NewTabPageProviders" separator="."> <suffix name="client" label="Suggestions coming from the client."/> - <suffix name="client0" - label="deprecated - Suggestions coming from the client source 0."/> + <suffix name="server" label="Suggestions coming from the server."/> <suffix name="popular" label="Non-personalized, popular suggestions."/> <suffix name="whitelist" label="Installed whitelist entry point suggestions."/> -<!-- Server providers 1 through 8 have never been logged. --> - - <suffix name="server" label="Suggestions coming from the server."/> - <suffix name="server0" label="Suggestions coming from server source 0."/> - <suffix name="server8" label="Suggestions coming from server source 8."/> - <suffix name="server9" label="Suggestions coming from server source 9."/> - <suffix name="server10" label="Suggestions coming from server source 10."/> - <suffix name="server11" label="Suggestions coming from server source 11."/> + <suffix name="client0"> + <obsolete> + Hasn't been used for a while, as of 2016-07. + </obsolete> + </suffix> + <suffix name="server0"> + <obsolete> + Hasn't been used for a while, as of 2016-07. + </obsolete> + </suffix> + <suffix name="server8"> + <obsolete> + Not used anymore as of 2016-07. + </obsolete> + </suffix> + <suffix name="server9"> + <obsolete> + Has never been used. + </obsolete> + </suffix> + <suffix name="server10"> + <obsolete> + Has never been used. + </obsolete> + </suffix> + <suffix name="server11"> + <obsolete> + Has never been used. + </obsolete> + </suffix> <affected-histogram name="NewTabPage.MostVisited"/> <affected-histogram name="NewTabPage.SuggestionsImpression"/> <affected-histogram name="NewTabPage.TileType"/> @@ -98210,6 +98442,7 @@ <histogram_suffixes name="OfflinePagesNamespace" separator="."> <suffix name="bookmark" label="Offline bookmark cache"/> <suffix name="last_n" label="Offline recent pages"/> + <suffix name="async_loading" label="Offline async loaded pages"/> <affected-histogram name="OfflinePages.DeletePage.AccessCount"/> <affected-histogram name="OfflinePages.DeletePage.LastOpenToCreated"/> <affected-histogram name="OfflinePages.DeletePage.PageSize"/> @@ -98464,7 +98697,8 @@ data reduction proxy."/> <suffix name="Clients.DataReductionProxy.LoFiOn" label="PageLoadMetrics that are a result of a navigation through the - data reduction proxy with LoFi requested."/> + data reduction proxy with session in LoFi enabled or control + field trial, and when the connection was slow."/> <suffix name="Clients.DocWrite.Evaluator" label="PageLoadMetrics from a page that could have been evaluated by the DocumentWriteEvaluator"/>
diff --git a/tools/perf/PRESUBMIT.py b/tools/perf/PRESUBMIT.py index 0572218..b6b3b87 100644 --- a/tools/perf/PRESUBMIT.py +++ b/tools/perf/PRESUBMIT.py
@@ -131,7 +131,7 @@ # TODO(prasadv): Uncomment this once crbug.com/601699 is fixed. # 'linux_perf_cq' ] - bots = ['tryserver.chromium.perf:%s' % s for s in bots] + bots = ['master.tryserver.chromium.perf:%s' % s for s in bots] bots_string = ';'.join(bots) description = original_description description += '\nCQ_INCLUDE_TRYBOTS=%s' % bots_string
diff --git a/tools/perf/benchmarks/system_health_smoke_test.py b/tools/perf/benchmarks/system_health_smoke_test.py index 95d326a3a..4f5c7b4 100644 --- a/tools/perf/benchmarks/system_health_smoke_test.py +++ b/tools/perf/benchmarks/system_health_smoke_test.py
@@ -34,12 +34,6 @@ _DISABLED_TESTS = frozenset({ # crbug.com/624474 'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_desktop.load:tools:dropbox', # pylint: disable=line-too-long - # crbug.com/624701 - 'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_mobile.load:games:bubbles', # pylint: disable=line-too-long - # crbug.com/624840 - 'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_mobile.load:tools:drive', # pylint: disable=line-too-long - 'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_mobile.load:tools:gmail', # pylint: disable=line-too-long - 'benchmarks.system_health_smoke_test.SystemHealthBenchmarkSmokeTest.system_health.memory_mobile.load:tools:dropbox', # pylint: disable=line-too-long })
diff --git a/tools/perf/benchmarks/v8_browsing.py b/tools/perf/benchmarks/v8_browsing.py new file mode 100644 index 0000000..9d2152fa --- /dev/null +++ b/tools/perf/benchmarks/v8_browsing.py
@@ -0,0 +1,93 @@ +# 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 re + +from core import perf_benchmark +from telemetry.timeline import chrome_trace_config +from telemetry.timeline import chrome_trace_category_filter +from telemetry.web_perf import timeline_based_measurement +import page_sets + + +# See tr.v.Numeric.getSummarizedScalarNumericsWithNames() +# https://github.com/catapult-project/catapult/blob/master/tracing/tracing/value/numeric.html#L323 +_IGNORED_MEMORY_STATS_RE = re.compile(r'_(std|count|min|sum|pct_\d{4}(_\d+)?)$') + +# Track only the high-level GC stats to reduce the data load on dashboard. +_IGNORED_V8_STATS_RE = re.compile( + r'_(idle_deadline_overrun|percentage_idle|outside_idle)') +_V8_GC_HIGH_LEVEL_STATS_RE = re.compile(r'^v8-gc-(' + r'full-mark-compactor_|' + r'incremental-finalize_|' + r'incremental-step_|' + r'latency-mark-compactor_|' + r'memory-mark-compactor_|' + r'scavenger_|' + r'total_)') + + +class _V8BrowsingBenchmark(perf_benchmark.PerfBenchmark): + """Base class for V8 browsing benchmarks. + This benchmark measures memory usage with periodic memory dumps and v8 times. + See browsing_stories._BrowsingStory for workload description. + """ + + def CreateTimelineBasedMeasurementOptions(self): + categories = [ + # Disable all categories by default. + '-*', + # Memory categories. + 'disabled-by-default-memory-infra', + # V8 categories. + 'blink.console', + 'disabled-by-default-v8.gc', + 'renderer.scheduler', + 'v8', + 'webkit.console', + ] + options = timeline_based_measurement.Options( + chrome_trace_category_filter.ChromeTraceCategoryFilter( + ','.join(categories))) + options.config.enable_android_graphics_memtrack = True + # Trigger periodic light memory dumps every 1000 ms. + memory_dump_config = chrome_trace_config.MemoryDumpConfig() + memory_dump_config.AddTrigger('light', 1000) + options.config.chrome_trace_config.SetMemoryDumpConfig(memory_dump_config) + options.SetTimelineBasedMetrics(['v8AndMemoryMetrics']) + return options + + @classmethod + def Name(cls): + return 'v8.browsing_%s' % cls.page_set.PLATFORM + + @classmethod + def ValueCanBeAddedPredicate(cls, value, is_first_result): + # TODO(crbug.com/610962): Remove this stopgap when the perf dashboard + # is able to cope with the data load generated by TBMv2 metrics. + if 'memory:chrome' in value.name: + return ('renderer_processes' in value.name and + not _IGNORED_MEMORY_STATS_RE.search(value.name)) + return (_V8_GC_HIGH_LEVEL_STATS_RE.search(value.name) and + not _IGNORED_V8_STATS_RE.search(value.name)) + + @classmethod + def ShouldTearDownStateAfterEachStoryRun(cls): + return True + + +class V8DesktopBrowsingBenchmark(_V8BrowsingBenchmark): + page_set = page_sets.DesktopBrowsingSystemHealthStorySet + + @classmethod + def ShouldDisable(cls, possible_browser): + return possible_browser.platform.GetDeviceTypeName() != 'Desktop' + + +class V8MobileBrowsingBenchmark(_V8BrowsingBenchmark): + page_set = page_sets.MobileBrowsingSystemHealthStorySet + + @classmethod + def ShouldDisable(cls, possible_browser): + return possible_browser.platform.GetDeviceTypeName() == 'Desktop'
diff --git a/tools/perf/page_sets/data/browsing_desktop.json b/tools/perf/page_sets/data/browsing_desktop.json new file mode 100644 index 0000000..d8fcf83 --- /dev/null +++ b/tools/perf/page_sets/data/browsing_desktop.json
@@ -0,0 +1,20 @@ +{ + "archives": { + "browsing_desktop_000.wpr": [ + "browse:news:cnn" + ], + "browsing_desktop_001.wpr": [ + "browse:news:hackernews" + ], + "browsing_desktop_002.wpr": [ + "browse:news:nytimes" + ], + "browsing_desktop_003.wpr": [ + "browse:news:reddit" + ], + "browsing_desktop_004.wpr": [ + "browse:social:twitter" + ] + }, + "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating." +} \ No newline at end of file
diff --git a/tools/perf/page_sets/data/browsing_desktop_000.wpr.sha1 b/tools/perf/page_sets/data/browsing_desktop_000.wpr.sha1 new file mode 100644 index 0000000..fc379d5 --- /dev/null +++ b/tools/perf/page_sets/data/browsing_desktop_000.wpr.sha1
@@ -0,0 +1 @@ +13fe92dcc66c3e400ef23544dc08e76a44c5c2cc \ No newline at end of file
diff --git a/tools/perf/page_sets/data/browsing_desktop_001.wpr.sha1 b/tools/perf/page_sets/data/browsing_desktop_001.wpr.sha1 new file mode 100644 index 0000000..9ab8fec6 --- /dev/null +++ b/tools/perf/page_sets/data/browsing_desktop_001.wpr.sha1
@@ -0,0 +1 @@ +ddafadda57bd321ecf0986622e2714687a159b0d \ No newline at end of file
diff --git a/tools/perf/page_sets/data/browsing_desktop_002.wpr.sha1 b/tools/perf/page_sets/data/browsing_desktop_002.wpr.sha1 new file mode 100644 index 0000000..d3d0bde --- /dev/null +++ b/tools/perf/page_sets/data/browsing_desktop_002.wpr.sha1
@@ -0,0 +1 @@ +1ca9c8f6a5561391f45f953db7106e194551f4bf \ No newline at end of file
diff --git a/tools/perf/page_sets/data/browsing_desktop_003.wpr.sha1 b/tools/perf/page_sets/data/browsing_desktop_003.wpr.sha1 new file mode 100644 index 0000000..feb3081 --- /dev/null +++ b/tools/perf/page_sets/data/browsing_desktop_003.wpr.sha1
@@ -0,0 +1 @@ +bc072ce9c4cb3aa8994b3482cdf1a214ce17cda2 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/browsing_desktop_004.wpr.sha1 b/tools/perf/page_sets/data/browsing_desktop_004.wpr.sha1 new file mode 100644 index 0000000..20f6d62 --- /dev/null +++ b/tools/perf/page_sets/data/browsing_desktop_004.wpr.sha1
@@ -0,0 +1 @@ +ca0fac3dcddf978c424334f7e3e4f5a589e98a4f \ No newline at end of file
diff --git a/tools/perf/page_sets/data/browsing_mobile.json b/tools/perf/page_sets/data/browsing_mobile.json new file mode 100644 index 0000000..37b649c --- /dev/null +++ b/tools/perf/page_sets/data/browsing_mobile.json
@@ -0,0 +1,29 @@ +{ + "archives": { + "browsing_mobile_000.wpr": [ + "browse:news:cnn" + ], + "browsing_mobile_001.wpr": [ + "browse:social:facebook" + ], + "browsing_mobile_002.wpr": [ + "browse:news:hackernews" + ], + "browsing_mobile_003.wpr": [ + "browse:news:nytimes" + ], + "browsing_mobile_004.wpr": [ + "browse:news:qq" + ], + "browsing_mobile_005.wpr": [ + "browse:news:reddit" + ], + "browsing_mobile_006.wpr": [ + "browse:social:twitter" + ], + "browsing_mobile_007.wpr": [ + "browse:news:washingtonpost" + ] + }, + "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating." +} \ No newline at end of file
diff --git a/tools/perf/page_sets/data/browsing_mobile_000.wpr.sha1 b/tools/perf/page_sets/data/browsing_mobile_000.wpr.sha1 new file mode 100644 index 0000000..ca90832 --- /dev/null +++ b/tools/perf/page_sets/data/browsing_mobile_000.wpr.sha1
@@ -0,0 +1 @@ +62e374b145af2b28056fd56d34b3296a4277691e \ No newline at end of file
diff --git a/tools/perf/page_sets/data/browsing_mobile_001.wpr.sha1 b/tools/perf/page_sets/data/browsing_mobile_001.wpr.sha1 new file mode 100644 index 0000000..c94eeac --- /dev/null +++ b/tools/perf/page_sets/data/browsing_mobile_001.wpr.sha1
@@ -0,0 +1 @@ +354566d7ceab53c5565ff0176ce94a00ce8bcd04 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/browsing_mobile_002.wpr.sha1 b/tools/perf/page_sets/data/browsing_mobile_002.wpr.sha1 new file mode 100644 index 0000000..2df556b --- /dev/null +++ b/tools/perf/page_sets/data/browsing_mobile_002.wpr.sha1
@@ -0,0 +1 @@ +3ae16f1f04f80ab673e8318bda02b1f751f9fd2d \ No newline at end of file
diff --git a/tools/perf/page_sets/data/browsing_mobile_003.wpr.sha1 b/tools/perf/page_sets/data/browsing_mobile_003.wpr.sha1 new file mode 100644 index 0000000..e867215 --- /dev/null +++ b/tools/perf/page_sets/data/browsing_mobile_003.wpr.sha1
@@ -0,0 +1 @@ +2faf0483fd16b14acb1b1a914c86e5d98df13777 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/browsing_mobile_004.wpr.sha1 b/tools/perf/page_sets/data/browsing_mobile_004.wpr.sha1 new file mode 100644 index 0000000..5d699f2 --- /dev/null +++ b/tools/perf/page_sets/data/browsing_mobile_004.wpr.sha1
@@ -0,0 +1 @@ +0961ce5e04b7136a2e7c72cd7f3a07410a26b29d \ No newline at end of file
diff --git a/tools/perf/page_sets/data/browsing_mobile_005.wpr.sha1 b/tools/perf/page_sets/data/browsing_mobile_005.wpr.sha1 new file mode 100644 index 0000000..384da63 --- /dev/null +++ b/tools/perf/page_sets/data/browsing_mobile_005.wpr.sha1
@@ -0,0 +1 @@ +88a33657d9f684b408af397137e31324d6ec054e \ No newline at end of file
diff --git a/tools/perf/page_sets/data/browsing_mobile_006.wpr.sha1 b/tools/perf/page_sets/data/browsing_mobile_006.wpr.sha1 new file mode 100644 index 0000000..a356639c --- /dev/null +++ b/tools/perf/page_sets/data/browsing_mobile_006.wpr.sha1
@@ -0,0 +1 @@ +1ce38b106fd3166eaae36fc51997f3772f2465bb \ No newline at end of file
diff --git a/tools/perf/page_sets/data/browsing_mobile_007.wpr.sha1 b/tools/perf/page_sets/data/browsing_mobile_007.wpr.sha1 new file mode 100644 index 0000000..beec4a4 --- /dev/null +++ b/tools/perf/page_sets/data/browsing_mobile_007.wpr.sha1
@@ -0,0 +1 @@ +b729e3ea1e7453eaabd6c0d0c4aed7def830e74f \ No newline at end of file
diff --git a/tools/perf/page_sets/data/dual_browser_story.json b/tools/perf/page_sets/data/dual_browser_story.json index 208221a..b9c8ffa3 100644 --- a/tools/perf/page_sets/data/dual_browser_story.json +++ b/tools/perf/page_sets/data/dual_browser_story.json
@@ -1,30 +1,34 @@ { - "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.", "archives": { - "dual_browser_story_001.wpr": [ - "http_en_m_wikipedia_org_wiki_Science", - "google_weather_94110", - "google_1600_amphitheatre_pkwy_mountain_view_ca", - "google_population_of_california", - "google_cat_pictures", - "google_tip_on_100_bill", - "http_www_amazon_com_gp_aw_s_k_nexus", - "http_search_yahoo_com_search__ylt_p_google", - "http_yandex_ru_touchsearch_text_science", - "google_sfo_jfk_flights", - "https_mobile_twitter_com_justinbieber_skip_interstitial_true", - "google_tom_hanks", - "http_m_taobao_com_channel_act_mobile_20131111_women_html", - "http_www_baidu_com_s_word_google", - "https_www_google_ca_hl_en_q_science", - "google_movies_94110", - "google_goog", - "google_science", - "https_m_facebook_com_rihanna", - "http_m_youtube_com_results_q_science" - ], "dual_browser_story_000.wpr": [ "https_www_google_com_hl_en_q_science" + ], + "dual_browser_story_001.wpr": [ + "http_m_taobao_com_channel_act_mobile_20131111_women_html", + "https_www_google_ca_hl_en_q_science" + ], + "dual_browser_story_002.wpr": [ + "http_www_amazon_com_gp_aw_s_k_nexus", + "http_m_youtube_com_results_q_science", + "google_weather_94110", + "google_tom_hanks", + "http_search_yahoo_com_search__ylt_p_google", + "google_sfo_jfk_flights", + "google_goog", + "https_mobile_twitter_com_justinbieber_skip_interstitial_true", + "http_m_intl_taobao_com_group_purchase_html", + "https_www_google_co_uk_hl_en_q_science", + "google_population_of_california", + "https_m_facebook_com_rihanna", + "http_yandex_ru_touchsearch_text_science", + "google_cat_pictures", + "google_movies_94110", + "google_science", + "http_en_m_wikipedia_org_wiki_Science", + "google_1600_amphitheatre_pkwy_mountain_view_ca", + "google_tip_on_100_bill", + "http_www_baidu_com_s_word_google" ] - } -} + }, + "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating." +} \ No newline at end of file
diff --git a/tools/perf/page_sets/data/dual_browser_story_002.wpr.sha1 b/tools/perf/page_sets/data/dual_browser_story_002.wpr.sha1 new file mode 100644 index 0000000..bdd814b --- /dev/null +++ b/tools/perf/page_sets/data/dual_browser_story_002.wpr.sha1
@@ -0,0 +1 @@ +c444ca554bd48238dd6a07d1f7773a68f7edc90d \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_system_health_desktop.json b/tools/perf/page_sets/data/memory_system_health_desktop.json index 18400562..12ee077 100644 --- a/tools/perf/page_sets/data/memory_system_health_desktop.json +++ b/tools/perf/page_sets/data/memory_system_health_desktop.json
@@ -1,54 +1,70 @@ { - "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.", "archives": { - "memory_system_health_desktop_004.wpr": [ - "load:tools:drive", - "load:tools:docs", - "load:tools:gmail", - "load:tools:maps", - "load:tools:stackoverflow", - "load:tools:dropbox", - "load:tools:weather" - ], - "memory_system_health_desktop_002.wpr": [ - "load:news:cnn", - "load:news:reddit", - "load:news:qq", - "load:news:bbc", - "load:news:wikipedia" - ], - "memory_system_health_desktop_005.wpr": [ - "load:games:spychase", - "load:games:alphabetty", - "load:games:bubbles", - "load:games:miniclip", - "load:games:lazors" - ], "memory_system_health_desktop_000.wpr": [ - "load:search:amazon", - "load:search:flipkart", - "load:search:ebay", - "load:search:google", - "load:search:yandex", - "load:search:taobao", - "load:search:yahoo", + "load:search:amazon", + "load:search:flipkart", + "load:search:ebay", + "load:search:google", + "load:search:yandex", + "load:search:taobao", + "load:search:yahoo", "load:search:baidu" - ], - "memory_system_health_desktop_003.wpr": [ - "load:media:soundcloud", - "load:media:dailymotion", - "load:media:9gag", - "load:media:flickr", - "load:media:google_images", - "load:media:youtube" - ], + ], "memory_system_health_desktop_001.wpr": [ - "load:social:facebook", - "load:social:instagram", - "load:social:twitter", - "load:social:pinterest", - "load:social:vk", + "load:social:instagram", + "load:social:pinterest", + "load:social:vk", "load:social:tumblr" + ], + "memory_system_health_desktop_002.wpr": [ + "load:news:bbc", + "load:news:wikipedia" + ], + "memory_system_health_desktop_003.wpr": [ + "load:media:soundcloud", + "load:media:dailymotion", + "load:media:9gag", + "load:media:flickr", + "load:media:google_images", + "load:media:youtube" + ], + "memory_system_health_desktop_004.wpr": [ + "load:tools:drive", + "load:tools:docs", + "load:tools:gmail", + "load:tools:maps", + "load:tools:stackoverflow", + "load:tools:dropbox", + "load:tools:weather" + ], + "memory_system_health_desktop_005.wpr": [ + "load:games:spychase", + "load:games:alphabetty", + "load:games:bubbles", + "load:games:miniclip", + "load:games:lazors" + ], + "memory_system_health_desktop_006.wpr": [ + "load:news:cnn" + ], + "memory_system_health_desktop_007.wpr": [ + "load:social:facebook" + ], + "memory_system_health_desktop_008.wpr": [ + "load:news:hackernews" + ], + "memory_system_health_desktop_009.wpr": [ + "load:news:nytimes" + ], + "memory_system_health_desktop_010.wpr": [ + "load:news:qq" + ], + "memory_system_health_desktop_011.wpr": [ + "load:news:reddit" + ], + "memory_system_health_desktop_012.wpr": [ + "load:social:twitter" ] - } -} + }, + "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating." +} \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_system_health_desktop_006.wpr.sha1 b/tools/perf/page_sets/data/memory_system_health_desktop_006.wpr.sha1 new file mode 100644 index 0000000..e84f1e36 --- /dev/null +++ b/tools/perf/page_sets/data/memory_system_health_desktop_006.wpr.sha1
@@ -0,0 +1 @@ +dbe6febc6e15c21ac96a6991d625bdb28e4458f1 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_system_health_desktop_007.wpr.sha1 b/tools/perf/page_sets/data/memory_system_health_desktop_007.wpr.sha1 new file mode 100644 index 0000000..ba5ea31 --- /dev/null +++ b/tools/perf/page_sets/data/memory_system_health_desktop_007.wpr.sha1
@@ -0,0 +1 @@ +8e70124ca04148babe5daf9627fbb099b76e7667 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_system_health_desktop_008.wpr.sha1 b/tools/perf/page_sets/data/memory_system_health_desktop_008.wpr.sha1 new file mode 100644 index 0000000..d9b6651 --- /dev/null +++ b/tools/perf/page_sets/data/memory_system_health_desktop_008.wpr.sha1
@@ -0,0 +1 @@ +e22ffae4bbc81029f1966383d9dd17748cfe9b77 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_system_health_desktop_009.wpr.sha1 b/tools/perf/page_sets/data/memory_system_health_desktop_009.wpr.sha1 new file mode 100644 index 0000000..234c214a --- /dev/null +++ b/tools/perf/page_sets/data/memory_system_health_desktop_009.wpr.sha1
@@ -0,0 +1 @@ +fdc4dc2cb02cb20a843ebb66645ae693860bdee7 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_system_health_desktop_010.wpr.sha1 b/tools/perf/page_sets/data/memory_system_health_desktop_010.wpr.sha1 new file mode 100644 index 0000000..7f017574 --- /dev/null +++ b/tools/perf/page_sets/data/memory_system_health_desktop_010.wpr.sha1
@@ -0,0 +1 @@ +cee43a0b4da2b4b3a9f6859dd5759326d832f24f \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_system_health_desktop_011.wpr.sha1 b/tools/perf/page_sets/data/memory_system_health_desktop_011.wpr.sha1 new file mode 100644 index 0000000..f9c82219 --- /dev/null +++ b/tools/perf/page_sets/data/memory_system_health_desktop_011.wpr.sha1
@@ -0,0 +1 @@ +ff746570bb75d6ba3cdfbe57091fbc0dddfe7caf \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_system_health_desktop_012.wpr.sha1 b/tools/perf/page_sets/data/memory_system_health_desktop_012.wpr.sha1 new file mode 100644 index 0000000..36f79dc --- /dev/null +++ b/tools/perf/page_sets/data/memory_system_health_desktop_012.wpr.sha1
@@ -0,0 +1 @@ +5146bd1a30d4e76fe4136d8a80bd0d279a8b6e43 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_system_health_mobile.json b/tools/perf/page_sets/data/memory_system_health_mobile.json index 672952e..cdaa155c 100644 --- a/tools/perf/page_sets/data/memory_system_health_mobile.json +++ b/tools/perf/page_sets/data/memory_system_health_mobile.json
@@ -1,51 +1,70 @@ { - "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.", "archives": { - "memory_system_health_mobile_005.wpr": [ - "load:games:lazors", - "load:games:bubbles", - "load:games:spychase" - ], - "memory_system_health_mobile_004.wpr": [ - "load:tools:gmail", - "load:tools:maps", - "load:tools:stackoverflow", - "load:tools:dropbox", - "load:tools:weather", - "load:tools:drive", - "load:tools:docs" - ], - "memory_system_health_mobile_001.wpr": [ - "load:social:facebook", - "load:social:tumblr", - "load:social:twitter", - "load:social:pinterest", - "load:social:instagram" - ], - "memory_system_health_mobile_003.wpr": [ - "load:media:9gag", - "load:media:google_images", - "load:media:soundcloud", - "load:media:youtube", - "load:media:dailymotion", - "load:media:flickr" - ], "memory_system_health_mobile_000.wpr": [ - "load:search:amazon", - "load:search:baidu", - "load:search:yandex", - "load:search:google", - "load:search:taobao", - "load:search:ebay", + "load:search:amazon", + "load:search:baidu", + "load:search:yandex", + "load:search:google", + "load:search:taobao", + "load:search:ebay", "load:search:yahoo" - ], + ], + "memory_system_health_mobile_001.wpr": [ + "load:social:tumblr", + "load:social:pinterest", + "load:social:instagram" + ], "memory_system_health_mobile_002.wpr": [ - "load:news:cnn", - "load:news:reddit", - "load:news:sohu", - "load:news:qq", - "load:news:bbc", + "load:news:sohu", + "load:news:bbc", "load:news:wikipedia" + ], + "memory_system_health_mobile_003.wpr": [ + "load:media:9gag", + "load:media:google_images", + "load:media:soundcloud", + "load:media:youtube", + "load:media:dailymotion", + "load:media:flickr" + ], + "memory_system_health_mobile_004.wpr": [ + "load:tools:gmail", + "load:tools:maps", + "load:tools:stackoverflow", + "load:tools:dropbox", + "load:tools:weather", + "load:tools:drive", + "load:tools:docs" + ], + "memory_system_health_mobile_005.wpr": [ + "load:games:lazors", + "load:games:bubbles", + "load:games:spychase" + ], + "memory_system_health_mobile_006.wpr": [ + "load:news:cnn" + ], + "memory_system_health_mobile_007.wpr": [ + "load:social:facebook" + ], + "memory_system_health_mobile_008.wpr": [ + "load:news:hackernews" + ], + "memory_system_health_mobile_009.wpr": [ + "load:news:nytimes" + ], + "memory_system_health_mobile_010.wpr": [ + "load:news:qq" + ], + "memory_system_health_mobile_011.wpr": [ + "load:news:reddit" + ], + "memory_system_health_mobile_012.wpr": [ + "load:social:twitter" + ], + "memory_system_health_mobile_013.wpr": [ + "load:news:washingtonpost" ] - } -} + }, + "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating." +} \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_system_health_mobile_006.wpr.sha1 b/tools/perf/page_sets/data/memory_system_health_mobile_006.wpr.sha1 new file mode 100644 index 0000000..5b8aab0b --- /dev/null +++ b/tools/perf/page_sets/data/memory_system_health_mobile_006.wpr.sha1
@@ -0,0 +1 @@ +7f86b3192dafcd133065c28898393df8c12fb941 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_system_health_mobile_007.wpr.sha1 b/tools/perf/page_sets/data/memory_system_health_mobile_007.wpr.sha1 new file mode 100644 index 0000000..24408df --- /dev/null +++ b/tools/perf/page_sets/data/memory_system_health_mobile_007.wpr.sha1
@@ -0,0 +1 @@ +eda06f1a8e7783a84c9ee72a88553fac2048a081 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_system_health_mobile_008.wpr.sha1 b/tools/perf/page_sets/data/memory_system_health_mobile_008.wpr.sha1 new file mode 100644 index 0000000..59e7ce3 --- /dev/null +++ b/tools/perf/page_sets/data/memory_system_health_mobile_008.wpr.sha1
@@ -0,0 +1 @@ +4fa19911cab200add04a6595d65ff0934bc3bb5d \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_system_health_mobile_009.wpr.sha1 b/tools/perf/page_sets/data/memory_system_health_mobile_009.wpr.sha1 new file mode 100644 index 0000000..77d53f7 --- /dev/null +++ b/tools/perf/page_sets/data/memory_system_health_mobile_009.wpr.sha1
@@ -0,0 +1 @@ +53eb718c4ec046aabc4d0a17a72de51322788cdf \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_system_health_mobile_010.wpr.sha1 b/tools/perf/page_sets/data/memory_system_health_mobile_010.wpr.sha1 new file mode 100644 index 0000000..98cfe00 --- /dev/null +++ b/tools/perf/page_sets/data/memory_system_health_mobile_010.wpr.sha1
@@ -0,0 +1 @@ +305273a313ba302c603c7684246d84d239763720 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_system_health_mobile_011.wpr.sha1 b/tools/perf/page_sets/data/memory_system_health_mobile_011.wpr.sha1 new file mode 100644 index 0000000..1a8dda0 --- /dev/null +++ b/tools/perf/page_sets/data/memory_system_health_mobile_011.wpr.sha1
@@ -0,0 +1 @@ +911fe0063555bef9df83f173a93a83711efccf49 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_system_health_mobile_012.wpr.sha1 b/tools/perf/page_sets/data/memory_system_health_mobile_012.wpr.sha1 new file mode 100644 index 0000000..3fe1c40 --- /dev/null +++ b/tools/perf/page_sets/data/memory_system_health_mobile_012.wpr.sha1
@@ -0,0 +1 @@ +30744e43b62592745a8d54a3d8d1bda3809f1240 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_system_health_mobile_013.wpr.sha1 b/tools/perf/page_sets/data/memory_system_health_mobile_013.wpr.sha1 new file mode 100644 index 0000000..eed63c2 --- /dev/null +++ b/tools/perf/page_sets/data/memory_system_health_mobile_013.wpr.sha1
@@ -0,0 +1 @@ +2e9a97079fa89da7a4769c36f832234d641d4712 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_top_10_mobile.json b/tools/perf/page_sets/data/memory_top_10_mobile.json index c300ea3..4ef26a5 100644 --- a/tools/perf/page_sets/data/memory_top_10_mobile.json +++ b/tools/perf/page_sets/data/memory_top_10_mobile.json
@@ -1,27 +1,33 @@ { - "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.", "archives": { "memory_top_10_mobile_000.wpr": [ - "after_http_en_m_wikipedia_org_wiki_Science", - "after_https_mobile_twitter_com_justinbieber_skip_interstitial_true", - "after_http_yandex_ru_touchsearch_text_science", - "https_www_google_com_hl_en_q_science", - "http_search_yahoo_com_search__ylt_p_google", - "after_http_m_youtube_com_results_q_science", - "https_mobile_twitter_com_justinbieber_skip_interstitial_true", - "https_m_facebook_com_rihanna", - "after_http_www_amazon_com_gp_aw_s_k_nexus", - "after_http_search_yahoo_com_search__ylt_p_google", - "after_https_www_google_com_hl_en_q_science", - "http_en_m_wikipedia_org_wiki_Science", - "http_www_baidu_com_s_word_google", - "after_http_www_baidu_com_s_word_google", - "after_https_m_facebook_com_rihanna", - "http_www_amazon_com_gp_aw_s_k_nexus", - "after_http_m_taobao_com_channel_act_mobile_20131111_women_html", - "http_yandex_ru_touchsearch_text_science", - "http_m_youtube_com_results_q_science", + "https_www_google_com_hl_en_q_science", + "after_https_www_google_com_hl_en_q_science", + "after_http_m_taobao_com_channel_act_mobile_20131111_women_html", "http_m_taobao_com_channel_act_mobile_20131111_women_html" + ], + "memory_top_10_mobile_001.wpr": [ + "after_http_m_intl_taobao_com_group_purchase_html", + "http_m_youtube_com_results_q_science", + "https_m_facebook_com_rihanna", + "http_m_intl_taobao_com_group_purchase_html", + "after_http_en_m_wikipedia_org_wiki_Science", + "after_http_m_youtube_com_results_q_science", + "http_search_yahoo_com_search__ylt_p_google", + "after_http_www_baidu_com_s_word_google", + "after_http_www_amazon_com_gp_aw_s_k_nexus", + "after_https_www_google_co_uk_hl_en_q_science", + "after_http_yandex_ru_touchsearch_text_science", + "http_en_m_wikipedia_org_wiki_Science", + "http_www_baidu_com_s_word_google", + "http_www_amazon_com_gp_aw_s_k_nexus", + "after_http_search_yahoo_com_search__ylt_p_google", + "http_yandex_ru_touchsearch_text_science", + "after_https_m_facebook_com_rihanna", + "https_www_google_co_uk_hl_en_q_science", + "after_https_mobile_twitter_com_justinbieber_skip_interstitial_true", + "https_mobile_twitter_com_justinbieber_skip_interstitial_true" ] - } + }, + "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating." } \ No newline at end of file
diff --git a/tools/perf/page_sets/data/memory_top_10_mobile_001.wpr.sha1 b/tools/perf/page_sets/data/memory_top_10_mobile_001.wpr.sha1 new file mode 100644 index 0000000..1c878f0 --- /dev/null +++ b/tools/perf/page_sets/data/memory_top_10_mobile_001.wpr.sha1
@@ -0,0 +1 @@ +8578c7ef3560fab0ad205affec3bf917ab1c9d13 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/top_10_mobile.json b/tools/perf/page_sets/data/top_10_mobile.json index fa98bb4..a1af9a4 100644 --- a/tools/perf/page_sets/data/top_10_mobile.json +++ b/tools/perf/page_sets/data/top_10_mobile.json
@@ -1,20 +1,24 @@ { - "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.", "archives": { "top_10_mobile_000.wpr": [ "https://mobile.twitter.com/justinbieber&" - ], + ], "top_10_mobile_003.wpr": [ - "http://m.youtube.com/results?q=science", - "http://yandex.ru/touchsearch?text=science", - "http://m.taobao.com/channel/act/mobile/20131111-women.html", - "http://search.yahoo.com/search;_ylt=?p=google", - "http://www.baidu.com/s?word=google", - "http://www.amazon.com/gp/aw/s/?k=nexus", - "http://en.m.wikipedia.org/wiki/Science", - "https://mobile.twitter.com/justinbieber?skip_interstitial=true", - "https://www.google.com/#hl=en&q=science", - "https://m.facebook.com/rihanna" + "http://m.taobao.com/channel/act/mobile/20131111-women.html", + "https://www.google.com/#hl=en&q=science" + ], + "top_10_mobile_004.wpr": [ + "https://m.facebook.com/rihanna", + "http://www.baidu.com/s?word=google", + "https://mobile.twitter.com/justinbieber?skip_interstitial=true", + "http://m.youtube.com/results?q=science", + "http://en.m.wikipedia.org/wiki/Science", + "http://m.intl.taobao.com/group-purchase.html", + "http://www.amazon.com/gp/aw/s/?k=nexus", + "https://www.google.co.uk/#hl=en&q=science", + "http://search.yahoo.com/search;_ylt=?p=google", + "http://yandex.ru/touchsearch?text=science" ] - } + }, + "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating." } \ No newline at end of file
diff --git a/tools/perf/page_sets/data/top_10_mobile_004.wpr.sha1 b/tools/perf/page_sets/data/top_10_mobile_004.wpr.sha1 new file mode 100644 index 0000000..64eb84c6f --- /dev/null +++ b/tools/perf/page_sets/data/top_10_mobile_004.wpr.sha1
@@ -0,0 +1 @@ +e4d9749fe4f1073674003142ff4ae77d95548296 \ No newline at end of file
diff --git a/tools/perf/page_sets/dual_browser_story.py b/tools/perf/page_sets/dual_browser_story.py index cb0826c..debaf60 100644 --- a/tools/perf/page_sets/dual_browser_story.py +++ b/tools/perf/page_sets/dual_browser_story.py
@@ -19,7 +19,7 @@ from page_sets.top_10_mobile import URL_LIST -GOOGLE_SEARCH = 'https://www.google.com/search?' +GOOGLE_SEARCH = 'https://www.google.co.uk/search?' SEARCH_QUERIES = [ 'science',
diff --git a/tools/perf/page_sets/mac_gpu_sites.py b/tools/perf/page_sets/mac_gpu_sites.py index f95e0994..71a2679 100644 --- a/tools/perf/page_sets/mac_gpu_sites.py +++ b/tools/perf/page_sets/mac_gpu_sites.py
@@ -22,6 +22,14 @@ ['--disable-mac-overlays']) +class _NoWebGLImageChromiumSharedPageState(shared_page_state.SharedPageState): + def __init__(self, test, finder_options, story_set): + super(_NoWebGLImageChromiumSharedPageState, self).__init__( + test, finder_options, story_set) + finder_options.browser_options.AppendExtraBrowserArgs( + ['--disable-webgl-image-chromium']) + + class TrivialScrollingPage(page_module.Page): def __init__(self, page_set, shared_page_state_class): @@ -42,6 +50,26 @@ shared_page_state_class=shared_page_state_class) +class TrivialCanvasPage(page_module.Page): + + def __init__(self, page_set, shared_page_state_class): + super(TrivialCanvasPage, self).__init__( + url='file://trivial_sites/trivial_canvas.html', + page_set=page_set, + name=self.__class__.__name__ + shared_page_state_class.__name__, + shared_page_state_class=shared_page_state_class) + + +class TrivialWebGLPage(page_module.Page): + + def __init__(self, page_set, shared_page_state_class): + super(TrivialWebGLPage, self).__init__( + url='file://trivial_sites/trivial_webgl.html', + page_set=page_set, + name=self.__class__.__name__ + shared_page_state_class.__name__, + shared_page_state_class=shared_page_state_class) + + class MacGpuTrivialPagesStorySet(story.StorySet): def __init__(self): @@ -49,10 +77,16 @@ self.AddStory(TrivialScrollingPage(self, shared_page_state.SharedPageState)) self.AddStory(TrivialBlinkingCursorPage( self, shared_page_state.SharedPageState)) + self.AddStory(TrivialCanvasPage(self, shared_page_state.SharedPageState)) + self.AddStory(TrivialWebGLPage(self, shared_page_state.SharedPageState)) self.AddStory(TrivialScrollingPage(self, _NoOverlaysSharedPageState)) self.AddStory(TrivialBlinkingCursorPage(self, _NoOverlaysSharedPageState)) + self.AddStory(TrivialCanvasPage(self, _NoOverlaysSharedPageState)) + self.AddStory(TrivialWebGLPage(self, _NoOverlaysSharedPageState)) self.AddStory(TrivialScrollingPage(self, _NoGpuSharedPageState)) self.AddStory(TrivialBlinkingCursorPage(self, _NoGpuSharedPageState)) + self.AddStory(TrivialCanvasPage(self, _NoGpuSharedPageState)) + self.AddStory(TrivialWebGLPage(self, _NoWebGLImageChromiumSharedPageState)) @property def allow_mixed_story_states(self):
diff --git a/tools/perf/page_sets/system_health/browsing_stories.py b/tools/perf/page_sets/system_health/browsing_stories.py new file mode 100644 index 0000000..fae4c966 --- /dev/null +++ b/tools/perf/page_sets/system_health/browsing_stories.py
@@ -0,0 +1,216 @@ +# 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 sys + +from page_sets.system_health import platforms +from page_sets.system_health import system_health_story + +from telemetry import story + + +class _BrowsingStory(system_health_story.SystemHealthStory): + """Abstract base class for browsing stories. + + A browsing story visits items on the main page. Subclasses provide + CSS selector to identify the items and implement interaction using + the helper methods of this class. + """ + + IS_SINGLE_PAGE_APP = False + ITEM_SELECTOR = NotImplemented + ITEMS_TO_VISIT = 4 + + def __init__(self, story_set): + super(_BrowsingStory, self).__init__( + story_set, take_memory_measurement=False) + + def _WaitForNavigation(self, action_runner): + if not self.IS_SINGLE_PAGE_APP: + action_runner.WaitForNavigate() + + def _NavigateToItem(self, action_runner, index): + item_selector = 'document.querySelectorAll("%s")[%d]' % ( + self.ITEM_SELECTOR, index) + self._ClickLink(action_runner, item_selector) + + def _ClickLink(self, action_runner, element_function): + action_runner.WaitForElement(element_function=element_function) + action_runner.ClickElement(element_function=element_function) + self._WaitForNavigation(action_runner) + + def _NavigateBack(self, action_runner): + action_runner.ExecuteJavaScript('window.history.back()') + self._WaitForNavigation(action_runner) + + +class _NewsBrowsingStory(_BrowsingStory): + """Abstract base class for news user stories. + + A news story imitates browsing a news website: + 1. Load the main page. + 2. Open and scroll the first news item. + 3. Go back to the main page and scroll it. + 4. Open and scroll the second news item. + 5. Go back to the main page and scroll it. + 6. etc. + """ + + ITEM_READ_TIME_IN_SECONDS = 3 + ITEM_SCROLL_REPEAT = 2 + MAIN_PAGE_SCROLL_REPEAT = 0 + + def _DidLoadDocument(self, action_runner): + for i in xrange(self.ITEMS_TO_VISIT): + self._NavigateToItem(action_runner, i) + self._ReadNewsItem(action_runner) + self._NavigateBack(action_runner) + self._ScrollMainPage(action_runner) + + def _ReadNewsItem(self, action_runner): + action_runner.tab.WaitForDocumentReadyStateToBeComplete() + action_runner.Wait(self.ITEM_READ_TIME_IN_SECONDS) + action_runner.RepeatableBrowserDrivenScroll( + repeat_count=self.ITEM_SCROLL_REPEAT) + + def _ScrollMainPage(self, action_runner): + action_runner.tab.WaitForDocumentReadyStateToBeComplete() + action_runner.RepeatableBrowserDrivenScroll( + repeat_count=self.MAIN_PAGE_SCROLL_REPEAT) + + +############################################################################## +# News browsing stories. +############################################################################## + + +class CnnStory(_NewsBrowsingStory): + """The second top website in http://www.alexa.com/topsites/category/News""" + NAME = 'browse:news:cnn' + URL = 'http://edition.cnn.com/' + ITEM_SELECTOR = '.cd__content > h3 > a' + ITEMS_TO_VISIT = 2 + # TODO(ulan): Enable this story on mobile once it uses less memory and + # does not crash with OOM. + SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY + + +class FacebookMobileStory(_NewsBrowsingStory): + NAME = 'browse:social:facebook' + URL = 'https://www.facebook.com/rihanna' + ITEM_SELECTOR = 'article ._5msj' + # Facebook on desktop is not interesting because it embeds post comments + # directly in the main timeline. + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY + + +class HackerNewsStory(_NewsBrowsingStory): + NAME = 'browse:news:hackernews' + URL = 'https://news.ycombinator.com' + ITEM_SELECTOR = '.athing .title > a' + + +class NytimesMobileStory(_NewsBrowsingStory): + """The third top website in http://www.alexa.com/topsites/category/News""" + NAME = 'browse:news:nytimes' + URL = 'http://mobile.nytimes.com' + ITEM_SELECTOR = '.sfgAsset-link' + # Visiting more items causes OOM. + ITEMS_TO_VISIT = 2 + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY + + +class NytimesDesktopStory(_NewsBrowsingStory): + """The third top website in http://www.alexa.com/topsites/category/News""" + NAME = 'browse:news:nytimes' + URL = 'http://www.nytimes.com' + ITEM_SELECTOR = '.story-heading > a' + SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY + + +class QqMobileStory(_NewsBrowsingStory): + NAME = 'browse:news:qq' + URL = 'http://news.qq.com' + # Desktop qq.com opens a news item in a separate tab, for which the back + # button does not work. + # Mobile qq.com is disabled due to crbug.com/627166 + ITEM_SELECTOR = '.list .full a' + SUPPORTED_PLATFORMS = platforms.NO_PLATFORMS + + +class RedditDesktopStory(_NewsBrowsingStory): + """The top website in http://www.alexa.com/topsites/category/News""" + NAME = 'browse:news:reddit' + URL = 'https://www.reddit.com/r/news/top/?sort=top&t=week' + ITEM_SELECTOR = '.thing .title > a' + SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY + + +class RedditMobileStory(_NewsBrowsingStory): + """The top website in http://www.alexa.com/topsites/category/News""" + NAME = 'browse:news:reddit' + URL = 'https://www.reddit.com/r/news/top/?sort=top&t=week' + IS_SINGLE_PAGE_APP = True + ITEM_SELECTOR = '.PostHeader__post-title-line' + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY + + +class TwitterMobileStory(_NewsBrowsingStory): + NAME = 'browse:social:twitter' + URL = 'https://www.twitter.com/justinbieber?skip_interstitial=true' + ITEM_SELECTOR = '.Tweet-text' + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY + + +class TwitterDesktopStory(_NewsBrowsingStory): + NAME = 'browse:social:twitter' + URL = 'https://www.twitter.com/justinbieber?skip_interstitial=true' + IS_SINGLE_PAGE_APP = True + ITEM_SELECTOR = '.tweet-text' + SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY + + +class WashingtonPostMobileStory(_NewsBrowsingStory): + """Progressive website""" + NAME = 'browse:news:washingtonpost' + URL = 'https://www.washingtonpost.com/pwa' + IS_SINGLE_PAGE_APP = True + ITEM_SELECTOR = '.hed > a' + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY + + def _DidLoadDocument(self, action_runner): + # Close the popup window. + action_runner.ClickElement(selector='.close') + super(WashingtonPostMobileStory, self)._DidLoadDocument(action_runner) + + +############################################################################## +# Browsing story sets. +############################################################################## + + +def _IterAllNewsBrowsingStoryClasses(): + return system_health_story.IterAllStoryClasses( + sys.modules[__name__], _NewsBrowsingStory) + + +class _BrowsingSystemHealthStorySet(story.StorySet): + PLATFORM = NotImplemented + + def __init__(self): + super(_BrowsingSystemHealthStorySet, self).__init__( + archive_data_file=('../data/browsing_%s.json' % self.PLATFORM), + cloud_storage_bucket=story.PARTNER_BUCKET) + for story_class in _IterAllNewsBrowsingStoryClasses(): + if self.PLATFORM not in story_class.SUPPORTED_PLATFORMS: + continue + self.AddStory(story_class(self)) + + +class DesktopBrowsingSystemHealthStorySet(_BrowsingSystemHealthStorySet): + PLATFORM = platforms.DESKTOP + + +class MobileBrowsingSystemHealthStorySet(_BrowsingSystemHealthStorySet): + PLATFORM = platforms.MOBILE
diff --git a/tools/perf/page_sets/system_health/loading_stories.py b/tools/perf/page_sets/system_health/loading_stories.py new file mode 100644 index 0000000..b46b2c8 --- /dev/null +++ b/tools/perf/page_sets/system_health/loading_stories.py
@@ -0,0 +1,373 @@ +# 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 sys + +from page_sets.system_health import platforms +from page_sets.system_health import system_health_story + +from page_sets.login_helpers import dropbox_login +from page_sets.login_helpers import google_login + + +class _LoadingStory(system_health_story.SystemHealthStory): + """Abstract base class for single-page System Health user stories.""" + pass + + +def IterAllStoryClasses(): + return system_health_story.IterAllStoryClasses( + sys.modules[__name__], _LoadingStory) + + +################################################################################ +# Search and e-commerce. +################################################################################ + + +class LoadGoogleStory(_LoadingStory): + NAME = 'load:search:google' + URL = 'https://www.google.com/#hl=en&q=science' + + +class LoadBaiduStory(_LoadingStory): + NAME = 'load:search:baidu' + URL = 'https://www.baidu.com/s?word=google' + + +class LoadYahooStory(_LoadingStory): + NAME = 'load:search:yahoo' + URL = 'https://search.yahoo.com/search;_ylt=?p=google' + + +class LoadAmazonStory(_LoadingStory): + NAME = 'load:search:amazon' + URL = 'https://www.amazon.com/s/?field-keywords=nexus' + + +class LoadTaobaoDesktopStory(_LoadingStory): + NAME = 'load:search:taobao' + URL = 'https://world.taobao.com/' + SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY + + +class LoadTaobaoMobileStory(_LoadingStory): + NAME = 'load:search:taobao' + # "ali_trackid" in the URL suppresses "Download app" interstitial. + URL = 'http://m.intl.taobao.com/?ali_trackid' + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY + + +class LoadYandexStory(_LoadingStory): + NAME = 'load:search:yandex' + URL = 'https://yandex.ru/touchsearch?text=science' + + +class LoadEbayStory(_LoadingStory): + NAME = 'load:search:ebay' + # Redirects to the "http://" version. + URL = 'https://www.ebay.com/sch/i.html?_nkw=headphones' + + +################################################################################ +# Social networks. +################################################################################ + + +class LoadFacebookStory(_LoadingStory): + # Using Facebook login often causes "404 Not Found" with WPR. + NAME = 'load:social:facebook' + URL = 'https://www.facebook.com/rihanna' + + +class LoadTwitterStory(_LoadingStory): + NAME = 'load:social:twitter' + URL = 'https://www.twitter.com/justinbieber?skip_interstitial=true' + + +class LoadVkStory(_LoadingStory): + NAME = 'load:social:vk' + URL = 'https://vk.com/sbeatles' + # Due to the deterministic date injected by WPR (February 2008), the cookie + # set by https://vk.com immediately expires, so the page keeps refreshing + # indefinitely on mobile + # (see https://github.com/chromium/web-page-replay/issues/71). + SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY + + +class LoadInstagramStory(_LoadingStory): + NAME = 'load:social:instagram' + URL = 'https://www.instagram.com/selenagomez/' + + +class LoadPinterestStory(_LoadingStory): + NAME = 'load:social:pinterest' + URL = 'https://uk.pinterest.com/categories/popular/' + + +class LoadTumblrStory(_LoadingStory): + NAME = 'load:social:tumblr' + # Redirects to the "http://" version. + URL = 'https://50thousand.tumblr.com/' + + +################################################################################ +# News, discussion and knowledge portals and blogs. +################################################################################ + + +class LoadBbcStory(_LoadingStory): + NAME = 'load:news:bbc' + # Redirects to the "http://" version. + URL = 'https://www.bbc.co.uk/news/world-asia-china-36189636' + + +class LoadCnnStory(_LoadingStory): + NAME = 'load:news:cnn' + # Using "https://" shows "Your connection is not private". + URL = 'http://edition.cnn.com' + + +class LoadHackerNewsStory(_LoadingStory): + NAME = 'load:news:hackernews' + URL = 'https://news.ycombinator.com' + + +class LoadNytimesDesktopStory(_LoadingStory): + NAME = 'load:news:nytimes' + URL = 'http://www.nytimes.com' + SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY + + +class LoadNytimesMobileStory(_LoadingStory): + NAME = 'load:news:nytimes' + URL = 'http://mobile.nytimes.com' + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY + + +class LoadQqMobileStory(_LoadingStory): + NAME = 'load:news:qq' + # Using "https://" hangs and shows "This site can't be reached". + URL = 'http://news.qq.com' + + +class LoadRedditDesktopStory(_LoadingStory): + NAME = 'load:news:reddit' + URL = 'https://www.reddit.com/r/news/top/?sort=top&t=week' + SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY + + +class LoadRedditMobileStory(_LoadingStory): + NAME = 'load:news:reddit' + URL = 'https://www.reddit.com/r/news/top/?sort=top&t=week' + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY + + +class LoadSohuStory(_LoadingStory): + NAME = 'load:news:sohu' + # Using "https://" leads to missing images and scripts on mobile (due to + # mixed content). + URL = 'http://m.sohu.com/n/447433356/' + # The desktop page (http://news.sohu.com/20160503/n447433356.shtml) almost + # always fails to completely load due to + # https://github.com/chromium/web-page-replay/issues/74. + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY + + +class LoadWashingtonPostMobileStory(_LoadingStory): + NAME = 'load:news:washingtonpost' + URL = 'https://www.washingtonpost.com/pwa' + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY + + def _DidLoadDocument(self, action_runner): + # Close the popup window. + action_runner.ClickElement(selector='.close') + + +class LoadWikipediaStory(_LoadingStory): + NAME = 'load:news:wikipedia' + URL = 'https://en.wikipedia.org/wiki/Science' + + +################################################################################ +# Audio and video. +################################################################################ + + +class LoadYouTubeStory(_LoadingStory): + # No way to disable autoplay on desktop. + NAME = 'load:media:youtube' + URL = 'https://www.youtube.com/watch?v=QGfhS1hfTWw&autoplay=false' + + +class LoadDailymotionStory(_LoadingStory): + # The side panel with related videos doesn't show on desktop due to + # https://github.com/chromium/web-page-replay/issues/74. + NAME = 'load:media:dailymotion' + URL = ( + 'https://www.dailymotion.com/video/x489k7d_street-performer-shows-off-slinky-skills_fun?autoplay=false') + + +class LoadGoogleImagesStory(_LoadingStory): + NAME = 'load:media:google_images' + URL = 'https://www.google.co.uk/search?tbm=isch&q=love' + + +class LoadSoundCloudStory(_LoadingStory): + # No way to disable autoplay on desktop. Album artwork doesn't load due to + # https://github.com/chromium/web-page-replay/issues/73. + NAME = 'load:media:soundcloud' + URL = 'https://soundcloud.com/lifeofdesiigner/desiigner-panda' + + +class Load9GagStory(_LoadingStory): + NAME = 'load:media:9gag' + URL = 'https://www.9gag.com/' + + +class LoadFlickr(_LoadingStory): + NAME = 'load:media:flickr' + URL = 'https://www.flickr.com/photos/tags/farm' + + def _DidLoadDocument(self, action_runner): + # Wait until the 'Recently tagged' view loads. + action_runner.WaitForJavaScriptCondition(''' + document.querySelector( + '.search-photos-everyone-trending-view .photo-list-view') + !== null''') + + +################################################################################ +# Online tools (documents, emails, storage, ...). +################################################################################ + + +class LoadDocsStory(_LoadingStory): + NAME = 'load:tools:docs' + URL = ( + 'https://docs.google.com/document/d/1GvzDP-tTLmJ0myRhUAfTYWs3ZUFilUICg8psNHyccwQ/edit?usp=sharing') + + +class _LoadGmailBaseStory(_LoadingStory): + NAME = 'load:tools:gmail' + URL = 'https://mail.google.com/mail/' + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY + + def _Login(self, action_runner): + google_login.LoginGoogleAccount(action_runner, 'googletest', + self.credentials_path) + + # Navigating to https://mail.google.com immediately leads to an infinite + # redirection loop due to a bug in WPR (see + # https://github.com/chromium/web-page-replay/issues/70). We therefore first + # navigate to a sub-URL to set up the session and hit the resulting + # redirection loop. Afterwards, we can safely navigate to + # https://mail.google.com. + action_runner.Navigate( + 'https://mail.google.com/mail/mu/mp/872/trigger_redirection_loop') + action_runner.tab.WaitForDocumentReadyStateToBeComplete() + + +class LoadGmailDesktopStory(_LoadGmailBaseStory): + SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY + + def _DidLoadDocument(self, action_runner): + # Wait until the UI loads. + action_runner.WaitForJavaScriptCondition( + 'document.getElementById("loading").style.display === "none"') + +class LoadGmailMobileStory(_LoadGmailBaseStory): + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY + + def _DidLoadDocument(self, action_runner): + # Close the "Get Inbox by Gmail" interstitial. + action_runner.WaitForJavaScriptCondition( + 'document.querySelector("#isppromo a") !== null') + action_runner.ExecuteJavaScript( + 'document.querySelector("#isppromo a").click()') + # Wait until the UI loads. + action_runner.WaitForJavaScriptCondition( + 'document.getElementById("apploadingdiv").style.height === "0px"') + + +class LoadMapsStory(_LoadingStory): + NAME = 'load:tools:maps' + URL = 'https://www.google.com/maps/place/London,+UK/' + + +class LoadStackOverflowStory(_LoadingStory): + NAME = 'load:tools:stackoverflow' + URL = ( + 'https://stackoverflow.com/questions/36827659/compiling-an-application-for-use-in-highly-radioactive-environments') + + +class LoadDropboxStory(_LoadingStory): + NAME = 'load:tools:dropbox' + URL = 'https://www.dropbox.com' + + def _Login(self, action_runner): + dropbox_login.LoginAccount(action_runner, 'dropbox', self.credentials_path) + + +class LoadWeatherStory(_LoadingStory): + NAME = 'load:tools:weather' + URL = 'https://weather.com/en-GB/weather/today/l/USCA0286:1:US' + + +class LoadDriveStory(_LoadingStory): + NAME = 'load:tools:drive' + URL = 'https://drive.google.com/drive/my-drive' + + def _Login(self, action_runner): + google_login.LoginGoogleAccount(action_runner, 'googletest', + self.credentials_path) + + +################################################################################ +# In-browser games (HTML5 and Flash). +################################################################################ + + +class LoadBubblesStory(_LoadingStory): + NAME = 'load:games:bubbles' + URL = ( + 'https://games.cdn.famobi.com/html5games/s/smarty-bubbles/v010/?fg_domain=play.famobi.com&fg_uid=d8f24956-dc91-4902-9096-a46cb1353b6f&fg_pid=4638e320-4444-4514-81c4-d80a8c662371&fg_beat=620') + + def _DidLoadDocument(self, action_runner): + # The #logo element is removed right before the main menu is displayed. + action_runner.WaitForJavaScriptCondition( + 'document.getElementById("logo") === null') + + +class LoadLazorsStory(_LoadingStory): + NAME = 'load:games:lazors' + # Using "https://" hangs and shows "This site can't be reached". + URL = 'http://www8.games.mobi/games/html5/lazors/lazors.html' + + +class LoadSpyChaseStory(_LoadingStory): + NAME = 'load:games:spychase' + # Using "https://" shows "Your connection is not private". + URL = 'http://playstar.mobi/games/spychase/index.php' + + def _DidLoadDocument(self, action_runner): + # The background of the game canvas is set when the "Tap screen to play" + # caption is displayed. + action_runner.WaitForJavaScriptCondition( + 'document.querySelector("#game canvas").style.background !== ""') + + +class LoadMiniclipStory(_LoadingStory): + NAME = 'load:games:miniclip' + # Using "https://" causes "404 Not Found" during WPR recording. + URL = 'http://www.miniclip.com/games/en/' + # Desktop only (requires Flash). + SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY + + +class LoadAlphabettyStory(_LoadingStory): + NAME = 'load:games:alphabetty' + URL = 'https://king.com/play/alphabetty' + # Desktop only (requires Flash). + SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY
diff --git a/tools/perf/page_sets/system_health/platforms.py b/tools/perf/page_sets/system_health/platforms.py new file mode 100644 index 0000000..cc6bb5b3 --- /dev/null +++ b/tools/perf/page_sets/system_health/platforms.py
@@ -0,0 +1,12 @@ +# 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. + +DESKTOP = 'desktop' +MOBILE = 'mobile' + +ALL_PLATFORMS = frozenset({DESKTOP, MOBILE}) +DESKTOP_ONLY = frozenset({DESKTOP}) +MOBILE_ONLY = frozenset({MOBILE}) +# This is used for disabling a story on all platforms. +NO_PLATFORMS = frozenset()
diff --git a/tools/perf/page_sets/system_health/single_page_stories.py b/tools/perf/page_sets/system_health/single_page_stories.py deleted file mode 100644 index efd8e09..0000000 --- a/tools/perf/page_sets/system_health/single_page_stories.py +++ /dev/null
@@ -1,407 +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 logging -import sys - -from page_sets.login_helpers import dropbox_login -from page_sets.login_helpers import google_login - -from telemetry.core import discover -from telemetry.page import page - - -_ALL_PLATFORMS = frozenset({'desktop', 'mobile'}) -_DESKTOP_ONLY = frozenset({'desktop'}) -_MOBILE_ONLY = frozenset({'mobile'}) -_NO_PLATFORMS = frozenset() - - -_DUMP_WAIT_TIME = 3 - - -class _SinglePageStory(page.Page): - """Abstract base class for single-page System Health user stories.""" - - # The full name of a single page story has the form CASE:GROUP:PAGE (e.g. - # 'load:search:google'). - NAME = NotImplemented - URL = NotImplemented - SUPPORTED_PLATFORMS = _ALL_PLATFORMS - - def __init__(self, story_set, take_memory_measurement): - case, group, _ = self.NAME.split(':') - super(_SinglePageStory, self).__init__( - page_set=story_set, name=self.NAME, url=self.URL, - credentials_path='../data/credentials.json', - grouping_keys={'case': case, 'group': group}) - self._take_memory_measurement = take_memory_measurement - - def _Measure(self, action_runner): - if not self._take_memory_measurement: - return - # TODO(petrcermak): This method is essentially the same as - # MemoryHealthPage._TakeMemoryMeasurement() in memory_health_story.py. - # Consider sharing the common code. - action_runner.Wait(_DUMP_WAIT_TIME) - action_runner.ForceGarbageCollection() - action_runner.Wait(_DUMP_WAIT_TIME) - tracing_controller = action_runner.tab.browser.platform.tracing_controller - if not tracing_controller.is_tracing_running: - return # Tracing is not running, e.g., when recording a WPR archive. - if not action_runner.tab.browser.DumpMemory(): - logging.error('Unable to get a memory dump for %s.', self.name) - - def _Login(self, action_runner): - pass - - def _DidLoadDocument(self, action_runner): - pass - - def RunNavigateSteps(self, action_runner): - self._Login(action_runner) - super(_SinglePageStory, self).RunNavigateSteps(action_runner) - - def RunPageInteractions(self, action_runner): - action_runner.tab.WaitForDocumentReadyStateToBeComplete() - self._DidLoadDocument(action_runner) - self._Measure(action_runner) - - -def IterAllStoryClasses(): - # Sort the classes by their names so that their order is stable and - # deterministic. - for unused_cls_name, cls in sorted(discover.DiscoverClassesInModule( - module=sys.modules[__name__], - base_class=_SinglePageStory, - index_by_class_name=True).iteritems()): - yield cls - - -################################################################################ -# Search and e-commerce. -################################################################################ - - -class LoadGoogleStory(_SinglePageStory): - NAME = 'load:search:google' - URL = 'https://www.google.com/#hl=en&q=science' - - -class LoadBaiduStory(_SinglePageStory): - NAME = 'load:search:baidu' - URL = 'https://www.baidu.com/s?word=google' - - -class LoadYahooStory(_SinglePageStory): - NAME = 'load:search:yahoo' - URL = 'https://search.yahoo.com/search;_ylt=?p=google' - - -class LoadAmazonStory(_SinglePageStory): - NAME = 'load:search:amazon' - URL = 'https://www.amazon.com/s/?field-keywords=nexus' - - -class LoadTaobaoDesktopStory(_SinglePageStory): - NAME = 'load:search:taobao' - URL = 'https://world.taobao.com/' - SUPPORTED_PLATFORMS = _DESKTOP_ONLY - - -class LoadTaobaoMobileStory(_SinglePageStory): - NAME = 'load:search:taobao' - # "ali_trackid" in the URL suppresses "Download app" interstitial. - URL = 'http://m.intl.taobao.com/?ali_trackid' - SUPPORTED_PLATFORMS = _MOBILE_ONLY - - -class LoadYandexStory(_SinglePageStory): - NAME = 'load:search:yandex' - URL = 'https://yandex.ru/touchsearch?text=science' - - -class LoadEbayStory(_SinglePageStory): - NAME = 'load:search:ebay' - # Redirects to the "http://" version. - URL = 'https://www.ebay.com/sch/i.html?_nkw=headphones' - - -################################################################################ -# Social networks. -################################################################################ - - -class LoadFacebookStory(_SinglePageStory): - # Using Facebook login often causes "404 Not Found" with WPR. - NAME = 'load:social:facebook' - URL = 'https://www.facebook.com/rihanna' - - -class LoadTwitterStory(_SinglePageStory): - NAME = 'load:social:twitter' - URL = 'https://www.twitter.com/justinbieber?skip_interstitial=true' - - -class LoadVkStory(_SinglePageStory): - NAME = 'load:social:vk' - URL = 'https://vk.com/sbeatles' - # Due to the deterministic date injected by WPR (February 2008), the cookie - # set by https://vk.com immediately expires, so the page keeps refreshing - # indefinitely on mobile - # (see https://github.com/chromium/web-page-replay/issues/71). - SUPPORTED_PLATFORMS = _DESKTOP_ONLY - - -class LoadInstagramStory(_SinglePageStory): - NAME = 'load:social:instagram' - URL = 'https://www.instagram.com/selenagomez/' - - -class LoadPinterestStory(_SinglePageStory): - NAME = 'load:social:pinterest' - URL = 'https://uk.pinterest.com/categories/popular/' - - -class LoadTumblrStory(_SinglePageStory): - NAME = 'load:social:tumblr' - # Redirects to the "http://" version. - URL = 'https://50thousand.tumblr.com/' - - -################################################################################ -# News, discussion and knowledge portals and blogs. -################################################################################ - - -class LoadBbcStory(_SinglePageStory): - NAME = 'load:news:bbc' - # Redirects to the "http://" version. - URL = 'https://www.bbc.co.uk/news/world-asia-china-36189636' - - -class LoadCnnStory(_SinglePageStory): - NAME = 'load:news:cnn' - # Using "https://" shows "Your connection is not private". - URL = ( - 'http://edition.cnn.com/2016/05/02/health/three-habitable-planets-earth-dwarf-star/index.html') - - -class LoadRedditDesktopStory(_SinglePageStory): - NAME = 'load:news:reddit' - URL = ( - 'https://www.reddit.com/r/AskReddit/comments/4hi90e/whats_your_best_wedding_horror_story/') - SUPPORTED_PLATFORMS = _DESKTOP_ONLY - - -class LoadRedditMobileStory(_SinglePageStory): - NAME = 'load:news:reddit' - URL = ( - 'https://m.reddit.com/r/AskReddit/comments/4hi90e/whats_your_best_wedding_horror_story/') - SUPPORTED_PLATFORMS = _MOBILE_ONLY - - -class LoadQqMobileStory(_SinglePageStory): - NAME = 'load:news:qq' - # Using "https://" hangs and shows "This site can't be reached". - URL = 'http://news.qq.com/a/20160503/003186.htm' - - -class LoadSohuStory(_SinglePageStory): - NAME = 'load:news:sohu' - # Using "https://" leads to missing images and scripts on mobile (due to - # mixed content). - URL = 'http://m.sohu.com/n/447433356/' - # The desktop page (http://news.sohu.com/20160503/n447433356.shtml) almost - # always fails to completely load due to - # https://github.com/chromium/web-page-replay/issues/74. - SUPPORTED_PLATFORMS = _MOBILE_ONLY - - -class LoadWikipediaStory(_SinglePageStory): - NAME = 'load:news:wikipedia' - URL = 'https://en.wikipedia.org/wiki/Science' - - -################################################################################ -# Audio and video. -################################################################################ - - -class LoadYouTubeStory(_SinglePageStory): - # No way to disable autoplay on desktop. - NAME = 'load:media:youtube' - URL = 'https://www.youtube.com/watch?v=QGfhS1hfTWw&autoplay=false' - - -class LoadDailymotionStory(_SinglePageStory): - # The side panel with related videos doesn't show on desktop due to - # https://github.com/chromium/web-page-replay/issues/74. - NAME = 'load:media:dailymotion' - URL = ( - 'https://www.dailymotion.com/video/x489k7d_street-performer-shows-off-slinky-skills_fun?autoplay=false') - - -class LoadGoogleImagesStory(_SinglePageStory): - NAME = 'load:media:google_images' - URL = 'https://www.google.co.uk/search?tbm=isch&q=love' - - -class LoadSoundCloudStory(_SinglePageStory): - # No way to disable autoplay on desktop. Album artwork doesn't load due to - # https://github.com/chromium/web-page-replay/issues/73. - NAME = 'load:media:soundcloud' - URL = 'https://soundcloud.com/lifeofdesiigner/desiigner-panda' - - -class Load9GagStory(_SinglePageStory): - NAME = 'load:media:9gag' - URL = 'https://www.9gag.com/' - - -class LoadFlickr(_SinglePageStory): - NAME = 'load:media:flickr' - URL = 'https://www.flickr.com/photos/tags/farm' - - def _DidLoadDocument(self, action_runner): - # Wait until the 'Recently tagged' view loads. - action_runner.WaitForJavaScriptCondition(''' - document.querySelector( - '.search-photos-everyone-trending-view .photo-list-view') - !== null''') - - -################################################################################ -# Online tools (documents, emails, storage, ...). -################################################################################ - - -class LoadDocsStory(_SinglePageStory): - NAME = 'load:tools:docs' - URL = ( - 'https://docs.google.com/document/d/1GvzDP-tTLmJ0myRhUAfTYWs3ZUFilUICg8psNHyccwQ/edit?usp=sharing') - - -class _LoadGmailBaseStory(_SinglePageStory): - NAME = 'load:tools:gmail' - URL = 'https://mail.google.com/mail/' - SUPPORTED_PLATFORMS = _NO_PLATFORMS - - def _Login(self, action_runner): - google_login.LoginGoogleAccount(action_runner, 'googletest', - self.credentials_path) - - # Navigating to https://mail.google.com immediately leads to an infinite - # redirection loop due to a bug in WPR (see - # https://github.com/chromium/web-page-replay/issues/70). We therefore first - # navigate to a sub-URL to set up the session and hit the resulting - # redirection loop. Afterwards, we can safely navigate to - # https://mail.google.com. - action_runner.Navigate( - 'https://mail.google.com/mail/mu/mp/872/trigger_redirection_loop') - action_runner.tab.WaitForDocumentReadyStateToBeComplete() - - -class LoadGmailDesktopStory(_LoadGmailBaseStory): - SUPPORTED_PLATFORMS = _DESKTOP_ONLY - - def _DidLoadDocument(self, action_runner): - # Wait until the UI loads. - action_runner.WaitForJavaScriptCondition( - 'document.getElementById("loading").style.display === "none"') - -class LoadGmailMobileStory(_LoadGmailBaseStory): - SUPPORTED_PLATFORMS = _MOBILE_ONLY - - def _DidLoadDocument(self, action_runner): - # Close the "Get Inbox by Gmail" interstitial. - action_runner.WaitForJavaScriptCondition( - 'document.querySelector("#isppromo a") !== null') - action_runner.ExecuteJavaScript( - 'document.querySelector("#isppromo a").click()') - # Wait until the UI loads. - action_runner.WaitForJavaScriptCondition( - 'document.getElementById("apploadingdiv").style.height === "0px"') - - -class LoadMapsStory(_SinglePageStory): - NAME = 'load:tools:maps' - URL = 'https://www.google.com/maps/place/London,+UK/' - - -class LoadStackOverflowStory(_SinglePageStory): - NAME = 'load:tools:stackoverflow' - URL = ( - 'https://stackoverflow.com/questions/36827659/compiling-an-application-for-use-in-highly-radioactive-environments') - - -class LoadDropboxStory(_SinglePageStory): - NAME = 'load:tools:dropbox' - URL = 'https://www.dropbox.com' - - def _Login(self, action_runner): - dropbox_login.LoginAccount(action_runner, 'dropbox', self.credentials_path) - - -class LoadWeatherStory(_SinglePageStory): - NAME = 'load:tools:weather' - URL = 'https://weather.com/en-GB/weather/today/l/USCA0286:1:US' - - -class LoadDriveStory(_SinglePageStory): - NAME = 'load:tools:drive' - URL = 'https://drive.google.com/drive/my-drive' - - def _Login(self, action_runner): - google_login.LoginGoogleAccount(action_runner, 'googletest', - self.credentials_path) - - -################################################################################ -# In-browser games (HTML5 and Flash). -################################################################################ - - -class LoadBubblesStory(_SinglePageStory): - NAME = 'load:games:bubbles' - URL = ( - 'https://games.cdn.famobi.com/html5games/s/smarty-bubbles/v010/?fg_domain=play.famobi.com&fg_uid=d8f24956-dc91-4902-9096-a46cb1353b6f&fg_pid=4638e320-4444-4514-81c4-d80a8c662371&fg_beat=620') - - def _DidLoadDocument(self, action_runner): - # The #logo element is removed right before the main menu is displayed. - action_runner.WaitForJavaScriptCondition( - 'document.getElementById("logo") === null') - - -class LoadLazorsStory(_SinglePageStory): - NAME = 'load:games:lazors' - # Using "https://" hangs and shows "This site can't be reached". - URL = 'http://www8.games.mobi/games/html5/lazors/lazors.html' - - -class LoadSpyChaseStory(_SinglePageStory): - NAME = 'load:games:spychase' - # Using "https://" shows "Your connection is not private". - URL = 'http://playstar.mobi/games/spychase/index.php' - - def _DidLoadDocument(self, action_runner): - # The background of the game canvas is set when the "Tap screen to play" - # caption is displayed. - action_runner.WaitForJavaScriptCondition( - 'document.querySelector("#game canvas").style.background !== ""') - - -class LoadMiniclipStory(_SinglePageStory): - NAME = 'load:games:miniclip' - # Using "https://" causes "404 Not Found" during WPR recording. - URL = 'http://www.miniclip.com/games/en/' - # Desktop only (requires Flash). - SUPPORTED_PLATFORMS = _DESKTOP_ONLY - - -class LoadAlphabettyStory(_SinglePageStory): - NAME = 'load:games:alphabetty' - URL = 'https://king.com/play/alphabetty' - # Desktop only (requires Flash). - SUPPORTED_PLATFORMS = _DESKTOP_ONLY
diff --git a/tools/perf/page_sets/system_health/system_health_stories.py b/tools/perf/page_sets/system_health/system_health_stories.py index 1defe24..569d5c01 100644 --- a/tools/perf/page_sets/system_health/system_health_stories.py +++ b/tools/perf/page_sets/system_health/system_health_stories.py
@@ -2,7 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -from page_sets.system_health import single_page_stories +from page_sets.system_health import platforms +from page_sets.system_health import loading_stories from telemetry import story @@ -19,7 +20,7 @@ archive_data_file=('../data/memory_system_health_%s.json' % self.PLATFORM), cloud_storage_bucket=story.PARTNER_BUCKET) - for story_class in single_page_stories.IterAllStoryClasses(): + for story_class in loading_stories.IterAllStoryClasses(): if self.PLATFORM not in story_class.SUPPORTED_PLATFORMS: continue self.AddStory(story_class(self, take_memory_measurement)) @@ -27,9 +28,9 @@ class DesktopSystemHealthStorySet(_SystemHealthStorySet): """Desktop user stories for Chrome System Health Plan.""" - PLATFORM = 'desktop' + PLATFORM = platforms.DESKTOP class MobileSystemHealthStorySet(_SystemHealthStorySet): """Mobile user stories for Chrome System Health Plan.""" - PLATFORM = 'mobile' + PLATFORM = platforms.MOBILE
diff --git a/tools/perf/page_sets/system_health/system_health_story.py b/tools/perf/page_sets/system_health/system_health_story.py new file mode 100644 index 0000000..cb7a21b5 --- /dev/null +++ b/tools/perf/page_sets/system_health/system_health_story.py
@@ -0,0 +1,71 @@ +# 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 logging + +from page_sets.system_health import platforms + +from telemetry.core import discover +from telemetry.page import page + + +_DUMP_WAIT_TIME = 3 + + +class SystemHealthStory(page.Page): + """Abstract base class for System Health user stories.""" + + # The full name of a single page story has the form CASE:GROUP:PAGE (e.g. + # 'load:search:google'). + NAME = NotImplemented + URL = NotImplemented + SUPPORTED_PLATFORMS = platforms.ALL_PLATFORMS + + def __init__(self, story_set, take_memory_measurement): + case, group, _ = self.NAME.split(':') + super(SystemHealthStory, self).__init__( + page_set=story_set, name=self.NAME, url=self.URL, + credentials_path='../data/credentials.json', + grouping_keys={'case': case, 'group': group}) + self._take_memory_measurement = take_memory_measurement + + def _Measure(self, action_runner): + if not self._take_memory_measurement: + return + # TODO(petrcermak): This method is essentially the same as + # MemoryHealthPage._TakeMemoryMeasurement() in memory_health_story.py. + # Consider sharing the common code. + action_runner.Wait(_DUMP_WAIT_TIME) + action_runner.ForceGarbageCollection() + action_runner.Wait(_DUMP_WAIT_TIME) + tracing_controller = action_runner.tab.browser.platform.tracing_controller + if not tracing_controller.is_tracing_running: + return # Tracing is not running, e.g., when recording a WPR archive. + if not action_runner.tab.browser.DumpMemory(): + logging.error('Unable to get a memory dump for %s.', self.name) + + def _Login(self, action_runner): + pass + + def _DidLoadDocument(self, action_runner): + pass + + def RunNavigateSteps(self, action_runner): + self._Login(action_runner) + super(SystemHealthStory, self).RunNavigateSteps(action_runner) + + def RunPageInteractions(self, action_runner): + action_runner.tab.WaitForDocumentReadyStateToBeComplete() + self._DidLoadDocument(action_runner) + self._Measure(action_runner) + + +def IterAllStoryClasses(module, base_class): + # Sort the classes by their names so that their order is stable and + # deterministic. + for unused_cls_name, cls in sorted(discover.DiscoverClassesInModule( + module=module, + base_class=base_class, + index_by_class_name=True).iteritems()): + yield cls
diff --git a/tools/perf/page_sets/text_selection_sites.py b/tools/perf/page_sets/text_selection_sites.py index 90885d57..435379cbc 100644 --- a/tools/perf/page_sets/text_selection_sites.py +++ b/tools/perf/page_sets/text_selection_sites.py
@@ -151,7 +151,7 @@ # A subset of top_10_mobile page set page_urls = [ - 'https://www.google.com/#hl=en&q=science', + 'https://www.google.co.uk/#hl=en&q=science', 'https://m.facebook.com/rihanna', 'http://search.yahoo.com/search;_ylt=?p=google', 'http://www.baidu.com/s?word=google',
diff --git a/tools/perf/page_sets/top_10_mobile.py b/tools/perf/page_sets/top_10_mobile.py index 485cac9..099b8ff 100644 --- a/tools/perf/page_sets/top_10_mobile.py +++ b/tools/perf/page_sets/top_10_mobile.py
@@ -9,7 +9,7 @@ URL_LIST = [ # Why: #1 (Alexa) most visited page worldwide, picked a reasonable # search term - 'https://www.google.com/#hl=en&q=science', + 'https://www.google.co.uk/#hl=en&q=science', # Why: #2 (Alexa) most visited page worldwide, picked the most liked # page 'https://m.facebook.com/rihanna', @@ -32,7 +32,7 @@ 'http://www.amazon.com/gp/aw/s/?k=nexus', # Why: #13 (Alexa) most visited page worldwide, picked the first real # page - 'http://m.taobao.com/channel/act/mobile/20131111-women.html', + 'http://m.intl.taobao.com/group-purchase.html', # Why: #18 (Alexa) most visited page worldwide, picked a reasonable # search term 'http://yandex.ru/touchsearch?text=science',
diff --git a/tools/perf/page_sets/trivial_sites/trivial_canvas.html b/tools/perf/page_sets/trivial_sites/trivial_canvas.html new file mode 100644 index 0000000..56719379 --- /dev/null +++ b/tools/perf/page_sets/trivial_sites/trivial_canvas.html
@@ -0,0 +1,37 @@ +<!doctype html> +<!-- +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. +--> +<html style="height:100%"> +<head> + <style> + html, body { + margin: 0; + padding: 0; + } + </style> +</head> +<body style="height:100%"> + <canvas id="canvas" width="200" height="100"></canvas> +</body> +<script> + var canvas = document.querySelector('canvas'); + canvas.style.width ='100%'; + canvas.style.height='100%'; + canvas.width = canvas.offsetWidth; + canvas.height = canvas.offsetHeight; + var ctx = canvas.getContext("2d"); + var rColor = 0; + + function animate() { + rColor += 1; + rColor %= 255; + ctx.fillStyle = 'rgb(' + rColor + ',0,0)'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + window.requestAnimationFrame(animate); + } + window.onload = animate; +</script> +</html>
diff --git a/tools/perf/page_sets/trivial_sites/trivial_webgl.html b/tools/perf/page_sets/trivial_sites/trivial_webgl.html new file mode 100644 index 0000000..cbfbe38 --- /dev/null +++ b/tools/perf/page_sets/trivial_sites/trivial_webgl.html
@@ -0,0 +1,37 @@ +<!doctype html> +<!-- +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. +--> +<html style="height:100%"> +<head> + <style> + html, body { + margin: 0; + padding: 0; + } + </style> +</head> +<body style="height:100%"> + <canvas id="canvas" width="200" height="100"></canvas> +</body> +<script> + var canvas = document.querySelector('canvas'); + canvas.style.width ='100%'; + canvas.style.height='100%'; + canvas.width = canvas.offsetWidth; + canvas.height = canvas.offsetHeight; + var gl = canvas.getContext("webgl"); + gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight); + var rColor = 0; + + function animate() { + rColor = (rColor + 1) % 255; + gl.clearColor(rColor / 255, 0.0, 0.0, 1.0); + gl.clear(gl.COLOR_BUFFER_BIT); + window.requestAnimationFrame(animate); + } + window.onload = animate; +</script> +</html>
diff --git a/tools/valgrind/drmemory/PRESUBMIT.py b/tools/valgrind/drmemory/PRESUBMIT.py index 2e56b63..95dcd657 100644 --- a/tools/valgrind/drmemory/PRESUBMIT.py +++ b/tools/valgrind/drmemory/PRESUBMIT.py
@@ -33,7 +33,7 @@ def GetPreferredTryMasters(project, change): return { - 'tryserver.chromium.win': { + 'master.tryserver.chromium.win': { 'win_drmemory': set(['defaulttests']), } }
diff --git a/tools/valgrind/drmemory/suppressions_full.txt b/tools/valgrind/drmemory/suppressions_full.txt index 32c46d9..bd01cffd 100644 --- a/tools/valgrind/drmemory/suppressions_full.txt +++ b/tools/valgrind/drmemory/suppressions_full.txt
@@ -1660,12 +1660,6 @@ *!SpellcheckLanguage::SpellCheckWord *!SpellCheck::SpellCheckWord -UNINITIALIZED READ -name=bug_387373 -*!blink::WebEmbeddedWorkerImpl::startWorkerContext -*!content::EmbeddedWorkerDispatcher::OnStartWorker -*!EmbeddedWorkerMsg_StartWorker::Dispatch<> - UNADDRESSABLE ACCESS name=bug_389132 content.dll!crypto_kernel_do_load_cipher_type
diff --git a/ui/android/view_android.cc b/ui/android/view_android.cc index 3771c37..63345260 100644 --- a/ui/android/view_android.cc +++ b/ui/android/view_android.cc
@@ -40,7 +40,7 @@ children_.push_back(child); if (child->parent_) - parent_->RemoveChild(child); + child->parent_->RemoveChild(child); child->parent_ = this; }
diff --git a/ui/app_list/app_list_menu.cc b/ui/app_list/app_list_menu.cc index 4f71d21a..8a1a069 100644 --- a/ui/app_list/app_list_menu.cc +++ b/ui/app_list/app_list_menu.cc
@@ -50,9 +50,6 @@ menu_model_.AddSeparator(ui::NORMAL_SEPARATOR); } - menu_model_.AddItem(SHOW_SETTINGS, l10n_util::GetStringUTF16( - IDS_APP_LIST_OPEN_SETTINGS)); - menu_model_.AddItem(SHOW_HELP, l10n_util::GetStringUTF16( IDS_APP_LIST_HELP)); @@ -73,8 +70,9 @@ return true; } -bool AppListMenu::GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) { +bool AppListMenu::GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const { return false; } @@ -85,9 +83,6 @@ return; } switch (command_id) { - case SHOW_SETTINGS: - delegate_->OpenSettings(); - break; case SHOW_HELP: delegate_->OpenHelp(); break;
diff --git a/ui/app_list/app_list_menu.h b/ui/app_list/app_list_menu.h index 232f82d..92b11b2 100644 --- a/ui/app_list/app_list_menu.h +++ b/ui/app_list/app_list_menu.h
@@ -13,7 +13,7 @@ // Menu for the app list. This is shown in the top right hand corner of the // app list. -// TODO(benwells): We should consider moving this into Chrome. +// TODO(benwells): We should delete this. http://crbug.com/600915. class AppListMenu : public ui::SimpleMenuModel::Delegate { public: enum AppListMenuCommands { @@ -36,7 +36,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; ui::SimpleMenuModel menu_model_;
diff --git a/ui/app_list/app_list_switches.cc b/ui/app_list/app_list_switches.cc index 0c47326..531ebc6 100644 --- a/ui/app_list/app_list_switches.cc +++ b/ui/app_list/app_list_switches.cc
@@ -40,11 +40,6 @@ const char kDisableDriveSearchInChromeLauncher[] = "disable-drive-search-in-app-launcher"; -// Enable/disable the new "blended" algorithm in app_list::Mixer. This is just -// forcing the AppListMixer/Blended field trial. -const char kEnableNewAppListMixer[] = "enable-new-app-list-mixer"; -const char kDisableNewAppListMixer[] = "disable-new-app-list-mixer"; - // If set, the app list will forget it has been installed on startup. Note this // doesn't prevent the app list from running, it just makes Chrome think the app // list hasn't been enabled (as in kEnableAppList) yet.
diff --git a/ui/app_list/app_list_switches.h b/ui/app_list/app_list_switches.h index 21955d5..05c6f0b 100644 --- a/ui/app_list/app_list_switches.h +++ b/ui/app_list/app_list_switches.h
@@ -18,8 +18,6 @@ APP_LIST_EXPORT extern const char kEnableCenteredAppList[]; APP_LIST_EXPORT extern const char kEnableExperimentalAppList[]; APP_LIST_EXPORT extern const char kDisableExperimentalAppList[]; -APP_LIST_EXPORT extern const char kEnableNewAppListMixer[]; -APP_LIST_EXPORT extern const char kDisableNewAppListMixer[]; APP_LIST_EXPORT extern const char kEnableSyncAppList[]; APP_LIST_EXPORT extern const char kDisableSyncAppList[]; APP_LIST_EXPORT extern const char kEnableDriveSearchInChromeLauncher[];
diff --git a/ui/app_list/app_list_view_delegate.h b/ui/app_list/app_list_view_delegate.h index b3c4c2c..51f9033 100644 --- a/ui/app_list/app_list_view_delegate.h +++ b/ui/app_list/app_list_view_delegate.h
@@ -117,9 +117,6 @@ // Invoked when the app list is closing. virtual void ViewClosing() = 0; - // Open the settings UI. - virtual void OpenSettings() = 0; - // Open the help UI. virtual void OpenHelp() = 0;
diff --git a/ui/app_list/search/mixer.cc b/ui/app_list/search/mixer.cc index e49f3ba4..f5b7e998 100644 --- a/ui/app_list/search/mixer.cc +++ b/ui/app_list/search/mixer.cc
@@ -10,10 +10,7 @@ #include <string> #include <vector> -#include "base/command_line.h" #include "base/macros.h" -#include "base/metrics/field_trial.h" -#include "ui/app_list/app_list_switches.h" #include "ui/app_list/search_provider.h" #include "ui/app_list/search_result.h" @@ -21,19 +18,8 @@ namespace { -// Maximum number of results to show. Ignored if the AppListMixer field trial is -// "Blended". -const size_t kMaxResults = 6; - -// The minimum number of results to show, if the AppListMixer field trial is -// "Blended". If this quota is not reached, the per-group limitations are -// removed and we try again. (We may still not reach the minumum, but at least -// we tried.) Ignored if the field trial is off. -const size_t kMinBlendedResults = 6; - -const char kAppListMixerFieldTrialName[] = "AppListMixer"; -const char kAppListMixerFieldTrialEnabled[] = "Blended"; -const char kAppListMixerFieldTrialDisabled[] = "Control"; +// Maximum number of results to show. +const size_t kMinResults = 6; void UpdateResult(const SearchResult& source, SearchResult* target) { target->set_display_type(source.display_type()); @@ -43,37 +29,6 @@ target->set_details_tags(source.details_tags()); } -// Returns true if the "AppListMixer" trial is set to "Blended". This is an -// experiment on the new Mixer logic that allows results from different groups -// to be blended together, rather than stratified. -bool IsBlendedMixerTrialEnabled() { - // Note: It's important to query the field trial state first, to ensure that - // UMA reports the correct group. - const std::string group_name = - base::FieldTrialList::FindFullName(kAppListMixerFieldTrialName); - - // Respect command-line flags first. - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableNewAppListMixer)) { - return false; - } - - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableNewAppListMixer)) { - return true; - } - - // Next, respect field-trial groups. - if (group_name == kAppListMixerFieldTrialEnabled) - return true; - - if (group_name == kAppListMixerFieldTrialDisabled) - return false; - - // By default, enable the new logic if the experimental app list is enabled. - return app_list::switches::IsExperimentalAppListEnabled(); -} - } // namespace Mixer::SortData::SortData() : result(NULL), score(0.0) { @@ -91,8 +46,8 @@ // Used to group relevant providers together for mixing their results. class Mixer::Group { public: - Group(size_t max_results, double boost, double multiplier) - : max_results_(max_results), boost_(boost), multiplier_(multiplier) {} + Group(size_t max_results, double multiplier) + : max_results_(max_results), multiplier_(multiplier) {} ~Group() {} void AddProvider(SearchProvider* provider) { providers_.push_back(provider); } @@ -110,7 +65,7 @@ double relevance = std::min(std::max(result->relevance(), 0.0), 1.0); double multiplier = multiplier_; - double boost = boost_; + double boost = 0.0; // Recommendations should not be affected by query-to-launch correlation // from KnownResults as it causes recommendations to become dominated by @@ -159,7 +114,6 @@ private: typedef std::vector<SearchProvider*> Providers; const size_t max_results_; - const double boost_; const double multiplier_; Providers providers_; // Not owned. @@ -174,28 +128,11 @@ Mixer::~Mixer() { } -size_t Mixer::AddGroup(size_t max_results, double boost, double multiplier) { - // Only consider |boost| if the AppListMixer field trial is default. - // Only consider |multiplier| if the AppListMixer field trial is "Blended". - if (IsBlendedMixerTrialEnabled()) - boost = 0.0; - else - multiplier = 1.0; - groups_.push_back(new Group(max_results, boost, multiplier)); +size_t Mixer::AddGroup(size_t max_results, double multiplier) { + groups_.push_back(new Group(max_results, multiplier)); return groups_.size() - 1; } -size_t Mixer::AddOmniboxGroup(size_t max_results, - double boost, - double multiplier) { - // There should not already be an omnibox group. - DCHECK(!has_omnibox_group_); - size_t id = AddGroup(max_results, boost, multiplier); - omnibox_group_ = id; - has_omnibox_group_ = true; - return id; -} - void Mixer::AddProviderToGroup(size_t group_id, SearchProvider* provider) { groups_[group_id]->AddProvider(provider); } @@ -205,78 +142,39 @@ FetchResults(is_voice_query, known_results); SortedResults results; + results.reserve(kMinResults); - if (IsBlendedMixerTrialEnabled()) { - results.reserve(kMinBlendedResults); + // Add results from each group. Limit to the maximum number of results in each + // group. + for (const Group* group : groups_) { + size_t num_results = + std::min(group->results().size(), group->max_results()); + results.insert(results.end(), group->results().begin(), + group->results().begin() + num_results); + } + // Remove results with duplicate IDs before sorting. If two providers give a + // result with the same ID, the result from the provider with the *lower group + // number* will be kept (e.g., an app result takes priority over a web store + // result with the same ID). + RemoveDuplicates(&results); + std::sort(results.begin(), results.end()); - // Add results from each group. Limit to the maximum number of results in - // each group. + if (results.size() < kMinResults) { + size_t original_size = results.size(); + // We didn't get enough results. Insert all the results again, and this + // time, do not limit the maximum number of results from each group. (This + // will result in duplicates, which will be removed by RemoveDuplicates.) for (const Group* group : groups_) { - size_t num_results = - std::min(group->results().size(), group->max_results()); results.insert(results.end(), group->results().begin(), - group->results().begin() + num_results); + group->results().end()); } - // Remove results with duplicate IDs before sorting. If two providers give a - // result with the same ID, the result from the provider with the *lower - // group number* will be kept (e.g., an app result takes priority over a web - // store result with the same ID). RemoveDuplicates(&results); - std::sort(results.begin(), results.end()); - - if (results.size() < kMinBlendedResults) { - size_t original_size = results.size(); - // We didn't get enough results. Insert all the results again, and this - // time, do not limit the maximum number of results from each group. (This - // will result in duplicates, which will be removed by RemoveDuplicates.) - for (const Group* group : groups_) { - results.insert(results.end(), group->results().begin(), - group->results().end()); - } - RemoveDuplicates(&results); - // Sort just the newly added results. This ensures that, for example, if - // there are 6 Omnibox results (score = 0.8) and 1 People result (score = - // 0.4) that the People result will be 5th, not 7th, because the Omnibox - // group has a soft maximum of 4 results. (Otherwise, the People result - // would not be seen at all once the result list is truncated.) - std::sort(results.begin() + original_size, results.end()); - } - } else { - results.reserve(kMaxResults); - - // Add results from non-omnibox groups first. Limit to the maximum number of - // results in each group. - for (size_t i = 0; i < groups_.size(); ++i) { - if (!has_omnibox_group_ || i != omnibox_group_) { - const Group& group = *groups_[i]; - size_t num_results = - std::min(group.results().size(), group.max_results()); - results.insert(results.end(), group.results().begin(), - group.results().begin() + num_results); - } - } - - // Collapse duplicate apps from local and web store. - RemoveDuplicates(&results); - - // Fill the remaining slots with omnibox results. Always add at least one - // omnibox result (even if there are no more slots; if we over-fill the - // vector, the web store and people results will be removed in a later - // step). Note: max_results() is ignored for the omnibox group. - if (has_omnibox_group_) { - CHECK_LT(omnibox_group_, groups_.size()); - const Group& omnibox_group = *groups_[omnibox_group_]; - const size_t omnibox_results = std::min( - omnibox_group.results().size(), - results.size() < kMaxResults ? kMaxResults - results.size() : 1); - results.insert(results.end(), omnibox_group.results().begin(), - omnibox_group.results().begin() + omnibox_results); - } - - std::sort(results.begin(), results.end()); - RemoveDuplicates(&results); - if (results.size() > kMaxResults) - results.resize(kMaxResults); + // Sort just the newly added results. This ensures that, for example, if + // there are 6 Omnibox results (score = 0.8) and 1 People result (score = + // 0.4) that the People result will be 5th, not 7th, because the Omnibox + // group has a soft maximum of 4 results. (Otherwise, the People result + // would not be seen at all once the result list is truncated.) + std::sort(results.begin() + original_size, results.end()); } Publish(results, ui_results_);
diff --git a/ui/app_list/search/mixer.h b/ui/app_list/search/mixer.h index b7898d7..e0aa3bd 100644 --- a/ui/app_list/search/mixer.h +++ b/ui/app_list/search/mixer.h
@@ -28,30 +28,18 @@ // Mixer collects results from providers, sorts them and publishes them to the // SearchResults UI model. The targeted results have 6 slots to hold the // result. The search controller can specify any number of groups, each with a -// different number of results and priority boost. The "omnibox" group is -// expected to contain omnibox results, and will be treated specially. +// different number of results and priority boost. class APP_LIST_EXPORT Mixer { public: explicit Mixer(AppListModel::SearchResults* ui_results); ~Mixer(); - // Adds a new mixer group. A maximum of |max_results| results will be - // displayed from this group (if 0, will allow unlimited results from this - // group). Behaviour depends on the AppListMixer field trial: - // - If default: Each result in the group will have its score boosted by - // |boost|. |multiplier| is ignored. - // - If "Blended": |max_results| is a "soft" maximum; if there aren't enough - // results from all groups, more than |max_results| may be chosen from this - // group. Each result in the group will have its score multiplied by - // |multiplier|. |boost| is ignored. - // Returns the group's group_id. - size_t AddGroup(size_t max_results, double boost, double multiplier); - - // Adds a new mixer group for the special "omnibox" group. This group will be - // treated specially by the Mixer (it will be truncated such that it fills the - // remaining slots without overflowing, but with at least one result). A - // maximum of one group should be added using this method. - size_t AddOmniboxGroup(size_t max_results, double boost, double multiplier); + // Adds a new mixer group. A "soft" maximum of |max_results| results will be + // chosen from this group (if 0, will allow unlimited results from this + // group). If there aren't enough results from all groups, more than + // |max_results| may be chosen from this group. Each result in the group will + // have its score multiplied by |multiplier|. Returns the group's group_id. + size_t AddGroup(size_t max_results, double multiplier); // Associates a provider with a mixer group. void AddProviderToGroup(size_t group_id, SearchProvider* provider); @@ -94,14 +82,6 @@ AppListModel::SearchResults* ui_results_; // Not owned. Groups groups_; - // The ID of the omnibox group. The group with this ID will be treated - // specially by the Mixer. Ignored if the AppListMixer field trial is - // "Blended". - // TODO(mgiuca): Remove this after the field trial is complete. - size_t omnibox_group_ = 0; - // Whether |omnibox_group_| has been set. - bool has_omnibox_group_ = false; - DISALLOW_COPY_AND_ASSIGN(Mixer); };
diff --git a/ui/app_list/search/mixer_unittest.cc b/ui/app_list/search/mixer_unittest.cc index 92e06298..6e1809c 100644 --- a/ui/app_list/search/mixer_unittest.cc +++ b/ui/app_list/search/mixer_unittest.cc
@@ -12,11 +12,9 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/scoped_vector.h" -#include "base/metrics/field_trial.h" #include "base/strings/string16.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "base/test/mock_entropy_provider.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/app_list/app_list_model.h" #include "ui/app_list/search/history_types.h" @@ -28,7 +26,6 @@ // Maximum number of results to show in each mixer group. const size_t kMaxAppsGroupResults = 4; -// Ignored unless AppListMixer field trial is "Blended". const size_t kMaxOmniboxResults = 4; const size_t kMaxWebstoreResults = 2; @@ -115,21 +112,13 @@ DISALLOW_COPY_AND_ASSIGN(TestSearchProvider); }; -// Test is parameterized with bool. True enables the "Blended" field trial. -class MixerTest : public testing::Test, - public testing::WithParamInterface<bool> { +class MixerTest : public testing::Test { public: - MixerTest() - : is_voice_query_(false), - field_trial_list_(new base::MockEntropyProvider()) {} + MixerTest() : is_voice_query_(false) {} ~MixerTest() override {} // testing::Test overrides: void SetUp() override { - // If the parameter is true, enable the field trial. - const char* field_trial_name = GetParam() ? "Blended" : "Control"; - base::FieldTrialList::CreateFieldTrial("AppListMixer", field_trial_name); - results_.reset(new AppListModel::SearchResults); providers_.push_back(new TestSearchProvider("app")); @@ -140,10 +129,9 @@ mixer_.reset(new Mixer(results_.get())); - size_t apps_group_id = mixer_->AddGroup(kMaxAppsGroupResults, 3.0, 1.0); - size_t omnibox_group_id = - mixer_->AddOmniboxGroup(kMaxOmniboxResults, 2.0, 1.0); - size_t webstore_group_id = mixer_->AddGroup(kMaxWebstoreResults, 1.0, 0.5); + size_t apps_group_id = mixer_->AddGroup(kMaxAppsGroupResults, 1.0); + size_t omnibox_group_id = mixer_->AddGroup(kMaxOmniboxResults, 1.0); + size_t webstore_group_id = mixer_->AddGroup(kMaxWebstoreResults, 0.5); mixer_->AddProviderToGroup(apps_group_id, providers_[0]); mixer_->AddProviderToGroup(omnibox_group_id, providers_[1]); @@ -196,57 +184,48 @@ ScopedVector<TestSearchProvider> providers_; - base::FieldTrialList field_trial_list_; - DISALLOW_COPY_AND_ASSIGN(MixerTest); }; -TEST_P(MixerTest, Basic) { - // Note: Some cases in |expected_blended| have vastly more results than - // others, due to the "at least 6" mechanism. If it gets at least 6 results - // from all providers, it stops at 6. If not, it fetches potentially many more - // results from all providers. Not ideal, but currently by design. +TEST_F(MixerTest, Basic) { + // Note: Some cases in |expected| have vastly more results than others, due to + // the "at least 6" mechanism. If it gets at least 6 results from all + // providers, it stops at 6. If not, it fetches potentially many more results + // from all providers. Not ideal, but currently by design. struct TestCase { const size_t app_results; const size_t omnibox_results; const size_t webstore_results; - const char* expected_default; // Expected results with trial off. - const char* expected_blended; // Expected results with trial on. + const char* expected; } kTestCases[] = { - {0, 0, 0, "", ""}, - {10, 0, 0, "app0,app1,app2,app3", - "app0,app1,app2,app3,app4,app5,app6,app7,app8,app9"}, - {0, 0, 10, "webstore0,webstore1", + {0, 0, 0, ""}, + {10, 0, 0, "app0,app1,app2,app3,app4,app5,app6,app7,app8,app9"}, + {0, 0, 10, "webstore0,webstore1,webstore2,webstore3,webstore4,webstore5,webstore6," "webstore7,webstore8,webstore9"}, - {4, 6, 0, "app0,app1,app2,app3,omnibox0,omnibox1", - "app0,omnibox0,app1,omnibox1,app2,omnibox2,app3,omnibox3"}, - {4, 6, 2, "app0,app1,app2,app3,omnibox0,webstore0", + {4, 6, 0, "app0,omnibox0,app1,omnibox1,app2,omnibox2,app3,omnibox3"}, + {4, 6, 2, "app0,omnibox0,app1,omnibox1,app2,omnibox2,app3,omnibox3,webstore0," "webstore1"}, - {10, 10, 10, "app0,app1,app2,app3,omnibox0,webstore0", + {10, 10, 10, "app0,omnibox0,app1,omnibox1,app2,omnibox2,app3,omnibox3,webstore0," "webstore1"}, - {0, 10, 0, "omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,omnibox5", + {0, 10, 0, "omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,omnibox5,omnibox6," "omnibox7,omnibox8,omnibox9"}, - {0, 10, 1, "omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,webstore0", + {0, 10, 1, "omnibox0,omnibox1,omnibox2,omnibox3,webstore0,omnibox4,omnibox5," "omnibox6,omnibox7,omnibox8,omnibox9"}, - {0, 10, 2, "omnibox0,omnibox1,omnibox2,omnibox3,webstore0,webstore1", - "omnibox0,omnibox1,omnibox2,omnibox3,webstore0,webstore1"}, - {1, 10, 0, "app0,omnibox0,omnibox1,omnibox2,omnibox3,omnibox4", + {0, 10, 2, "omnibox0,omnibox1,omnibox2,omnibox3,webstore0,webstore1"}, + {1, 10, 0, "app0,omnibox0,omnibox1,omnibox2,omnibox3,omnibox4,omnibox5,omnibox6," "omnibox7,omnibox8,omnibox9"}, - {2, 10, 0, "app0,app1,omnibox0,omnibox1,omnibox2,omnibox3", - "app0,omnibox0,app1,omnibox1,omnibox2,omnibox3"}, - {2, 10, 1, "app0,app1,omnibox0,omnibox1,omnibox2,webstore0", - "app0,omnibox0,app1,omnibox1,omnibox2,omnibox3,webstore0"}, - {2, 10, 2, "app0,app1,omnibox0,omnibox1,webstore0,webstore1", + {2, 10, 0, "app0,omnibox0,app1,omnibox1,omnibox2,omnibox3"}, + {2, 10, 1, "app0,omnibox0,app1,omnibox1,omnibox2,omnibox3,webstore0"}, + {2, 10, 2, "app0,omnibox0,app1,omnibox1,omnibox2,omnibox3,webstore0,webstore1"}, - {2, 0, 2, "app0,app1,webstore0,webstore1", - "app0,app1,webstore0,webstore1"}, - {0, 0, 0, "", ""}, + {2, 0, 2, "app0,app1,webstore0,webstore1"}, + {0, 0, 0, ""}, }; for (size_t i = 0; i < arraysize(kTestCases); ++i) { @@ -255,13 +234,11 @@ webstore_provider()->set_count(kTestCases[i].webstore_results); RunQuery(); - const char* expected = GetParam() ? kTestCases[i].expected_blended - : kTestCases[i].expected_default; - EXPECT_EQ(expected, GetResults()) << "Case " << i; + EXPECT_EQ(kTestCases[i].expected, GetResults()) << "Case " << i; } } -TEST_P(MixerTest, RemoveDuplicates) { +TEST_F(MixerTest, RemoveDuplicates) { const std::string dup = "dup"; // This gives "dup0,dup1,dup2". @@ -283,7 +260,7 @@ } // Tests that "known results" have priority over others. -TEST_P(MixerTest, KnownResultsPriority) { +TEST_F(MixerTest, KnownResultsPriority) { // This gives omnibox 0 -- 5. omnibox_provider()->set_count(6); @@ -302,7 +279,7 @@ } // Tests that "known results" are not considered for recommendation results. -TEST_P(MixerTest, KnownResultsIgnoredForRecommendations) { +TEST_F(MixerTest, KnownResultsIgnoredForRecommendations) { // This gives omnibox 0 -- 5. omnibox_provider()->set_count(6); omnibox_provider()->set_display_type(SearchResult::DISPLAY_RECOMMENDATION); @@ -320,7 +297,7 @@ GetResults()); } -TEST_P(MixerTest, VoiceQuery) { +TEST_F(MixerTest, VoiceQuery) { omnibox_provider()->set_count(3); RunQuery(); EXPECT_EQ("omnibox0,omnibox1,omnibox2", GetResults()); @@ -342,7 +319,7 @@ EXPECT_EQ("omnibox1,omnibox2,omnibox0", GetResults()); } -TEST_P(MixerTest, Publish) { +TEST_F(MixerTest, Publish) { std::unique_ptr<SearchResult> result1(new TestSearchResult("app1", 0)); std::unique_ptr<SearchResult> result2(new TestSearchResult("app2", 0)); std::unique_ptr<SearchResult> result3(new TestSearchResult("app3", 0)); @@ -430,7 +407,5 @@ TestSearchResult::GetInstanceId(ui_results.GetItemAt(2))); } -INSTANTIATE_TEST_CASE_P(MixerTestInstance, MixerTest, testing::Bool()); - } // namespace test } // namespace app_list
diff --git a/ui/app_list/search_controller.cc b/ui/app_list/search_controller.cc index c72080e..589134154 100644 --- a/ui/app_list/search_controller.cc +++ b/ui/app_list/search_controller.cc
@@ -112,16 +112,8 @@ result->InvokeAction(action_index, event_flags); } -size_t SearchController::AddGroup(size_t max_results, - double boost, - double multiplier) { - return mixer_->AddGroup(max_results, boost, multiplier); -} - -size_t SearchController::AddOmniboxGroup(size_t max_results, - double boost, - double multiplier) { - return mixer_->AddOmniboxGroup(max_results, boost, multiplier); +size_t SearchController::AddGroup(size_t max_results, double multiplier) { + return mixer_->AddGroup(max_results, multiplier); } void SearchController::AddProvider(size_t group_id,
diff --git a/ui/app_list/search_controller.h b/ui/app_list/search_controller.h index 8ba61d2..8df0d61 100644 --- a/ui/app_list/search_controller.h +++ b/ui/app_list/search_controller.h
@@ -43,10 +43,7 @@ int event_flags); // Adds a new mixer group. See Mixer::AddGroup. - size_t AddGroup(size_t max_results, double boost, double multiplier); - - // Adds a new mixer group. See Mixer::AddOmniboxGroup. - size_t AddOmniboxGroup(size_t max_results, double boost, double multiplier); + size_t AddGroup(size_t max_results, double multiplier); // Takes ownership of |provider| and associates it with given mixer group. void AddProvider(size_t group_id, std::unique_ptr<SearchProvider> provider);
diff --git a/ui/app_list/test/app_list_test_view_delegate.h b/ui/app_list/test/app_list_test_view_delegate.h index bc370e0..d6a9e87 100644 --- a/ui/app_list/test/app_list_test_view_delegate.h +++ b/ui/app_list/test/app_list_test_view_delegate.h
@@ -72,7 +72,6 @@ void ViewInitialized() override {} void Dismiss() override; void ViewClosing() override {} - void OpenSettings() override {} void OpenHelp() override {} void OpenFeedback() override {} void StartSpeechRecognition() override {}
diff --git a/ui/arc/BUILD.gn b/ui/arc/BUILD.gn index f73d031b..f36d77f 100644 --- a/ui/arc/BUILD.gn +++ b/ui/arc/BUILD.gn
@@ -48,6 +48,7 @@ ":arc", "//base", "//base/test:test_support", + "//components/arc:arc_base", "//components/arc:arc_test_support", "//mojo/edk/system", "//testing/gtest",
diff --git a/ui/arc/notification/arc_notification_manager.cc b/ui/arc/notification/arc_notification_manager.cc index a6e3fa5..ced4c101 100644 --- a/ui/arc/notification/arc_notification_manager.cc +++ b/ui/arc/notification/arc_notification_manager.cc
@@ -4,8 +4,8 @@ #include "ui/arc/notification/arc_notification_manager.h" +#include "ash/common/system/toast/toast_manager.h" #include "ash/shell.h" -#include "ash/system/toast/toast_manager.h" #include "base/memory/ptr_util.h" #include "base/stl_util.h" #include "ui/arc/notification/arc_custom_notification_item.h" @@ -27,17 +27,18 @@ main_profile_id_(main_profile_id), message_center_(message_center), binding_(this) { - arc_bridge_service()->AddObserver(this); + arc_bridge_service()->notifications()->AddObserver(this); } ArcNotificationManager::~ArcNotificationManager() { - arc_bridge_service()->RemoveObserver(this); + arc_bridge_service()->notifications()->RemoveObserver(this); } -void ArcNotificationManager::OnNotificationsInstanceReady() { +void ArcNotificationManager::OnInstanceReady() { DCHECK(!ready_); - auto notifications_instance = arc_bridge_service()->notifications_instance(); + auto notifications_instance = + arc_bridge_service()->notifications()->instance(); if (!notifications_instance) { VLOG(2) << "Request to refresh app list when bridge service is not ready."; return; @@ -47,7 +48,7 @@ ready_ = true; } -void ArcNotificationManager::OnNotificationsInstanceClosed() { +void ArcNotificationManager::OnInstanceClosed() { DCHECK(ready_); while (!items_.empty()) { auto it = items_.begin(); @@ -109,7 +110,8 @@ std::unique_ptr<ArcNotificationItem> item = std::move(it->second); items_.erase(it); - auto notifications_instance = arc_bridge_service()->notifications_instance(); + auto notifications_instance = + arc_bridge_service()->notifications()->instance(); // On shutdown, the ARC channel may quit earlier then notifications. if (!notifications_instance) { @@ -130,7 +132,8 @@ return; } - auto notifications_instance = arc_bridge_service()->notifications_instance(); + auto notifications_instance = + arc_bridge_service()->notifications()->instance(); // On shutdown, the ARC channel may quit earlier then notifications. if (!notifications_instance) { @@ -144,14 +147,16 @@ } void ArcNotificationManager::SendNotificationButtonClickedOnChrome( - const std::string& key, int button_index) { + const std::string& key, + int button_index) { if (items_.find(key) == items_.end()) { VLOG(3) << "Chrome requests to fire a click event on notification (key: " << key << "), but it is gone."; return; } - auto notifications_instance = arc_bridge_service()->notifications_instance(); + auto notifications_instance = + arc_bridge_service()->notifications()->instance(); // On shutdown, the ARC channel may quit earlier then notifications. if (!notifications_instance) { @@ -178,8 +183,8 @@ command = mojom::ArcNotificationEvent::BUTTON_5_CLICKED; break; default: - VLOG(3) << "Invalid button index (key: " << key << ", index: " << - button_index << ")."; + VLOG(3) << "Invalid button index (key: " << key + << ", index: " << button_index << ")."; return; }
diff --git a/ui/arc/notification/arc_notification_manager.h b/ui/arc/notification/arc_notification_manager.h index f75b828..26fe969 100644 --- a/ui/arc/notification/arc_notification_manager.h +++ b/ui/arc/notification/arc_notification_manager.h
@@ -11,6 +11,7 @@ #include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service.h" #include "components/arc/common/notifications.mojom.h" +#include "components/arc/instance_holder.h" #include "components/signin/core/account_id/account_id.h" #include "mojo/public/cpp/bindings/binding.h" #include "ui/message_center/message_center.h" @@ -19,9 +20,10 @@ class ArcNotificationItem; -class ArcNotificationManager : public ArcService, - public ArcBridgeService::Observer, - public mojom::NotificationsHost { +class ArcNotificationManager + : public ArcService, + public InstanceHolder<mojom::NotificationsInstance>::Observer, + public mojom::NotificationsHost { public: ArcNotificationManager(ArcBridgeService* bridge_service, const AccountId& main_profile_id); @@ -32,9 +34,9 @@ ~ArcNotificationManager() override; - // ArcBridgeService::Observer implementation: - void OnNotificationsInstanceReady() override; - void OnNotificationsInstanceClosed() override; + // InstanceHolder<mojom::NotificationsInstance>::Observer implementation: + void OnInstanceReady() override; + void OnInstanceClosed() override; // mojom::NotificationsHost implementation: void OnNotificationPosted(mojom::ArcNotificationDataPtr data) override; @@ -45,8 +47,8 @@ // Methods called from ArcNotificationItem: void SendNotificationRemovedFromChrome(const std::string& key); void SendNotificationClickedOnChrome(const std::string& key); - void SendNotificationButtonClickedOnChrome( - const std::string& key, int button_index); + void SendNotificationButtonClickedOnChrome(const std::string& key, + int button_index); private: const AccountId main_profile_id_;
diff --git a/ui/arc/notification/arc_notification_manager_unittest.cc b/ui/arc/notification/arc_notification_manager_unittest.cc index eadbb84..f7298c7a 100644 --- a/ui/arc/notification/arc_notification_manager_unittest.cc +++ b/ui/arc/notification/arc_notification_manager_unittest.cc
@@ -2,8 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <memory> +#include <string> +#include <vector> + #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "components/arc/instance_holder.h" #include "components/arc/test/fake_arc_bridge_instance.h" #include "components/arc/test/fake_arc_bridge_service.h" #include "components/arc/test/fake_notifications_instance.h" @@ -52,17 +57,18 @@ DISALLOW_COPY_AND_ASSIGN(MockMessageCenter); }; -class ArcBridgeServiceObserver : public ArcBridgeService::Observer { +class NotificationsObserver + : public InstanceHolder<mojom::NotificationsInstance>::Observer { public: - ArcBridgeServiceObserver() = default; - void OnNotificationsInstanceReady() override { ready_ = true; } + NotificationsObserver() = default; + void OnInstanceReady() override { ready_ = true; } bool IsReady() { return ready_; } private: bool ready_ = false; - DISALLOW_COPY_AND_ASSIGN(ArcBridgeServiceObserver); + DISALLOW_COPY_AND_ASSIGN(NotificationsObserver); }; } // anonymous namespace @@ -117,15 +123,15 @@ arc_notification_manager_.reset(new ArcNotificationManager( service(), EmptyAccountId(), message_center_.get())); - ArcBridgeServiceObserver observer; - service_->AddObserver(&observer); + NotificationsObserver observer; + service_->notifications()->AddObserver(&observer); service_->OnNotificationsInstanceReady( std::move(arc_notifications_instance)); while (!observer.IsReady()) loop_.RunUntilIdle(); - service_->RemoveObserver(&observer); + service_->notifications()->RemoveObserver(&observer); } void TearDown() override { @@ -177,7 +183,7 @@ CreateNotificationWithKey("notification3"); EXPECT_EQ(3u, message_center()->GetVisibleNotifications().size()); - arc_notification_manager()->OnNotificationsInstanceClosed(); + arc_notification_manager()->OnInstanceClosed(); EXPECT_EQ(0u, message_center()->GetVisibleNotifications().size()); }
diff --git a/ui/base/accelerators/accelerator.h b/ui/base/accelerators/accelerator.h index e3f079c..e1a140f 100644 --- a/ui/base/accelerators/accelerator.h +++ b/ui/base/accelerators/accelerator.h
@@ -118,8 +118,9 @@ public: // Gets the accelerator for the specified command id. Returns true if the // command id has a valid accelerator, false otherwise. - virtual bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) = 0; + virtual bool GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const = 0; protected: virtual ~AcceleratorProvider() {}
diff --git a/ui/base/cocoa/menu_controller_unittest.mm b/ui/base/cocoa/menu_controller_unittest.mm index 1b56248..138c112 100644 --- a/ui/base/cocoa/menu_controller_unittest.mm +++ b/ui/base/cocoa/menu_controller_unittest.mm
@@ -46,7 +46,7 @@ return true; } bool GetAcceleratorForCommandId(int command_id, - Accelerator* accelerator) override { + Accelerator* accelerator) const override { return false; } void ExecuteCommand(int command_id, int event_flags) override {
diff --git a/ui/base/ime/win/imm32_manager.cc b/ui/base/ime/win/imm32_manager.cc index 20bf937..bd50e933 100644 --- a/ui/base/ime/win/imm32_manager.cc +++ b/ui/base/ime/win/imm32_manager.cc
@@ -283,8 +283,9 @@ } } -void IMM32Manager::GetCompositionInfo(HIMC imm_context, LPARAM lparam, - CompositionText* composition) { +void IMM32Manager::GetCompositionInfo(HIMC imm_context, + LPARAM lparam, + CompositionText* composition) { // We only care about GCS_COMPATTR, GCS_COMPCLAUSE and GCS_CURSORPOS, and // convert them into underlines and selection range respectively. composition->underlines.clear(); @@ -319,28 +320,29 @@ } // Set default underlines in case there is no clause information. - if (!composition->underlines.size()) { - CompositionUnderline underline; - underline.color = SK_ColorBLACK; - underline.background_color = SK_ColorTRANSPARENT; - if (target_start > 0) { - underline.start_offset = 0U; - underline.end_offset = static_cast<uint32_t>(target_start); - underline.thick = false; - composition->underlines.push_back(underline); - } - if (target_end > target_start) { - underline.start_offset = static_cast<uint32_t>(target_start); - underline.end_offset = static_cast<uint32_t>(target_end); - underline.thick = true; - composition->underlines.push_back(underline); - } - if (target_end < length) { - underline.start_offset = static_cast<uint32_t>(target_end); - underline.end_offset = static_cast<uint32_t>(length); - underline.thick = false; - composition->underlines.push_back(underline); - } + if (!composition->underlines.empty()) + return; + + CompositionUnderline underline; + underline.color = SK_ColorBLACK; + underline.background_color = SK_ColorTRANSPARENT; + if (target_start > 0) { + underline.start_offset = 0U; + underline.end_offset = static_cast<uint32_t>(target_start); + underline.thick = false; + composition->underlines.push_back(underline); + } + if (target_end > target_start) { + underline.start_offset = static_cast<uint32_t>(target_start); + underline.end_offset = static_cast<uint32_t>(target_end); + underline.thick = true; + composition->underlines.push_back(underline); + } + if (target_end < length) { + underline.start_offset = static_cast<uint32_t>(target_end); + underline.end_offset = static_cast<uint32_t>(length); + underline.thick = false; + composition->underlines.push_back(underline); } }
diff --git a/ui/base/models/button_menu_item_model.h b/ui/base/models/button_menu_item_model.h index 9c78b598..efe3f8f 100644 --- a/ui/base/models/button_menu_item_model.h +++ b/ui/base/models/button_menu_item_model.h
@@ -39,8 +39,9 @@ // Gets the accelerator for the specified command id. Returns true if the // command id has a valid accelerator, false otherwise. - virtual bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) = 0; + virtual bool GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const = 0; protected: virtual ~Delegate() {}
diff --git a/ui/base/models/simple_menu_model.cc b/ui/base/models/simple_menu_model.cc index b466051..09b08d2 100644 --- a/ui/base/models/simple_menu_model.cc +++ b/ui/base/models/simple_menu_model.cc
@@ -256,8 +256,8 @@ MenuItemsChanged(); } -int SimpleMenuModel::GetIndexOfCommandId(int command_id) { - for (ItemVector::iterator i = items_.begin(); i != items_.end(); ++i) { +int SimpleMenuModel::GetIndexOfCommandId(int command_id) const { + for (ItemVector::const_iterator i = items_.begin(); i != items_.end(); ++i) { if (i->command_id == command_id) return static_cast<int>(std::distance(items_.begin(), i)); }
diff --git a/ui/base/models/simple_menu_model.h b/ui/base/models/simple_menu_model.h index 639830d1..c86f958 100644 --- a/ui/base/models/simple_menu_model.h +++ b/ui/base/models/simple_menu_model.h
@@ -39,7 +39,7 @@ // command id has a valid accelerator, false otherwise. virtual bool GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) = 0; + ui::Accelerator* accelerator) const = 0; // Some command ids have labels, sublabels, minor text and icons that change // over time. @@ -134,7 +134,7 @@ // Returns the index of the item that has the given |command_id|. Returns // -1 if not found. - int GetIndexOfCommandId(int command_id); + int GetIndexOfCommandId(int command_id) const; // Overridden from MenuModel: bool HasIcons() const override;
diff --git a/ui/base/win/open_file_name_win_unittest.cc b/ui/base/win/open_file_name_win_unittest.cc index bce8abc..a6e6ff1f 100644 --- a/ui/base/win/open_file_name_win_unittest.cc +++ b/ui/base/win/open_file_name_win_unittest.cc
@@ -19,7 +19,7 @@ ADD_FAILURE() << "filename buffer insufficient."; return; } - if (!result.size()) { + if (result.empty()) { ofn->GetOPENFILENAME()->lpstrFile[0] = 0; } else { // Because the result has embedded nulls, we must memcpy.
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index cbd42b6..b217cdd 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc
@@ -211,7 +211,7 @@ host_->animation_host()->AddAnimationTimeline(animation_timeline_.get()); host_->SetRootLayer(root_web_layer_); - host_->set_surface_id_namespace(surface_id_allocator_->id_namespace()); + host_->set_surface_client_id(surface_id_allocator_->client_id()); host_->SetVisible(true); }
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index d845d68..ac8ea89 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc
@@ -590,7 +590,7 @@ } void Layer::SetShowSurface( - cc::SurfaceId surface_id, + const cc::SurfaceId& surface_id, const cc::SurfaceLayer::SatisfyCallback& satisfy_callback, const cc::SurfaceLayer::RequireCallback& require_callback, gfx::Size surface_size, @@ -673,6 +673,11 @@ damaged_region_.Union(invalid_rect); ScheduleDraw(); + + if (layer_mask_) { + layer_mask_->damaged_region_.Union(invalid_rect); + layer_mask_->ScheduleDraw(); + } return true; } @@ -690,6 +695,8 @@ for (cc::Region::Iterator iter(damaged_region_); iter.has_rect(); iter.next()) cc_layer_->SetNeedsDisplayRect(iter.rect()); + if (layer_mask_) + layer_mask_->SendDamagedRects(); if (content_layer_) paint_region_.Union(damaged_region_);
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h index f5d4526..8167fa7 100644 --- a/ui/compositor/layer.h +++ b/ui/compositor/layer.h
@@ -297,7 +297,7 @@ void SetTextureScale(float x_scale, float y_scale); // Begins showing content from a surface with a particular id. - void SetShowSurface(cc::SurfaceId surface_id, + void SetShowSurface(const cc::SurfaceId& surface_id, const cc::SurfaceLayer::SatisfyCallback& satisfy_callback, const cc::SurfaceLayer::RequireCallback& require_callback, gfx::Size surface_size,
diff --git a/ui/compositor/layer_animator_collection.cc b/ui/compositor/layer_animator_collection.cc index ce4d708..54951f0 100644 --- a/ui/compositor/layer_animator_collection.cc +++ b/ui/compositor/layer_animator_collection.cc
@@ -24,7 +24,7 @@ void LayerAnimatorCollection::StartAnimator( scoped_refptr<LayerAnimator> animator) { DCHECK_EQ(0U, animators_.count(animator)); - if (!animators_.size()) + if (animators_.empty()) last_tick_time_ = base::TimeTicks::Now(); animators_.insert(animator); if (animators_.size() == 1U && compositor_)
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc index 6aeaec31..0e65b71 100644 --- a/ui/compositor/layer_unittest.cc +++ b/ui/compositor/layer_unittest.cc
@@ -633,6 +633,28 @@ EXPECT_FALSE(d3.painted()); } +// Tests that scheduling paint on a layer with a mask updates the mask. +TEST_F(LayerWithRealCompositorTest, SchedulePaintUpdatesMask) { + std::unique_ptr<Layer> layer( + CreateColorLayer(SK_ColorRED, gfx::Rect(20, 20, 400, 400))); + std::unique_ptr<Layer> mask_layer(CreateLayer(ui::LAYER_TEXTURED)); + mask_layer->SetBounds(gfx::Rect(layer->GetTargetBounds().size())); + layer->SetMaskLayer(mask_layer.get()); + + GetCompositor()->SetRootLayer(layer.get()); + WaitForDraw(); + + DrawTreeLayerDelegate d1(layer->bounds()); + layer->set_delegate(&d1); + DrawTreeLayerDelegate d2(mask_layer->bounds()); + mask_layer->set_delegate(&d2); + + layer->SchedulePaint(gfx::Rect(5, 5, 5, 5)); + WaitForDraw(); + EXPECT_TRUE(d1.painted()); + EXPECT_TRUE(d2.painted()); +} + // Tests no-texture Layers. // Create this hierarchy: // L1 - red
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc index f923cd3..b2f4bfee 100644 --- a/ui/compositor/test/in_process_context_factory.cc +++ b/ui/compositor/test/in_process_context_factory.cc
@@ -85,7 +85,6 @@ context_provider_->ContextSupport()->SignalSyncToken( sync_token, base::Bind(&OutputSurface::OnSwapBuffersComplete, weak_ptr_factory_.GetWeakPtr())); - client_->DidSwapBuffers(); } uint32_t GetFramebufferCopyTextureFormat() override { auto* gl = static_cast<InProcessContextProvider*>(context_provider()); @@ -103,7 +102,7 @@ InProcessContextFactory::InProcessContextFactory( bool context_factory_for_test, cc::SurfaceManager* surface_manager) - : next_surface_id_namespace_(1u), + : next_surface_client_id_(1u), use_test_surface_(true), context_factory_for_test_(context_factory_for_test), surface_manager_(surface_manager) { @@ -179,7 +178,7 @@ per_compositor_data_[compositor.get()] = base::MakeUnique<cc::Display>( surface_manager_, GetSharedBitmapManager(), GetGpuMemoryBufferManager(), compositor->GetRendererSettings(), - compositor->surface_id_allocator()->id_namespace(), + compositor->surface_id_allocator()->client_id(), std::move(begin_frame_source), std::move(display_output_surface), std::move(scheduler), base::MakeUnique<cc::TextureMailboxDeleter>( compositor->task_runner().get())); @@ -252,9 +251,9 @@ std::unique_ptr<cc::SurfaceIdAllocator> InProcessContextFactory::CreateSurfaceIdAllocator() { std::unique_ptr<cc::SurfaceIdAllocator> allocator( - new cc::SurfaceIdAllocator(next_surface_id_namespace_++)); + new cc::SurfaceIdAllocator(next_surface_client_id_++)); if (surface_manager_) - allocator->RegisterSurfaceIdNamespace(surface_manager_); + allocator->RegisterSurfaceClientId(surface_manager_); return allocator; }
diff --git a/ui/compositor/test/in_process_context_factory.h b/ui/compositor/test/in_process_context_factory.h index 1e2321c..e84cd285 100644 --- a/ui/compositor/test/in_process_context_factory.h +++ b/ui/compositor/test/in_process_context_factory.h
@@ -79,7 +79,7 @@ cc::TestGpuMemoryBufferManager gpu_memory_buffer_manager_; cc::TestImageFactory image_factory_; cc::TestTaskGraphRunner task_graph_runner_; - uint32_t next_surface_id_namespace_; + uint32_t next_surface_client_id_; bool use_test_surface_; bool context_factory_for_test_; cc::SurfaceManager* surface_manager_;
diff --git a/ui/display/chromeos/x11/display_util_x11.cc b/ui/display/chromeos/x11/display_util_x11.cc index 560edd0..b328655 100644 --- a/ui/display/chromeos/x11/display_util_x11.cc +++ b/ui/display/chromeos/x11/display_util_x11.cc
@@ -5,6 +5,7 @@ #include "ui/display/chromeos/x11/display_util_x11.h" #include "base/macros.h" +#include "base/strings/string_util.h" namespace ui { @@ -30,7 +31,8 @@ DisplayConnectionType GetDisplayConnectionTypeFromName( const std::string& name) { for (unsigned int i = 0; i < arraysize(kDisplayConnectionTypeMapping); ++i) { - if (name.find(kDisplayConnectionTypeMapping[i].name) == 0) { + if (base::StartsWith(name, kDisplayConnectionTypeMapping[i].name, + base::CompareCase::SENSITIVE)) { return kDisplayConnectionTypeMapping[i].type; } }
diff --git a/ui/display/mac/screen_mac.mm b/ui/display/mac/screen_mac.mm index fa1edd29b..4621dfab 100644 --- a/ui/display/mac/screen_mac.mm +++ b/ui/display/mac/screen_mac.mm
@@ -262,10 +262,8 @@ } } - if (!displays.size()) - return std::vector<Display>(1, GetPrimaryDisplay()); - - return displays; + return displays.empty() ? std::vector<Display>(1, GetPrimaryDisplay()) + : displays; } // The displays currently attached to the device.
diff --git a/ui/events/keycodes/keyboard_code_conversion_xkb.cc b/ui/events/keycodes/keyboard_code_conversion_xkb.cc index f6bd7df..e164054 100644 --- a/ui/events/keycodes/keyboard_code_conversion_xkb.cc +++ b/ui/events/keycodes/keyboard_code_conversion_xkb.cc
@@ -238,7 +238,7 @@ case XKB_KEY_XF86AudioRaiseVolume: return DomKey::AUDIO_VOLUME_UP; case XKB_KEY_XF86AudioPlay: - return DomKey::MEDIA_PLAY; + return DomKey::MEDIA_PLAY_PAUSE; case XKB_KEY_XF86AudioStop: return DomKey::MEDIA_STOP; case XKB_KEY_XF86AudioPrev:
diff --git a/ui/events/mojo/event.typemap b/ui/events/mojo/event.typemap index fea94a7..b34142e 100644 --- a/ui/events/mojo/event.typemap +++ b/ui/events/mojo/event.typemap
@@ -15,4 +15,4 @@ ] # TODO(moshayedi): crbug.com/617167. Map mojom.Event directly to ui::Event. -type_mappings = [ "ui.mojom.Event=std::unique_ptr<ui::Event>[pass_by_value]" ] +type_mappings = [ "ui.mojom.Event=std::unique_ptr<ui::Event>[move_only]" ]
diff --git a/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc b/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc index 65388a2e..b1d46ce 100644 --- a/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc +++ b/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc
@@ -20,8 +20,8 @@ std::string FormatLog(const char* fmt, va_list args) { std::string msg = base::StringPrintV(fmt, args); - if (!msg.empty() && msg[msg.size() - 1] == '\n') - msg.erase(msg.end() - 1, msg.end()); + if (!msg.empty() && msg.back() == '\n') + msg.pop_back(); return msg; }
diff --git a/ui/events/ozone/evdev/libgestures_glue/gesture_logging.cc b/ui/events/ozone/evdev/libgestures_glue/gesture_logging.cc index 009fc93..b1a50bb 100644 --- a/ui/events/ozone/evdev/libgestures_glue/gesture_logging.cc +++ b/ui/events/ozone/evdev/libgestures_glue/gesture_logging.cc
@@ -14,8 +14,8 @@ std::string FormatLog(const char* fmt, va_list args) { std::string msg = base::StringPrintV(fmt, args); - if (!msg.empty() && msg[msg.size() - 1] == '\n') - msg.erase(msg.end() - 1, msg.end()); + if (!msg.empty() && msg.back() == '\n') + msg.pop_back(); return msg; }
diff --git a/ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.cc b/ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.cc index cde3791..c12564c 100644 --- a/ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.cc +++ b/ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.cc
@@ -1078,8 +1078,7 @@ // one. if (is_parsing) { // Stop parsing the current line if the format is wrong. - if (piece.size() <= 2 || piece[0] != '\"' || - piece[piece.size() - 1] != '\"') { + if (piece.size() <= 2 || piece[0] != '\"' || piece.back() != '\"') { LOG(ERROR) << "Error parsing line: " << lines.token(); has_error = true; if (next_is_section_type)
diff --git a/ui/file_manager/audio_player/js/compiled_resources.gyp b/ui/file_manager/audio_player/js/compiled_resources.gyp index 98f6fa3..0099655 100644 --- a/ui/file_manager/audio_player/js/compiled_resources.gyp +++ b/ui/file_manager/audio_player/js/compiled_resources.gyp
@@ -12,8 +12,6 @@ '../../../webui/resources/js/cr/event_target.js', '../../../webui/resources/js/cr/ui.js', '../../../webui/resources/js/cr/ui/array_data_model.js', - # Referenced in common/js/util.js. - '../../../webui/resources/js/cr/ui/dialogs.js', '../../../webui/resources/js/load_time_data.js', '../../../webui/resources/js/promise_resolver.js', '../../../webui/resources/js/util.js',
diff --git a/ui/file_manager/file_manager/background/js/compiled_resources.gyp b/ui/file_manager/file_manager/background/js/compiled_resources.gyp index 8232bc9..60de7c33 100644 --- a/ui/file_manager/file_manager/background/js/compiled_resources.gyp +++ b/ui/file_manager/file_manager/background/js/compiled_resources.gyp
@@ -15,7 +15,6 @@ '../../../../webui/resources/js/util.js', '../../../../webui/resources/js/cr/event_target.js', '../../../../webui/resources/js/cr/ui/array_data_model.js', - '../../../../webui/resources/js/cr/ui/dialogs.js', '../../common/js/lru_cache.js', '../../../image_loader/image_loader_client.js', '../../common/js/error_util.js',
diff --git a/ui/file_manager/file_manager/common/js/util.js b/ui/file_manager/file_manager/common/js/util.js index 7f60f6d3d..1f0a9de1 100644 --- a/ui/file_manager/file_manager/common/js/util.js +++ b/ui/file_manager/file_manager/common/js/util.js
@@ -885,45 +885,6 @@ }; /** - * Sets up and shows the alert to inform a user the task is opened in the - * desktop of the running profile. - * - * TODO(hirono): Move the function from the util namespace. - * @param {cr.ui.dialogs.AlertDialog} alertDialog Alert dialog to be shown. - * @param {Array<Entry>} entries List of opened entries. - */ -util.showOpenInOtherDesktopAlert = function(alertDialog, entries) { - if (!entries.length) - return; - chrome.fileManagerPrivate.getProfiles( - function(profiles, currentId, displayedId) { - // Find strings. - var displayName; - for (var i = 0; i < profiles.length; i++) { - if (profiles[i].profileId === currentId) { - displayName = profiles[i].displayName; - break; - } - } - if (!displayName) { - console.warn('Display name is not found.'); - return; - } - - var title = entries.length > 1 ? - entries[0].name + '\u2026' /* ellipsis */ : entries[0].name; - var message = strf(entries.length > 1 ? - 'OPEN_IN_OTHER_DESKTOP_MESSAGE_PLURAL' : - 'OPEN_IN_OTHER_DESKTOP_MESSAGE', - displayName, - currentId); - - // Show the dialog. - alertDialog.showWithTitle(title, message, null, null, null); - }.bind(this)); -}; - -/** * Runs chrome.test.sendMessage in test environment. Does nothing if running * in production environment. *
diff --git a/ui/file_manager/file_manager/foreground/css/common.css b/ui/file_manager/file_manager/foreground/css/common.css index 07b43bb2..ff6d1ee 100644 --- a/ui/file_manager/file_manager/foreground/css/common.css +++ b/ui/file_manager/file_manager/foreground/css/common.css
@@ -138,7 +138,7 @@ -webkit-margin-end: 0; -webkit-margin-start: 5px; font-weight: 500; - height: 32px; + min-height: 32px; min-width: 70px; padding: auto; }
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks.js b/ui/file_manager/file_manager/foreground/js/file_tasks.js index 89f5402..64381415 100644 --- a/ui/file_manager/file_manager/foreground/js/file_tasks.js +++ b/ui/file_manager/file_manager/foreground/js/file_tasks.js
@@ -496,10 +496,8 @@ break; case 'message_sent': util.isTeleported(window).then(function(teleported) { - if (teleported) { - util.showOpenInOtherDesktopAlert( - this.ui_.alertDialog, this.entries_); - } + if (teleported) + this.ui_.showOpenInOtherDesktopAlert(this.entries_); }.bind(this)); callback(true, this.entries_); break; @@ -546,10 +544,8 @@ if (result !== 'message_sent') return; util.isTeleported(window).then(function(teleported) { - if (teleported) { - util.showOpenInOtherDesktopAlert( - this.ui_.alertDialog, this.entries_); - } + if (teleported) + this.ui_.showOpenInOtherDesktopAlert(this.entries_); }.bind(this)); }.bind(this)); }
diff --git a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js index 9d50915..a6e91eed 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js +++ b/ui/file_manager/file_manager/foreground/js/ui/file_manager_ui.js
@@ -550,3 +550,40 @@ customSplitter.decorate(splitterElement); splitterElement.resizeNextElement = !!opt_resizeNextElement; }; + +/** + * Sets up and shows the alert to inform a user the task is opened in the + * desktop of the running profile. + * + * @param {Array<Entry>} entries List of opened entries. + */ +FileManagerUI.prototype.showOpenInOtherDesktopAlert = function(entries) { + if (!entries.length) + return; + chrome.fileManagerPrivate.getProfiles( + function(profiles, currentId, displayedId) { + // Find strings. + var displayName; + for (var i = 0; i < profiles.length; i++) { + if (profiles[i].profileId === currentId) { + displayName = profiles[i].displayName; + break; + } + } + if (!displayName) { + console.warn('Display name is not found.'); + return; + } + + var title = entries.length > 1 ? + entries[0].name + '\u2026' /* ellipsis */ : entries[0].name; + var message = strf(entries.length > 1 ? + 'OPEN_IN_OTHER_DESKTOP_MESSAGE_PLURAL' : + 'OPEN_IN_OTHER_DESKTOP_MESSAGE', + displayName, + currentId); + + // Show the dialog. + this.alertDialog.showWithTitle(title, message, null, null, null); + }.bind(this)); +};
diff --git a/ui/file_manager/gallery/js/compiled_resources.gyp b/ui/file_manager/gallery/js/compiled_resources.gyp index 4038e15..0c168d46 100644 --- a/ui/file_manager/gallery/js/compiled_resources.gyp +++ b/ui/file_manager/gallery/js/compiled_resources.gyp
@@ -12,7 +12,6 @@ '../../../webui/resources/js/cr/event_target.js', '../../../webui/resources/js/cr/ui.js', '../../../webui/resources/js/cr/ui/array_data_model.js', - '../../../webui/resources/js/cr/ui/dialogs.js', '../../../webui/resources/js/load_time_data.js', '../../../webui/resources/js/promise_resolver.js', '../../../webui/resources/js/util.js',
diff --git a/ui/file_manager/video_player/js/compiled_resources.gyp b/ui/file_manager/video_player/js/compiled_resources.gyp index 749d44b1..a5377d2c 100644 --- a/ui/file_manager/video_player/js/compiled_resources.gyp +++ b/ui/file_manager/video_player/js/compiled_resources.gyp
@@ -12,8 +12,6 @@ '../../../webui/resources/js/cr/event_target.js', '../../../webui/resources/js/cr/ui.js', '../../../webui/resources/js/cr/ui/array_data_model.js', - # Referenced in common/js/util.js. - '../../../webui/resources/js/cr/ui/dialogs.js', '../../../webui/resources/js/promise_resolver.js', '../../../webui/resources/js/load_time_data.js', '../../../webui/resources/js/util.js',
diff --git a/ui/gfx/color_space.cc b/ui/gfx/color_space.cc index 7650b1e3..ad0f1350 100644 --- a/ui/gfx/color_space.cc +++ b/ui/gfx/color_space.cc
@@ -2,15 +2,92 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "build/build_config.h" #include "ui/gfx/color_space.h" +#include <map> + +#include "base/lazy_instance.h" +#include "base/synchronization/lock.h" + namespace gfx { namespace { static const size_t kMinProfileLength = 128; static const size_t kMaxProfileLength = 4 * 1024 * 1024; -} +} // namespace + +// The structure used to look up GlobalData structures. +struct ColorSpace::Key { + Key(ColorSpace::Type type, const std::vector<char>& icc_profile) + : type(type), icc_profile(icc_profile) {} + + bool operator<(const Key& other) const { + if (type < other.type) + return true; + if (type > other.type) + return false; + if (type != Type::ICC_PROFILE) + return false; + + if (icc_profile.size() < other.icc_profile.size()) + return true; + if (icc_profile.size() > other.icc_profile.size()) + return false; + for (size_t i = 0; i < icc_profile.size(); ++i) { + if (icc_profile[i] < other.icc_profile[i]) + return true; + if (icc_profile[i] > other.icc_profile[i]) + return false; + } + return false; + } + + ColorSpace::Type type; + const std::vector<char> icc_profile; +}; + +// Because this structure is shared across gfx::ColorSpace objects on +// different threads, it needs to be thread-safe. +class ColorSpace::GlobalData + : public base::RefCountedThreadSafe<ColorSpace::GlobalData> { + public: + static void Get(const Key& key, scoped_refptr<GlobalData>* value) { + base::AutoLock lock(map_lock_.Get()); + auto insert_result = map_.Get().insert(std::make_pair(key, nullptr)); + if (insert_result.second) + insert_result.first->second = new GlobalData(key, insert_result.first); + *value = make_scoped_refptr(insert_result.first->second); + } + + const std::vector<char>& GetICCProfile() const { return icc_profile_; } + + private: + friend class base::RefCountedThreadSafe<GlobalData>; + + GlobalData(const Key& key, std::map<Key, GlobalData*>::iterator iterator) + : iterator_(iterator) { + // TODO: Compute the ICC profile for named color spaces. + if (key.type == Type::ICC_PROFILE) + icc_profile_ = key.icc_profile; + } + ~GlobalData() { + base::AutoLock lock(map_lock_.Get()); + map_.Get().erase(iterator_); + } + + std::vector<char> icc_profile_; + + // In order to remove |this| from |map_| when its last reference goes away, + // keep in |iterator_| the corresponding iterator in |map_|. + std::map<Key, GlobalData*>::iterator iterator_; + static base::LazyInstance<std::map<Key, GlobalData*>> map_; + static base::LazyInstance<base::Lock> map_lock_; +}; + +base::LazyInstance<std::map<ColorSpace::Key, ColorSpace::GlobalData*>> + ColorSpace::GlobalData::map_ = LAZY_INSTANCE_INITIALIZER; +base::LazyInstance<base::Lock> + ColorSpace::GlobalData::map_lock_ = LAZY_INSTANCE_INITIALIZER; ColorSpace::ColorSpace() = default; ColorSpace::ColorSpace(ColorSpace&& other) = default; @@ -19,13 +96,26 @@ ColorSpace::~ColorSpace() = default; bool ColorSpace::operator==(const ColorSpace& other) const { - return icc_profile_ == other.icc_profile_; + if (type_ == Type::ICC_PROFILE && other.type_ == Type::ICC_PROFILE) + return global_data_ == other.global_data_; + return type_ == other.type_; } +bool ColorSpace::operator<(const ColorSpace& other) const { + // Note that this does a pointer-based comparision. + if (type_ == Type::ICC_PROFILE && other.type_ == Type::ICC_PROFILE) + return global_data_.get() < other.global_data_.get(); + return type_ < other.type_; +} + +// static ColorSpace ColorSpace::FromICCProfile(const std::vector<char>& icc_profile) { ColorSpace color_space; - if (IsValidProfileLength(icc_profile.size())) - color_space.icc_profile_ = icc_profile; + if (IsValidProfileLength(icc_profile.size())) { + color_space.type_ = Type::ICC_PROFILE; + Key key(Type::ICC_PROFILE, icc_profile); + GlobalData::Get(key, &color_space.global_data_); + } return color_space; } @@ -36,6 +126,14 @@ } #endif +const std::vector<char>& ColorSpace::GetICCProfile() const { + if (!global_data_) { + Key key(type_, std::vector<char>()); + GlobalData::Get(key, &global_data_); + } + return global_data_->GetICCProfile(); +} + // static bool ColorSpace::IsValidProfileLength(size_t length) { return length >= kMinProfileLength && length <= kMaxProfileLength;
diff --git a/ui/gfx/color_space.h b/ui/gfx/color_space.h index 0129e7e..44a85eb 100644 --- a/ui/gfx/color_space.h +++ b/ui/gfx/color_space.h
@@ -8,6 +8,7 @@ #include <vector> #include "base/macros.h" +#include "base/memory/ref_counted.h" #include "build/build_config.h" #include "ui/gfx/gfx_export.h" @@ -25,6 +26,7 @@ ColorSpace& operator=(const ColorSpace& other); ~ColorSpace(); bool operator==(const ColorSpace& other) const; + bool operator<(const ColorSpace& other) const; // Returns the color profile of the monitor that can best represent color. // This profile should be used for creating content that does not know on @@ -35,7 +37,7 @@ static ColorSpace FromCGColorSpace(CGColorSpaceRef cg_color_space); #endif - const std::vector<char>& GetICCProfile() const { return icc_profile_; } + const std::vector<char>& GetICCProfile() const; #if defined(OS_WIN) // This will read monitor ICC profiles from disk and cache the results for the @@ -47,7 +49,20 @@ static bool IsValidProfileLength(size_t length); private: - std::vector<char> icc_profile_; + struct Key; + class GlobalData; + friend struct Key; + friend class GlobalData; + enum class Type { + UNDEFINED, + ICC_PROFILE, + }; + Type type_ = Type::UNDEFINED; + + // GlobalData stores large or expensive-to-compute data about a color space + // (e.g, ICC profile). This structure is shared by all identical ColorSpace + // objects in the process. It is lazily initialized for named color spaces. + mutable scoped_refptr<GlobalData> global_data_; }; } // namespace gfx
diff --git a/ui/gfx/color_space_win.cc b/ui/gfx/color_space_win.cc index e9db49fc0..9446c4ee 100644 --- a/ui/gfx/color_space_win.cc +++ b/ui/gfx/color_space_win.cc
@@ -59,9 +59,10 @@ void ColorSpace::UpdateCachedProfilesOnBackgroundThread() { std::vector<char> icc_profile; ReadBestMonitorICCProfile(&icc_profile); + gfx::ColorSpace color_space = FromICCProfile(icc_profile); base::AutoLock lock(g_best_monitor_color_space_lock.Get()); - g_best_monitor_color_space.Get().icc_profile_ = icc_profile; + g_best_monitor_color_space.Get() = color_space; g_has_initialized_best_monitor_color_space = true; }
diff --git a/ui/gfx/color_space_x11.cc b/ui/gfx/color_space_x11.cc index 7dacae21..dfa1e12 100644 --- a/ui/gfx/color_space_x11.cc +++ b/ui/gfx/color_space_x11.cc
@@ -17,7 +17,6 @@ // static ColorSpace ColorSpace::FromBestMonitor() { - ColorSpace color_space; Atom property = XInternAtom(GetXDisplay(), "_ICC_PROFILE", true); if (property != None) { Atom prop_type = None; @@ -30,11 +29,13 @@ 0x1FFFFFFF /* MAXINT32 / 4 */, False, AnyPropertyType, &prop_type, &prop_format, &nitems, &nbytes, reinterpret_cast<unsigned char**>(&property_data)) == Success) { - color_space.icc_profile_.assign(property_data, property_data + nitems); + std::vector<char> icc_profile; + icc_profile.assign(property_data, property_data + nitems); XFree(property_data); + return FromICCProfile(icc_profile); } } - return color_space; + return ColorSpace(); } } // namespace gfx
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc index b3eea35..6ee8250 100644 --- a/ui/gfx/render_text_unittest.cc +++ b/ui/gfx/render_text_unittest.cc
@@ -3193,7 +3193,7 @@ render_text->SetHorizontalAlignment(ALIGN_LEFT); render_text->SetColor(SK_ColorBLACK); - for (auto string : kTestStrings) { + for (auto* string : kTestStrings) { surface->getCanvas()->clear(SK_ColorWHITE); render_text->SetText(WideToUTF16(string)); const Size string_size = render_text->GetStringSize(); @@ -3285,7 +3285,7 @@ render_text->SetHorizontalAlignment(ALIGN_LEFT); render_text->SetColor(SK_ColorBLACK); - for (auto string : kTestStrings) { + for (auto* string : kTestStrings) { surface->getCanvas()->clear(SK_ColorWHITE); render_text->SetText(WideToUTF16(string)); const Size string_size = render_text->GetStringSize();
diff --git a/ui/gfx/vector_icons/upgrade_menu_item.icon b/ui/gfx/vector_icons/upgrade_menu_item.icon deleted file mode 100644 index dcf04ed..0000000 --- a/ui/gfx/vector_icons/upgrade_menu_item.icon +++ /dev/null
@@ -1,16 +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. - -CANVAS_DIMENSIONS, 32, -ROUND_RECT, 2, 2, 28, 28, 4, -MOVE_TO, 12, 24, -R_H_LINE_TO, 8, -R_V_LINE_TO, -6, -R_H_LINE_TO, 4, -LINE_TO, 16, 8, -LINE_TO, 8, 18, -R_H_LINE_TO, 4, -R_V_LINE_TO, 6, -CLOSE, -END
diff --git a/ui/gfx/vector_icons_sources.gypi b/ui/gfx/vector_icons_sources.gypi index 1e3207fd..08ffc81 100644 --- a/ui/gfx/vector_icons_sources.gypi +++ b/ui/gfx/vector_icons_sources.gypi
@@ -170,7 +170,6 @@ 'vector_icons/tab_usb_connected.icon', 'vector_icons/tablet.icon', 'vector_icons/translate.icon', - 'vector_icons/upgrade_menu_item.icon', 'vector_icons/videocam.icon', 'vector_icons/warning.icon', 'vector_icons/warning_badge.icon',
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn index 69b94d2..bf88fd6 100644 --- a/ui/gl/BUILD.gn +++ b/ui/gl/BUILD.gn
@@ -96,6 +96,11 @@ "gl_share_group.h", "gl_state_restorer.cc", "gl_state_restorer.h", + "gl_stub_api.cc", + "gl_stub_api.h", + "gl_stub_api_base.h", + "gl_stub_autogen_gl.cc", + "gl_stub_autogen_gl.h", "gl_surface.cc", "gl_surface.h", "gl_surface_osmesa.cc",
diff --git a/ui/gl/generate_bindings.py b/ui/gl/generate_bindings.py index 070c9b6a..1a4d972 100755 --- a/ui/gl/generate_bindings.py +++ b/ui/gl/generate_bindings.py
@@ -1869,7 +1869,7 @@ SELF_LOCATION = os.path.dirname(os.path.abspath(__file__)) LICENSE_AND_HEADER = """\ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. // @@ -2037,6 +2037,51 @@ file.write('\n') +def GenerateStubHeader(file, functions): + """Generates gl_stub_autogen_gl.h""" + + # Write file header. + file.write(LICENSE_AND_HEADER) + + # Write API declaration. + for func in functions: + args = func['arguments'] + if args == 'void': + args = '' + return_type = func['return_type']; + file.write(' %s gl%sFn(%s) override' % (return_type, func['known_as'][2:], + args)) + if return_type == 'void': + file.write(' {}\n'); + else: + file.write(';\n'); + + file.write('\n') + +def GenerateStubSource(file, functions): + """Generates gl_stub_autogen_gl.cc""" + + # Write file header. + file.write(LICENSE_AND_HEADER) + file.write('\n#include "ui/gl/gl_stub_api_base.h"\n\n') + file.write('namespace gl {\n\n') + + # Write API declaration. + for func in functions: + return_type = func['return_type']; + if return_type == 'void': + continue + args = func['arguments'] + if args == 'void': + args = '' + file.write('%s GLStubApiBase::gl%sFn(%s) {\n' % (return_type, + func['known_as'][2:], + args)) + file.write(' return 0;\n'); + file.write('}\n\n'); + + file.write('\n} // namespace gl\n') + def GenerateSource(file, functions, set_name, used_extensions, used_client_extensions, options): @@ -2878,6 +2923,18 @@ GenerateEnumUtils(header_file, enum_header_filenames) header_file.close() ClangFormat(header_file.name) + + header_file = open( + os.path.join(directory, 'gl_stub_autogen_gl.h'), 'wb') + GenerateStubHeader(header_file, GL_FUNCTIONS) + header_file.close() + ClangFormat(header_file.name) + + header_file = open( + os.path.join(directory, 'gl_stub_autogen_gl.cc'), 'wb') + GenerateStubSource(header_file, GL_FUNCTIONS) + header_file.close() + ClangFormat(header_file.name) return 0
diff --git a/ui/gl/gl.gyp b/ui/gl/gl.gyp index aee1bab..a98ecdf 100644 --- a/ui/gl/gl.gyp +++ b/ui/gl/gl.gyp
@@ -101,6 +101,11 @@ 'gl_surface_overlay.h', 'gl_surface_stub.cc', 'gl_surface_stub.h', + "gl_stub_api.cc", + "gl_stub_api.h", + "gl_stub_api_base.h", + "gl_stub_autogen_gl.cc", + "gl_stub_autogen_gl.h", 'gl_switches.cc', 'gl_switches.h', 'gl_version_info.cc',
diff --git a/ui/gl/gl_bindings_api_autogen_egl.h b/ui/gl/gl_bindings_api_autogen_egl.h index 7c5b160c..2d32466 100644 --- a/ui/gl/gl_bindings_api_autogen_egl.h +++ b/ui/gl/gl_bindings_api_autogen_egl.h
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_bindings_api_autogen_gl.h b/ui/gl/gl_bindings_api_autogen_gl.h index ed809dd..4b13dfd 100644 --- a/ui/gl/gl_bindings_api_autogen_gl.h +++ b/ui/gl/gl_bindings_api_autogen_gl.h
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_bindings_api_autogen_glx.h b/ui/gl/gl_bindings_api_autogen_glx.h index d36199ce..15e5c9f4 100644 --- a/ui/gl/gl_bindings_api_autogen_glx.h +++ b/ui/gl/gl_bindings_api_autogen_glx.h
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_bindings_api_autogen_osmesa.h b/ui/gl/gl_bindings_api_autogen_osmesa.h index c061275c..46ce5c3d 100644 --- a/ui/gl/gl_bindings_api_autogen_osmesa.h +++ b/ui/gl/gl_bindings_api_autogen_osmesa.h
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_bindings_api_autogen_wgl.h b/ui/gl/gl_bindings_api_autogen_wgl.h index 7be2a7e..8a2edc1 100644 --- a/ui/gl/gl_bindings_api_autogen_wgl.h +++ b/ui/gl/gl_bindings_api_autogen_wgl.h
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_bindings_autogen_egl.cc b/ui/gl/gl_bindings_autogen_egl.cc index bc74888..7ef188c 100644 --- a/ui/gl/gl_bindings_autogen_egl.cc +++ b/ui/gl/gl_bindings_autogen_egl.cc
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_bindings_autogen_egl.h b/ui/gl/gl_bindings_autogen_egl.h index ae18719..b304e30 100644 --- a/ui/gl/gl_bindings_autogen_egl.h +++ b/ui/gl/gl_bindings_autogen_egl.h
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_bindings_autogen_gl.cc b/ui/gl/gl_bindings_autogen_gl.cc index 158132cf..04ba21a1 100644 --- a/ui/gl/gl_bindings_autogen_gl.cc +++ b/ui/gl/gl_bindings_autogen_gl.cc
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_bindings_autogen_gl.h b/ui/gl/gl_bindings_autogen_gl.h index 28e951aa..beb63df 100644 --- a/ui/gl/gl_bindings_autogen_gl.h +++ b/ui/gl/gl_bindings_autogen_gl.h
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_bindings_autogen_glx.cc b/ui/gl/gl_bindings_autogen_glx.cc index 2e9b0a2..9dd188b9 100644 --- a/ui/gl/gl_bindings_autogen_glx.cc +++ b/ui/gl/gl_bindings_autogen_glx.cc
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_bindings_autogen_glx.h b/ui/gl/gl_bindings_autogen_glx.h index 0f64f0f..2f75778 100644 --- a/ui/gl/gl_bindings_autogen_glx.h +++ b/ui/gl/gl_bindings_autogen_glx.h
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_bindings_autogen_mock.cc b/ui/gl/gl_bindings_autogen_mock.cc index 4cc5c8e..f89adfe3 100644 --- a/ui/gl/gl_bindings_autogen_mock.cc +++ b/ui/gl/gl_bindings_autogen_mock.cc
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_bindings_autogen_mock.h b/ui/gl/gl_bindings_autogen_mock.h index 72b2138..746eb84 100644 --- a/ui/gl/gl_bindings_autogen_mock.h +++ b/ui/gl/gl_bindings_autogen_mock.h
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_bindings_autogen_osmesa.cc b/ui/gl/gl_bindings_autogen_osmesa.cc index 5dfee26..7756f8a 100644 --- a/ui/gl/gl_bindings_autogen_osmesa.cc +++ b/ui/gl/gl_bindings_autogen_osmesa.cc
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_bindings_autogen_osmesa.h b/ui/gl/gl_bindings_autogen_osmesa.h index 02b8a3f..a40bf78 100644 --- a/ui/gl/gl_bindings_autogen_osmesa.h +++ b/ui/gl/gl_bindings_autogen_osmesa.h
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_bindings_autogen_wgl.cc b/ui/gl/gl_bindings_autogen_wgl.cc index d0935a9..c66533f2 100644 --- a/ui/gl/gl_bindings_autogen_wgl.cc +++ b/ui/gl/gl_bindings_autogen_wgl.cc
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_bindings_autogen_wgl.h b/ui/gl/gl_bindings_autogen_wgl.h index 844232b..2377f416 100644 --- a/ui/gl/gl_bindings_autogen_wgl.h +++ b/ui/gl/gl_bindings_autogen_wgl.h
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_context_stub.cc b/ui/gl/gl_context_stub.cc index 97a97d8..9b42a09 100644 --- a/ui/gl/gl_context_stub.cc +++ b/ui/gl/gl_context_stub.cc
@@ -4,6 +4,8 @@ #include "ui/gl/gl_context_stub.h" +#include "ui/gl/gl_gl_api_implementation.h" + namespace gl { GLContextStub::GLContextStub() : GLContextReal(nullptr) {} @@ -16,7 +18,7 @@ } bool GLContextStub::MakeCurrent(GLSurface* surface) { - SetRealGLApi(); + SetGLToStubGLApi(); SetCurrent(surface); InitializeDynamicBindings(); return true;
diff --git a/ui/gl/gl_enums_implementation_autogen.h b/ui/gl/gl_enums_implementation_autogen.h index 5d666e7d..0b58319 100644 --- a/ui/gl/gl_enums_implementation_autogen.h +++ b/ui/gl/gl_enums_implementation_autogen.h
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. // @@ -652,9 +652,6 @@ 0x78FC, "GL_RGB_YCBCR_420V_CHROMIUM", }, { - 0x78FD, "GL_GPU_MEMORY_BUFFER_ID", - }, - { 0x8, "GL_CA_LAYER_EDGE_TOP_CHROMIUM", }, {
diff --git a/ui/gl/gl_gl_api_implementation.cc b/ui/gl/gl_gl_api_implementation.cc index 3ef10a5..9dbb29f 100644 --- a/ui/gl/gl_gl_api_implementation.cc +++ b/ui/gl/gl_gl_api_implementation.cc
@@ -28,6 +28,8 @@ static NoContextGLApi* g_no_context_gl = NULL; // A GL Api that calls TRACE and then calls another GL api. static TraceGLApi* g_trace_gl = NULL; +// The GL Api being used for stub contexts. If null, g_gl is used instead. +static GLApi* g_stub_gl = NULL; // GL version used when initializing dynamic bindings. static GLVersionInfo* g_version_info = NULL; @@ -380,10 +382,18 @@ SetGLApi(g_gl); } +void SetGLToStubGLApi() { + SetGLApi(g_stub_gl ? g_stub_gl : g_gl); +} + void SetGLApiToNoContext() { SetGLApi(g_no_context_gl); } +void SetStubGLApi(GLApi* api) { + g_stub_gl = api; +} + const GLVersionInfo* GetGLVersionInfo() { return g_version_info; } @@ -430,6 +440,7 @@ g_no_context_gl = NULL; } g_gl = NULL; + g_stub_gl = NULL; g_driver_gl.ClearBindings(); if (g_current_gl_context_tls) { delete g_current_gl_context_tls;
diff --git a/ui/gl/gl_gl_api_implementation.h b/ui/gl/gl_gl_api_implementation.h index cb54c69..575a1b6 100644 --- a/ui/gl/gl_gl_api_implementation.h +++ b/ui/gl/gl_gl_api_implementation.h
@@ -34,9 +34,11 @@ bool SetNullDrawGLBindingsEnabledGL(bool enabled); GL_EXPORT void ClearGLBindingsGL(); void SetGLToRealGLApi(); +void SetGLToStubGLApi(); void SetGLApi(GLApi* api); void SetGLApiToNoContext(); GLApi* GetCurrentGLApi(); +GL_EXPORT void SetStubGLApi(GLApi* api); const GLVersionInfo* GetGLVersionInfo(); class GL_EXPORT GLApiBase : public GLApi {
diff --git a/ui/gl/gl_mock_autogen_gl.h b/ui/gl/gl_mock_autogen_gl.h index 5490842..70fbbba 100644 --- a/ui/gl/gl_mock_autogen_gl.h +++ b/ui/gl/gl_mock_autogen_gl.h
@@ -1,4 +1,4 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. +// 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. //
diff --git a/ui/gl/gl_stub_api.cc b/ui/gl/gl_stub_api.cc new file mode 100644 index 0000000..e4b634a --- /dev/null +++ b/ui/gl/gl_stub_api.cc
@@ -0,0 +1,296 @@ +// 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 "ui/gl/gl_stub_api.h" + +namespace gl { + +namespace { + +void GenHelper(GLsizei count, GLuint* objects) { + for (GLsizei i = 0; i < count; ++i) + objects[i] = i + 1; +} + +} // anonymous namespace + +GLenum GLStubApi::glCheckFramebufferStatusEXTFn(GLenum target) { + return GL_FRAMEBUFFER_COMPLETE; +} + +GLuint GLStubApi::glCreateProgramFn(void) { + return 1; +} + +GLuint GLStubApi::glCreateShaderFn(GLenum type) { + return 2; +} + +GLsync GLStubApi::glFenceSyncFn(GLenum condition, GLbitfield flags) { + return reinterpret_cast<GLsync>(1); +} + +void GLStubApi::glGenBuffersARBFn(GLsizei n, GLuint* buffers) { + GenHelper(n, buffers); +} + +void GLStubApi::glGenerateMipmapEXTFn(GLenum target) {} + +void GLStubApi::glGenFencesAPPLEFn(GLsizei n, GLuint* fences) { + GenHelper(n, fences); +} + +void GLStubApi::glGenFencesNVFn(GLsizei n, GLuint* fences) { + GenHelper(n, fences); +} + +void GLStubApi::glGenFramebuffersEXTFn(GLsizei n, GLuint* framebuffers) { + GenHelper(n, framebuffers); +} + +GLuint GLStubApi::glGenPathsNVFn(GLsizei range) { + return 1; +} + +void GLStubApi::glGenQueriesFn(GLsizei n, GLuint* ids) { + GenHelper(n, ids); +} + +void GLStubApi::glGenRenderbuffersEXTFn(GLsizei n, GLuint* renderbuffers) { + GenHelper(n, renderbuffers); +} + +void GLStubApi::glGenSamplersFn(GLsizei n, GLuint* samplers) { + GenHelper(n, samplers); +} + +void GLStubApi::glGenTexturesFn(GLsizei n, GLuint* textures) { + GenHelper(n, textures); +} + +void GLStubApi::glGenTransformFeedbacksFn(GLsizei n, GLuint* ids) { + GenHelper(n, ids); +} + +void GLStubApi::glGenVertexArraysOESFn(GLsizei n, GLuint* arrays) { + GenHelper(n, arrays); +} + +void GLStubApi::glGetIntegervFn(GLenum pname, GLint* params) { + // We need some values to be large enough to initialize ContextGroup. + switch (pname) { + default: + *params = 1; + break; + case GL_MAX_RENDERBUFFER_SIZE: + *params = 512; + break; + case GL_MAX_SAMPLES: + *params = 4; + break; + case GL_MAX_COLOR_ATTACHMENTS_EXT: + *params = 4; + break; + case GL_MAX_DRAW_BUFFERS_ARB: + *params = 4; + break; + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: + *params = 4; + break; + case GL_MAX_UNIFORM_BUFFER_BINDINGS: + *params = 24; + break; + case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: + *params = 256; + break; + case GL_MAX_VERTEX_ATTRIBS: + *params = 8; + break; + case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: + *params = 8; + break; + case GL_MAX_TEXTURE_IMAGE_UNITS: + *params = 8; + break; + case GL_MAX_TEXTURE_SIZE: + *params = 2048; + break; + case GL_MAX_CUBE_MAP_TEXTURE_SIZE: + *params = 2048; + break; + case GL_MAX_3D_TEXTURE_SIZE: + *params = 256; + break; + case GL_MAX_ARRAY_TEXTURE_LAYERS: + *params = 256; + break; + case GL_MAX_VARYING_VECTORS: + *params = 8; + break; + case GL_MAX_VERTEX_UNIFORM_VECTORS: + *params = 128; + break; + case GL_MAX_FRAGMENT_UNIFORM_VECTORS: + *params = 16; + break; + case GL_MAX_VERTEX_OUTPUT_COMPONENTS: + *params = 64; + break; + case GL_MAX_FRAGMENT_INPUT_COMPONENTS: + *params = 60; + break; + case GL_MAX_PROGRAM_TEXEL_OFFSET: + *params = 7; + break; + case GL_MIN_PROGRAM_TEXEL_OFFSET: + *params = -8; + break; + case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: + *params = 32; + break; + case GL_MAX_VIEWPORT_DIMS: + *params = 1024 << 8; + break; + case GL_ALPHA_BITS: + *params = 8; + break; + case GL_DEPTH_BITS: + *params = 24; + break; + case GL_STENCIL_BITS: + *params = 8; + break; + case GL_TEXTURE_BINDING_2D: + *params = 1; + break; + case GL_FRAMEBUFFER_BINDING: + *params = 1; + break; + case GL_IMPLEMENTATION_COLOR_READ_TYPE: + *params = GL_UNSIGNED_BYTE; + break; + case GL_IMPLEMENTATION_COLOR_READ_FORMAT: + *params = GL_RGBA; + break; + } +} + +void GLStubApi::glGetProgramivFn(GLuint program, GLenum pname, GLint* params) { + switch (pname) { + case GL_LINK_STATUS: + *params = GL_TRUE; + break; + case GL_VALIDATE_STATUS: + *params = GL_TRUE; + break; + default: + break; + } +} + +void GLStubApi::glGetShaderivFn(GLuint shader, GLenum pname, GLint* params) { + switch (pname) { + case GL_COMPILE_STATUS: + *params = GL_TRUE; + break; + default: + break; + } +} + +const GLubyte* GLStubApi::glGetStringFn(GLenum name) { + switch (name) { + case GL_RENDERER: + default: + return reinterpret_cast<const GLubyte*>(""); + case GL_VERSION: + return reinterpret_cast<const GLubyte*>("OpenGL ES 3.0"); + case GL_EXTENSIONS: + return reinterpret_cast<const GLubyte*>("GL_EXT_framebuffer_object"); + } +} + +const GLubyte* GLStubApi::glGetStringiFn(GLenum name, GLuint index) { + return reinterpret_cast<const GLubyte*>(""); +} + +GLboolean GLStubApi::glIsBufferFn(GLuint buffer) { + return GL_TRUE; +} + +GLboolean GLStubApi::glIsEnabledFn(GLenum cap) { + return GL_TRUE; +} + +GLboolean GLStubApi::glIsFenceAPPLEFn(GLuint fence) { + return GL_TRUE; +} + +GLboolean GLStubApi::glIsFenceNVFn(GLuint fence) { + return GL_TRUE; +} + +GLboolean GLStubApi::glIsFramebufferEXTFn(GLuint framebuffer) { + return GL_TRUE; +} + +GLboolean GLStubApi::glIsPathNVFn(GLuint path) { + return GL_TRUE; +} + +GLboolean GLStubApi::glIsProgramFn(GLuint program) { + return GL_TRUE; +} + +GLboolean GLStubApi::glIsQueryFn(GLuint query) { + return GL_TRUE; +} + +GLboolean GLStubApi::glIsRenderbufferEXTFn(GLuint renderbuffer) { + return GL_TRUE; +} + +GLboolean GLStubApi::glIsSamplerFn(GLuint sampler) { + return GL_TRUE; +} + +GLboolean GLStubApi::glIsShaderFn(GLuint shader) { + return GL_TRUE; +} + +GLboolean GLStubApi::glIsSyncFn(GLsync sync) { + return GL_TRUE; +} + +GLboolean GLStubApi::glIsTextureFn(GLuint texture) { + return GL_TRUE; +} + +GLboolean GLStubApi::glIsTransformFeedbackFn(GLuint id) { + return GL_TRUE; +} + +GLboolean GLStubApi::glIsVertexArrayOESFn(GLuint array) { + return GL_TRUE; +} + +GLboolean GLStubApi::glTestFenceAPPLEFn(GLuint fence) { + return GL_TRUE; +} + +GLboolean GLStubApi::glTestFenceNVFn(GLuint fence) { + return GL_TRUE; +} + +GLboolean GLStubApi::glUnmapBufferFn(GLenum target) { + return GL_TRUE; +} + +GLenum GLStubApi::glWaitSyncFn(GLsync sync, + GLbitfield flags, + GLuint64 timeout) { + return GL_TRUE; +} + +} // namespace gl
diff --git a/ui/gl/gl_stub_api.h b/ui/gl/gl_stub_api.h new file mode 100644 index 0000000..e654ffb --- /dev/null +++ b/ui/gl/gl_stub_api.h
@@ -0,0 +1,61 @@ +// 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 UI_GL_GL_STUB_API_H_ +#define UI_GL_GL_STUB_API_H_ + +#include "ui/gl/gl_export.h" +#include "ui/gl/gl_stub_api_base.h" + +namespace gl { + +class GL_EXPORT GLStubApi: public GLStubApiBase { + public: + GLenum glCheckFramebufferStatusEXTFn(GLenum target) override; + GLuint glCreateProgramFn(void) override; + GLuint glCreateShaderFn(GLenum type) override; + GLsync glFenceSyncFn(GLenum condition, GLbitfield flags) override; + void glGenBuffersARBFn(GLsizei n, GLuint* buffers) override; + void glGenerateMipmapEXTFn(GLenum target) override; + void glGenFencesAPPLEFn(GLsizei n, GLuint* fences) override; + void glGenFencesNVFn(GLsizei n, GLuint* fences) override; + void glGenFramebuffersEXTFn(GLsizei n, GLuint* framebuffers) override; + GLuint glGenPathsNVFn(GLsizei range) override; + void glGenQueriesFn(GLsizei n, GLuint* ids) override; + void glGenRenderbuffersEXTFn(GLsizei n, GLuint* renderbuffers) override; + void glGenSamplersFn(GLsizei n, GLuint* samplers) override; + void glGenTexturesFn(GLsizei n, GLuint* textures) override; + void glGenTransformFeedbacksFn(GLsizei n, GLuint* ids) override; + void glGenVertexArraysOESFn(GLsizei n, GLuint* arrays) override; + void glGetIntegervFn(GLenum pname, GLint* params) override; + void glGetProgramivFn(GLuint program, GLenum pname, GLint* params) override; + void glGetShaderivFn(GLuint shader, GLenum pname, GLint* params) override; + const GLubyte* glGetStringFn(GLenum name) override; + const GLubyte* glGetStringiFn(GLenum name, GLuint index) override; + GLboolean glIsBufferFn(GLuint buffer) override; + GLboolean glIsEnabledFn(GLenum cap) override; + GLboolean glIsFenceAPPLEFn(GLuint fence) override; + GLboolean glIsFenceNVFn(GLuint fence) override; + GLboolean glIsFramebufferEXTFn(GLuint framebuffer) override; + GLboolean glIsPathNVFn(GLuint path) override; + GLboolean glIsProgramFn(GLuint program) override; + GLboolean glIsQueryFn(GLuint query) override; + GLboolean glIsRenderbufferEXTFn(GLuint renderbuffer) override; + GLboolean glIsSamplerFn(GLuint sampler) override; + GLboolean glIsShaderFn(GLuint shader) override; + GLboolean glIsSyncFn(GLsync sync) override; + GLboolean glIsTextureFn(GLuint texture) override; + GLboolean glIsTransformFeedbackFn(GLuint id) override; + GLboolean glIsVertexArrayOESFn(GLuint array) override; + GLboolean glTestFenceAPPLEFn(GLuint fence) override; + GLboolean glTestFenceNVFn(GLuint fence) override; + GLboolean glUnmapBufferFn(GLenum target) override; + GLenum glWaitSyncFn(GLsync sync, + GLbitfield flags, + GLuint64 timeout) override; +}; + +} // namespace gl + +#endif // UI_GL_GL_STUB_API_H_
diff --git a/ui/gl/gl_stub_api_base.h b/ui/gl/gl_stub_api_base.h new file mode 100644 index 0000000..13d1fde --- /dev/null +++ b/ui/gl/gl_stub_api_base.h
@@ -0,0 +1,28 @@ +// 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. + +// This file implements a stub GL Interface for unit testing. The interface +// corresponds to the set of functionally distinct GL functions defined in +// generate_bindings.py, which may originate from either desktop GL or GLES. + +#ifndef UI_GL_GL_STUB_API_BASE_H_ +#define UI_GL_GL_STUB_API_BASE_H_ + +#include "ui/gl/gl_bindings.h" +#include "ui/gl/gl_export.h" +#include "ui/gl/gl_gl_api_implementation.h" + +namespace gl { + +class GL_EXPORT GLStubApiBase : public gl::GLApi { + public: + GLStubApiBase() {} + ~GLStubApiBase() override {} + +#include "ui/gl/gl_stub_autogen_gl.h" +}; + +} // namespace gl + +#endif // UI_GL_GL_STUB_API_BASE_H_
diff --git a/ui/gl/gl_stub_autogen_gl.cc b/ui/gl/gl_stub_autogen_gl.cc new file mode 100644 index 0000000..95f66430 --- /dev/null +++ b/ui/gl/gl_stub_autogen_gl.cc
@@ -0,0 +1,173 @@ +// 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. +// +// This file is auto-generated from +// ui/gl/generate_bindings.py +// It's formatted by clang-format using chromium coding style: +// clang-format -i -style=chromium filename +// DO NOT EDIT! + +#include "ui/gl/gl_stub_api_base.h" + +namespace gl { + +GLenum GLStubApiBase::glCheckFramebufferStatusEXTFn(GLenum target) { + return 0; +} + +GLenum GLStubApiBase::glClientWaitSyncFn(GLsync sync, + GLbitfield flags, + GLuint64 timeout) { + return 0; +} + +GLuint GLStubApiBase::glCreateProgramFn() { + return 0; +} + +GLuint GLStubApiBase::glCreateShaderFn(GLenum type) { + return 0; +} + +GLsync GLStubApiBase::glFenceSyncFn(GLenum condition, GLbitfield flags) { + return 0; +} + +GLuint GLStubApiBase::glGenPathsNVFn(GLsizei range) { + return 0; +} + +GLint GLStubApiBase::glGetAttribLocationFn(GLuint program, const char* name) { + return 0; +} + +GLenum GLStubApiBase::glGetErrorFn() { + return 0; +} + +GLint GLStubApiBase::glGetFragDataIndexFn(GLuint program, const char* name) { + return 0; +} + +GLint GLStubApiBase::glGetFragDataLocationFn(GLuint program, const char* name) { + return 0; +} + +GLenum GLStubApiBase::glGetGraphicsResetStatusARBFn() { + return 0; +} + +GLint GLStubApiBase::glGetProgramResourceLocationFn(GLuint program, + GLenum programInterface, + const char* name) { + return 0; +} + +const GLubyte* GLStubApiBase::glGetStringFn(GLenum name) { + return 0; +} + +const GLubyte* GLStubApiBase::glGetStringiFn(GLenum name, GLuint index) { + return 0; +} + +GLuint GLStubApiBase::glGetUniformBlockIndexFn(GLuint program, + const char* uniformBlockName) { + return 0; +} + +GLint GLStubApiBase::glGetUniformLocationFn(GLuint program, const char* name) { + return 0; +} + +GLboolean GLStubApiBase::glIsBufferFn(GLuint buffer) { + return 0; +} + +GLboolean GLStubApiBase::glIsEnabledFn(GLenum cap) { + return 0; +} + +GLboolean GLStubApiBase::glIsFenceAPPLEFn(GLuint fence) { + return 0; +} + +GLboolean GLStubApiBase::glIsFenceNVFn(GLuint fence) { + return 0; +} + +GLboolean GLStubApiBase::glIsFramebufferEXTFn(GLuint framebuffer) { + return 0; +} + +GLboolean GLStubApiBase::glIsPathNVFn(GLuint path) { + return 0; +} + +GLboolean GLStubApiBase::glIsProgramFn(GLuint program) { + return 0; +} + +GLboolean GLStubApiBase::glIsQueryFn(GLuint query) { + return 0; +} + +GLboolean GLStubApiBase::glIsRenderbufferEXTFn(GLuint renderbuffer) { + return 0; +} + +GLboolean GLStubApiBase::glIsSamplerFn(GLuint sampler) { + return 0; +} + +GLboolean GLStubApiBase::glIsShaderFn(GLuint shader) { + return 0; +} + +GLboolean GLStubApiBase::glIsSyncFn(GLsync sync) { + return 0; +} + +GLboolean GLStubApiBase::glIsTextureFn(GLuint texture) { + return 0; +} + +GLboolean GLStubApiBase::glIsTransformFeedbackFn(GLuint id) { + return 0; +} + +GLboolean GLStubApiBase::glIsVertexArrayOESFn(GLuint array) { + return 0; +} + +void* GLStubApiBase::glMapBufferFn(GLenum target, GLenum access) { + return 0; +} + +void* GLStubApiBase::glMapBufferRangeFn(GLenum target, + GLintptr offset, + GLsizeiptr length, + GLbitfield access) { + return 0; +} + +GLboolean GLStubApiBase::glTestFenceAPPLEFn(GLuint fence) { + return 0; +} + +GLboolean GLStubApiBase::glTestFenceNVFn(GLuint fence) { + return 0; +} + +GLboolean GLStubApiBase::glUnmapBufferFn(GLenum target) { + return 0; +} + +GLenum GLStubApiBase::glWaitSyncFn(GLsync sync, + GLbitfield flags, + GLuint64 timeout) { + return 0; +} + +} // namespace gl
diff --git a/ui/gl/gl_stub_autogen_gl.h b/ui/gl/gl_stub_autogen_gl.h new file mode 100644 index 0000000..f55fb91 --- /dev/null +++ b/ui/gl/gl_stub_autogen_gl.h
@@ -0,0 +1,855 @@ +// 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. +// +// This file is auto-generated from +// ui/gl/generate_bindings.py +// It's formatted by clang-format using chromium coding style: +// clang-format -i -style=chromium filename +// DO NOT EDIT! + +void glActiveTextureFn(GLenum texture) override {} +void glApplyFramebufferAttachmentCMAAINTELFn() override {} +void glAttachShaderFn(GLuint program, GLuint shader) override {} +void glBeginQueryFn(GLenum target, GLuint id) override {} +void glBeginTransformFeedbackFn(GLenum primitiveMode) override {} +void glBindAttribLocationFn(GLuint program, + GLuint index, + const char* name) override {} +void glBindBufferFn(GLenum target, GLuint buffer) override {} +void glBindBufferBaseFn(GLenum target, GLuint index, GLuint buffer) override {} +void glBindBufferRangeFn(GLenum target, + GLuint index, + GLuint buffer, + GLintptr offset, + GLsizeiptr size) override {} +void glBindFragDataLocationFn(GLuint program, + GLuint colorNumber, + const char* name) override {} +void glBindFragDataLocationIndexedFn(GLuint program, + GLuint colorNumber, + GLuint index, + const char* name) override {} +void glBindFramebufferEXTFn(GLenum target, GLuint framebuffer) override {} +void glBindImageTextureEXTFn(GLuint index, + GLuint texture, + GLint level, + GLboolean layered, + GLint layer, + GLenum access, + GLint format) override {} +void glBindRenderbufferEXTFn(GLenum target, GLuint renderbuffer) override {} +void glBindSamplerFn(GLuint unit, GLuint sampler) override {} +void glBindTextureFn(GLenum target, GLuint texture) override {} +void glBindTransformFeedbackFn(GLenum target, GLuint id) override {} +void glBindUniformLocationCHROMIUMFn(GLuint program, + GLint location, + const char* name) override {} +void glBindVertexArrayOESFn(GLuint array) override {} +void glBlendBarrierKHRFn() override {} +void glBlendColorFn(GLclampf red, + GLclampf green, + GLclampf blue, + GLclampf alpha) override {} +void glBlendEquationFn(GLenum mode) override {} +void glBlendEquationSeparateFn(GLenum modeRGB, GLenum modeAlpha) override {} +void glBlendFuncFn(GLenum sfactor, GLenum dfactor) override {} +void glBlendFuncSeparateFn(GLenum srcRGB, + GLenum dstRGB, + GLenum srcAlpha, + GLenum dstAlpha) override {} +void glBlitFramebufferFn(GLint srcX0, + GLint srcY0, + GLint srcX1, + GLint srcY1, + GLint dstX0, + GLint dstY0, + GLint dstX1, + GLint dstY1, + GLbitfield mask, + GLenum filter) override {} +void glBlitFramebufferANGLEFn(GLint srcX0, + GLint srcY0, + GLint srcX1, + GLint srcY1, + GLint dstX0, + GLint dstY0, + GLint dstX1, + GLint dstY1, + GLbitfield mask, + GLenum filter) override {} +void glBlitFramebufferEXTFn(GLint srcX0, + GLint srcY0, + GLint srcX1, + GLint srcY1, + GLint dstX0, + GLint dstY0, + GLint dstX1, + GLint dstY1, + GLbitfield mask, + GLenum filter) override {} +void glBufferDataFn(GLenum target, + GLsizeiptr size, + const void* data, + GLenum usage) override {} +void glBufferSubDataFn(GLenum target, + GLintptr offset, + GLsizeiptr size, + const void* data) override {} +GLenum glCheckFramebufferStatusEXTFn(GLenum target) override; +void glClearFn(GLbitfield mask) override {} +void glClearBufferfiFn(GLenum buffer, + GLint drawbuffer, + const GLfloat depth, + GLint stencil) override {} +void glClearBufferfvFn(GLenum buffer, + GLint drawbuffer, + const GLfloat* value) override {} +void glClearBufferivFn(GLenum buffer, + GLint drawbuffer, + const GLint* value) override {} +void glClearBufferuivFn(GLenum buffer, + GLint drawbuffer, + const GLuint* value) override {} +void glClearColorFn(GLclampf red, + GLclampf green, + GLclampf blue, + GLclampf alpha) override {} +void glClearDepthFn(GLclampd depth) override {} +void glClearDepthfFn(GLclampf depth) override {} +void glClearStencilFn(GLint s) override {} +GLenum glClientWaitSyncFn(GLsync sync, + GLbitfield flags, + GLuint64 timeout) override; +void glColorMaskFn(GLboolean red, + GLboolean green, + GLboolean blue, + GLboolean alpha) override {} +void glCompileShaderFn(GLuint shader) override {} +void glCompressedTexImage2DFn(GLenum target, + GLint level, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLint border, + GLsizei imageSize, + const void* data) override {} +void glCompressedTexImage3DFn(GLenum target, + GLint level, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLsizei imageSize, + const void* data) override {} +void glCompressedTexSubImage2DFn(GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLsizei width, + GLsizei height, + GLenum format, + GLsizei imageSize, + const void* data) override {} +void glCompressedTexSubImage3DFn(GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLsizei width, + GLsizei height, + GLsizei depth, + GLenum format, + GLsizei imageSize, + const void* data) override {} +void glCopyBufferSubDataFn(GLenum readTarget, + GLenum writeTarget, + GLintptr readOffset, + GLintptr writeOffset, + GLsizeiptr size) override {} +void glCopyTexImage2DFn(GLenum target, + GLint level, + GLenum internalformat, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border) override {} +void glCopyTexSubImage2DFn(GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) override {} +void glCopyTexSubImage3DFn(GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) override {} +void glCoverageModulationNVFn(GLenum components) override {} +void glCoverFillPathInstancedNVFn(GLsizei numPaths, + GLenum pathNameType, + const void* paths, + GLuint pathBase, + GLenum coverMode, + GLenum transformType, + const GLfloat* transformValues) override {} +void glCoverFillPathNVFn(GLuint path, GLenum coverMode) override {} +void glCoverStrokePathInstancedNVFn(GLsizei numPaths, + GLenum pathNameType, + const void* paths, + GLuint pathBase, + GLenum coverMode, + GLenum transformType, + const GLfloat* transformValues) override {} +void glCoverStrokePathNVFn(GLuint name, GLenum coverMode) override {} +GLuint glCreateProgramFn() override; +GLuint glCreateShaderFn(GLenum type) override; +void glCullFaceFn(GLenum mode) override {} +void glDeleteBuffersARBFn(GLsizei n, const GLuint* buffers) override {} +void glDeleteFencesAPPLEFn(GLsizei n, const GLuint* fences) override {} +void glDeleteFencesNVFn(GLsizei n, const GLuint* fences) override {} +void glDeleteFramebuffersEXTFn(GLsizei n, const GLuint* framebuffers) override { +} +void glDeletePathsNVFn(GLuint path, GLsizei range) override {} +void glDeleteProgramFn(GLuint program) override {} +void glDeleteQueriesFn(GLsizei n, const GLuint* ids) override {} +void glDeleteRenderbuffersEXTFn(GLsizei n, + const GLuint* renderbuffers) override {} +void glDeleteSamplersFn(GLsizei n, const GLuint* samplers) override {} +void glDeleteShaderFn(GLuint shader) override {} +void glDeleteSyncFn(GLsync sync) override {} +void glDeleteTexturesFn(GLsizei n, const GLuint* textures) override {} +void glDeleteTransformFeedbacksFn(GLsizei n, const GLuint* ids) override {} +void glDeleteVertexArraysOESFn(GLsizei n, const GLuint* arrays) override {} +void glDepthFuncFn(GLenum func) override {} +void glDepthMaskFn(GLboolean flag) override {} +void glDepthRangeFn(GLclampd zNear, GLclampd zFar) override {} +void glDepthRangefFn(GLclampf zNear, GLclampf zFar) override {} +void glDetachShaderFn(GLuint program, GLuint shader) override {} +void glDisableFn(GLenum cap) override {} +void glDisableVertexAttribArrayFn(GLuint index) override {} +void glDiscardFramebufferEXTFn(GLenum target, + GLsizei numAttachments, + const GLenum* attachments) override {} +void glDrawArraysFn(GLenum mode, GLint first, GLsizei count) override {} +void glDrawArraysInstancedANGLEFn(GLenum mode, + GLint first, + GLsizei count, + GLsizei primcount) override {} +void glDrawBufferFn(GLenum mode) override {} +void glDrawBuffersARBFn(GLsizei n, const GLenum* bufs) override {} +void glDrawElementsFn(GLenum mode, + GLsizei count, + GLenum type, + const void* indices) override {} +void glDrawElementsInstancedANGLEFn(GLenum mode, + GLsizei count, + GLenum type, + const void* indices, + GLsizei primcount) override {} +void glDrawRangeElementsFn(GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const void* indices) override {} +void glEGLImageTargetRenderbufferStorageOESFn(GLenum target, + GLeglImageOES image) override {} +void glEGLImageTargetTexture2DOESFn(GLenum target, + GLeglImageOES image) override {} +void glEnableFn(GLenum cap) override {} +void glEnableVertexAttribArrayFn(GLuint index) override {} +void glEndQueryFn(GLenum target) override {} +void glEndTransformFeedbackFn() override {} +GLsync glFenceSyncFn(GLenum condition, GLbitfield flags) override; +void glFinishFn() override {} +void glFinishFenceAPPLEFn(GLuint fence) override {} +void glFinishFenceNVFn(GLuint fence) override {} +void glFlushFn() override {} +void glFlushMappedBufferRangeFn(GLenum target, + GLintptr offset, + GLsizeiptr length) override {} +void glFramebufferRenderbufferEXTFn(GLenum target, + GLenum attachment, + GLenum renderbuffertarget, + GLuint renderbuffer) override {} +void glFramebufferTexture2DEXTFn(GLenum target, + GLenum attachment, + GLenum textarget, + GLuint texture, + GLint level) override {} +void glFramebufferTexture2DMultisampleEXTFn(GLenum target, + GLenum attachment, + GLenum textarget, + GLuint texture, + GLint level, + GLsizei samples) override {} +void glFramebufferTexture2DMultisampleIMGFn(GLenum target, + GLenum attachment, + GLenum textarget, + GLuint texture, + GLint level, + GLsizei samples) override {} +void glFramebufferTextureLayerFn(GLenum target, + GLenum attachment, + GLuint texture, + GLint level, + GLint layer) override {} +void glFrontFaceFn(GLenum mode) override {} +void glGenBuffersARBFn(GLsizei n, GLuint* buffers) override {} +void glGenerateMipmapEXTFn(GLenum target) override {} +void glGenFencesAPPLEFn(GLsizei n, GLuint* fences) override {} +void glGenFencesNVFn(GLsizei n, GLuint* fences) override {} +void glGenFramebuffersEXTFn(GLsizei n, GLuint* framebuffers) override {} +GLuint glGenPathsNVFn(GLsizei range) override; +void glGenQueriesFn(GLsizei n, GLuint* ids) override {} +void glGenRenderbuffersEXTFn(GLsizei n, GLuint* renderbuffers) override {} +void glGenSamplersFn(GLsizei n, GLuint* samplers) override {} +void glGenTexturesFn(GLsizei n, GLuint* textures) override {} +void glGenTransformFeedbacksFn(GLsizei n, GLuint* ids) override {} +void glGenVertexArraysOESFn(GLsizei n, GLuint* arrays) override {} +void glGetActiveAttribFn(GLuint program, + GLuint index, + GLsizei bufsize, + GLsizei* length, + GLint* size, + GLenum* type, + char* name) override {} +void glGetActiveUniformFn(GLuint program, + GLuint index, + GLsizei bufsize, + GLsizei* length, + GLint* size, + GLenum* type, + char* name) override {} +void glGetActiveUniformBlockivFn(GLuint program, + GLuint uniformBlockIndex, + GLenum pname, + GLint* params) override {} +void glGetActiveUniformBlockNameFn(GLuint program, + GLuint uniformBlockIndex, + GLsizei bufSize, + GLsizei* length, + char* uniformBlockName) override {} +void glGetActiveUniformsivFn(GLuint program, + GLsizei uniformCount, + const GLuint* uniformIndices, + GLenum pname, + GLint* params) override {} +void glGetAttachedShadersFn(GLuint program, + GLsizei maxcount, + GLsizei* count, + GLuint* shaders) override {} +GLint glGetAttribLocationFn(GLuint program, const char* name) override; +void glGetBooleanvFn(GLenum pname, GLboolean* params) override {} +void glGetBufferParameterivFn(GLenum target, + GLenum pname, + GLint* params) override {} +GLenum glGetErrorFn() override; +void glGetFenceivNVFn(GLuint fence, GLenum pname, GLint* params) override {} +void glGetFloatvFn(GLenum pname, GLfloat* params) override {} +GLint glGetFragDataIndexFn(GLuint program, const char* name) override; +GLint glGetFragDataLocationFn(GLuint program, const char* name) override; +void glGetFramebufferAttachmentParameterivEXTFn(GLenum target, + GLenum attachment, + GLenum pname, + GLint* params) override {} +GLenum glGetGraphicsResetStatusARBFn() override; +void glGetInteger64i_vFn(GLenum target, GLuint index, GLint64* data) override {} +void glGetInteger64vFn(GLenum pname, GLint64* params) override {} +void glGetIntegeri_vFn(GLenum target, GLuint index, GLint* data) override {} +void glGetIntegervFn(GLenum pname, GLint* params) override {} +void glGetInternalformativFn(GLenum target, + GLenum internalformat, + GLenum pname, + GLsizei bufSize, + GLint* params) override {} +void glGetProgramBinaryFn(GLuint program, + GLsizei bufSize, + GLsizei* length, + GLenum* binaryFormat, + GLvoid* binary) override {} +void glGetProgramInfoLogFn(GLuint program, + GLsizei bufsize, + GLsizei* length, + char* infolog) override {} +void glGetProgramInterfaceivFn(GLuint program, + GLenum programInterface, + GLenum pname, + GLint* params) override {} +void glGetProgramivFn(GLuint program, GLenum pname, GLint* params) override {} +void glGetProgramResourceivFn(GLuint program, + GLenum programInterface, + GLuint index, + GLsizei propCount, + const GLenum* props, + GLsizei bufSize, + GLsizei* length, + GLint* params) override {} +GLint glGetProgramResourceLocationFn(GLuint program, + GLenum programInterface, + const char* name) override; +void glGetProgramResourceNameFn(GLuint program, + GLenum programInterface, + GLuint index, + GLsizei bufSize, + GLsizei* length, + GLchar* name) override {} +void glGetQueryivFn(GLenum target, GLenum pname, GLint* params) override {} +void glGetQueryObjecti64vFn(GLuint id, GLenum pname, GLint64* params) override { +} +void glGetQueryObjectivFn(GLuint id, GLenum pname, GLint* params) override {} +void glGetQueryObjectui64vFn(GLuint id, + GLenum pname, + GLuint64* params) override {} +void glGetQueryObjectuivFn(GLuint id, GLenum pname, GLuint* params) override {} +void glGetRenderbufferParameterivEXTFn(GLenum target, + GLenum pname, + GLint* params) override {} +void glGetSamplerParameterfvFn(GLuint sampler, + GLenum pname, + GLfloat* params) override {} +void glGetSamplerParameterivFn(GLuint sampler, + GLenum pname, + GLint* params) override {} +void glGetShaderInfoLogFn(GLuint shader, + GLsizei bufsize, + GLsizei* length, + char* infolog) override {} +void glGetShaderivFn(GLuint shader, GLenum pname, GLint* params) override {} +void glGetShaderPrecisionFormatFn(GLenum shadertype, + GLenum precisiontype, + GLint* range, + GLint* precision) override {} +void glGetShaderSourceFn(GLuint shader, + GLsizei bufsize, + GLsizei* length, + char* source) override {} +const GLubyte* glGetStringFn(GLenum name) override; +const GLubyte* glGetStringiFn(GLenum name, GLuint index) override; +void glGetSyncivFn(GLsync sync, + GLenum pname, + GLsizei bufSize, + GLsizei* length, + GLint* values) override {} +void glGetTexLevelParameterfvFn(GLenum target, + GLint level, + GLenum pname, + GLfloat* params) override {} +void glGetTexLevelParameterivFn(GLenum target, + GLint level, + GLenum pname, + GLint* params) override {} +void glGetTexParameterfvFn(GLenum target, + GLenum pname, + GLfloat* params) override {} +void glGetTexParameterivFn(GLenum target, + GLenum pname, + GLint* params) override {} +void glGetTransformFeedbackVaryingFn(GLuint program, + GLuint index, + GLsizei bufSize, + GLsizei* length, + GLsizei* size, + GLenum* type, + char* name) override {} +void glGetTranslatedShaderSourceANGLEFn(GLuint shader, + GLsizei bufsize, + GLsizei* length, + char* source) override {} +GLuint glGetUniformBlockIndexFn(GLuint program, + const char* uniformBlockName) override; +void glGetUniformfvFn(GLuint program, + GLint location, + GLfloat* params) override {} +void glGetUniformIndicesFn(GLuint program, + GLsizei uniformCount, + const char* const* uniformNames, + GLuint* uniformIndices) override {} +void glGetUniformivFn(GLuint program, GLint location, GLint* params) override {} +GLint glGetUniformLocationFn(GLuint program, const char* name) override; +void glGetUniformuivFn(GLuint program, + GLint location, + GLuint* params) override {} +void glGetVertexAttribfvFn(GLuint index, + GLenum pname, + GLfloat* params) override {} +void glGetVertexAttribivFn(GLuint index, GLenum pname, GLint* params) override { +} +void glGetVertexAttribPointervFn(GLuint index, + GLenum pname, + void** pointer) override {} +void glHintFn(GLenum target, GLenum mode) override {} +void glInsertEventMarkerEXTFn(GLsizei length, const char* marker) override {} +void glInvalidateFramebufferFn(GLenum target, + GLsizei numAttachments, + const GLenum* attachments) override {} +void glInvalidateSubFramebufferFn(GLenum target, + GLsizei numAttachments, + const GLenum* attachments, + GLint x, + GLint y, + GLint width, + GLint height) override {} +GLboolean glIsBufferFn(GLuint buffer) override; +GLboolean glIsEnabledFn(GLenum cap) override; +GLboolean glIsFenceAPPLEFn(GLuint fence) override; +GLboolean glIsFenceNVFn(GLuint fence) override; +GLboolean glIsFramebufferEXTFn(GLuint framebuffer) override; +GLboolean glIsPathNVFn(GLuint path) override; +GLboolean glIsProgramFn(GLuint program) override; +GLboolean glIsQueryFn(GLuint query) override; +GLboolean glIsRenderbufferEXTFn(GLuint renderbuffer) override; +GLboolean glIsSamplerFn(GLuint sampler) override; +GLboolean glIsShaderFn(GLuint shader) override; +GLboolean glIsSyncFn(GLsync sync) override; +GLboolean glIsTextureFn(GLuint texture) override; +GLboolean glIsTransformFeedbackFn(GLuint id) override; +GLboolean glIsVertexArrayOESFn(GLuint array) override; +void glLineWidthFn(GLfloat width) override {} +void glLinkProgramFn(GLuint program) override {} +void* glMapBufferFn(GLenum target, GLenum access) override; +void* glMapBufferRangeFn(GLenum target, + GLintptr offset, + GLsizeiptr length, + GLbitfield access) override; +void glMatrixLoadfEXTFn(GLenum matrixMode, const GLfloat* m) override {} +void glMatrixLoadIdentityEXTFn(GLenum matrixMode) override {} +void glMemoryBarrierEXTFn(GLbitfield barriers) override {} +void glPathCommandsNVFn(GLuint path, + GLsizei numCommands, + const GLubyte* commands, + GLsizei numCoords, + GLenum coordType, + const GLvoid* coords) override {} +void glPathParameterfNVFn(GLuint path, GLenum pname, GLfloat value) override {} +void glPathParameteriNVFn(GLuint path, GLenum pname, GLint value) override {} +void glPathStencilFuncNVFn(GLenum func, GLint ref, GLuint mask) override {} +void glPauseTransformFeedbackFn() override {} +void glPixelStoreiFn(GLenum pname, GLint param) override {} +void glPointParameteriFn(GLenum pname, GLint param) override {} +void glPolygonOffsetFn(GLfloat factor, GLfloat units) override {} +void glPopGroupMarkerEXTFn() override {} +void glPrimitiveRestartIndexFn(GLuint index) override {} +void glProgramBinaryFn(GLuint program, + GLenum binaryFormat, + const GLvoid* binary, + GLsizei length) override {} +void glProgramParameteriFn(GLuint program, GLenum pname, GLint value) override { +} +void glProgramPathFragmentInputGenNVFn(GLuint program, + GLint location, + GLenum genMode, + GLint components, + const GLfloat* coeffs) override {} +void glPushGroupMarkerEXTFn(GLsizei length, const char* marker) override {} +void glQueryCounterFn(GLuint id, GLenum target) override {} +void glReadBufferFn(GLenum src) override {} +void glReadPixelsFn(GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + void* pixels) override {} +void glReleaseShaderCompilerFn() override {} +void glRenderbufferStorageEXTFn(GLenum target, + GLenum internalformat, + GLsizei width, + GLsizei height) override {} +void glRenderbufferStorageMultisampleFn(GLenum target, + GLsizei samples, + GLenum internalformat, + GLsizei width, + GLsizei height) override {} +void glRenderbufferStorageMultisampleANGLEFn(GLenum target, + GLsizei samples, + GLenum internalformat, + GLsizei width, + GLsizei height) override {} +void glRenderbufferStorageMultisampleEXTFn(GLenum target, + GLsizei samples, + GLenum internalformat, + GLsizei width, + GLsizei height) override {} +void glRenderbufferStorageMultisampleIMGFn(GLenum target, + GLsizei samples, + GLenum internalformat, + GLsizei width, + GLsizei height) override {} +void glResumeTransformFeedbackFn() override {} +void glSampleCoverageFn(GLclampf value, GLboolean invert) override {} +void glSamplerParameterfFn(GLuint sampler, + GLenum pname, + GLfloat param) override {} +void glSamplerParameterfvFn(GLuint sampler, + GLenum pname, + const GLfloat* params) override {} +void glSamplerParameteriFn(GLuint sampler, GLenum pname, GLint param) override { +} +void glSamplerParameterivFn(GLuint sampler, + GLenum pname, + const GLint* params) override {} +void glScissorFn(GLint x, GLint y, GLsizei width, GLsizei height) override {} +void glSetFenceAPPLEFn(GLuint fence) override {} +void glSetFenceNVFn(GLuint fence, GLenum condition) override {} +void glShaderBinaryFn(GLsizei n, + const GLuint* shaders, + GLenum binaryformat, + const void* binary, + GLsizei length) override {} +void glShaderSourceFn(GLuint shader, + GLsizei count, + const char* const* str, + const GLint* length) override {} +void glStencilFillPathInstancedNVFn(GLsizei numPaths, + GLenum pathNameType, + const void* paths, + GLuint pathBase, + GLenum fillMode, + GLuint mask, + GLenum transformType, + const GLfloat* transformValues) override {} +void glStencilFillPathNVFn(GLuint path, GLenum fillMode, GLuint mask) override { +} +void glStencilFuncFn(GLenum func, GLint ref, GLuint mask) override {} +void glStencilFuncSeparateFn(GLenum face, + GLenum func, + GLint ref, + GLuint mask) override {} +void glStencilMaskFn(GLuint mask) override {} +void glStencilMaskSeparateFn(GLenum face, GLuint mask) override {} +void glStencilOpFn(GLenum fail, GLenum zfail, GLenum zpass) override {} +void glStencilOpSeparateFn(GLenum face, + GLenum fail, + GLenum zfail, + GLenum zpass) override {} +void glStencilStrokePathInstancedNVFn(GLsizei numPaths, + GLenum pathNameType, + const void* paths, + GLuint pathBase, + GLint ref, + GLuint mask, + GLenum transformType, + const GLfloat* transformValues) override { +} +void glStencilStrokePathNVFn(GLuint path, + GLint reference, + GLuint mask) override {} +void glStencilThenCoverFillPathInstancedNVFn( + GLsizei numPaths, + GLenum pathNameType, + const void* paths, + GLuint pathBase, + GLenum fillMode, + GLuint mask, + GLenum coverMode, + GLenum transformType, + const GLfloat* transformValues) override {} +void glStencilThenCoverFillPathNVFn(GLuint path, + GLenum fillMode, + GLuint mask, + GLenum coverMode) override {} +void glStencilThenCoverStrokePathInstancedNVFn( + GLsizei numPaths, + GLenum pathNameType, + const void* paths, + GLuint pathBase, + GLint ref, + GLuint mask, + GLenum coverMode, + GLenum transformType, + const GLfloat* transformValues) override {} +void glStencilThenCoverStrokePathNVFn(GLuint path, + GLint reference, + GLuint mask, + GLenum coverMode) override {} +GLboolean glTestFenceAPPLEFn(GLuint fence) override; +GLboolean glTestFenceNVFn(GLuint fence) override; +void glTexImage2DFn(GLenum target, + GLint level, + GLint internalformat, + GLsizei width, + GLsizei height, + GLint border, + GLenum format, + GLenum type, + const void* pixels) override {} +void glTexImage3DFn(GLenum target, + GLint level, + GLint internalformat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + const void* pixels) override {} +void glTexParameterfFn(GLenum target, GLenum pname, GLfloat param) override {} +void glTexParameterfvFn(GLenum target, + GLenum pname, + const GLfloat* params) override {} +void glTexParameteriFn(GLenum target, GLenum pname, GLint param) override {} +void glTexParameterivFn(GLenum target, + GLenum pname, + const GLint* params) override {} +void glTexStorage2DEXTFn(GLenum target, + GLsizei levels, + GLenum internalformat, + GLsizei width, + GLsizei height) override {} +void glTexStorage3DFn(GLenum target, + GLsizei levels, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLsizei depth) override {} +void glTexSubImage2DFn(GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + const void* pixels) override {} +void glTexSubImage3DFn(GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLsizei width, + GLsizei height, + GLsizei depth, + GLenum format, + GLenum type, + const void* pixels) override {} +void glTransformFeedbackVaryingsFn(GLuint program, + GLsizei count, + const char* const* varyings, + GLenum bufferMode) override {} +void glUniform1fFn(GLint location, GLfloat x) override {} +void glUniform1fvFn(GLint location, GLsizei count, const GLfloat* v) override {} +void glUniform1iFn(GLint location, GLint x) override {} +void glUniform1ivFn(GLint location, GLsizei count, const GLint* v) override {} +void glUniform1uiFn(GLint location, GLuint v0) override {} +void glUniform1uivFn(GLint location, GLsizei count, const GLuint* v) override {} +void glUniform2fFn(GLint location, GLfloat x, GLfloat y) override {} +void glUniform2fvFn(GLint location, GLsizei count, const GLfloat* v) override {} +void glUniform2iFn(GLint location, GLint x, GLint y) override {} +void glUniform2ivFn(GLint location, GLsizei count, const GLint* v) override {} +void glUniform2uiFn(GLint location, GLuint v0, GLuint v1) override {} +void glUniform2uivFn(GLint location, GLsizei count, const GLuint* v) override {} +void glUniform3fFn(GLint location, GLfloat x, GLfloat y, GLfloat z) override {} +void glUniform3fvFn(GLint location, GLsizei count, const GLfloat* v) override {} +void glUniform3iFn(GLint location, GLint x, GLint y, GLint z) override {} +void glUniform3ivFn(GLint location, GLsizei count, const GLint* v) override {} +void glUniform3uiFn(GLint location, GLuint v0, GLuint v1, GLuint v2) override {} +void glUniform3uivFn(GLint location, GLsizei count, const GLuint* v) override {} +void glUniform4fFn(GLint location, + GLfloat x, + GLfloat y, + GLfloat z, + GLfloat w) override {} +void glUniform4fvFn(GLint location, GLsizei count, const GLfloat* v) override {} +void glUniform4iFn(GLint location, + GLint x, + GLint y, + GLint z, + GLint w) override {} +void glUniform4ivFn(GLint location, GLsizei count, const GLint* v) override {} +void glUniform4uiFn(GLint location, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) override {} +void glUniform4uivFn(GLint location, GLsizei count, const GLuint* v) override {} +void glUniformBlockBindingFn(GLuint program, + GLuint uniformBlockIndex, + GLuint uniformBlockBinding) override {} +void glUniformMatrix2fvFn(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value) override {} +void glUniformMatrix2x3fvFn(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value) override {} +void glUniformMatrix2x4fvFn(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value) override {} +void glUniformMatrix3fvFn(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value) override {} +void glUniformMatrix3x2fvFn(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value) override {} +void glUniformMatrix3x4fvFn(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value) override {} +void glUniformMatrix4fvFn(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value) override {} +void glUniformMatrix4x2fvFn(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value) override {} +void glUniformMatrix4x3fvFn(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat* value) override {} +GLboolean glUnmapBufferFn(GLenum target) override; +void glUseProgramFn(GLuint program) override {} +void glValidateProgramFn(GLuint program) override {} +void glVertexAttrib1fFn(GLuint indx, GLfloat x) override {} +void glVertexAttrib1fvFn(GLuint indx, const GLfloat* values) override {} +void glVertexAttrib2fFn(GLuint indx, GLfloat x, GLfloat y) override {} +void glVertexAttrib2fvFn(GLuint indx, const GLfloat* values) override {} +void glVertexAttrib3fFn(GLuint indx, GLfloat x, GLfloat y, GLfloat z) override { +} +void glVertexAttrib3fvFn(GLuint indx, const GLfloat* values) override {} +void glVertexAttrib4fFn(GLuint indx, + GLfloat x, + GLfloat y, + GLfloat z, + GLfloat w) override {} +void glVertexAttrib4fvFn(GLuint indx, const GLfloat* values) override {} +void glVertexAttribDivisorANGLEFn(GLuint index, GLuint divisor) override {} +void glVertexAttribI4iFn(GLuint indx, + GLint x, + GLint y, + GLint z, + GLint w) override {} +void glVertexAttribI4ivFn(GLuint indx, const GLint* values) override {} +void glVertexAttribI4uiFn(GLuint indx, + GLuint x, + GLuint y, + GLuint z, + GLuint w) override {} +void glVertexAttribI4uivFn(GLuint indx, const GLuint* values) override {} +void glVertexAttribIPointerFn(GLuint indx, + GLint size, + GLenum type, + GLsizei stride, + const void* ptr) override {} +void glVertexAttribPointerFn(GLuint indx, + GLint size, + GLenum type, + GLboolean normalized, + GLsizei stride, + const void* ptr) override {} +void glViewportFn(GLint x, GLint y, GLsizei width, GLsizei height) override {} +GLenum glWaitSyncFn(GLsync sync, GLbitfield flags, GLuint64 timeout) override;
diff --git a/ui/message_center/message_center_impl.cc b/ui/message_center/message_center_impl.cc index 22243fa2..9b5ffb9c 100644 --- a/ui/message_center/message_center_impl.cc +++ b/ui/message_center/message_center_impl.cc
@@ -343,7 +343,7 @@ void MessageCenterImpl::NotificationCache::RecountUnread() { unread_count = 0; - for (const auto& notification : visible_notifications) { + for (auto* notification : visible_notifications) { if (!notification->IsRead()) ++unread_count; } @@ -641,7 +641,7 @@ const NotifierId& notifier_id) { NotificationList::Notifications notifications = notification_list_->GetNotificationsByNotifierId(notifier_id); - for (const auto& notification : notifications) + for (auto* notification : notifications) RemoveNotification(notification->id(), false); if (!notifications.empty()) { notification_cache_.Rebuild( @@ -659,7 +659,7 @@ const NotificationList::Notifications notifications = notification_list_->GetVisibleNotifications(blockers); std::set<std::string> ids; - for (const auto& notification : notifications) { + for (auto* notification : notifications) { if (!remove_pinned && notification->pinned()) continue;
diff --git a/ui/message_center/message_center_style.h b/ui/message_center/message_center_style.h index ab2965d..602ff6bc 100644 --- a/ui/message_center/message_center_style.h +++ b/ui/message_center/message_center_style.h
@@ -91,7 +91,7 @@ // Foreground of small icon image. const SkColor kSmallImageMaskForegroundColor = SK_ColorWHITE; // Background of small icon image. -const SkColor kSmallImageMaskBackgroundColor = SkColorSetRGB(0xa3, 0xa3, 0xa); +const SkColor kSmallImageMaskBackgroundColor = SkColorSetRGB(0xa3, 0xa3, 0xa3); // Limits.
diff --git a/ui/message_center/message_center_tray.cc b/ui/message_center/message_center_tray.cc index ffafe5d..246054e 100644 --- a/ui/message_center/message_center_tray.cc +++ b/ui/message_center/message_center_tray.cc
@@ -41,7 +41,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; private: @@ -83,7 +83,7 @@ bool NotificationMenuModel::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; }
diff --git a/ui/message_center/notification_list_unittest.cc b/ui/message_center/notification_list_unittest.cc index aad9154be..9daa1031 100644 --- a/ui/message_center/notification_list_unittest.cc +++ b/ui/message_center/notification_list_unittest.cc
@@ -295,8 +295,8 @@ } popups.clear(); popups = GetPopups(); - EXPECT_EQ(1u, popups.size()); - EXPECT_EQ(ids[ids.size() - 1], (*popups.begin())->id()); + ASSERT_EQ(1u, popups.size()); + EXPECT_EQ(ids.back(), (*popups.begin())->id()); } TEST_F(NotificationListTest, Priority) {
diff --git a/ui/message_center/popup_timers_controller.cc b/ui/message_center/popup_timers_controller.cc index 2da3e270..c50d7e6 100644 --- a/ui/message_center/popup_timers_controller.cc +++ b/ui/message_center/popup_timers_controller.cc
@@ -96,7 +96,7 @@ NotificationList::PopupNotifications popup_notifications = message_center_->GetPopupNotifications(); - if (!popup_notifications.size()) { + if (popup_notifications.empty()) { CancelAll(); return; }
diff --git a/ui/message_center/views/desktop_popup_alignment_delegate.cc b/ui/message_center/views/desktop_popup_alignment_delegate.cc index 27a2aed7..a6c0e53 100644 --- a/ui/message_center/views/desktop_popup_alignment_delegate.cc +++ b/ui/message_center/views/desktop_popup_alignment_delegate.cc
@@ -14,7 +14,7 @@ DesktopPopupAlignmentDelegate::DesktopPopupAlignmentDelegate() : alignment_(POPUP_ALIGNMENT_BOTTOM | POPUP_ALIGNMENT_RIGHT), - display_id_(display::Display::kInvalidDisplayID), + primary_display_id_(display::Display::kInvalidDisplayID), screen_(NULL) {} DesktopPopupAlignmentDelegate::~DesktopPopupAlignmentDelegate() { @@ -29,7 +29,7 @@ screen_ = screen; screen_->AddObserver(this); display::Display display = screen_->GetPrimaryDisplay(); - display_id_ = display.id(); + primary_display_id_ = display.id(); RecomputeAlignment(display); } @@ -89,19 +89,40 @@ // Do nothing, which will use the default container. } +// Anytime the display configuration changes, we need to recompute the alignment +// on the primary display. But, we get different events on different platforms. +// On Windows, for example, when switching from a laptop display to an external +// monitor, we get a OnDisplayMetricsChanged() event. On Linux, we get a +// OnDisplayRemoved() and a OnDisplayAdded() instead. In order to account for +// these slightly different abstractions, we update on every event. +void DesktopPopupAlignmentDelegate::UpdatePrimaryDisplay() { + display::Display primary_display = screen_->GetPrimaryDisplay(); + if (primary_display.id() != primary_display_id_) { + primary_display_id_ = primary_display.id(); + RecomputeAlignment(primary_display); + DoUpdateIfPossible(); + } +} + void DesktopPopupAlignmentDelegate::OnDisplayAdded( - const display::Display& new_display) {} + const display::Display& added_display) { + // The added display could be the new primary display. + UpdatePrimaryDisplay(); +} void DesktopPopupAlignmentDelegate::OnDisplayRemoved( - const display::Display& old_display) {} + const display::Display& removed_display) { + // The removed display may have been the primary display. + UpdatePrimaryDisplay(); +} void DesktopPopupAlignmentDelegate::OnDisplayMetricsChanged( const display::Display& display, uint32_t metrics) { - if (display.id() == display_id_) { - RecomputeAlignment(display); - DoUpdateIfPossible(); - } + // Set to kInvalidDisplayID so the alignment is updated regardless of whether + // the primary display actually changed. + primary_display_id_ = display::Display::kInvalidDisplayID; + UpdatePrimaryDisplay(); } } // namespace message_center
diff --git a/ui/message_center/views/desktop_popup_alignment_delegate.h b/ui/message_center/views/desktop_popup_alignment_delegate.h index aa919db..00807dc5 100644 --- a/ui/message_center/views/desktop_popup_alignment_delegate.h +++ b/ui/message_center/views/desktop_popup_alignment_delegate.h
@@ -52,6 +52,8 @@ POPUP_ALIGNMENT_RIGHT = 1 << 3, }; + void UpdatePrimaryDisplay(); + // Overridden from display::DisplayObserver: void OnDisplayAdded(const display::Display& new_display) override; void OnDisplayRemoved(const display::Display& old_display) override; @@ -59,7 +61,7 @@ uint32_t metrics) override; int32_t alignment_; - int64_t display_id_; + int64_t primary_display_id_; display::Screen* screen_; gfx::Rect work_area_;
diff --git a/ui/message_center/views/message_center_bubble.cc b/ui/message_center/views/message_center_bubble.cc index c65587b..8b1b7705 100644 --- a/ui/message_center/views/message_center_bubble.cc +++ b/ui/message_center/views/message_center_bubble.cc
@@ -107,10 +107,15 @@ // |new_bubble_view| actually wants. See crbug.com/169390. bubble_view()->Layout(); UpdateBubbleView(); - bubble_view() - ->GetFocusManager() - ->GetNextFocusableView(nullptr, nullptr, false, false) - ->RequestFocus(); + views::FocusManager* focus_manager = bubble_view()->GetFocusManager(); + // new_bubble_view should be a top level view and have a focus manager. + DCHECK(focus_manager); + views::View* next_focusable_view = focus_manager + ->GetNextFocusableView(nullptr, nullptr, false, false); + // The bubble may not have any focusable view (eg. on lock screen). In such + // case, |next_focusable_view| is null. + if (next_focusable_view) + next_focusable_view->RequestFocus(); } void MessageCenterBubble::OnBubbleViewDestroyed() {
diff --git a/ui/message_center/views/notification_view.cc b/ui/message_center/views/notification_view.cc index 4e6246c6..b37c8a9 100644 --- a/ui/message_center/views/notification_view.cc +++ b/ui/message_center/views/notification_view.cc
@@ -95,7 +95,7 @@ // message next to each other within a single column. class ItemView : public views::View { public: - ItemView(const message_center::NotificationItem& item); + explicit ItemView(const message_center::NotificationItem& item); ~ItemView() override; // Overridden from views::View: @@ -435,7 +435,7 @@ message_view_->SetText(text); } - message_view_->SetVisible(!notification.items().size()); + message_view_->SetVisible(notification.items().empty()); } base::string16 NotificationView::FormatContextMessage( @@ -545,7 +545,7 @@ if (!is_indeterminate) progress_bar_view_->SetValue(notification.progress() / 100.0); - progress_bar_view_->SetVisible(!notification.items().size()); + progress_bar_view_->SetVisible(notification.items().empty()); } void NotificationView::CreateOrUpdateListItemViews(
diff --git a/ui/message_center/views/notification_view_unittest.cc b/ui/message_center/views/notification_view_unittest.cc index fd23617..cbf4bac7 100644 --- a/ui/message_center/views/notification_view_unittest.cc +++ b/ui/message_center/views/notification_view_unittest.cc
@@ -7,6 +7,7 @@ #include <memory> #include "base/macros.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -641,10 +642,12 @@ // The url has been elided (it starts with an ellipsis) // The end of the domainsuffix is shown // the url piece is not shown - EXPECT_TRUE(base::UTF16ToUTF8(result).find( - ".veryveryveyrylong.chromium.org") != std::string::npos); - EXPECT_TRUE(base::UTF16ToUTF8(result).find("\xE2\x80\xA6") == 0); - EXPECT_TRUE(base::UTF16ToUTF8(result).find("hello") == std::string::npos); + std::string result_utf8 = base::UTF16ToUTF8(result); + EXPECT_TRUE(result_utf8.find(".veryveryveyrylong.chromium.org") != + std::string::npos); + EXPECT_TRUE(base::StartsWith(result_utf8, "\xE2\x80\xA6", + base::CompareCase::SENSITIVE)); + EXPECT_TRUE(result_utf8.find("hello") == std::string::npos); } TEST_F(NotificationViewTest, SlideOut) {
diff --git a/ui/message_center/views/notifier_settings_view.cc b/ui/message_center/views/notifier_settings_view.cc index 2d6e15d..2f5afe2 100644 --- a/ui/message_center/views/notifier_settings_view.cc +++ b/ui/message_center/views/notifier_settings_view.cc
@@ -218,7 +218,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; private: @@ -257,7 +257,7 @@ bool NotifierGroupMenuModel::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; }
diff --git a/ui/ozone/platform/drm/gpu/drm_device.cc b/ui/ozone/platform/drm/gpu/drm_device.cc index c017f207c..462ec64 100644 --- a/ui/ozone/platform/drm/gpu/drm_device.cc +++ b/ui/ozone/platform/drm/gpu/drm_device.cc
@@ -278,7 +278,7 @@ (lut_in[base_index + 1].b - lut_in[base_index].b) * remaining / desired_size; } else { - result[i] = lut_in[lut_in.size() - 1]; + result[i] = lut_in.back(); } } @@ -304,8 +304,7 @@ } DrmDevice::PageFlipCallback callback = it->callback; - it->pending_calls -= 1; - + it->pending_calls--; if (it->pending_calls) return; @@ -329,11 +328,11 @@ }; struct FindCallback { - FindCallback(uint64_t id) : id(id) {} + explicit FindCallback(uint64_t id) : id(id) {} bool operator()(const PageFlip& flip) const { return flip.id == id; } - uint64_t id; + const uint64_t id; }; uint64_t next_id_;
diff --git a/ui/strings/ui_strings.grd b/ui/strings/ui_strings.grd index 83cb365..c4587b3 100644 --- a/ui/strings/ui_strings.grd +++ b/ui/strings/ui_strings.grd
@@ -591,15 +591,15 @@ <message name="IDS_MESSAGE_CENTER_NOTIFIER_HATS_NAME" desc="The name of hats notifier that is a system component"> Hats </message> + <message name="IDS_MESSAGE_CENTER_NOTIFIER_QUICK_UNLOCK_FEATURE_NAME" desc="The name of quick unlock feature notifier that is a system component"> + Quick Unlock Feature + </message> </if> <!-- App list --> <message name="IDS_APP_LIST_HELP" desc="The menu entry to show the app list help UI."> Help </message> - <message name="IDS_APP_LIST_OPEN_SETTINGS" desc="The menu entry to show the settings UI."> - Settings - </message> <message name="IDS_APP_LIST_OPEN_FEEDBACK" desc="The menu entry to show the feedback UI."> Send feedback </message>
diff --git a/ui/views/controls/button/label_button.cc b/ui/views/controls/button/label_button.cc index 0618cca6..53b9247 100644 --- a/ui/views/controls/button/label_button.cc +++ b/ui/views/controls/button/label_button.cc
@@ -541,6 +541,7 @@ void LabelButton::ChildPreferredSizeChanged(View* child) { ResetCachedPreferredSize(); PreferredSizeChanged(); + Layout(); } ui::NativeTheme::Part LabelButton::GetThemePart() const {
diff --git a/ui/views/controls/button/label_button_unittest.cc b/ui/views/controls/button/label_button_unittest.cc index 5c94c30..702ed68 100644 --- a/ui/views/controls/button/label_button_unittest.cc +++ b/ui/views/controls/button/label_button_unittest.cc
@@ -311,16 +311,29 @@ const base::string16 text(ASCIIToUTF16("abc")); const base::string16 longer_text(ASCIIToUTF16("abcdefghijklm")); button_->SetText(text); - + button_->SizeToPreferredSize(); + gfx::Rect bounds(button_->bounds()); const int original_width = button_->GetPreferredSize().width(); + EXPECT_EQ(original_width, bounds.width()); - // The button size increases when the text size is increased. + // Reserve more space in the button. + bounds.set_width(bounds.width() * 10); + button_->SetBoundsRect(bounds); + + // Label view in the button is sized to short text. + const int original_label_width = button_->label()->bounds().width(); + + // The button preferred size and the label size increase when the text size + // is increased. button_->SetText(longer_text); - EXPECT_GT(button_->GetPreferredSize().width(), original_width); + EXPECT_GT(button_->label()->bounds().width(), original_label_width * 2); + EXPECT_GT(button_->GetPreferredSize().width(), original_width * 2); - // The button returns to its original size when the original text is restored. + // The button and the label view return to its original size when the original + // text is restored. button_->SetMinSize(gfx::Size()); button_->SetText(text); + EXPECT_EQ(original_label_width, button_->label()->bounds().width()); EXPECT_EQ(original_width, button_->GetPreferredSize().width()); }
diff --git a/ui/views/controls/menu/menu_runner_cocoa_unittest.mm b/ui/views/controls/menu/menu_runner_cocoa_unittest.mm index 09449d2..b9a6656 100644 --- a/ui/views/controls/menu/menu_runner_cocoa_unittest.mm +++ b/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
@@ -35,8 +35,9 @@ return command_id == model_->checked_command_; } bool IsCommandIdEnabled(int command_id) const override { return true; } - bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override { + bool GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const override { return false; } void ExecuteCommand(int command_id, int event_flags) override {}
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc index fa1025e..381fef4 100644 --- a/ui/views/controls/textfield/textfield.cc +++ b/ui/views/controls/textfield/textfield.cc
@@ -1179,7 +1179,7 @@ } bool Textfield::GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { switch (command_id) { case IDS_APP_UNDO: *accelerator = ui::Accelerator(ui::VKEY_Z, ui::EF_CONTROL_DOWN);
diff --git a/ui/views/controls/textfield/textfield.h b/ui/views/controls/textfield/textfield.h index ac1f0cf..54391a38 100644 --- a/ui/views/controls/textfield/textfield.h +++ b/ui/views/controls/textfield/textfield.h
@@ -272,7 +272,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; // ui::TextInputClient overrides:
diff --git a/ui/views/controls/textfield/textfield_model.cc b/ui/views/controls/textfield/textfield_model.cc index 297ea19..7c6d5917 100644 --- a/ui/views/controls/textfield/textfield_model.cc +++ b/ui/views/controls/textfield/textfield_model.cc
@@ -441,7 +441,7 @@ } bool TextfieldModel::CanRedo() { - if (!edit_history_.size()) + if (edit_history_.empty()) return false; // There is no redo iff the current edit is the last element in the history. EditHistory::iterator iter = current_edit_; @@ -464,7 +464,7 @@ if (current_edit_ == edit_history_.begin()) current_edit_ = edit_history_.end(); else - current_edit_--; + --current_edit_; return old != text() || old_cursor != GetCursorPosition(); } @@ -478,7 +478,7 @@ if (current_edit_ == edit_history_.end()) current_edit_ = edit_history_.begin(); else - current_edit_ ++; + ++current_edit_; base::string16 old = text(); size_t old_cursor = GetCursorPosition(); (*current_edit_)->Redo(this); @@ -716,7 +716,7 @@ return; } EditHistory::iterator delete_start = current_edit_; - delete_start++; + ++delete_start; STLDeleteContainerPointers(delete_start, edit_history_.end()); edit_history_.erase(delete_start, edit_history_.end()); } @@ -789,7 +789,7 @@ DCHECK_EQ(1u, edit_history_.size()); current_edit_ = edit_history_.begin(); } else { - current_edit_++; + ++current_edit_; } return false; }
diff --git a/ui/views/examples/menu_example.cc b/ui/views/examples/menu_example.cc index 378c90a..8f86c61 100644 --- a/ui/views/examples/menu_example.cc +++ b/ui/views/examples/menu_example.cc
@@ -32,7 +32,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; private: @@ -121,7 +121,7 @@ bool ExampleMenuModel::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { // We don't use this in the example. return false; }
diff --git a/ui/views/examples/tree_view_example.cc b/ui/views/examples/tree_view_example.cc index 68f99e2..35a812c 100644 --- a/ui/views/examples/tree_view_example.cc +++ b/ui/views/examples/tree_view_example.cc
@@ -155,7 +155,7 @@ bool TreeViewExample::GetAcceleratorForCommandId( int command_id, - ui::Accelerator* accelerator) { + ui::Accelerator* accelerator) const { return false; }
diff --git a/ui/views/examples/tree_view_example.h b/ui/views/examples/tree_view_example.h index fb0ccf93..bbdc02f0 100644 --- a/ui/views/examples/tree_view_example.h +++ b/ui/views/examples/tree_view_example.h
@@ -64,7 +64,7 @@ bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override; + ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; // The tree view to be tested.
diff --git a/ui/views/layout/grid_layout.cc b/ui/views/layout/grid_layout.cc index c79b600f..438d376 100644 --- a/ui/views/layout/grid_layout.cc +++ b/ui/views/layout/grid_layout.cc
@@ -937,8 +937,8 @@ LayoutElement::CalculateLocationsFromSize(&rows_); // We now know the preferred height, set it here. - pref->set_height(rows_[rows_.size() - 1]->Location() + - rows_[rows_.size() - 1]->Size() + insets_.height()); + pref->set_height(rows_.back()->Location() + rows_.back()->Size() + + insets_.height()); if (layout && height != pref->height()) { // We're doing a layout, and the height differs from the preferred height,
diff --git a/ui/views/mus/native_widget_mus.cc b/ui/views/mus/native_widget_mus.cc index b80998e95..979f879 100644 --- a/ui/views/mus/native_widget_mus.cc +++ b/ui/views/mus/native_widget_mus.cc
@@ -693,6 +693,7 @@ ownership_ = params.ownership; window_->SetCanFocus(params.activatable == Widget::InitParams::ACTIVATABLE_YES); + window_->SetCanAcceptEvents(params.accept_events); window_tree_host_->AddObserver(this); window_tree_host_->InitHost();
diff --git a/ui/views/mus/window_manager_connection.cc b/ui/views/mus/window_manager_connection.cc index 3936c25..bbefa730 100644 --- a/ui/views/mus/window_manager_connection.cc +++ b/ui/views/mus/window_manager_connection.cc
@@ -21,6 +21,7 @@ #include "ui/views/mus/native_widget_mus.h" #include "ui/views/mus/screen_mus.h" #include "ui/views/pointer_watcher.h" +#include "ui/views/touch_event_watcher.h" #include "ui/views/views_delegate.h" namespace views { @@ -81,6 +82,8 @@ } void WindowManagerConnection::AddPointerWatcher(PointerWatcher* watcher) { + // TODO(riajiang): Support multiple event matchers (crbug.com/627146). + DCHECK(!HasTouchEventWatcher()); bool had_watcher = HasPointerWatcher(); pointer_watchers_.AddObserver(watcher); if (!had_watcher) { @@ -101,6 +104,28 @@ } } +void WindowManagerConnection::AddTouchEventWatcher(TouchEventWatcher* watcher) { + // TODO(riajiang): Support multiple event matchers (crbug.com/627146). + DCHECK(!HasPointerWatcher()); + bool had_watcher = HasTouchEventWatcher(); + touch_event_watchers_.AddObserver(watcher); + if (!had_watcher) { + ui::mojom::EventMatcherPtr matcher = ui::mojom::EventMatcher::New(); + matcher->pointer_kind_matcher = ui::mojom::PointerKindMatcher::New(); + matcher->pointer_kind_matcher->pointer_kind = ui::mojom::PointerKind::TOUCH; + client_->SetEventObserver(std::move(matcher)); + } +} + +void WindowManagerConnection::RemoveTouchEventWatcher( + TouchEventWatcher* watcher) { + touch_event_watchers_.RemoveObserver(watcher); + if (!HasTouchEventWatcher()) { + // Last TouchEventWatcher removed, stop the event observer. + client_->SetEventObserver(nullptr); + } +} + const std::set<ui::Window*>& WindowManagerConnection::GetRoots() const { return client_->GetRoots(); } @@ -151,6 +176,15 @@ return !!iterator.GetNext(); } +bool WindowManagerConnection::HasTouchEventWatcher() { + // Check to see if we really have any observers left. This doesn't use + // base::ObserverList<>::might_have_observers() because that returns true + // during iteration over the list even when the last observer is removed. + base::ObserverList<TouchEventWatcher>::Iterator iterator( + &touch_event_watchers_); + return !!iterator.GetNext(); +} + void WindowManagerConnection::OnEmbed(ui::Window* root) {} void WindowManagerConnection::OnDidDestroyClient(ui::WindowTreeClient* client) { @@ -175,14 +209,22 @@ // to store screen coordinates. Screen coordinates really should be returned // separately. See http://crbug.com/608547 gfx::Point location_in_screen = event.AsLocatedEvent()->root_location(); - if (event.type() == ui::ET_MOUSE_PRESSED) { - FOR_EACH_OBSERVER(PointerWatcher, pointer_watchers_, - OnMousePressed(*event.AsMouseEvent(), location_in_screen, - target_widget)); - } else if (event.type() == ui::ET_TOUCH_PRESSED) { - FOR_EACH_OBSERVER(PointerWatcher, pointer_watchers_, - OnTouchPressed(*event.AsTouchEvent(), location_in_screen, - target_widget)); + if (HasPointerWatcher()) { + if (event.type() == ui::ET_MOUSE_PRESSED) { + FOR_EACH_OBSERVER(PointerWatcher, pointer_watchers_, + OnMousePressed(*event.AsMouseEvent(), + location_in_screen, target_widget)); + } else if (event.type() == ui::ET_TOUCH_PRESSED) { + FOR_EACH_OBSERVER(PointerWatcher, pointer_watchers_, + OnTouchPressed(*event.AsTouchEvent(), + location_in_screen, target_widget)); + } + } else if (HasTouchEventWatcher()) { + if (event.IsTouchEvent() || event.IsTouchPointerEvent()) { + FOR_EACH_OBSERVER( + TouchEventWatcher, touch_event_watchers_, + OnTouchEventObserved(*event.AsLocatedEvent(), target_widget)); + } } }
diff --git a/ui/views/mus/window_manager_connection.h b/ui/views/mus/window_manager_connection.h index be8338a248..ea9619e 100644 --- a/ui/views/mus/window_manager_connection.h +++ b/ui/views/mus/window_manager_connection.h
@@ -28,6 +28,7 @@ class ClipboardMus; class NativeWidget; class PointerWatcher; +class TouchEventWatcher; class ScreenMus; namespace internal { class NativeWidgetDelegate; @@ -67,6 +68,9 @@ void AddPointerWatcher(PointerWatcher* watcher); void RemovePointerWatcher(PointerWatcher* watcher); + void AddTouchEventWatcher(TouchEventWatcher* watcher); + void RemoveTouchEventWatcher(TouchEventWatcher* watcher); + const std::set<ui::Window*>& GetRoots() const; private: @@ -75,8 +79,9 @@ WindowManagerConnection(shell::Connector* connector, const shell::Identity& identity); - // Returns true if there is one or more pointer watchers for this client. + // Returns true if there is one or more watchers for this client. bool HasPointerWatcher(); + bool HasTouchEventWatcher(); // ui::WindowTreeClientDelegate: void OnEmbed(ui::Window* root) override; @@ -93,6 +98,7 @@ std::unique_ptr<ui::WindowTreeClient> client_; // Must be empty on destruction. base::ObserverList<PointerWatcher, true> pointer_watchers_; + base::ObserverList<TouchEventWatcher, true> touch_event_watchers_; DISALLOW_COPY_AND_ASSIGN(WindowManagerConnection); };
diff --git a/ui/views/mus/window_manager_connection_unittest.cc b/ui/views/mus/window_manager_connection_unittest.cc index 967b5ad8..e84d9ea 100644 --- a/ui/views/mus/window_manager_connection_unittest.cc +++ b/ui/views/mus/window_manager_connection_unittest.cc
@@ -11,6 +11,7 @@ #include "ui/events/event.h" #include "ui/views/pointer_watcher.h" #include "ui/views/test/scoped_views_test_helper.h" +#include "ui/views/touch_event_watcher.h" namespace views { namespace { @@ -49,6 +50,31 @@ } // namespace +namespace { + +class TestTouchEventWatcher : public TouchEventWatcher { + public: + TestTouchEventWatcher() {} + ~TestTouchEventWatcher() override {} + + bool touch_observed() const { return touch_observed_; } + + void Reset() { touch_observed_ = false; } + + // TouchEventWatcher: + void OnTouchEventObserved(const ui::LocatedEvent& event, + Widget* target) override { + touch_observed_ = true; + } + + private: + bool touch_observed_ = false; + + DISALLOW_COPY_AND_ASSIGN(TestTouchEventWatcher); +}; + +} // namespace + class WindowManagerConnectionTest : public testing::Test { public: WindowManagerConnectionTest() {} @@ -115,4 +141,74 @@ EXPECT_FALSE(watcher1.touch_pressed()); } +TEST_F(WindowManagerConnectionTest, TouchEventWatcher) { + base::MessageLoop message_loop(base::MessageLoop::TYPE_UI); + ScopedViewsTestHelper helper; + WindowManagerConnection* connection = WindowManagerConnection::Get(); + ASSERT_TRUE(connection); + + const ui::EventType kMouseType[] = { + ui::ET_MOUSE_PRESSED, ui::ET_MOUSE_DRAGGED, ui::ET_MOUSE_MOVED, + ui::ET_MOUSE_ENTERED, ui::ET_MOUSE_EXITED, ui::ET_MOUSE_RELEASED}; + const ui::EventType kTouchType[] = {ui::ET_TOUCH_PRESSED, ui::ET_TOUCH_MOVED, + ui::ET_TOUCH_RELEASED, + ui::ET_TOUCH_CANCELLED}; + + TestTouchEventWatcher watcher1; + connection->AddTouchEventWatcher(&watcher1); + + // TouchEventWatchers do not trigger for mouse events. + for (size_t i = 0; i < arraysize(kMouseType); i++) { + ui::MouseEvent mouse_event(kMouseType[i], gfx::Point(), gfx::Point(), + base::TimeTicks(), 0, 0); + ui::PointerEvent mouse_pointer_event(mouse_event); + EXPECT_TRUE(mouse_pointer_event.IsMousePointerEvent()); + OnEventObserved(mouse_pointer_event); + EXPECT_FALSE(watcher1.touch_observed()); + watcher1.Reset(); + } + + // TouchEventWatchers receive both TouchEvent and TouchPointerEvent. + for (size_t i = 0; i < arraysize(kTouchType); i++) { + ui::TouchEvent touch_event(kTouchType[i], gfx::Point(), 0, + base::TimeTicks()); + EXPECT_TRUE(touch_event.IsTouchEvent()); + OnEventObserved(touch_event); + EXPECT_TRUE(watcher1.touch_observed()); + watcher1.Reset(); + + ui::PointerEvent touch_pointer_event(touch_event); + EXPECT_TRUE(touch_pointer_event.IsTouchPointerEvent()); + OnEventObserved(touch_pointer_event); + EXPECT_TRUE(watcher1.touch_observed()); + watcher1.Reset(); + } + + // Two TouchEventWatchers can both receive a single observed event. + TestTouchEventWatcher watcher2; + connection->AddTouchEventWatcher(&watcher2); + ui::TouchEvent touch_event(ui::ET_TOUCH_PRESSED, gfx::Point(), 0, + base::TimeTicks()); + ui::PointerEvent touch_pointer_event(touch_event); + OnEventObserved(touch_pointer_event); + EXPECT_TRUE(watcher1.touch_observed()); + EXPECT_TRUE(watcher2.touch_observed()); + watcher1.Reset(); + watcher2.Reset(); + + // Removing the first TouchEventWatcher stops sending events to it. + connection->RemoveTouchEventWatcher(&watcher1); + OnEventObserved(touch_pointer_event); + EXPECT_FALSE(watcher1.touch_observed()); + EXPECT_TRUE(watcher2.touch_observed()); + watcher1.Reset(); + watcher2.Reset(); + + // Removing the last TouchEventWatcher stops sending events to it. + connection->RemoveTouchEventWatcher(&watcher2); + OnEventObserved(touch_pointer_event); + EXPECT_FALSE(watcher1.touch_observed()); + EXPECT_FALSE(watcher2.touch_observed()); +} + } // namespace views
diff --git a/ui/views/pointer_watcher.h b/ui/views/pointer_watcher.h index 2abc4cb4..5ca10ef 100644 --- a/ui/views/pointer_watcher.h +++ b/ui/views/pointer_watcher.h
@@ -5,6 +5,7 @@ #ifndef UI_VIEWS_POINTER_WATCHER_H_ #define UI_VIEWS_POINTER_WATCHER_H_ +#include "base/macros.h" #include "ui/views/views_export.h" namespace gfx { @@ -27,14 +28,19 @@ // event.target() is always null. class VIEWS_EXPORT PointerWatcher { public: - virtual ~PointerWatcher() {} - + PointerWatcher() {} virtual void OnMousePressed(const ui::MouseEvent& event, const gfx::Point& location_in_screen, Widget* target) = 0; virtual void OnTouchPressed(const ui::TouchEvent& event, const gfx::Point& location_in_screen, Widget* target) = 0; + + protected: + virtual ~PointerWatcher() {} + + private: + DISALLOW_COPY_AND_ASSIGN(PointerWatcher); }; } // namespace views
diff --git a/ui/views/touch_event_watcher.h b/ui/views/touch_event_watcher.h new file mode 100644 index 0000000..e1647de --- /dev/null +++ b/ui/views/touch_event_watcher.h
@@ -0,0 +1,43 @@ +// 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 UI_VIEWS_TOUCH_EVENT_WATCHER_H_ +#define UI_VIEWS_TOUCH_EVENT_WATCHER_H_ + +#include "base/macros.h" +#include "ui/views/views_export.h" + +namespace gfx { +class Point; +} + +namespace ui { +class LocatedEvent; +} + +namespace views { +class Widget; + +// An interface for read-only observation of touch events (in particular, the +// events cannot be marked as handled). Only touch pointer kind are supported. +// The |target| is the top-level widget that will receive the event, if any. +// NOTE: On mus this allows observation of events outside of windows owned +// by the current process, in which case the |target| will be null. On mus +// event.target() is always null. +class VIEWS_EXPORT TouchEventWatcher { + public: + TouchEventWatcher() {} + virtual void OnTouchEventObserved(const ui::LocatedEvent& event, + Widget* target) = 0; + + protected: + virtual ~TouchEventWatcher() {} + + private: + DISALLOW_COPY_AND_ASSIGN(TouchEventWatcher); +}; + +} // namespace views + +#endif // UI_VIEWS_TOUCH_EVENT_WATCHER_H_
diff --git a/ui/views/touchui/touch_selection_controller_impl_unittest.cc b/ui/views/touchui/touch_selection_controller_impl_unittest.cc index b1a5e36..68cb780 100644 --- a/ui/views/touchui/touch_selection_controller_impl_unittest.cc +++ b/ui/views/touchui/touch_selection_controller_impl_unittest.cc
@@ -688,7 +688,7 @@ return false; } bool GetAcceleratorForCommandId(int command_id, - ui::Accelerator* accelerator) override { + ui::Accelerator* accelerator) const override { NOTREACHED(); return false; }
diff --git a/ui/views/views.gyp b/ui/views/views.gyp index 5dd8411..7e688d9 100644 --- a/ui/views/views.gyp +++ b/ui/views/views.gyp
@@ -299,6 +299,7 @@ 'style/platform_style.cc', 'style/platform_style.h', 'style/platform_style_mac.mm', + 'touch_event_watcher.h', 'view.cc', 'view.h', 'view_constants.cc',
diff --git a/ui/views/views_exports.cc b/ui/views/views_exports.cc index f1ba3f5..1aeec123 100644 --- a/ui/views/views_exports.cc +++ b/ui/views/views_exports.cc
@@ -8,3 +8,4 @@ // the resulting dynamic library. #include "ui/views/pointer_watcher.h" +#include "ui/views/touch_event_watcher.h"
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc index f1cc3f6..2bb3b4b 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -1173,7 +1173,7 @@ depth, InputOutput, visual, attribute_mask, &swa); if (ui::PlatformEventSource::GetInstance()) ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); - open_windows().push_back(xwindow_); + open_windows().push_front(xwindow_); // TODO(erg): Maybe need to set a ViewProp here like in RWHL::RWHL().
diff --git a/ui/webui/resources/PRESUBMIT.py b/ui/webui/resources/PRESUBMIT.py index 2ac87faf..1a7cbb3 100644 --- a/ui/webui/resources/PRESUBMIT.py +++ b/ui/webui/resources/PRESUBMIT.py
@@ -11,7 +11,8 @@ existing_bots = (change.CQ_INCLUDE_TRYBOTS or '').split(';') clean_bots = set(filter(None, map(lambda s: s.strip(), existing_bots))) - new_bots = clean_bots | set(['tryserver.chromium.linux:closure_compilation']) + new_bots = clean_bots | set( + ['master.tryserver.chromium.linux:closure_compilation']) new_tag = 'CQ_INCLUDE_TRYBOTS=%s' % ';'.join(new_bots) if clean_bots:
diff --git a/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources2.gyp b/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources2.gyp index 1ff8af3..745731b 100644 --- a/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources2.gyp +++ b/ui/webui/resources/cr_elements/cr_shared_menu/compiled_resources2.gyp
@@ -9,8 +9,7 @@ '../../js/compiled_resources2.gyp:assert', '../../js/compiled_resources2.gyp:cr', '../../js/compiled_resources2.gyp:util', - '../../js/cr/ui/compiled_resources2.gyp:position_util', - '<(EXTERNS_GYP):web_animations', + '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/compiled_resources2.gyp:iron-a11y-keys-behavior-extracted', ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
diff --git a/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.html b/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.html index e140f73f..6522f729 100644 --- a/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.html +++ b/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.html
@@ -1,26 +1,33 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr.html"> -<link rel="import" href="chrome://resources/html/cr/ui/position_util.html"> <link rel="import" href="chrome://resources/html/util.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/web-animations.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/iron-dropdown/iron-dropdown.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/fade-in-animation.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/animations/fade-out-animation.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-listbox/paper-listbox.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-menu-button/paper-menu-button-animations.html"> <dom-module id="cr-shared-menu"> <template> <style> - :host { + #menu { @apply(--shadow-elevation-2dp); - display: none; + background-color: white; overflow: hidden; - position: absolute; + padding: 8px 0; + position: relative; } - </style> - <paper-listbox id="menu"> - <content></content> - </paper-listbox> + <iron-dropdown id="dropdown" allow-outside-scroll restore-focus-on-close + vertical-align="auto" horizontal-align="right" opened="{{menuOpen}}" + open-animation-config="[[openAnimationConfig]]" + close-animation-config="[[closeAnimationConfig]]"> + <div id="menu" class="dropdown-content" role="menu"> + <content></content> + </div> + </iron-dropdown> </template> <script src="cr_shared_menu.js"></script> </dom-module>
diff --git a/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.js b/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.js index ab746bd..e08fd0d 100644 --- a/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.js +++ b/ui/webui/resources/cr_elements/cr_shared_menu/cr_shared_menu.js
@@ -4,14 +4,16 @@ /** Same as paper-menu-button's custom easing cubic-bezier param. */ var SLIDE_CUBIC_BEZIER = 'cubic-bezier(0.3, 0.95, 0.5, 1)'; -var FADE_CUBIC_BEZIER = 'cubic-bezier(0.4, 0, 0.2, 1)'; Polymer({ is: 'cr-shared-menu', + behaviors: [Polymer.IronA11yKeysBehavior], + properties: { menuOpen: { type: Boolean, + observer: 'menuOpenChanged_', value: false, }, @@ -24,48 +26,112 @@ type: Object, value: null, }, + + /** @override */ + keyEventTarget: { + type: Object, + value: function() { + return this.$.menu; + } + }, + + openAnimationConfig: { + type: Object, + value: function() { + return [{ + name: 'fade-in-animation', + timing: { + delay: 50, + duration: 200 + } + }, { + name: 'paper-menu-grow-width-animation', + timing: { + delay: 50, + duration: 150, + easing: SLIDE_CUBIC_BEZIER + } + }, { + name: 'paper-menu-grow-height-animation', + timing: { + delay: 100, + duration: 275, + easing: SLIDE_CUBIC_BEZIER + } + }]; + } + }, + + closeAnimationConfig: { + type: Object, + value: function() { + return [{ + name: 'fade-out-animation', + timing: { + duration: 150 + } + }, { + name: 'paper-menu-shrink-width-animation', + timing: { + delay: 100, + duration: 50, + easing: SLIDE_CUBIC_BEZIER + } + }, { + name: 'paper-menu-shrink-height-animation', + timing: { + delay: 200, + easing: 'ease-in' + } + }]; + } + } + }, + + keyBindings: { + 'tab': 'onTabPressed_', }, /** - * Current animation being played, or null if there is none. - * @type {?Animation} - * @private - */ - animation_: null, - - /** * The last anchor that was used to open a menu. It's necessary for toggling. - * @type {?Element} + * @private {?Element} */ lastAnchor_: null, /** - * Adds listeners to the window in order to dismiss the menu on resize and - * when escape is pressed. + * The first focusable child in the menu's light DOM. + * @private {?Element} */ + firstFocus_: null, + + /** + * The last focusable child in the menu's light DOM. + * @private {?Element} + */ + lastFocus_: null, + + /** @override */ attached: function() { window.addEventListener('resize', this.closeMenu.bind(this)); - window.addEventListener('keydown', function(e) { - // Escape button on keyboard - if (e.keyCode == 27) - this.closeMenu(); - }.bind(this)); + + var focusableChildren = Polymer.dom(this).querySelectorAll( + '[tabindex],button'); + if (focusableChildren.length > 0) { + this.$.dropdown.focusTarget = focusableChildren[0]; + this.firstFocus_ = focusableChildren[0]; + this.lastFocus_ = focusableChildren[focusableChildren.length - 1]; + } }, /** Closes the menu. */ closeMenu: function() { - if (!this.menuOpen) - return; - // If there is a open menu animation going, cancel it and start closing. - this.cancelAnimation_(); + if (this.root.activeElement == null) { + // Something else has taken focus away from the menu. Do not attempt to + // restore focus to the button which opened the menu. + this.$.dropdown.restoreFocusOnClose = false; + } this.menuOpen = false; - this.itemData = null; - this.animation_ = this.animateClose_(); - this.animation_.addEventListener('finish', function() { - this.style.display = 'none'; - // Reset the animation for the next time the menu opens. - this.cancelAnimation_(); - }.bind(this)); + this.$.dropdown.restoreFocusOnClose = true; }, /** @@ -74,30 +140,12 @@ * @param {!Object} itemData The contextual item's data. */ openMenu: function(anchor, itemData) { - this.menuOpen = true; - this.style.display = 'block'; this.itemData = itemData; this.lastAnchor_ = anchor; // Move the menu to the anchor. - var anchorRect = anchor.getBoundingClientRect(); - var parentRect = this.offsetParent.getBoundingClientRect(); - - var left = (isRTL() ? anchorRect.left : anchorRect.right) - parentRect.left; - var top = anchorRect.top - parentRect.top; - - cr.ui.positionPopupAtPoint(left, top, this, cr.ui.AnchorType.BEFORE); - - // Handle the bottom of the screen. - if (this.getBoundingClientRect().top != anchorRect.top) { - var bottom = anchorRect.bottom - parentRect.top; - cr.ui.positionPopupAtPoint(left, bottom, this, cr.ui.AnchorType.BEFORE); - } - - this.$.menu.focus(); - - this.cancelAnimation_(); - this.animation_ = this.animateOpen_(); + this.$.dropdown.positionTarget = anchor; + this.menuOpen = true; }, /** @@ -106,128 +154,44 @@ * @param {!Object} itemData The contextual item's data. */ toggleMenu: function(anchor, itemData) { - // If there is an animation going (e.g. user clicks too fast), cancel it and - // start the new action. - this.cancelAnimation_(); if (anchor == this.lastAnchor_ && this.menuOpen) this.closeMenu(); else this.openMenu(anchor, itemData); }, - /** @private */ - cancelAnimation_: function() { - if (this.animation_) { - this.animation_.cancel(); - this.animation_ = null; - } - }, - /** - * @param {!Array<!KeyframeEffect>} effects - * @return {!Animation} + * Trap focus inside the menu. As a very basic heuristic, will wrap focus from + * the first element with a nonzero tabindex to the last such element. + * TODO(tsergeant): Use iron-focus-wrap-behavior once it is available + * (https://github.com/PolymerElements/iron-overlay-behavior/issues/179). + * @param {CustomEvent} e */ - playEffects: function(effects) { - /** @type {function(new:Object, !Array<!KeyframeEffect>)} */ - window.GroupEffect; + onTabPressed_: function(e) { + if (!this.firstFocus_ || !this.lastFocus_) + return; - /** @type {{play: function(Object): !Animation}} */ - document.timeline; + var toFocus; + var keyEvent = e.detail.keyboardEvent; + if (keyEvent.shiftKey && keyEvent.target == this.firstFocus_) + toFocus = this.lastFocus_; + else if (keyEvent.target == this.lastFocus_) + toFocus = this.firstFocus_; - return document.timeline.play(new window.GroupEffect(effects)); + if (!toFocus) + return; + + e.preventDefault(); + toFocus.focus(); }, /** - * Slide-in animation when opening the menu. The animation configuration is - * the same as paper-menu-button except for a shorter delay time. + * Ensure the menu is reset properly when it is closed by the dropdown (eg, + * clicking outside). * @private - * @return {!Animation} */ - animateOpen_: function() { - var rect = this.getBoundingClientRect(); - var height = rect.height; - var width = rect.width; - - var fadeIn = new KeyframeEffect(/** @type {Animatable} */(this), [{ - 'opacity': '0' - }, { - 'opacity': '1' - }], /** @type {!KeyframeEffectOptions} */({ - delay: 50, - duration: 200, - easing: FADE_CUBIC_BEZIER, - fill: 'both' - })); - - var growHeight = new KeyframeEffect(/** @type {Animatable} */(this), [{ - height: (height / 2) + 'px' - }, { - height: height + 'px' - }], /** @type {!KeyframeEffectOptions} */({ - delay: 50, - duration: 275, - easing: SLIDE_CUBIC_BEZIER, - fill: 'both' - })); - - var growWidth = new KeyframeEffect(/** @type {Animatable} */(this), [{ - width: (width / 2) + 'px' - }, { - width: width + 'px' - }], /** @type {!KeyframeEffectOptions} */({ - delay: 50, - duration: 150, - easing: SLIDE_CUBIC_BEZIER, - fill: 'both' - })); - - return this.playEffects([fadeIn, growHeight, growWidth]); - }, - - /** - * Slide-out animation when closing the menu. The animation configuration is - * the same as paper-menu-button. - * @private - * @return {!Animation} - */ - animateClose_: function() { - var rect = this.getBoundingClientRect(); - var height = rect.height; - var width = rect.width; - - var fadeOut = new KeyframeEffect(/** @type {Animatable} */(this), [{ - 'opacity': '1' - }, { - 'opacity': '0' - }], /** @type {!KeyframeEffectOptions} */({ - duration: 150, - easing: FADE_CUBIC_BEZIER, - fill: 'both' - })); - - var shrinkHeight = new KeyframeEffect(/** @type {Animatable} */(this), [{ - height: height + 'px', - transform: 'translateY(0)' - }, { - height: height / 2 + 'px', - transform: 'translateY(-20px)' - }], /** @type {!KeyframeEffectOptions} */({ - duration: 200, - easing: 'ease-in', - fill: 'both' - })); - - var shrinkWidth = new KeyframeEffect(/** @type {Animatable} */(this), [{ - width: width + 'px' - }, { - width: width - (width / 20) + 'px' - }], /** @type {!KeyframeEffectOptions} */({ - delay: 100, - duration: 50, - easing: SLIDE_CUBIC_BEZIER, - fill: 'both' - })); - - return this.playEffects([fadeOut, shrinkHeight, shrinkWidth]); + menuOpenChanged_: function() { + if (!this.menuOpen) + this.itemData = null; }, });
diff --git a/ui/webui/resources/images/eol.svg b/ui/webui/resources/images/eol.svg index 00743f8..14d9498 100644 --- a/ui/webui/resources/images/eol.svg +++ b/ui/webui/resources/images/eol.svg
@@ -1 +1,7 @@ -<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><title>EOL_setting_100</title><path d="M3.97 2.13h-.025l.01.01.016-.01zM1.668 4.41v.024c.004-.005.007-.01.012-.014l-.013-.01zm14.16-2.54C14.19.7 12.192 0 10.026 0 7.863 0 5.865.698 4.23 1.87c-.006.005 4.594 4.624 4.594 4.624l1.204-1.505 4.986 6.234h-1.462l4.567 4.57c1.183-1.65 1.88-3.65 1.88-5.817 0-2.166-.697-4.165-1.87-5.8-.637-.89-1.415-1.668-2.304-2.306zm2.045 14.194v-.027c-.004.005-.008.01-.01.015l.01.012zm.248 2.02l-1.036-1.057-4.563-4.565-4.713-4.696-4.835-4.838-1.047-1.046-.79-.792L0 2.224 1.925 4.15C.753 5.812.055 7.81.055 9.977s.698 4.166 1.87 5.8c.638.89 1.416 1.67 2.305 2.307 1.634 1.173 3.632 1.87 5.798 1.87 2.165 0 4.163-.697 5.798-1.87L17.768 20l1.134-1.135-.782-.78zm-5.705-3H7.488v-3.86H5.042L6.8 9.027l5.615 5.724v.335z" fill="#DB4437" fill-rule="evenodd"/></svg> +<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <g id="Notification-Icon" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> + <g id="Artboard-4-Copy-3" fill="#DB4437"> + <path d="M4.57403661,2.91638517 L4.55031697,2.91638517 L4.56057411,2.92664728 C4.56506161,2.92344037 4.56954911,2.91959208 4.57403661,2.91638517 Z M2.50042738,4.96765297 L2.50042738,4.99074272 C2.50363274,4.98625305 2.50683809,4.98240475 2.51068452,4.97791508 L2.50042738,4.96765297 Z M17.0847995,15.4572626 L17.0847995,15.4335314 C17.0815941,15.4380211 17.0777477,15.4425108 17.0745423,15.4470005 L17.0847995,15.4572626 Z M17.3075718,17.2753239 L16.3754541,16.3241544 L12.2687513,12.2154616 L8.02614146,7.98939582 L3.67454947,3.63505366 L2.73281573,2.69350494 L2.02058551,1.98092958 L1,3.00200966 L2.73281573,4.73502373 C1.67761237,6.23072647 1.05000356,8.02980288 1.05000356,9.97960405 C1.05000356,11.9294052 1.67761237,13.7284816 2.73281573,15.2004532 C3.30657454,16.0008979 4.0066244,16.701287 4.80668139,17.2753239 C6.27794002,18.3310386 8.07614502,18.9589516 10.0250018,18.9589516 C11.9738585,18.9589516 13.7720635,18.3310386 15.2433222,17.2753239 L16.9908825,19 L18.0114681,17.9789199 L17.3075718,17.2753239 Z M15.2433222,2.68362766 C13.7720635,1.62855433 11.9738585,1 10.0250018,1 C8.07614502,1 6.27794002,1.62855433 4.80668139,2.68362766 C4.80155282,2.68747595 8.94159128,6.84491384 8.94159128,6.84491384 L10.0250018,5.0300293 L15.0415647,11 L13.1963815,11 L17.3069307,15.2143071 C18.3723912,13.7288665 19,11.9291487 19,9.9793475 C19,8.03018771 18.3723912,6.23046992 17.3171878,4.75849831 C16.743429,3.95805362 16.0433792,3.25766451 15.2433222,2.68362766 Z M12,15 L7.012146,15 L7.01214607,11.0111083 L4.5,11 L6.7267679,9.12400051 L12,14.6000004 L12,15 Z" id="Combined-Shape"></path> + </g> + </g> +</svg>
diff --git a/ui/webui/resources/js/cr.js b/ui/webui/resources/js/cr.js index 090cfd9..3c1b75e 100644 --- a/ui/webui/resources/js/cr.js +++ b/ui/webui/resources/js/cr.js
@@ -475,6 +475,11 @@ /** Whether this is on Android. */ get isAndroid() { return /Android/.test(navigator.userAgent); + }, + + /** Whether this is on iOS. */ + get isIOS() { + return /iPad|iPhone|iPod/.test(navigator.platform); } }; }();
diff --git a/url/origin_unittest.cc b/url/origin_unittest.cc index 6a3128b7..74ffd303 100644 --- a/url/origin_unittest.cc +++ b/url/origin_unittest.cc
@@ -27,7 +27,7 @@ "yay", "http::///invalid.example.com/"}; - for (const auto& test_url : urls) { + for (auto* test_url : urls) { SCOPED_TRACE(test_url); GURL url(test_url); url::Origin origin(url);
diff --git a/url/scheme_host_port_unittest.cc b/url/scheme_host_port_unittest.cc index 7e9351f..a2b594c 100644 --- a/url/scheme_host_port_unittest.cc +++ b/url/scheme_host_port_unittest.cc
@@ -26,7 +26,7 @@ "blob:https://example.com/uuid-goes-here", "filesystem:https://example.com/temporary/yay.png"}; - for (const auto& test : urls) { + for (auto* test : urls) { SCOPED_TRACE(test); GURL url(test); url::SchemeHostPort tuple(url);